A forum API, powered by Flask and SQLAlchemy.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Tomáš Hozman a98a9e9245 fix required hasher kwargs in write() 11 months ago
avatars directory structure changes, TODO: RST docstrings 2 years ago
contexts fixed local account totp generation, allowed deletion, created missing JSON-LD schemas & other minor fixes 1 year ago
docs updated docstring 1 year ago
files fixed user OpenID registration (config, group assignment, etc.), file uploading & logging level envvar 2 years ago
heiwa fix required hasher kwargs in write() 11 months ago
.gitignore statistic -> statistics URL, default permission fix 2 years ago
Dockerfile fixed sa_session arg in .create() 1 year ago
LICENSE updated license (GPL -> AGPL) 2 years ago
Pipfile updated dependencies 1 year ago
Pipfile.lock updated dependencies 1 year ago
README.md openid names 1 year ago
config.example.json added unique name option 1 year ago
docker-compose.yml fixed sa_session arg in .create() 1 year ago
pylintrc added pylint config file 2 years ago
requirements.txt fixed python dependencies 1 year ago
run.sh updated name 1 year ago



A forum software, powered by Flask and SQLAlchemy. Unfinished, but steadily approaching v1.0.

This repository only contains the API. The frontend can be found at heiwa-frontend.

Requires Python 3.10.

Supports many features, including but not limited to:

  • Basic forum functionality - categories, forums, threads, posts.
  • A public API that covers everything.
  • Users, split into zero or more groups.
  • OpenID authentication, local logins with 2FA support and guest accounts.
  • Fine-grained permissions, can be set for specific users, groups, or forums. Calculated based on priority and / or group order.
  • Encrypted messaging, using RSA keys and AES.
  • File uploads, with libmagic type validation.
  • Notifications.
  • Statistics.
  • JSON-LD support.



Copy the config.example.json file to config.json, and make the required, as well as any additional changes.

Must be changed, you will be exposed to serious security vulnerabilities otherwise:

  • SECRET_KEY, the default secret key some extensions will use.
  • LOCAL_ACCOUNT_VERIFICATION_JWT_SECRET_KEY, the secret key used for generating local account e-mail verification JWTs.
  • USER_JWT_SECRET_KEY, the secret key used for generating authentication JWTs for all users.
  • DATABASE_URI, the URI used to access the Postgres database.
  • LOCAL_ACCOUNT_EMAIL_SMTP_PASSWORD, the password for your SMTP server.
  • OIDC_SERVICES, the OpenID services you want to make available to your users. If left empty, the endpoints will still be visible, but effectively disabled.

Passwords and secret keys should ideally be very long sequences of ASCII, as well as non-ASCII characters. For example, *B8付Llbpふ7LとPšd3€a7!A様ůřShov&žt3Nm&9peIKig6J%でもそう繰り返すččšbyにSqMB5ěcøけば+いつまがkpP1.

Must be changed, otherwise things will break:

  • JSON_LD_CONTEXT_URL, the base URL to your JSON-LD contexts. If using the default frontend, this should be https://yourdomain.tld/static/contexts/.
  • LOCAL_ACCOUNT_EMAIL_SMTP_SERVER and LOCAL_ACCOUNT_EMAIL_SMTP_USERNAME, information about how to access your SMTP server. These are very likely different than the provided defaults.
  • LOCAL_ACCOUNT_PASSWORD_RESET_SMTP_ADDRESS, the e-mail address which password reset e-mails should come from.
  • LOCAL_ACCOUNT_VERIFICATION_SMTP_ADDRESS, the e-mail address which account verification e-mails should come from. This is usually the same as the previous value.
  • LOCAL_ACCOUNT_PASSWORD_RESET_URL, the URL where local accounts' passwords are reset. If using the default frontend, this should be https://yourdomain.tld/account/local/reset-password?token={jwt}.
  • LOCAL_ACCOUNT_VERIFICATION_URL, the URL where local accounts are verified. If using the default frontend, this should be https://yourdomain.tld/account/local/verify?token={jwt}.

Probably should be changed:

  • META_NAME, META_CONTACT and META_TOS, basic information about your forum.
  • RATELIMIT_DEFAULT and RATELIMIT_SPECIFIC, default and endpoint-specific rate limits.

Note that the task scheduler the cron config keys affect parses all time in UTC. For example, if you live in the CET timezone and set the hour key to 0, the task will run at CET 1 AM - UTC midnight.

Running standalone

Run these commands first:

pip install -r requirements.txt  # Install Python dependencies
pip install gunicorn  # Install WSGI server

Then, to start the server, run:


or bring your own web server that integrates the heiwa:create_app() function. For local development, set the FLASK_ENV environment variable to development in order to disable authentication redirect URLs' requirement for destinations to be external.

Running in Docker

Change docker-compose.yml's database login information to reflect those in the config.json file.

If you're running Heiwa in a production environment, change the FLASK_ENV environment variable on line 21 from development to production. This enables the requirement for authentication redirect URLs' destinations to be external.

Then, proceed with the standard way of running containers:

docker-compose up