How to Self-Host Vikunja in 2026: Public URL, Database and File Storage
Self-host Vikunja with correct ports, persistent storage, HTTPS, secrets, backups and upgrade checks. Learn how to fix when the API public URL is wrong.
If you already tried to self-host Vikunja, the frustrating state is probably familiar: the UI appears, but the API public URL is wrong or uploaded files are not on a volume. Recreating the container rarely fixes a disagreement between URLs, state and dependencies.
This walkthrough uses one concrete completion criterion — create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification. Every configuration choice is evaluated against that criterion rather than against a green container badge.
What Vikunja depends on
Draw three boundaries around Vikunja: ingress to port 3456, durable state and supporting requirements. The container is replaceable, but the other two need explicit owners. The network contract for Vikunja is Postgres or MySQL and SMTP for production teams. Keep private endpoints on internal DNS, permit only required outbound calls and give Vikunja a scoped service credential.
The diagram is complete when a clean client can create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification. Capture timing and resource data for attachment traffic, database queries, background jobs and outbound email rather than the small API process alone. If the transaction fails, the first boundary that does not behave as documented identifies whether to investigate routing, local capacity or a supporting service.
Volumes are only the first recovery layer
List the state before the first real record is created: database, uploaded files and configuration. Mount /app/vikunja/files before bootstrap, write harmless sample data and replace the container to prove that path is actually persistent. Confirm the mount by writing harmless data, replacing Vikunja and reading it back.
Snapshots are valuable for quick rollback, but an independent backup is needed when the host or volume disappears. Restore into an empty environment with the pinned image and verify that projects, task history, attachments, reminders and users return and a scheduled notification still fires. Use persistent volumes and snapshots to keep those two recovery mechanisms distinct.
Protect the valuable part of Vikunja
After first login, review what an anonymous visitor, ordinary user and administrator can each do. The Vikunja failure to avoid is using an unchanged JWT secret or leaving registration open accidentally. The intended policy is to use a stable JWT secret, close registration when enrollment ends and separate ordinary members from project administrators.
Generate VIKUNJA_SERVICE_JWTSECRET as a long random value; rotating it normally invalidates sessions or tokens, so plan the user impact rather than calling it an encryption migration. Keep dependency accounts separate from human accounts, deny unused egress where practical and cap work influenced by attachment traffic, database queries, background jobs and outbound email rather than the small API process alone.
Turn the Vikunja smoke test into a release check
A release candidate for Vikunja earns traffic by completing a fixed scenario: create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification. Capture the image digest, effective non-secret configuration, public origin and timestamps for that scenario. The test data should be disposable but realistic enough to exercise the same path as users.
Run it after replacing the runtime, then rebuild the service from database, uploaded files and configuration. Recovery passes when projects, task history, attachments, reminders and users return and a scheduled notification still fires. Compare resource measurements for attachment traffic, database queries, background jobs and outbound email rather than the small API process alone with the prior release and investigate meaningful drift before promotion.
Finally, exercise this controlled failure: temporarily deny the test identity access to Postgres or MySQL and SMTP for production teams. Verify that Vikunja explains the failure, does not damage existing state and resumes after the valid condition returns. Save a redacted log excerpt and the recovery time. Together these checks cover behavior, durability and operability rather than just process uptime.
Build a replaceable Vikunja container
The following command makes the container boundary visible without pretending to provision every external service.
docker run -d \
--name vikunja \
--restart unless-stopped \
-p 127.0.0.1:3456:3456 \
-v vikunja-data:/app/vikunja/files \
-e VIKUNJA_SERVICE_JWTSECRET=replace-with-a-long-random-value \
vikunja/vikunja:latest
Before opening ingress, inspect the resolved environment, mounts and listener. Add the reviewed connection settings for Postgres or MySQL and SMTP for production teams; use private names for private services. A successful launch ends when you can create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification, not when docker ps prints Up.
Route Vikunja without lying about HTTPS
Avoid temporary and permanent public origins for Vikunja. Instead, set VIKUNJA_SERVICE_PUBLICURL to the exact HTTPS origin, point the chosen DNS name at the platform route and proxy only to port 3456.
Exercise this action from outside the host: create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification. If ingress fails, the 502 troubleshooting guide covers port and listener mistakes. If Vikunja receives the request but the API public URL is wrong or uploaded files are not on a volume, the evidence now points beyond the proxy.
Diagnose a healthy-looking Vikunja
For Vikunja, monitor a transaction rather than a process: create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification. Combine its latency and error rate with attachment traffic, database queries, background jobs and outbound email rather than the small API process alone so an alert identifies the constrained component.
The upgrade rehearsal must cover that database migrations and frontend/API compatibility should be tested before changing Vikunja versions. Restore, migrate and run the transaction before production replacement. If the API public URL is wrong or uploaded files are not on a volume, do not erase data to make startup green; compare version, variables, mounts and dependency reachability in that order.
Deploy Vikunja on Dockup without losing its boundaries
Dockup can own the replaceable platform pieces: route traffic to port 3456, issue the domain and certificate, inject secrets, attach persistent storage and connect Vikunja to managed or privately attached services. It can do this on Dockup infrastructure or on a server you attach.
The Vikunja acceptance work remains explicit. After the one-click deployment, set VIKUNJA_SERVICE_PUBLICURL to the exact HTTPS origin, connect and test Postgres or MySQL and SMTP for production teams and run this scenario: create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification. That division is intentional: Dockup removes repetitive infrastructure setup without pretending that application roles, provider credentials or restore policy choose themselves.
Frequently asked questions
What does Vikunja need for a production deployment?
Route the Vikunja container on port 3456 through one HTTPS origin. The supporting network requirement is Postgres or MySQL and SMTP for production teams. Do not call Vikunja ready until you can create a project, task, attachment and reminder, move the task on a board and verify its calendar event and notification.
Which Vikunja data belongs in a backup?
Persist /app/vikunja/files and include database, uploaded files and configuration in the same recovery manifest. A clean Vikunja restore passes only when projects, task history, attachments, reminders and users return and a scheduled notification still fires.
Does Vikunja require HTTPS behind a reverse proxy?
Use HTTPS for the public Vikunja origin and keep port 3456 on the internal route. Apply the Vikunja setting correctly: set VIKUNJA_SERVICE_PUBLICURL to the exact HTTPS origin. For Vikunja, HTTPS protects credentials or user content in transit and keeps origin-sensitive client behavior consistent.
How should a Vikunja upgrade be tested?
Restore current Vikunja state into an isolated deployment, apply the candidate version and repeat its acceptance transaction. Pay particular attention because database migrations and frontend/API compatibility should be tested before changing Vikunja versions. Keep the previous Vikunja image until its data-migration and rollback boundary are understood.
