How to Self-Host Vikunja: Open Source Todoist and TickTick Alternative 2026
TL;DR
Vikunja (GPL 3.0, ~3K GitHub stars, Go + Vue) is a self-hosted task management app — a free replacement for Todoist or TickTick. It supports projects, team sharing, labels, priorities, due dates, recurring tasks, reminders, and CalDAV sync (connects to any CalDAV client for todo sync). Todoist Pro costs $4/month; TickTick Premium $2.79/month. Vikunja is free to self-host. Single Go binary + SQLite/MySQL/PostgreSQL backend.
Key Takeaways
- Vikunja: GPL 3.0, ~3K stars — full-featured todo manager, CalDAV sync
- CalDAV sync: Connect to iOS/macOS Reminders, Thunderbird, DAVx⁵ for bidirectional task sync
- Team sharing: Share projects with team members, assign tasks
- Multiple views: List, Gantt chart, table view
- Reminders: Push notifications, email reminders
- Labels and priorities: Organize tasks across projects
Vikunja vs Todoist vs Alternatives
| Feature | Vikunja | Todoist Pro | Tasks.org (OSS) |
|---|---|---|---|
| License | GPL 3.0 | Proprietary | GPL 3.0 |
| Cost | Free | $4/mo | Free |
| CalDAV | Yes | No | Yes |
| Team projects | Yes | Yes | No (personal) |
| Subtasks | Yes | Yes | Yes |
| Recurring tasks | Yes | Yes | Yes |
| Labels | Yes | Yes | Yes |
| Priorities | Yes | Yes | Yes |
| Gantt chart | Yes | No (add-on) | No |
| Mobile app | PWA (web) | iOS/Android | Android only |
| API | Yes | Yes | — |
| Self-hosted | Yes | No | — |
Part 1: Docker Setup
# docker-compose.yml
services:
vikunja:
image: vikunja/vikunja:latest
container_name: vikunja
restart: unless-stopped
ports:
- "3456:3456"
volumes:
- vikunja_files:/app/vikunja/files
- ./config.yml:/app/vikunja/config.yml:ro
depends_on:
- db
environment:
VIKUNJA_DATABASE_TYPE: postgres
VIKUNJA_DATABASE_HOST: db
VIKUNJA_DATABASE_DATABASE: vikunja
VIKUNJA_DATABASE_USER: vikunja
VIKUNJA_DATABASE_PASSWORD: "${POSTGRES_PASSWORD}"
VIKUNJA_SERVICE_JWTSECRET: "${JWT_SECRET}"
VIKUNJA_SERVICE_FRONTENDURL: "https://tasks.yourdomain.com"
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: vikunja
POSTGRES_USER: vikunja
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U vikunja"]
interval: 10s
volumes:
vikunja_files:
postgres_data:
# .env
POSTGRES_PASSWORD=your-db-password
JWT_SECRET=$(openssl rand -hex 32)
docker compose up -d
Visit http://your-server:3456 → register your account.
Part 2: HTTPS with Caddy
tasks.yourdomain.com {
reverse_proxy localhost:3456
}
Part 3: Configuration (config.yml)
# config.yml
service:
JWTSecret: "${VIKUNJA_SERVICE_JWTSECRET}"
frontendUrl: "https://tasks.yourdomain.com"
enableRegistration: false # Set true for initial setup, then disable
enableEmailReminders: true
enableTaskAttachments: true
maxAvatarSize: 1048576 # 1MB
database:
type: postgres
host: db
database: vikunja
user: vikunja
password: "${VIKUNJA_DATABASE_PASSWORD}"
mailer:
enabled: true
host: smtp.yourdomain.com
port: 587
username: noreply@yourdomain.com
password: "${SMTP_PASSWORD}"
skiptlsverify: false
fromemail: noreply@yourdomain.com
fromname: Vikunja
Part 4: CalDAV Sync
Vikunja exposes a CalDAV endpoint for todo sync with any CalDAV client.
CalDAV URL: https://tasks.yourdomain.com/dav/principals/USER/
iOS Reminders
- Settings → Reminders → Accounts → Add Account → Other
- Add CalDAV Account
- Server:
https://tasks.yourdomain.com/dav/ - Username + password
- iOS Reminders now shows your Vikunja projects as lists
DAVx⁵ (Android)
- Install DAVx⁵
- Add account with base URL:
https://tasks.yourdomain.com/dav/ - Enable CalDAV (for todo sync)
- Use with Tasks.org or any Android todo app
Thunderbird
- Install the TbSync and Provider for CalDAV extensions
- Add CalDAV account with the Vikunja DAV URL
Part 5: Creating and Organizing Tasks
Projects (formerly Namespaces + Lists)
My Projects/
Work/
Q1 Roadmap
Bug Backlog
Personal/
Shopping
Home Projects
- + New Project → name it
- Add tasks within the project
Task Properties
Each task supports:
- Title + description (Markdown)
- Due date + time
- Reminders: Email or push notifications
- Priority: Urgent / High / Medium / Low / None
- Labels: Color-coded tags
- Assignees: Assign to team members
- Subtasks: Nested task hierarchy
- Attachments: File uploads
- Recurring: Daily/weekly/monthly/custom repeat
Bulk Operations
Select multiple tasks → bulk change due date, priority, assignee, labels.
Part 6: Team Sharing
Share a project with other users:
- Project → Share → Invite User
- Enter their username or email
- Set permission: Read, Write, or Admin
- They see the project in their dashboard
For public sharing (no account required):
- Project → Share → Generate Share Link
- Share the link — viewers can see tasks without logging in
Part 7: Views
Switch between views on any project:
- List: Default linear task list, group by priority/due date/label
- Gantt Chart: Timeline view for projects with due dates — see task overlaps
- Table: Spreadsheet-like, shows all task properties as columns
- Kanban Board: Drag-and-drop cards across status columns
Part 8: Labels
Create labels across all projects:
- Labels → + New Label
- Set name and color
- Apply to any task from any project
Labels are shared across all projects — useful for cross-project filtering:
- Filter all tasks labeled
#urgentacross every project
Part 9: API
# Get auth token:
TOKEN=$(curl -s -X POST https://tasks.yourdomain.com/api/v1/login \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"your-password"}' \
| jq -r .token)
# List all projects:
curl https://tasks.yourdomain.com/api/v1/projects \
-H "Authorization: Bearer $TOKEN" | jq '.[].title'
# Create a task:
curl -X POST "https://tasks.yourdomain.com/api/v1/projects/42/tasks" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Review pull request",
"description": "PR #123",
"due_date": "2026-03-15T10:00:00Z",
"priority": 3
}'
# Complete a task:
curl -X POST "https://tasks.yourdomain.com/api/v1/tasks/123" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"done": true}'
Maintenance
# Update Vikunja:
docker compose pull
docker compose up -d
# Backup database:
docker exec db pg_dump -U vikunja vikunja \
| gzip > vikunja-db-$(date +%Y%m%d).sql.gz
# Backup file attachments:
tar -czf vikunja-files-$(date +%Y%m%d).tar.gz \
$(docker volume inspect vikunja_vikunja_files --format '{{.Mountpoint}}')
# Logs:
docker compose logs -f vikunja
See all open source productivity and task management tools at OSSAlt.com/categories/productivity.