Vikunja Task Management Installation

Vikunja is an open-source self-hosted task management and project planning platform that combines to-do lists, Kanban boards, Gantt charts, and CalDAV synchronization in a single application. As a Todoist or Trello alternative, Vikunja lets teams manage projects on their own Linux server with full data ownership, REST API access, and notification integrations.

Prerequisites

  • Ubuntu 20.04+, Debian 11+, or CentOS/Rocky 8+
  • Docker and Docker Compose installed
  • Root or sudo access
  • A domain name for HTTPS access (required for CalDAV)
  • Open port 3456 (default Vikunja port)

Installing Vikunja with Docker

# Create Vikunja directory
sudo mkdir -p /opt/vikunja/files

# Create docker-compose.yml
sudo tee /opt/vikunja/docker-compose.yml <<'EOF'
version: '3.8'

services:
  vikunja:
    image: vikunja/vikunja
    restart: unless-stopped
    ports:
      - "3456:3456"
    environment:
      VIKUNJA_DATABASE_HOST: db
      VIKUNJA_DATABASE_PASSWORD: changeme      # Change this!
      VIKUNJA_DATABASE_TYPE: mysql
      VIKUNJA_DATABASE_USER: vikunja
      VIKUNJA_DATABASE_DATABASE: vikunja
      VIKUNJA_SERVICE_JWTSECRET: your-jwt-secret-here  # Change!
      VIKUNJA_SERVICE_FRONTENDURL: https://tasks.example.com
      VIKUNJA_MAILER_ENABLED: "true"
      VIKUNJA_MAILER_HOST: smtp.example.com
      VIKUNJA_MAILER_PORT: "587"
      VIKUNJA_MAILER_USERNAME: [email protected]
      VIKUNJA_MAILER_PASSWORD: smtp-password
      VIKUNJA_MAILER_FROMEMAIL: [email protected]
    volumes:
      - /opt/vikunja/files:/app/vikunja/files
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword        # Change this!
      MYSQL_USER: vikunja
      MYSQL_PASSWORD: changeme                 # Change this!
      MYSQL_DATABASE: vikunja
    volumes:
      - /opt/vikunja/db:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
      start_period: 30s
      interval: 10s
      timeout: 5s
      retries: 3
EOF

# Generate a random JWT secret
JWT_SECRET=$(openssl rand -hex 32)
sed -i "s/your-jwt-secret-here/${JWT_SECRET}/" /opt/vikunja/docker-compose.yml

# Start Vikunja
cd /opt/vikunja
sudo docker compose up -d

# Monitor startup
sudo docker compose logs -f vikunja

Access Vikunja at http://your-server:3456.

Initial Configuration

Register the first admin account:

  1. Navigate to http://your-server:3456
  2. Click Sign up
  3. Register with email and password
  4. The first registered user gets admin privileges

Configuration file approach:

# Create a config.yml for advanced settings
sudo tee /opt/vikunja/config.yml <<'EOF'
service:
  JWTSecret: "your-jwt-secret"
  frontendurl: "https://tasks.example.com"
  interface: "0.0.0.0"
  port: 3456

database:
  type: "mysql"
  host: "db"
  user: "vikunja"
  password: "changeme"
  database: "vikunja"

mailer:
  enabled: true
  host: "smtp.example.com"
  port: 587
  username: "[email protected]"
  password: "smtp-password"
  fromemail: "[email protected]"

auth:
  local:
    enabled: true
  openid:
    enabled: false
EOF

Set up Nginx reverse proxy:

# /etc/nginx/sites-available/vikunja
server {
    listen 80;
    server_name tasks.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name tasks.example.com;

    ssl_certificate /etc/letsencrypt/live/tasks.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/tasks.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3456;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
sudo ln -s /etc/nginx/sites-available/vikunja /etc/nginx/sites-enabled/
sudo certbot --nginx -d tasks.example.com
sudo systemctl reload nginx

Project and Kanban Board Setup

Create a project:

  1. In Vikunja, click + New Project in the left sidebar
  2. Enter project name and optional description
  3. Choose color for visual identification
  4. Click Create

Switch to Kanban view:

  1. Open a project
  2. Click the view toggle icons at the top right
  3. Select Kanban view
  4. Columns are automatically created: To Do, In Progress, Done

Create custom Kanban buckets:

# Via API
curl -X PUT "https://tasks.example.com/api/v1/projects/1/buckets" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "In Review",
    "limit": 5
  }'

