Self-hosting
Docker Compose is the recommended way to run Ifrit. The repository's docker-compose.yml defines two
services:
- app: one container with nginx serving the web interface and reverse-proxying the API to the application server.
- db: a standard, unmodified PostgreSQL 18 container with a named volume (
ifrit-db).
Uploaded files (the organization logo and project documents) live in a second named volume,
ifrit-storage, mounted at STORAGE_ROOT inside the app container.
If you have not run Ifrit yet, start with Getting started.
Run it behind HTTPS
The application container serves plain HTTP on port 80. For a real deployment, put a reverse proxy or load balancer that terminates TLS in front of it (nginx, Caddy, Traefik, a cloud load balancer), and set:
CORS_ORIGINS=["https://ifrit.mydomain.com"]
COOKIE_SECURE=true
CORS_ORIGINSmust list the exact origin users type in the browser, scheme included.COOKIE_SECURE=truemakes the session cookies HTTPS-only. Leaving itfalsebehind a TLS proxy would send session cookies without theSecureflag.
Your proxy must allow request bodies of at least 11 MB through, or uploads fail before they reach the application (see Uploads).
Use your own PostgreSQL
Inside the default stack the application reaches the database at host db. To use a database you
run yourself, remove the db service from your compose file and point DATABASE_URL at it:
DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@HOST:5432/DATABASE
The asyncpg driver part of the URL is required. The compose file builds this URL from
POSTGRES_USER, POSTGRES_PASSWORD and POSTGRES_DB; a custom DATABASE_URL replaces it.
Releases and image tags
Ifrit follows semantic versioning. Each release is a vX.Y.Z tag on GitHub
and publishes a container image to the GitHub Container Registry:
| Image | What it is |
|---|---|
ghcr.io/tonyp7/ifrit:X.Y.Z |
An exact release. Recommended for production. |
ghcr.io/tonyp7/ifrit:X.Y |
The latest patch release of that minor version. |
ghcr.io/tonyp7/ifrit:X |
The latest release of that major version. |
ghcr.io/tonyp7/ifrit:latest |
The current state of main, which can be ahead of the last release. Not recommended for production. |
The provided docker-compose.yml builds the image from your checkout, so to run a release, check
out its tag:
git fetch --tags
git checkout vX.Y.Z
docker compose up -d --build
If you run your own compose file, use image: ghcr.io/tonyp7/ifrit:X.Y.Z in place of the build:
section of the app service, with the same environment variables and the same storage volume.
Backups
Back up both of these together:
-
The database:
shell docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > ifrit-backup.sql -
The uploaded files: the
ifrit-storagevolume (for example withdocker run --rm -v ifrit-storage:/data -v "$PWD":/backup busybox tar czf /backup/ifrit-storage.tgz -C /data .; note that Compose prefixes volume names with the project name, checkdocker volume ls).
To restore, recreate the stack, load the SQL dump into the database and put the files back into the storage volume.
Upgrading
- Read the changelog for the release you are moving to.
- Take a backup (above).
- Check out the new tag (or change the image tag) and run
docker compose up -d --build.
Database migrations are applied automatically every time the container starts, so there is no separate migration step. Migrations only go forward: to return to an earlier release, restore your backup.
Security notes
- Generate a strong
JWT_SECRET_KEYand keep.envout of version control and out of backups you share. Changing the key signs everyone out. - Change
SEED_ADMIN_PASSWORDafter the first sign-in, or remove it from.envonce the bootstrap administrator exists (the application still requires the setting to be present, so replace it with a long random value rather than deleting the line). - Accounts are created by an administrator only. There is no self-registration and no self-service password reset: an administrator sets a new password for a user who forgot theirs.