Fully verified5,832

Task management

Vikunja

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.

Alternative to TodoistAlternative to TrelloAGPL-3.0-or-laterVersion 2.7.1

Overview

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.

Security assessment

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.

Update tracking

These are stored results of separate checks, not real-time data. An unknown status means the check has not been performed yet.

New releases

Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.

Current version 2.7.1Oct 23, 2026, 9:32 PM UTC

Critical vulnerabilities

Result of a dedicated Docker image scan, not a Compose configuration check.

Not checkedNot checked

Breaking updates

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.

Not checkedNot checked

compose.yaml

Upstream Compose changes relative to the verified recipe.

Upstream Compose is not trackedNot checked

Outdated Docker images

Pinned image tags checked for newer versions.

Not checkedNot checked

From observation to action

Update plan

The recipe already pins the latest known release. The steps below show the evidence retained for that version.

2.7.12.7.1
  1. Open the release evidence

    Open this release on GitHub ↗ The link is evidence to review, not proof of compatibility.

  2. Review the version boundary

    The version numbers do not cross a major compatibility boundary. No compatibility verdict has been recorded.

  3. Prepare image-tag changes

    No image-tag change is currently planned.

  4. Follow the documented migration shape

    Change the tag and restart. Release-specific migration steps still come from the release notes and installation guide.

  5. Protect the rollback point

    No version change is currently planned. The recipe includes a backup procedure. Restore has been tested.

  6. Verify the updated recipe

    An exact Fully verified check for this target was recorded on 2026-10-23.

Read the update procedure in the installation guide ↓

Specifications

Security and exposure

Installation levels

The status shows how fully the published recipe meets each level's requirements.

Ready

For home

A minimal setup for a local network or access through a VPN.

  • Single server
  • Local access
  • Minimum components

The recipe covers every requirement at this level.

Ready

For a VPS

A public deployment with protected access and backups.

  • Domain
  • HTTPS via reverse proxy
  • Off-server backup

The recipe covers every requirement at this level.

Partial

Reliable

A setup designed for predictable operations and observability.

  • Separate database
  • Healthcheck
  • External monitoring
  • CPU and memory limits

You still need to add: external monitoring, cpu and memory limits.

Tailored to your server

Configuration generator

Answer five questions and download a ready-to-run Vikunja bundle.

Runs locally
01 Do you have a domain?
02 Which reverse proxy?
03 Server architecture
04 Where should data be stored?

Use an absolute path for a separate disk, such as /srv/vikunja.

05 Is VPN access required?

Your bundle is ready

The archive is created in your browser. Your answers are never sent anywhere.

The same files as one shell script, written in plain heredocs so you can read the whole thing before it runs. It checks Docker, the architecture, memory, disk and the ports it needs, and writes nothing until you add --apply.

Screenshots

Quick start

Read the full guide first: it explains external access, backups, and data locations.

Prepare settingscp .env.example .env
Launchdocker compose up -d
Check statusdocker compose ps

Step-by-step guide

Requirements and preparation

Use 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.

Start and create your account

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.

VPS

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.

Trusted local network

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.

Domain and HTTPS

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

./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

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.

Update

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.

Rollback

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.

Stop and remove

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.

Report a recipe problem

Tell us how it went on your server

Opens a prefilled GitHub issue. A GitHub account is required; submitting the issue makes it public.

Troubleshooting

Startup and database health

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.

Database authentication or locked SQLite database

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.

Cannot register or sign in

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.

Wrong public address or desktop connection

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.

Upload or permission failures

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).

Backup or restore fails

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.

Official sources

Latest release: 2026-10-20 · GitHub Stars: 5,832 · metadata checked Oct 23, 2026, 9:32 PM UTC

Disclaimer

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.