Setting Up Vikunja: Self-Hosted Task Management for Couples
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:
- Go to https://login.tailscale.com/admin/settings/users
- Invite by email
- They install Tailscale app, accept the invite
- 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