Setting Up Vikunja: Self-Hosted Task Management for Couples

#docker#raspberry-pi#homelab#tailscale#vikunja#self-hosted#task-management#sqlite

My wife and I needed a shared task management system. The problem: we have grocery lists scattered across Notes, garden planning in a Google Doc, IKEA shopping lists in messages / Telegram, and recurring plant care / quarterly cleaning schedule reminders… nowhere. It’s chaos. Total mayhem.

The requirements were simple:

  • Shared lists (groceries, store-specific shopping)
  • Project management (house renovation, garden planning)
  • Recurring tasks (water the tomatoes every 3 days)
  • Self-hosted (no vendor lock-in, no subscriptions)
  • Easy to use (if it’s complicated, it won’t get used)

After reading up on the most common alternatives - everything from bareboned todo apps to full on self-hosted cloud setups - we settled on at least trying out Vikunja.

The Stack

  • Hardware: Raspberry Pi 5 (16GB) already running several containers for god knows what
  • Database: SQLite (perfectly adequate for 2 users)
  • Access: Tailscale for secure remote access
  • Version: Vikunja 0.24.6 (important - see gotchas below)

Docker Compose Setup

The bare minimum configuration for SQLite:

version: "3"

services:
  vikunja:
    image: vikunja/vikunja:0.24.6
    container_name: vikunja
    restart: unless-stopped
    ports:
      - "3456:3456"
    environment:
      VIKUNJA_SERVICE_JWTSECRET: <openssl rand -base64 32>
      VIKUNJA_SERVICE_PUBLICURL: http://[tailscale-magic-dns]:3456/
      VIKUNJA_DATABASE_PATH: /db/vikunja.db
    volumes:
      - ./vikunja/vikunja-files:/app/vikunja/files
      - ./vikunja/vikunja-db:/db

Generate the JWT secret:

openssl rand -base64 32

File Permissions

This is critical. Vikunja runs as user 1000, and the container will fail silently if it can’t write to these directories:

cd ~/docker
mkdir -p vikunja/vikunja-files vikunja/vikunja-db
chown 1000:1000 vikunja/vikunja-files vikunja/vikunja-db
docker compose up -d vikunja

Skip the chown and you’ll get cryptic errors about database writes failing.

Multi-User Access with Tailscale

For secure remote access without exposing ports or dealing with reverse proxies, we’ll be using Tailscale.

For the second user:

  1. Go to https://login.tailscale.com/admin/settings/users
  2. Invite by email
  3. They install Tailscale app, accept the invite
  4. Both users access via http://http://[tailscale-magic-dns]:3456

Why HTTP over Tailscale is fine:

Tailscale uses WireGuard for end-to-end encryption at the network layer. The connection is already encrypted in transit - adding HTTPS on top should just be redundant complexity for a private homelab service. The browser might not show the much wanted green padlock, but the traffic is secure (hopefully).

Critical: Make sure VIKUNJA_SERVICE_PUBLICURL matches your actual access method. If you’re using http://, the env var needs http://, not https://.

User Registration

Access the web interface and create accounts for both users. Registration is enabled by default. After creating your accounts, you can optionally disable it:

environment:
  VIKUNJA_SERVICE_ENABLEREGISTRATION: false

Then docker compose up -d vikunja to apply.

Gotchas

1. Version Pinning is Essential

Don’t use vikunja/vikunja:latest. At the time of writing, it points to v1.0.0-rc2 which has a bug preventing user registration - you’ll get “Unauthorized” errors when trying to create accounts. Pin to 0.24.6 (last stable release) instead.

2. Protocol Mismatch

If your PUBLICURL says https:// but you’re actually accessing via http://, the frontend will fail to connect to the API. Match the protocol to reality.

3. SQLite vs PostgreSQL

For 2 users with moderate usage, SQLite is perfectly fine and eliminates an entire container. Most Vikunja documentation shows PostgreSQL/MySQL examples, but SQLite is simpler and sufficient unless you’re running this for 10+ users or need advanced features.

Use Cases

We’re using it for:

  • Shared grocery list - both add items throughout the week
  • Store-specific lists - “IKEA”, “Hardware Store” so we remember what to grab when we’re there
  • Garden project - with subtasks for each plant, watering schedules as recurring tasks
  • House renovation tracking - bigger projects with notes and due dates

The mobile web interface is responsive enough. There’s an official iOS app, though it’s not as polished as the web UI. Alternatively, Vikunja supports CalDAV, so you can sync tasks to iOS Reminders or other CalDAV-compatible apps if you prefer native apps.

Why Not [Insert Alternative Here]?

Nextcloud Tasks: Considered it, but Nextcloud is heavy for just tasks. Would make sense if we were already running Nextcloud for other things.

Synology apps: Have a NAS but want to avoid vendor lock-in. Keeping homelab services portable via Docker.

Notion/Todoist/etc: Subscription fatigue is real. Self-hosted means I control the data and there’s no monthly bill.

Conclusion

For couples (or small teams) wanting shared task management without cloud dependencies, Vikunja seems to hit the sweet spot. It’s lightweight enough to run alongside other homelab services, feature-rich enough to replace multiple apps, and self-hosted so you’re not locked into someone else’s platform.

The combination of Vikunja + Tailscale provides secure access from anywhere without the complexity of reverse proxies, SSL certificates, or exposing ports to the internet.

Now we just need to actually do the tasks on the lists.


Quick Reference:

# Setup
mkdir -p ~/docker/vikunja/vikunja-files ~/docker/vikunja/vikunja-db
chown 1000:1000 ~/docker/vikunja/vikunja-files ~/docker/vikunja/vikunja-db

# Generate secret
openssl rand -base64 32

# Start
cd ~/docker
docker compose up -d vikunja

# Logs
docker compose logs vikunja

# Access
http://your-tailscale-hostname:3456