Add tasks with labels and due dates:

  1. Click + Add Task in any Kanban bucket
  2. Set title, description, due date, assignee
  3. Add labels for categorization
  4. Set priority (1-5 stars)

CalDAV Synchronization

Vikunja exposes a CalDAV endpoint for syncing tasks with calendar apps:

CalDAV endpoint URL:

https://tasks.example.com/dav/principals/[email protected]/

Configure in Thunderbird (with DAV extension):

  1. Install the TbSync add-on with the Provider for CalDAV & CardDAV add-on
  2. In TbSync → Add account → CalDAV & CardDAV
  3. Set server URL: https://tasks.example.com/dav/
  4. Enter username (email) and password
  5. Sync tasks appear as calendar events

Configure in GNOME Calendar / GNOME Tasks:

# GNOME Online Accounts (Settings > Online Accounts)
# Add account > Nextcloud (use generic CalDAV)
# URL: https://tasks.example.com/dav/

iOS/Android native sync:

CalDAV Server: https://tasks.example.com/dav/
Username: [email protected]
Password: your-password

Notifications and Reminders

Configure email notifications:

  1. Go to Settings > Notifications
  2. Enable notification types:
    • Task reminders
    • Task assignments
    • Comments on assigned tasks
    • Project shares

Set task reminders:

  1. Open a task
  2. Click Add a reminder
  3. Set date/time or relative reminder (e.g., "1 hour before due date")
  4. Choose notification type: email, web push

Webhook notifications:

# Configure webhooks in Settings > Webhooks
# Supported events:
# - task.created
# - task.updated
# - task.deleted
# - task.comment.created

# Example webhook payload test
curl -X POST "https://your-webhook-endpoint.example.com/vikunja" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "task.created",
    "data": {"task_id": 1, "title": "New task"}
  }'

Team Collaboration

Share a project with team members:

  1. Open a project
  2. Click the Share icon (people icon at top)
  3. Search for a user by name or email
  4. Set permission level:
    • Read: View only
    • Write: Create and edit tasks
    • Admin: Full control including sharing

Create a team:

# Via API
curl -X PUT "https://tasks.example.com/api/v1/teams" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering Team",
    "description": "Backend and frontend developers"
  }'

# Add members to team
curl -X PUT "https://tasks.example.com/api/v1/teams/1/members" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"user_id": 2}'

API Usage

Get an API token:

# Login to get a token
TOKEN=$(curl -s -X POST "https://tasks.example.com/api/v1/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"[email protected]","password":"your-password"}' | \
  jq -r '.token')

echo $TOKEN

Common API operations:

# List all projects
curl -s "https://tasks.example.com/api/v1/projects" \
  -H "Authorization: Bearer $TOKEN" | jq '.[].title'

# Create a task
curl -X PUT "https://tasks.example.com/api/v1/projects/1/tasks" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Deploy application",
    "description": "Deploy to production server",
    "due_date": "2024-12-31T00:00:00Z",
    "priority": 4
  }'

# Mark a task as done
curl -X POST "https://tasks.example.com/api/v1/tasks/42" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"done": true}'

Troubleshooting

Cannot log in after deployment:

# Check Vikunja container logs
sudo docker compose logs vikunja -n 50

# Verify database connection
sudo docker compose exec db mysql -u vikunja -p vikunja -e "SHOW TABLES;"

# Check the JWT secret is set
sudo docker compose exec vikunja env | grep JWT

CalDAV sync not working:

# Verify the CalDAV endpoint responds
curl -u "[email protected]:password" \
  "https://tasks.example.com/dav/principals/[email protected]/"

# Check Nginx is passing CalDAV headers correctly
# CalDAV requires PROPFIND, REPORT methods:
sudo nginx -t

Tasks not syncing between devices:

# Trigger a manual sync in the client app
# Or check if the JWT token has expired (default: 7 days)
# Re-login to get a fresh token

# Check server time synchronization
timedatectl status

Conclusion

Vikunja provides a feature-complete self-hosted task management solution that covers individual productivity through Kanban boards and lists, team collaboration through project sharing and assignments, and calendar tool integration through CalDAV sync. Its REST API enables automation and integration with CI/CD pipelines and other tools, making it a flexible replacement for commercial project management services in teams that require data sovereignty and customizable workflows.