New releases
Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.
Vikunja keeps tasks, project boards, deadlines, and attachments on your own server. Use lists or kanban to plan household work and small team projects, with recurring tasks and built-in two-factor authentication. This recipe uses the official image and a separate PostgreSQL database.
Vikunja is a self-hosted task manager for household work and small team projects. Collect tasks in projects, switch between a list and a kanban board, set priorities and deadlines, and keep notes and attachments beside the work. Recurring tasks, labels, assignees, and project sharing support routines that need more than a personal checklist.
It can replace the task-list part of Todoist or a straightforward Trello board. It does not reproduce every hosted automation, integration, or enterprise administration feature. The interface includes English and Russian. Use the web interface on computers and phones, or the project’s separately distributed desktop wrapper; this recipe does not provide a native Android or iOS client.
The recipe pins the official Vikunja 2.7.1 image and PostgreSQL 18.4. The app runs as UID/GID 1000:1000, with a read-only root filesystem and a temporary /tmp; a short-lived Alpine container assigns ownership of its data volume. The app volume holds attachments under /data/files, while a separate PostgreSQL volume holds tasks, accounts, permissions, and settings. Neither the database nor an administrative port is published.
PostgreSQL is a deliberate choice: the SQLite trial of this release returned database is locked when deleting a task and moving it between board columns. This recipe’s smoke test uses PostgreSQL and checks real task/attachment creation, deletion, and recovery. Resource figures are planning estimates for a small installation: one CPU core, 1 GB RAM minimum, 2 GB recommended, and 5 GB disk before attachments. Both service images offer amd64 and arm64; only amd64 has been run here. The reliable level is partial because monitoring, resource limits, and high availability are not included.
The server is AGPL-3.0-or-later licensed. Optional Pro features, including the web administration panel, require a separate license; the recipe uses the free core. Local accounts and native TOTP two-factor authentication are available, and OIDC can be configured separately. SAML and proxy user-header login are not supplied by this recipe. SMTP is not configured, so email reminders and email recovery need additional setup.
Open registration is disabled, and there is no public default account: create the first user through the container CLI. Keep the service secret and database password private, expose the app through HTTPS, and protect both persistent volumes. Backups contain private tasks, attachments, and credentials; encrypt them and keep a copy off-server. Review share-link permissions before distributing links outside the registered user group. The functional checks do not constitute an image vulnerability scan.
Sources: documentation, configuration, CLI, backup/restore, official image, desktop wrapper, and release v2.7.1.
These are stored results of separate checks, not real-time data. An unknown status means the check has not been performed yet.
Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.
Result of a dedicated Docker image scan, not a Compose configuration check.
A new major version is found by comparing version numbers. A compatibility verdict is entered by hand after reading the release notes and the migration steps.
Upstream Compose changes relative to the verified recipe.
Pinned image tags checked for newer versions.
From observation to action
The recipe already pins the latest known release. The steps below show the evidence retained for that version.
2.7.12.7.1Open this release on GitHub ↗ The link is evidence to review, not proof of compatibility.
The version numbers do not cross a major compatibility boundary. No compatibility verdict has been recorded.
No image-tag change is currently planned.
Change the tag and restart. Release-specific migration steps still come from the release notes and installation guide.
No version change is currently planned. The recipe includes a backup procedure. Restore has been tested.
An exact Fully verified check for this target was recorded on 2026-10-23.
The status shows how fully the published recipe meets each level's requirements.
A minimal setup for a local network or access through a VPN.
The recipe covers every requirement at this level.
A public deployment with protected access and backups.
The recipe covers every requirement at this level.
A setup designed for predictable operations and observability.
You still need to add: external monitoring, cpu and memory limits.
Tailored to your server
Answer five questions and download a ready-to-run Vikunja bundle.
Read the full guide first: it explains external access, backups, and data locations.
cp .env.example .envdocker compose up -ddocker compose psUse 64-bit Ubuntu 22.04+ or Debian 12+ with Docker Engine and Compose v2.24+. Plan for one CPU core, at least 1 GB RAM (2 GB recommended), and 5 GB disk plus attachments. Images support amd64 and arm64; this recipe was tested on amd64.
mkdir -p ~/services/vikunja
cd ~/services/vikunja
# Copy the recipe files, including backup.sh, restore.sh, and proxy/ here.
cp .env.example .env
chmod 600 .env
# Run twice, for an independent service secret and database password.
openssl rand -hex 32
openssl rand -hex 32
Edit .env before starting. Every parameter:
| Parameter | Meaning |
|---|---|
VIKUNJA_VERSION |
Exact application version, initially 2.7.1. Do not add v to this Docker tag. |
VIKUNJA_PORT |
Loopback host port, default 3456. |
VIKUNJA_PUBLIC_URL |
Exact browser URL with scheme, port if needed, and trailing slash. Default http://localhost:3456/; use the external HTTPS URL behind a proxy. |
VIKUNJA_SECRET |
Random service secret generated above; preserve it across restarts and recovery. |
VIKUNJA_DB_PASSWORD |
Different random PostgreSQL password; replace the placeholder before first start. |
VIKUNJA_DATA_VOLUME |
App volume with uploaded files under /data/files. |
VIKUNJA_DB_VOLUME |
PostgreSQL 18 volume mounted at /var/lib/postgresql, including its versioned data directory. |
TZ |
IANA time zone, default Etc/UTC. Set account time zones separately in the app. |
VIKUNJA_BACKUP_DIR |
Optional absolute backup directory; defaults to backups/ beside the recipe. |
The scripts source the active .env as trusted shell configuration. Keep it private and use the generated simple values. Changing a database password in .env does not rotate an initialized PostgreSQL role’s password.
docker compose config --quiet
docker compose pull
docker compose up -d --wait --wait-timeout 300
curl --fail http://127.0.0.1:3456/health
# Use your username and email; the CLI prompts for a password.
docker compose exec vikunja /app/vikunja/vikunja user create \
--username=alex --email=you@example.com
There is no default account. Open the exact VIKUNJA_PUBLIC_URL and sign in with the account you created. Registration stays disabled; create additional accounts through the same CLI. Choose a language and time zone in account settings, and enroll TOTP if desired. The optional Pro web administration panel is not required for these steps. No SMTP or external identity provider is configured.
The permissions container exits successfully after assigning the app volume to 1000:1000; this is expected. The app’s root filesystem is read-only, with writable attachments in /data and temporary files in /tmp.
Keep port 3456 on loopback and PostgreSQL private. Point a domain to the host, set VIKUNJA_PUBLIC_URL=https://tasks.example.com/, configure an HTTPS proxy, and allow only SSH/HTTP/HTTPS through the firewall. Store encrypted backups off-server. Registration is disabled, but each account still needs a unique password and carefully chosen project-sharing permissions.
For personal access use ssh -L 3456:127.0.0.1:3456 user@server and http://localhost:3456/ with the matching public URL. For shared LAN access use an HTTPS proxy, or bind the host port to a specific private IP and restrict it with a firewall. Keep PostgreSQL unexposed. The configured public URL must match the address clients actually use.
Use one file from proxy/. Caddy obtains certificates; Nginx expects certificate files; Traefik expects a websecure entry point and letsencrypt resolver. Samples run on the host and proxy to 127.0.0.1:3456. A containerized proxy needs a shared network and the app’s internal port 3456 instead.
Set the external HTTPS URL, including its trailing slash, in .env and run docker compose up -d --wait --wait-timeout 300 after a URL change. Nginx permits 50 MB requests, but Vikunja’s default maximum file size is 20 MB; both limits apply. OIDC and desktop clients must use the same reachable application URL.
./backup.sh
The script stops Vikunja, dumps PostgreSQL, and archives the app volume, .env, and Compose file into one private backups/vikunja-<timestamp>.tar. An app that was running is restarted; an already stopped app stays stopped. PostgreSQL keeps running. The database and attachments describe the same stopped state. Encrypt the complete archive and copy it off-server: it includes credentials and private user data. A database dump alone cannot restore file contents.
Restore replaces the database’s public schema and the app volume. Use only your own trusted archives and matching application/database versions. Compare archived configuration.env with .env manually, preserving its service secret; the script does not activate the archived environment.
# On a fresh host, initialize the matching recipe first.
docker compose up -d --wait --wait-timeout 300
./restore.sh ./backups/vikunja-TIMESTAMP.tar
curl --fail http://127.0.0.1:3456/health
docker compose logs --tail=100 vikunja database
Before replacement the script validates the archive and makes a safety backup. A replacement failure leaves the app stopped; repair the problem or restore again before starting it. Afterward, sign in, open a task, and download an attachment. The amd64 smoke exercises this path with a real uploaded file.
Read release notes, run ./backup.sh, and copy the archive off-server. Set VIKUNJA_VERSION to the exact reviewed Docker tag:
docker compose pull
docker compose up -d --wait --wait-timeout 300
docker compose logs --tail=100 vikunja
Do not use latest. Migrations run at startup. PostgreSQL’s version is pinned separately in Compose; review its upgrade procedure before changing it.
Never run an older app against a database migrated by a newer release. Keep PostgreSQL running, stop Vikunja, set its previous exact version and original service secret in .env, then recreate its container without starting it:
docker compose stop vikunja
# Edit .env now: previous VIKUNJA_VERSION and original VIKUNJA_SECRET.
docker compose pull vikunja
docker compose create vikunja
./restore.sh ./backups/vikunja-BEFORE-UPDATE.tar
curl --fail http://127.0.0.1:3456/health
The safety backup can run against the stopped container without launching the old app on migrated data. Do not downgrade a PostgreSQL physical data directory. If the database version changed, restore the SQL into a clean compatible database volume and preserve the existing one until recovery is verified.
docker compose down removes containers while retaining both volumes. After verifying an off-server backup, docker compose down --volumes permanently deletes tasks, accounts, settings, and attachments. Removing the recipe directory also removes local backups; keep a protected copy elsewhere first.
Sources: documentation, CLI, configuration, backup/restore, and PostgreSQL Docker image.
Tell us how it went on your server
Opens a prefilled GitHub issue. A GitHub account is required; submitting the issue makes it public.
docker compose ps --all
docker compose logs --tail=150 vikunja database permissions
curl --fail http://127.0.0.1:3456/health
permissions should exit with code 0; it is a one-time ownership step, not a web service. PostgreSQL and Vikunja should become healthy. The app’s built-in healthcheck avoids needing a shell or curl in its minimal image. Startup runs database migrations; wait for healthy status before creating accounts or using the API.
This recipe uses PostgreSQL. If logs name SQLite or database is locked, check that you are running this Compose file and that VIKUNJA_DATABASE_TYPE=postgres reaches the container. Verify VIKUNJA_DB_PASSWORD matches the initialized PostgreSQL role. Editing initialization variables does not rotate existing credentials; never delete the database volume to fix a password mismatch.
Public registration is intentionally disabled. Create an account through vikunja user create inside the container; no default password exists. Run docker compose exec vikunja /app/vikunja/vikunja user --help for supported recovery commands. SMTP must be configured before relying on email password recovery or task reminders. A Pro features have been disabled log line is expected for the free core and does not prevent lists or kanban.
Match VIKUNJA_PUBLIC_URL to the exact reachable browser URL, with scheme, port, and trailing slash, then recreate the app. Desktop clients need that server URL too. Keep Host and X-Forwarded-Proto correct at the HTTPS proxy. Changing the service secret invalidates issued tokens, so preserve it instead of generating a new one during a routine restart or restore.
Check free disk space on the Docker host and both volumes. The app writes to /data as 1000:1000; inspect the permissions container instead of making files world-writable or running the app as root. The root filesystem is read-only by design. Requests must fit both the proxy limit and Vikunja’s file-size limit (20 MB by default).
Use the complete archive from backup.sh, not a standalone dump or app-volume archive. Check disk space, PostgreSQL logs, and archive permissions. Restore replaces the database public schema and app files; after a failed replacement, leave Vikunja stopped until recovery is complete. Compare archived configuration with active .env without exposing credentials, and use matching versions. Do not downgrade a PostgreSQL physical data directory.
Sources: CLI, configuration, backup/restore, and official image.
Fossary is an independent informational catalog and is not affiliated with the developers of the listed applications. We collect information from public sources and verify published recipes, but we do not develop, distribute, or control these applications.
A listing or validation status is not a requirement, endorsement, or personal recommendation to use an application. You decide whether it is suitable and use it at your own risk. We do not warrant an application's security, availability, or fitness for purpose and, to the extent permitted by law, are not liable for resulting loss or damage. Review its license, security settings, data processing, and backup procedures before installation.