Vikunja — Self-Hosted Task Manager

Self-hosted task and project management at tasks.haiven.site. Vikunja 2.3.0 provides kanban boards, task lists, CalDAV sync, due-date reminders, and a full REST API — all from a single Go binary backed by dedicated PostgreSQL 17 and the shared Haiven Redis cache.

URLs

Type URL
Web UI https://tasks.haiven.site
API health https://tasks.haiven.site/api/v1/info
API (OpenAPI UI) https://tasks.haiven.site/api/v1/docs
CalDAV https://tasks.haiven.site/dav/

Quick Start

# Start
docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml up -d

# Status
docker inspect vikunja --format='{{.State.Health.Status}}'
docker inspect vikunja-db --format='{{.State.Health.Status}}'

# Smoke test
curl -sf https://tasks.haiven.site/api/v1/info | python3 -m json.tool

# Logs
docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml logs -f vikunja

Features

Architecture

flowchart TD
    Browser([Browser / Mobile]) -->|HTTPS 443| Traefik
    CalDAV([DAVx5 / Tasks.org]) -->|HTTPS /dav/| Traefik
    API([API clients]) -->|HTTPS /api/v1/| Traefik

    subgraph web["web network"]
        Traefik[Traefik\ntasks.haiven.site\nwildcard cert]
    end

    Traefik -->|HTTP 3456| Vikunja

    subgraph container["vikunja container"]
        V[Go backend + Vue frontend\nPort 3456]
        FV["./files\nUpload volume"]
        CV["config.yml\nread-only"]
        V --- FV
        V --- CV
    end

    subgraph backend["backend network"]
        DB[(vikunja-db\nPostgreSQL 17\n5432)]
        RD[(redis\nDB index 2\n6379)]
        SMTP[smtp-relay\n1025]
        AUTH[Authentik\nsso.haiven.site]
    end

    V -->|SQL| DB
    V -->|cache| RD
    V -->|SMTP| SMTP
    V -->|OIDC discovery| AUTH

Design notes:

Configuration

File Purpose
/mnt/apps/docker/vikunja/.env All secrets and runtime settings (chmod 600)
/mnt/apps/docker/vikunja/config.yml Minimal config; env vars take precedence

Key env vars:

Variable Value
VIKUNJA_SERVICE_PUBLICURL https://tasks.haiven.site/
VIKUNJA_DATABASE_TYPE postgres
VIKUNJA_DATABASE_HOST vikunja-db
VIKUNJA_CACHE_TYPE redis
VIKUNJA_CACHE_REDIS_DB 2
VIKUNJA_MAILER_HOST smtp-relay
VIKUNJA_AUTH_OPENID_ENABLED true

See .env.example for the full template with all options documented.

Backup and Restore

Database backup

docker exec vikunja-db pg_dump -U vikunja vikunja \
  | gzip > /mnt/storage/backups/vikunja/vikunja-$(date +%Y%m%d_%H%M%S).sql.gz

Files backup

rsync -avz /mnt/apps/docker/vikunja/files/ /mnt/storage/backups/vikunja/files/

Database restore

docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml stop vikunja
docker exec -it vikunja-db psql -U vikunja -d postgres \
  -c "DROP DATABASE vikunja WITH (FORCE);"
docker exec -it vikunja-db psql -U vikunja -d postgres \
  -c "CREATE DATABASE vikunja OWNER vikunja;"
gunzip -c /mnt/storage/backups/vikunja/<timestamp>.sql.gz \
  | docker exec -i vikunja-db psql -U vikunja -d vikunja
docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml start vikunja

Warning: Project deletion in Vikunja is permanent — no trash bin. Maintain daily backups.

Monitoring

Vikunja 2.3.0 does not expose a Prometheus /metrics endpoint. No built-in exporter exists at this version.

Current monitoring:

TODO: Add a custom Blackbox Exporter probe or track the upstream Prometheus metrics issue for a future Vikunja release.

Upgrade

# Update image tag in docker-compose.yml, then:
docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml pull
docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml up -d
docker compose -f /mnt/apps/docker/vikunja/docker-compose.yml logs -f vikunja
# Watch for xormigrate migration lines — clean output = success

Troubleshooting

Symptom Check
502 Bad Gateway Verify port label (3456) and both networks attached
OIDC login loop VIKUNJA_SERVICE_PUBLICURL must have trailing slash; redirect URI must match exactly
JWT secret error VIKUNJA_SERVICE_JWTSECRET must be >= 32 chars
DB connection refused Both containers on backend network; vikunja-db healthy
File uploads fail chown -R 1000:1000 /mnt/apps/docker/vikunja/files/
CalDAV not working Use a CalDAV token (not OIDC credentials) from Account Settings
Mobile OIDC errors Use API token (tk_ prefix) for mobile app auth

For detailed troubleshooting, see the full plan at /mnt/apps/docker/_server-setup/08/08l-vikunja-v2.md Section 15.

Key Paths

Path Purpose
/mnt/apps/docker/vikunja/ Service root
/mnt/apps/docker/vikunja/files/ User file attachments (must be chown 1000:1000)
/mnt/apps/docker/vikunja/openapi.json Static copy of OpenAPI spec (fetched from live instance)
/mnt/storage/backups/vikunja/ Backup destination