jawanndenn is a simple web application to schedule meetings and run polls, a libre alternative to Doodle. It is using the following technology:
-
Python
-
TypeScript / CSS / Fonts
-
Storage
-
Scheduling
jawanndenn is libre software developed by Sebastian Pipping. The code is licensed under the GNU Affero GPL license version 3 or later.
Please report bugs and let me know if you like it.
The textarea titled "Setup (JSON)" uses a simple JSON-based format that knows the following keys:
lifetime
— duration after which this poll will be deleted; can be"week"
or"month"
; an enum-like stringoptions
— a list of strings, one for each option; supports Markdown-like syntax for: bold, italic, inline codetitle
— the title or headline of the poll to run; supports Markdown-like syntax for: bold, italic, inline code
To install the latest release without cloning the Git repository:
# pip3 install jawanndenn --user
To install from a Git clone:
# ./setup.py install --user
Create a simple file .env
like this one:
JAWANNDENN_POSTGRES_NAME=jawanndenn
JAWANNDENN_POSTGRES_USER=jawanndenn
JAWANNDENN_POSTGRES_PASSWORD=dEb2PIcinemA8poH
JAWANNDENN_SECRET_KEY=606ea88f183a27919d5c27ec7f948906d23fdd7821684eb59e8bcf7377e3853b
Make sure to adjust these values after copy and paste!
You can then build and run a docker image using
docker-compose up --build
.
The app is served on localhost:54080
. PostgreSQL data is saved to
~/.jawanndenn-docker-pgdata/
on the host system. There is also an
instance of Redis used for cross-process rate limiting, and a "cron"
housekeeping container that will go delete polls that have exceeded
their configured lifetime, every 60 minutes.
(If you need a low-maintenance SSL reverse proxy in front of jawanndenn, docker-ssl-reverse-proxy could be of interest.)
There is a few more environment variables that you could want to adjust in your environment. Altogether, there are these variables:
Variable | Function |
---|---|
DJANGO_SETTINGS_MODULE |
Django settings module to use, leave as is, defaults to jawanndenn.settings (see docker-compose.yml ) |
JAWANNDENN_ALLOWED_HOSTS |
Hostnames to serve jawanndenn at, list separated by comma, is set to jawanndenn.de,www.jawanndenn.de on the main production server, defaults to 127.0.0.1,0.0.0.0,localhost (see jawanndenn/settings.py ) |
JAWANNDENN_DEBUG |
Debug mode, disabled for all values but True , disabled by default, should never be enabled in production for security (see jawanndenn/settings.py ) |
JAWANNDENN_MAX_POLLS |
Maximum total number of polls to store, denial of service protection, defaults to 1000 (see jawanndenn/settings.py and docker-compose.yml ) |
JAWANNDENN_MAX_VOTES_PER_POLL |
Maximum total number of polls to store, denial of service protection, defaults to 40 (see jawanndenn/settings.py ) |
JAWANNDENN_POSTGRES_HOST |
Hostname of the PostgreSQL database to connect to; defaults to postgres (see docker-compose.yml ) |
JAWANNDENN_POSTGRES_NAME |
Database name of the PostgreSQL database to connect to; no default, always required |
JAWANNDENN_POSTGRES_PASSWORD |
Password for log-in with the PostgreSQL database; no default, always required |
JAWANNDENN_POSTGRES_PORT |
Port of the PostgreSQL database to connect to; defaults to 5432 (see docker-compose.yml ) |
JAWANNDENN_POSTGRES_USER |
Username for log-in with the PostgreSQL database; no default, always required |
JAWANNDENN_REDIS_HOST |
Hostname of the Redis database to connect to; defaults to redis (see docker-compose.yml ) |
JAWANNDENN_REDIS_PORT |
Port of the Redis database to connect to; defaults to 6379 (see docker-compose.yml ) |
JAWANNDENN_SECRET_KEY |
Django secret key; should be long, generated, not used elsewhere; no default, always required |
JAWANNDENN_SENTRY_DSN |
Data source name (DSN) for use with Sentry, disabled/empty by default (see jawanndenn/settings.py ) |
JAWANNDENN_URL_PREFIX |
Prefix string to insert into URLs rather after the domain name to help with hosting multiple apps under the same domain side by side; e.g. prefix prefix123 will result in URLs like https://<domain>/prefix123/poll/<id> ; empty by default (see jawanndenn/settings.py ) |
A simple way to create and apply backups of Django's view on the PostgreSQL poll data is the following.
Let's assume you add a docker-compose.override.yml
like this:
services:
jawanndenn:
volumes:
- ~/.jawanndenn-docker-backups/:/home/jawanndenn/backups/:rw
Now Django management command dumpdata
can be used to backup the poll data to a JSON file like this:
# docker compose run jawanndenn python3 -m django dumpdata -v3 --format json -o "/home/jawanndenn/backups/data-$(date -I).json"
To reset the database to the state of a backup, Django management loaddata
would do the job:
# docker compose run jawanndenn python3 -m django loaddata -v3 /home/jawanndenn/backups/data-2025-05-23.json
When installed, invocation is as simple as
# jawanndenn
During development, you may want to run jawanndenn from the Git clone using
# PYTHONPATH=. python3 -m jawanndenn --debug
Currently supported arguments are:
# COLUMNS=80 jawanndenn --help
usage: jawanndenn [-h] [--version] [--debug] [--host HOST] [--port PORT]
[--url-prefix PATH] [--database-sqlite3 FILE]
[--django-secret-key-file FILE] [--max-polls COUNT]
[--max-votes-per-poll COUNT] [--dumpdata]
[--loaddata FILE.json]
options:
-h, --help show this help message and exit
--version show program's version number and exit
--debug Enable debug mode (default: disabled)
--host HOST Hostname or IP address to listen at (default:
127.0.0.1)
--port PORT Port to listen at (default: 8080)
--url-prefix PATH Path to prepend to URLs (default: "")
--database-sqlite3 FILE
File to write the database to (default:
~/jawanndenn.sqlite3)
--django-secret-key-file FILE
File to use for Django secret key data (default:
~/jawanndenn.secret_key)
limit configuration:
--max-polls COUNT Maximum number of polls total (default: 1000)
--max-votes-per-poll COUNT
Maximum number of votes per poll (default: 40)
data import/export arguments:
--dumpdata Dump a JSON export of the database to standard output,
then quit.
--loaddata FILE.json Load a JSON export of the database from FILE.json,
then quit.
Migration takes four steps:
-
Update to the latest version of jawanndenn 1.x, e.g. by running:
pip2 install --upgrade 'jawanndenn<2'
; the JSON data export was first introduced with release 1.6.3. -
Export existing polls:
- If you're using the commend line app:
python2 -m jawanndenn --dumpdata > dump.json
- If you're using docker-compose:
docker-compose run -T jawanndenn --database-pickle /data/polls.pickle --dumpdata > dump.json
- If you're using the commend line app:
-
Deploy latest jawanndenn 2.x somewhere (as described above) or just
pip3 install 'jawanndenn>=2'
it somewhere -
Import the JSON dump created in step (2):
-
If you're using the commend line app:
python3 -m jawanndenn --loaddata dump.json
-
If you're using docker-compose:
docker-compose run -T jawanndenn sh -c 'cat > /tmp/dump.json && DJANGO_SETTINGS_MODULE=jawanndenn.settings python3 -m django loaddata /tmp/dump.json' < dump.json
-
- Libre software to host yourself, unlike Doodle
- More simplistic, sexy and/or fun than
libre alternatives,
in alphabetic order:
- Bitpoll (ex. Dudel)
- Crab Fit
- Croodle
- Dudle
- (Drupal Date picker formatter)
- (Foodle (discontinued; on GitHub, ex. DFN scheduler, ex. DFN Terminplaner+))
- Framadata (Sources, ex. OpenSondage, ex. STUdS)
- Nextcloud Polls
- Noodle
- Nuages
- Pleft
- Rallly
- RDVz
- sowhenthen
- VoteOn.Date
- Keep things simple, usable, maintainable
- Support invocation from the command line, e.g. for spontaneous polls in a LAN
- Have security in mind
Please check out the list of upcoming features.
- Adding any new non-tiny features
- Read availability from calendars
Special thanks to Arne Maier (@KordonDev) for reporting an XSS vulnerability, responsibly.