Skip to content
Author Nejat Hakan
eMail nejat.hakan@outlook.de
PayPal Me https://paypal.me/nejathakan


Task/Project Management Vikunja

Introduction Why Self-Host Vikunja

Welcome to the world of self-hosted project management with Vikunja! In today's digital age, managing tasks and projects effectively is crucial for both personal productivity and team collaboration. While numerous cloud-based solutions exist, self-hosting offers a unique set of advantages, particularly for those who value control, privacy, and customization. This guide will take you from the basics of deploying Vikunja to advanced management techniques, equipping you with the knowledge to run your own powerful project management instance.

What is Vikunja Features and Benefits

Vikunja is an open-source, self-hostable task management application designed to help you organize everything, from simple to-do lists to complex projects. It aims to provide a feature-rich yet user-friendly experience.

Key Features:

  • Task Management: Create, assign, schedule, and track tasks with due dates, reminders, priorities, and progress indicators.
  • Projects & Lists: Organize tasks into projects and further subdivide them into lists for granular control. Think of projects as high-level goals (e.g., "Thesis Paper") and lists as stages or categories within them (e.g., "Research", "Drafting", "Revision").
  • Namespaces: A powerful feature allowing you to group related projects. This is useful for separating personal projects from work projects or different team responsibilities.
  • Tags & Filtering: Assign tags to tasks for easy categorization and use powerful filters to quickly find what you need.
  • Subtasks: Break down complex tasks into smaller, manageable subtasks.
  • Attachments: Attach files directly to tasks.
  • Comments: Collaborate on tasks by leaving comments.
  • Calendar View: Visualize tasks with due dates on a calendar.
  • Gantt Charts: Plan project timelines and dependencies visually (available in certain views/integrations).
  • Kanban Boards: Visualize workflow using Kanban-style boards by dragging tasks between lists (columns).
  • User Management: Support for multiple users, teams, and sharing capabilities.
  • API Access: A comprehensive REST API allows for integration with other tools and automation.
  • Open Source: Free to use, modify, and contribute to. The codebase is transparent and community-driven.

Benefits:

  • Clarity and Organization: Brings structure to your tasks and projects.
  • Improved Productivity: Helps you focus on what needs to be done and track progress.
  • Enhanced Collaboration: Facilitates teamwork through shared projects, comments, and assignments (if used with multiple users).
  • Flexibility: Adapts to various workflows, from simple checklists to more structured project management methodologies.

Why Self-Hosting Control Privacy Customization Learning

While using Vikunja's official hosted service or other cloud platforms is convenient, self-hosting Vikunja on your own server (whether a home server, a VPS, or a dedicated machine) provides distinct advantages:

  • Data Control & Privacy: This is often the primary motivator. When you self-host, your data resides entirely on infrastructure you control. You are not subject to the terms of service, privacy policies, or potential data mining practices of third-party providers. This is crucial for sensitive personal information or confidential company projects. You decide who has access and how the data is secured.
  • No Subscription Fees: Vikunja itself is open-source and free. While you'll have infrastructure costs (hardware, electricity, or VPS hosting fees), you avoid recurring subscription fees tied to user counts or feature tiers often found in SaaS solutions.
  • Customization: Self-hosting gives you the freedom to configure the application precisely to your needs. You can tweak performance settings, integrate it with other self-hosted services, modify themes (where possible), and directly interact with the database if required. You are not limited by the options provided by a cloud vendor.
  • Learning Opportunity: Setting up and maintaining a web application like Vikunja is an excellent way to learn about Linux system administration, Docker, containerization, web servers, databases, networking, security, and backup strategies. It's a hands-on experience that significantly enhances technical skills.
  • Long-Term Availability: Cloud services can shut down, change pricing models, or alter features unexpectedly. By self-hosting, you ensure the longevity of your chosen tool as long as you maintain the infrastructure. You are not dependent on the provider's business decisions.
  • Performance: Depending on your hardware and network connection, a self-hosted instance can sometimes offer better performance and responsiveness compared to a cloud service, especially if you are accessing it primarily from your local network.

Comparison to Cloud Alternatives Trello Asana etc

How does self-hosted Vikunja stack up against popular Software-as-a-Service (SaaS) project management tools?

Feature Self-Hosted Vikunja Cloud Alternatives (Trello, Asana, Todoist, etc.)
Cost Free software; Infrastructure costs Free tiers (often limited); Paid subscriptions
Data Control Full control (on your server) Controlled by the provider (their servers)
Privacy Determined by your setup & security Subject to provider's privacy policy
Customization High (server config, themes, API) Limited to provided settings/integrations
Maintenance Your responsibility (updates, backups) Handled by the provider
Setup Requires technical setup Instant sign-up
Scalability Depends on your hardware/setup Managed by provider (often tiered pricing)
Features Comprehensive, evolving Often very polished; specific feature sets
Support Community, official docs Official support channels (often tiered)
Learning High learning curve/reward Minimal technical learning required

In essence:

  • Choose Cloud Alternatives if you prioritize convenience, ease of setup, and don't want to manage infrastructure, and if you are comfortable with their pricing and privacy policies.
  • Choose Self-Hosted Vikunja if you prioritize data control, privacy, cost-effectiveness in the long run (especially for many users), customization, and are willing to invest the time in setup and maintenance for the learning experience and control it provides.

Prerequisites Conceptual Linux basics Docker basics Networking basics

Before diving into the installation and configuration, it's helpful to have a foundational understanding of a few key areas. You don't need to be an expert, but familiarity will make the process smoother.

  • Linux Basics:
    • Command Line Interface (CLI): Comfort using a terminal to navigate directories (cd), list files (ls), create directories (mkdir), edit text files (using nano, vim, or similar), manage file permissions (chmod, chown), and run commands as an administrator (sudo).
    • Users and Permissions: Understanding the difference between regular users and the root user, and the concept of file ownership and permissions.
    • Package Management: Knowing how to install software using your distribution's package manager (e.g., apt for Debian/Ubuntu, yum/dnf for CentOS/Fedora).
    • Services: Basic understanding of how system services run (e.g., using systemctl to start, stop, enable services).
  • Docker Basics:
    • Containers vs. Virtual Machines: Understanding that containers virtualize the operating system, offering lightweight isolation, while VMs virtualize hardware.
    • Images: Read-only templates used to create containers.
    • Containers: Runnable instances of images.
    • Volumes: Mechanisms for persisting data generated by containers, keeping it separate from the container's lifecycle.
    • Networks: How containers communicate with each other and the host system.
    • Docker Compose: A tool for defining and running multi-container Docker applications using a YAML file. This is the primary method we will use.
  • Networking Basics:
    • IP Addresses: Unique identifiers for devices on a network (e.g., 192.168.1.100, 10.0.0.5). Understanding private vs. public IPs.
    • Ports: Endpoints for network communication (e.g., port 80 for HTTP, 443 for HTTPS). Understanding that only one application can typically listen on a specific port on a given IP address at a time.
    • DNS (Domain Name System): How domain names (e.g., vikunja.example.com) are translated into IP addresses.
    • Firewalls: Software or hardware that controls incoming and outgoing network traffic based on predefined security rules.
    • Reverse Proxy: A server that sits in front of web servers and forwards client requests to those web servers. Often used for load balancing, SSL encryption, and security.

Having a grasp of these concepts will significantly help you understand the "why" behind the steps we take in setting up and managing Vikunja.

1. Basic Vikunja Deployment

This section focuses on getting a functional Vikunja instance up and running quickly using Docker Compose. This is the recommended method for most users as it simplifies dependency management and deployment.

Understanding Docker and Containerization

Before we jump into commands, let's solidify our understanding of Docker, the technology that makes deploying Vikunja relatively straightforward.

  • What is Docker? Docker is a platform for developing, shipping, and running applications inside containers. It packages an application and all its dependencies (libraries, system tools, code, runtime) together into a single unit.
  • Images: Think of a Docker image as a blueprint or a template. It's a lightweight, standalone, executable package that includes everything needed to run a piece of software. Vikunja provides official Docker images for its frontend and API components. These images contain the Vikunja application code, necessary libraries, and a specific operating system environment (usually a minimal Linux distribution). Images are typically stored in registries like Docker Hub. When you run docker pull vikunja/api, you are downloading the Vikunja API image from Docker Hub.
  • Containers: A container is a running instance of a Docker image. You can start, stop, move, and delete containers. When you run a container from an image, Docker creates a writable layer on top of the read-only image layers. Any changes made inside the running container (like temporary files) happen in this writable layer. Crucially, if you delete the container without special precautions, these changes are lost. This leads us to volumes.
  • Volumes: Since containers are ephemeral (meaning they can be destroyed and recreated easily), we need a way to store persistent data, such as your Vikunja tasks, user accounts, and uploaded files. Docker volumes are the preferred mechanism for this. Volumes are managed by Docker and exist outside the container's writable layer, typically on the host filesystem (though Docker manages their exact location). When you attach a volume to a container, data written to the specified path inside the container is actually stored in the volume. If you delete and recreate the container, you can attach the same volume, and your data will still be there.
  • Networks: Docker allows you to create virtual networks that containers can connect to. This enables containers to communicate with each other while being isolated from the host system or other container groups if desired. Docker Compose automatically creates a dedicated network for the services defined in your docker-compose.yml file, allowing the Vikunja frontend, API, and database containers to find and talk to each other easily using their service names (e.g., api, db).

Why use Docker for Vikunja?

  • Isolation: Vikunja and its dependencies run in isolated environments (containers), preventing conflicts with other software on your host system.
  • Reproducibility: Docker images ensure that the application runs the same way regardless of where the container is deployed (your laptop, a server, the cloud).
  • Ease of Deployment: Docker simplifies the setup process. You don't need to manually install specific versions of programming languages, web servers, or databases on your host system. Docker handles these dependencies within the images.
  • Simplified Updates: Updating Vikunja often involves just pulling the newer image version and recreating the containers.
  • Resource Efficiency: Compared to traditional Virtual Machines (VMs), containers share the host system's kernel, making them much more lightweight in terms of RAM and disk space usage.

Simple Docker Compose Setup

Docker Compose is a tool that allows you to define and manage multi-container Docker applications using a simple YAML configuration file. Since Vikunja consists of multiple components (at minimum, the API backend and the frontend, plus usually a database), Docker Compose is the ideal way to manage them together.

  • Introduction to Docker Compose: Instead of running multiple complex docker run commands with many flags for volumes, networks, and environment variables, you define all your services, networks, and volumes in a single file called docker-compose.yml. Then, with simple commands like docker-compose up and docker-compose down, you can start and stop your entire application stack.
  • Creating the docker-compose.yml file: This file is the heart of your Vikunja deployment. It tells Docker how to set up and connect the different services. Let's create a basic example using the default SQLite database, which is simpler for a first setup.

    Create a directory for your Vikunja configuration, for example, ~/vikunja. Inside this directory, create a file named docker-compose.yml with the following content:

    version: '3'
    
    services:
      api:
        image: vikunja/api:latest # Use the latest official Vikunja API image
        container_name: vikunja-api
        environment:
          # Sets the database type to SQLite
          VIKUNJA_DATABASE_TYPE: "sqlite"
          # Specifies the path *inside the container* where the SQLite file will be stored
          VIKUNJA_DATABASE_PATH: "/app/vikunja/data/vikunja.db"
          # Important: Set a strong, secret key for security! Generate one yourself.
          # Example generation: openssl rand -base64 32
          VIKUNJA_SERVICE_JWTSECRET: "replace-this-with-a-very-strong-random-secret-key"
          # Set the service URL (adjust if needed, especially behind a proxy later)
          VIKUNJA_SERVICE_FRONTENDURL: "http://localhost:8080" # Or your server's IP/domain
        volumes:
          # Mounts the 'vikunja_data' volume to /app/vikunja/data inside the container
          # This persists the SQLite database and any file uploads
          - vikunja_data:/app/vikunja/data
        ports:
          # Exposes the API port 3456 on the host machine
          # Format: "HOST_PORT:CONTAINER_PORT"
          - "3456:3456"
        restart: unless-stopped # Automatically restart the container unless manually stopped
    
      frontend:
        image: vikunja/frontend:latest # Use the latest official Vikunja Frontend image
        container_name: vikunja-frontend
        ports:
          # Exposes the frontend port 8080 on the host machine
          - "8080:80" # Access Vikunja via port 8080 on the host
        environment:
          # Tells the frontend where to find the API
          # Use the service name 'api' and its container port '3456'
          VIKUNJA_API_URL: "http://api:3456/api/v1"
        restart: unless-stopped
        depends_on:
          # Ensures the API container is started before the frontend container
          - api
    
    volumes:
      # Defines the named volume 'vikunja_data'
      # Docker manages the actual location of this volume on the host
      vikunja_data:
    

    Explanation of Key Parts:

    • version: '3': Specifies the Docker Compose file format version.
    • services:: Defines the containers that make up your application.
    • api: & frontend:: Names you give to your services (containers). These names are also used for DNS resolution within the Docker network created by Compose.
    • image:: Specifies the Docker image to use for the service (e.g., vikunja/api:latest).
    • container_name:: Assigns a specific, readable name to the running container.
    • environment:: Sets environment variables inside the container. These are used to configure Vikunja.
      • VIKUNJA_DATABASE_TYPE: Tells the API which database system to use (here, sqlite).
      • VIKUNJA_DATABASE_PATH: Specifies where the SQLite file should be stored inside the container. This path needs to be within a mounted volume to persist data.
      • VIKUNJA_SERVICE_JWTSECRET: Crucial for security. This secret key is used for signing authentication tokens. It must be changed to a long, random, unpredictable string. You can generate one using openssl rand -base64 32 on a Linux command line.
      • VIKUNJA_SERVICE_FRONTENDURL: The URL users will use to access the frontend. This is used in emails and redirects. Replace http://localhost:8080 with your server's IP address and port if accessing from other machines (e.g., http://192.168.1.100:8080).
      • VIKUNJA_API_URL: Tells the frontend container how to reach the API container. http://api:3456/api/v1 works because Docker Compose sets up DNS so that the service name api resolves to the API container's IP address within the Docker network, and the API listens on port 3456 inside its container.
    • volumes: (under a service): Defines volume mounts.
      • - vikunja_data:/app/vikunja/data: This maps the named volume vikunja_data (defined at the bottom of the file) to the directory /app/vikunja/data inside the api container. Any data the API writes to /app/vikunja/data (like the SQLite DB and file uploads) will be stored in the vikunja_data volume on the host machine, thus persisting it.
    • ports:: Exposes container ports to the host machine.
      • - "3456:3456" (api): Maps port 3456 inside the API container to port 3456 on the host machine. You generally don't need to expose the API port directly if you only access Vikunja through the frontend or a reverse proxy, but it can be useful for debugging or direct API access.
      • - "8080:80" (frontend): Maps port 80 inside the frontend container (which is the default port web servers listen on) to port 8080 on the host machine. This means you will access the Vikunja web interface by going to http://<your-server-ip>:8080 in your browser.
    • restart: unless-stopped: Policy ensuring the container restarts automatically if it crashes or if the Docker daemon restarts, unless it was explicitly stopped by the user.
    • depends_on:: Specifies dependencies between services. frontend depends on api, meaning Docker Compose will attempt to start the api service before starting the frontend service.
    • volumes: (at the bottom): Declares named volumes used by the services. vikunja_data: creates a Docker-managed volume named vikunja_data.
  • Choosing a Database: For this basic setup, we're using SQLite. It's the simplest option because the database is just a single file stored within the volume. It requires no separate database server setup. However, SQLite may not perform as well under heavy load or with many concurrent users compared to PostgreSQL or MySQL. We will explore using PostgreSQL in the intermediate section.

Initial Launch and Configuration

Now that you have your docker-compose.yml file ready, let's launch Vikunja!

  1. Navigate to the Directory: Open your terminal and navigate to the directory where you saved the docker-compose.yml file (e.g., cd ~/vikunja).
  2. Run Docker Compose: Execute the following command:
    docker-compose up -d
    
    • docker-compose up: This command reads the docker-compose.yml file, pulls the necessary images (if they aren't already downloaded), creates the network, creates the volume, and starts the containers defined in the file.
    • -d: This flag stands for "detached mode". It runs the containers in the background and prints the container names. Without -d, the logs from all containers would be streamed to your terminal, and closing the terminal would stop the containers.
  3. Check Container Status: You can verify that the containers are running using:
    docker-compose ps
    # OR
    docker ps
    
    You should see output listing vikunja-api and vikunja-frontend with a status like Up X seconds.
  4. Accessing the Vikunja Web UI: Open your web browser and navigate to the URL corresponding to the frontend port you exposed. Based on our docker-compose.yml, this would be http://<your-server-ip>:8080 or http://localhost:8080 if running on your local machine.
  5. First-Time Setup: The first time you access Vikunja, it should redirect you to a registration page to create the initial administrator account. Fill in the required details (username, email, password).
  6. Log In: After registering, log in with the credentials you just created.
  7. Basic Vikunja Tour: Take a moment to familiarize yourself with the interface:
    • Dashboard: Your central overview page.
    • Projects: Located in the sidebar. Click the '+' button to create a new project. Projects are the main containers for your tasks.
    • Lists: Within a project, you can create lists. Lists act as columns in the default view or Kanban board, helping you categorize tasks (e.g., "To Do", "In Progress", "Done").
    • Tasks: Click the '+' button within a list to add a new task. You can give it a title, description, due date, assignees (if you add more users later), labels, etc.
    • Tags (Labels): Create tags (e.g., "Urgent", "Bug", "Feature") to categorize tasks across different projects and lists. You can manage them via the settings or create them on the fly when editing a task.
    • Namespaces: Found in the settings or usually via a dropdown near your projects. Namespaces allow you to group multiple projects together (e.g., "Work", "Personal", "University").

You now have a functioning Vikunja instance running!

Workshop Basic Deployment and First Project

Let's put the theory into practice by deploying Vikunja and creating a simple project to manage university coursework.

Goal: Deploy Vikunja using Docker Compose with SQLite and create a project named "COMP SCI 101" to track assignments and readings.

Steps:

  1. Prerequisites Check: Ensure you have Docker and Docker Compose installed on your system (typically a Linux server or your local machine). If not, follow the official Docker installation guide for your operating system.
  2. Create Project Directory:
    • Open your terminal.
    • Create a directory for Vikunja: mkdir ~/vikunja_workshop
    • Navigate into the new directory: cd ~/vikunja_workshop
  3. Create docker-compose.yml:

    • Create the file: touch docker-compose.yml
    • Open the file in a text editor (e.g., nano docker-compose.yml).
    • Copy and paste the following content into the file:

      version: '3'
      
      services:
        api:
          image: vikunja/api:latest
          container_name: vikunja-ws-api # Unique name for workshop
          environment:
            VIKUNJA_DATABASE_TYPE: "sqlite"
            VIKUNJA_DATABASE_PATH: "/app/vikunja/data/vikunja.db"
            # !!! GENERATE YOUR OWN SECRET KEY !!!
            # Use: openssl rand -base64 32
            VIKUNJA_SERVICE_JWTSECRET: "replace-this-workshop-secret-ASAP"
            # Use localhost for workshop, change if your server has a different IP
            VIKUNJA_SERVICE_FRONTENDURL: "http://localhost:8081"
          volumes:
            - vikunja_ws_data:/app/vikunja/data
          # Using different ports to avoid conflict with other examples if needed
          ports:
            - "3457:3456" # Host:Container
          restart: unless-stopped
      
        frontend:
          image: vikunja/frontend:latest
          container_name: vikunja-ws-frontend # Unique name for workshop
          ports:
            - "8081:80" # Access via port 8081 on the host
          environment:
            # Use the API service name and internal container port
            VIKUNJA_API_URL: "http://api:3456/api/v1"
          restart: unless-stopped
          depends_on:
            - api
      
      volumes:
        vikunja_ws_data: # Unique volume name for workshop
      
    • Crucially: Replace "replace-this-workshop-secret-ASAP" with a real secret generated using openssl rand -base64 32 in your terminal.

    • Adjust VIKUNJA_SERVICE_FRONTENDURL if localhost is not appropriate (e.g., use http://<your_server_ip>:8081).
    • Save and close the file (e.g., in nano, press Ctrl+X, then Y, then Enter).
  4. Launch Vikunja:

    • In the ~/vikunja_workshop directory, run: docker-compose up -d
    • Wait for the command to complete. It might take a minute or two to download the images the first time.
    • Check the status: docker-compose ps. Ensure both vikunja-ws-api and vikunja-ws-frontend show as Up.
  5. Access and Register:

    • Open your web browser and go to http://localhost:8081 (or http://<your_server_ip>:8081).
    • You should see the Vikunja registration page. Create your admin user account.
    • Log in with your new credentials.
  6. Create "University Course Planner" Project:

    • In the Vikunja interface, look for the "Projects" section in the left sidebar.
    • Click the '+' icon next to "Projects".
    • Enter the project name: COMP SCI 101
    • (Optional) Add a description like "Tracking tasks for Introduction to Computer Science".
    • Click "Create".
  7. Add Lists:

    • You should now be inside the "COMP SCI 101" project. By default, there might be one list. Let's create specific ones.
    • Find the area to add lists (usually looks like columns or has an "Add List" button).
    • Create a list named: Assignments
    • Create another list named: Readings
    • Create a third list named: Exams
  8. Add Tasks:

    • Task 1 (Assignment):
      • Under the "Assignments" list, click the '+' or "Add Task" button.
      • Title: Programming Assignment 1 - Hello World
      • Description: Write a simple program that prints "Hello, World!" in Python.
      • Click the calendar icon to set a Due Date (e.g., next Friday).
      • Click "Create" or press Enter.
    • Task 2 (Reading):
      • Under the "Readings" list, click '+'.
      • Title: Read Chapter 1 - Introduction to Computing
      • Description: Focus on sections 1.1 to 1.3.
      • Set a Due Date (e.g., next Monday).
      • Click "Create".
    • Task 3 (Exam Prep):
      • Under the "Exams" list, click '+'.
      • Title: Prepare for Midterm 1
      • Click "Create". (You can add subtasks or details later).
  9. Explore: Click on the tasks you created. Explore options like adding comments, setting priorities (using labels/tags perhaps), or marking them as done. Drag tasks between lists if your workflow changes.

Outcome: You have successfully deployed Vikunja using Docker Compose and created your first project with lists and tasks, simulating a real-world use case for managing university studies. You've also learned how to configure essential parameters like the JWT secret and frontend URL. To stop this workshop instance later, navigate back to ~/vikunja_workshop in the terminal and run docker-compose down.

2. Intermediate Vikunja Configuration

Now that you have a basic Vikunja instance running, let's explore ways to make it more robust, secure, and scalable. This section covers setting up a reverse proxy for secure HTTPS access and switching to a more powerful database like PostgreSQL.

Securing Vikunja with a Reverse Proxy

Exposing Vikunja directly to the internet over HTTP (port 8080 in our basic example) is insecure. Credentials and task data are sent in plain text, making them vulnerable to eavesdropping. Furthermore, using non-standard ports like 8080 can be inconvenient. A reverse proxy solves these issues.

  • What is a Reverse Proxy? A reverse proxy is a server that sits in front of one or more web servers (like your Vikunja containers) and acts as an intermediary for client requests. Clients connect to the reverse proxy, and the reverse proxy forwards the request to the appropriate backend server.

  • Benefits:

    • SSL/TLS Encryption (HTTPS): The reverse proxy can handle the encryption and decryption of traffic, allowing your backend Vikunja containers to communicate internally over HTTP while ensuring traffic between the client (your browser) and the reverse proxy is encrypted using HTTPS. This is essential for security.
    • Centralized Access Point: You can run multiple web applications on the same server, each on its own internal port, and use the reverse proxy to direct traffic based on the domain name (e.g., vikunja.yourdomain.com goes to Vikunja, blog.yourdomain.com goes to your blog), all typically using standard ports 80 and 443.
    • Load Balancing: (More advanced) If you had multiple Vikunja API instances, a reverse proxy could distribute incoming requests among them.
    • Caching: Some reverse proxies can cache static content (like Vikunja's frontend assets), potentially speeding up load times.
    • Improved Security: Can provide an additional layer of security, hiding the specifics of your backend infrastructure.
  • Popular Reverse Proxies:

    • Nginx: A very popular, high-performance web server and reverse proxy. Known for its stability and efficiency. Configuration is done via text files.
    • Traefik: A modern reverse proxy designed with containers in mind. It can automatically discover services (like your Vikunja containers) via Docker labels and configure routing and SSL certificates (using Let's Encrypt) dynamically. Often considered easier for Docker-centric setups once the initial learning curve is overcome.
    • Caddy: Another modern web server with automatic HTTPS configuration built-in. Known for its simple configuration file format.
  • Configuring Nginx for Vikunja: (Requires Nginx installed on the host system or run as another Docker container)

    1. Prerequisites: You need a domain name pointing to your server's public IP address. You also need Nginx installed (sudo apt install nginx on Debian/Ubuntu) and potentially Certbot for free Let's Encrypt SSL certificates (sudo apt install certbot python3-certbot-nginx).
    2. Nginx Configuration: Create a configuration file for Vikunja in /etc/nginx/sites-available/vikunja (replace vikunja.yourdomain.com with your actual domain):

      server {
          listen 80;
          server_name vikunja.yourdomain.com;
      
          # Redirect HTTP to HTTPS
          location / {
              return 301 https://$host$request_uri;
          }
      }
      
      server {
          listen 443 ssl http2; # Enable SSL and HTTP/2
          server_name vikunja.yourdomain.com;
      
          # SSL Certificate paths (managed by Certbot)
          ssl_certificate /etc/letsencrypt/live/vikunja.yourdomain.com/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/vikunja.yourdomain.com/privkey.pem;
          include /etc/letsencrypt/options-ssl-nginx.conf; # Recommended SSL settings
          ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Diffie-Hellman parameters
      
          # Increase max body size for file uploads (adjust as needed)
          client_max_body_size 100M;
      
          location / {
              proxy_pass http://127.0.0.1:8080; # Proxy to Vikunja frontend (host port)
              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; # Important for Vikunja redirects
      
              # WebSocket support (needed for real-time features)
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
          }
      
          # Optional: Proxy API requests directly if needed (usually handled by frontend)
          # location /api/v1/ {
          #     proxy_pass http://127.0.0.1:3456/api/v1/; # Proxy to Vikunja API (host port)
          #     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;
          # }
      }
      
      3. Enable the Site: sudo ln -s /etc/nginx/sites-available/vikunja /etc/nginx/sites-enabled/ 4. Test Nginx Configuration: sudo nginx -t 5. Obtain SSL Certificate: sudo certbot --nginx -d vikunja.yourdomain.com (Follow prompts) 6. Reload Nginx: sudo systemctl reload nginx 7. Adjust Vikunja Config: Update VIKUNJA_SERVICE_FRONTENDURL in your docker-compose.yml to https://vikunja.yourdomain.com. You might also need to configure Vikunja to trust the proxy's headers (often handled automatically if X-Forwarded-Proto is https). Restart Vikunja: docker-compose down && docker-compose up -d. 8. Firewall: Ensure port 443 (and potentially 80 for the initial redirect) is open in your firewall. You might be able to close the direct ports (8080, 3456) in the firewall now, as traffic only needs to go through Nginx. You could also remove the ports: section from the Vikunja services in docker-compose.yml if Nginx is running on the host and accessing them via 127.0.0.1 or if Nginx is in the same Docker network.

  • Configuring Traefik with Docker Labels: (Traefik running as a Docker container)

    1. Setup Traefik: Deploy Traefik itself using Docker or Docker Compose. This typically involves creating a docker-compose.yml for Traefik, configuring its static entry points (ports 80, 443), setting up the Docker provider (so Traefik can read container labels), and configuring Let's Encrypt certificate resolvers. This setup is beyond the scope of this Vikunja guide but is well-documented on the Traefik website.
    2. Modify Vikunja docker-compose.yml: Add labels to your Vikunja services to tell Traefik how to route traffic. Remove the ports section from the Vikunja services as Traefik will handle external access. Ensure both Traefik and Vikunja are on the same Docker network (e.g., traefik-proxy).

      version: '3'
      
      services:
        api:
          image: vikunja/api:latest
          container_name: vikunja-api
          environment:
            # ... (Keep existing environment vars like DB config, JWT secret)
            VIKUNJA_SERVICE_FRONTENDURL: "https://vikunja.yourdomain.com" # Use your domain
          volumes:
            - vikunja_data:/app/vikunja/data
          restart: unless-stopped
          networks:
            - traefik-proxy # Connect to Traefik's network
            - default # Connect to default network for frontend communication
          labels:
            # Traefik Labels for API (Optional - usually frontend handles API calls)
            # - "traefik.enable=true"
            # - "traefik.http.routers.vikunja-api.rule=Host(`vikunja.yourdomain.com`) && PathPrefix(`/api/v1`)"
            # - "traefik.http.routers.vikunja-api.entrypoints=websecure"
            # - "traefik.http.routers.vikunja-api.tls.certresolver=myresolver" # Your Let's Encrypt resolver
            # - "traefik.http.services.vikunja-api.loadbalancer.server.port=3456"
            - "traefik.docker.network=traefik-proxy" # Specify which network Traefik uses
      
        frontend:
          image: vikunja/frontend:latest
          container_name: vikunja-frontend
          environment:
            # API URL uses internal service name and port
            VIKUNJA_API_URL: "http://api:3456/api/v1"
          restart: unless-stopped
          depends_on:
            - api
          networks:
            - traefik-proxy # Connect to Traefik's network
            - default # Connect to default network for api communication
          labels:
            # Traefik Labels for Frontend
            - "traefik.enable=true"
            # Define router 'vikunja-web'
            - "traefik.http.routers.vikunja-web.rule=Host(`vikunja.yourdomain.com`)"
            - "traefik.http.routers.vikunja-web.entrypoints=websecure" # Use the HTTPS entrypoint
            - "traefik.http.routers.vikunja-web.tls.certresolver=myresolver" # Your Let's Encrypt resolver
            # Define service 'vikunja-web-svc' pointing to container port 80
            - "traefik.http.services.vikunja-web-svc.loadbalancer.server.port=80"
            - "traefik.docker.network=traefik-proxy" # Specify which network Traefik uses
            # Middleware for redirecting HTTP to HTTPS (Optional but recommended)
            - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
            - "traefik.http.routers.vikunja-web-http.rule=Host(`vikunja.yourdomain.com`)"
            - "traefik.http.routers.vikunja-web-http.entrypoints=web" # Use the HTTP entrypoint
            - "traefik.http.routers.vikunja-web-http.middlewares=https-redirect"
      
      volumes:
        vikunja_data:
      
      networks:
        traefik-proxy: # Define the external Traefik network
          external: true
        default: # Default network for internal communication
          driver: bridge
      
      3. Restart: Run docker-compose down && docker-compose up -d in your Vikunja directory. Traefik should automatically detect the new labels and configure routing and SSL.

  • Adjusting Vikunja Config: Regardless of the proxy used, ensure VIKUNJA_SERVICE_FRONTENDURL points to the final HTTPS URL (e.g., https://vikunja.yourdomain.com). Vikunja needs this to generate correct links in emails or other places. Depending on your proxy setup, you might need to configure Vikunja to trust proxy headers. Add these environment variables to the api service if you encounter redirect loops or issues with Vikunja detecting HTTPS:

    environment:
      # ... other variables
      VIKUNJA_SERVICE_TRUSTPROXYHEADERS: "true"
      # Optional: Specify exact number of proxies if needed
      # VIKUNJA_SERVICE_PROXYHEADERDEPTH: 1
    

Using External Databases PostgreSQL MySQL

While SQLite is convenient for single-user or light usage, PostgreSQL or MySQL (MariaDB is a popular compatible alternative) offer significant advantages for larger installations, multiple users, or when higher performance and concurrency are required.

  • Why use an external database?

    • Scalability: PostgreSQL and MySQL are designed to handle much larger datasets and higher numbers of simultaneous connections than SQLite.
    • Concurrency: They use more sophisticated locking mechanisms, leading to better performance when multiple users or processes are reading/writing data at the same time.
    • Robustness & Features: Offer advanced features like replication, point-in-time recovery, complex querying capabilities, and stricter data typing.
    • Centralized Management: If you run multiple applications requiring a database, you can potentially use a single, well-managed PostgreSQL or MySQL instance for several of them.
    • Mature Backup Tools: Dedicated tools exist for efficiently backing up and restoring these databases (e.g., pg_dump, mysqldump).
  • Setting up PostgreSQL/MySQL: You have two main options:

    1. Dedicated Server: Install PostgreSQL or MySQL directly on the host OS or another server. Use your distribution's package manager (e.g., sudo apt install postgresql postgresql-contrib). You'll need to create a database and a user specifically for Vikunja.
    2. Docker Container: Run PostgreSQL or MySQL as another service within your Docker environment. This keeps everything containerized.

    Example: Adding PostgreSQL as a Docker service: Modify your docker-compose.yml to include a db service:

    version: '3'
    
    services:
      api:
        image: vikunja/api:latest
        container_name: vikunja-api
        environment:
          VIKUNJA_DATABASE_TYPE: "postgres" # Change to postgres
          VIKUNJA_DATABASE_HOST: "db" # Use the service name 'db'
          VIKUNJA_DATABASE_DATABASE: "vikunja" # Database name
          VIKUNJA_DATABASE_USER: "vikunja_user" # Database user
          VIKUNJA_DATABASE_PASSWORD: "replace-with-a-strong-db-password" # DB password
          VIKUNJA_SERVICE_JWTSECRET: "your-strong-random-jwt-secret"
          VIKUNJA_SERVICE_FRONTENDURL: "https://vikunja.yourdomain.com" # Your frontend URL
          VIKUNJA_SERVICE_TRUSTPROXYHEADERS: "true" # If using a reverse proxy
        volumes:
          - vikunja_files:/app/vikunja/files # Separate volume for files
        restart: unless-stopped
        depends_on:
          - db # API depends on the database being ready
        networks:
          # Add networks if using Traefik or other specific network setups
          - default
    
      frontend:
        image: vikunja/frontend:latest
        container_name: vikunja-frontend
        environment:
          VIKUNJA_API_URL: "http://api:3456/api/v1"
        restart: unless-stopped
        depends_on:
          - api
        networks:
          # Add networks if needed
          - default
        # Add labels if using Traefik
    
      db: # New PostgreSQL service
        image: postgres:15 # Use a specific PostgreSQL version
        container_name: vikunja-db
        environment:
          POSTGRES_DB: "vikunja" # Database name to create
          POSTGRES_USER: "vikunja_user" # User to create
          POSTGRES_PASSWORD: "replace-with-a-strong-db-password" # Password for the user
        volumes:
          - vikunja_postgres_data:/var/lib/postgresql/data # Persist database data
        restart: unless-stopped
        networks:
          - default
    
    volumes:
      # Note: We renamed the old volume to be specific for files
      vikunja_files:
      vikunja_postgres_data: # New volume for PostgreSQL data
    
    networks:
      default:
        driver: bridge
      # Add external network definitions if needed (e.g., for Traefik)
    

    Important Changes:

    • Added a db service using the postgres:15 image.
    • Configured POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD environment variables for the db service. Use a strong, unique password.
    • Mounted a new named volume vikunja_postgres_data to /var/lib/postgresql/data within the db container to persist the actual database files.
    • Changed VIKUNJA_DATABASE_TYPE to postgres in the api service.
    • Set VIKUNJA_DATABASE_HOST to db (the service name of the PostgreSQL container). Docker Compose networking allows services to reach each other using their service names.
    • Set VIKUNJA_DATABASE_DATABASE, VIKUNJA_DATABASE_USER, and VIKUNJA_DATABASE_PASSWORD in the api service to match the credentials defined in the db service.
    • Made the api service depends_on: db.
    • Volume Change: It's good practice to separate file uploads from database data. I've renamed the original volume to vikunja_files and changed the api volume mount to - vikunja_files:/app/vikunja/files. You'll need to adjust VIKUNJA_FILES_BASEPATH in the api environment if it's not the default /app/vikunja/files. The SQLite DB is no longer used, so the old path /app/vikunja/data is less relevant now unless other config files are stored there. Check Vikunja docs for the default file path. Correction: Vikunja typically stores files in /app/vikunja/files. Let's stick to that. The config for the path might be VIKUNJA_FILES_BASEPATH: "/app/vikunja/files" if needed, but the default often works. The original example used /app/vikunja/data which would store both SQLite and files. Let's adjust the PostgreSQL example for clarity:
    # ... (api service)
        volumes:
          # Mounts a volume for file uploads to the default location
          - vikunja_files:/app/vikunja/files
    # ... (rest of the file)
    volumes:
      vikunja_files: # Volume specifically for file uploads
      vikunja_postgres_data: # Volume for PostgreSQL data
    
  • Data Migration Considerations: If you are switching from an existing SQLite setup to PostgreSQL/MySQL, you cannot simply change the configuration and expect your data to appear. Vikunja does not automatically migrate data between different database types.

    • Manual Migration: You would typically need to export your data from SQLite (potentially using Vikunja's export features if available, or manual scripting) and then import it into the new PostgreSQL/MySQL database. This can be complex.
    • Fresh Start: Often, the simplest approach when switching database types is to start with a fresh, empty database in the new system. This means you will lose all existing tasks, projects, and users.
    • Backup First: Always back up your existing SQLite database file (the .db file within the volume) before attempting any migration or switching.

User Management and Authentication

Vikunja supports multiple users and allows for collaboration.

  • Inviting Users: As an administrator, you can invite new users via the Vikunja settings/administration panel. This usually involves sending an email invitation link. You'll need to configure email settings (SMTP server details) in Vikunja's configuration (via environment variables like VIKUNJA_MAILER_*) for invitations and notifications to work.
    # Add these to the 'api' service environment section
    environment:
      # ... other variables
      VIKUNJA_MAILER_ENABLED: "true"
      VIKUNJA_MAILER_HOST: "your_smtp_server.com" # e.g., smtp.gmail.com
      VIKUNJA_MAILER_PORT: "587" # Common port for TLS
      VIKUNJA_MAILER_USERNAME: "your_email@example.com"
      VIKUNJA_MAILER_PASSWORD: "your_email_password_or_app_password"
      VIKUNJA_MAILER_FROMEMAIL: "vikunja@yourdomain.com" # 'From' address
      VIKUNJA_MAILER_USETLS: "true" # Use TLS encryption
      # VIKUNJA_MAILER_USESSL: "false" # Usually one or the other
    
  • Managing Roles and Permissions: Vikunja typically has standard users and administrator roles. Administrators can manage system settings, users, and potentially see all projects (depending on configuration). Users can create and manage their own projects and tasks and collaborate on projects they are invited to. Permissions are usually managed at the project or namespace level (sharing).
  • External Authentication (Conceptual): For more advanced setups, especially in organizations, Vikunja often supports integration with external authentication providers:
    • LDAP/Active Directory: Allows users to log in using their existing corporate credentials. Requires configuring connection details to your LDAP/AD server.
    • OpenID Connect (OIDC) / OAuth2: Enables login via third-party identity providers like Google, GitHub, Keycloak, Authentik, etc. Requires setting up client IDs and secrets with the provider and configuring Vikunja accordingly.
    • These options usually require specific environment variables or configuration file settings (e.g., VIKUNJA_AUTH_LDAP_*, VIKUNJA_AUTH_OIDC_*). Consult the official Vikunja documentation for details on configuring these methods.

Workshop Setting up HTTPS and PostgreSQL

Let's enhance the workshop deployment by adding a PostgreSQL database and securing it with Nginx and a Let's Encrypt SSL certificate.

Goal: Reconfigure the workshop Vikunja instance to use PostgreSQL and make it accessible securely via HTTPS using a real domain name and Nginx.

Prerequisites:

  1. A Linux server with Docker and Docker Compose installed.
  2. A registered domain name (e.g., myvikunja.myuniversity.club) with DNS configured to point an A record to your server's public IP address.
  3. Nginx and Certbot installed on the host system (sudo apt update && sudo apt install nginx certbot python3-certbot-nginx -y).
  4. Ports 80 and 443 open in your server's firewall, pointing to the host system where Nginx will run.

Steps:

  1. Stop Existing Workshop Instance:
    • Navigate to your previous workshop directory: cd ~/vikunja_workshop
    • Stop and remove the containers: docker-compose down
    • (Optional but recommended for a clean start): Remove the old SQLite data volume: docker volume rm vikunja_workshop_vikunja_ws_data (Use the correct volume name from docker volume ls). This means you will lose any data entered previously.
  2. Update docker-compose.yml for PostgreSQL:

    • Open ~/vikunja_workshop/docker-compose.yml in your text editor.
    • Replace the entire content with the following, adapting where necessary:

      version: '3'
      
      services:
        api:
          image: vikunja/api:latest
          container_name: vikunja-ws-api-pg # New container name
          environment:
            VIKUNJA_DATABASE_TYPE: "postgres"
            VIKUNJA_DATABASE_HOST: "db"
            VIKUNJA_DATABASE_DATABASE: "vikunja_workshop_db"
            VIKUNJA_DATABASE_USER: "vikunja_workshop_user"
            # !!! USE A STRONG PASSWORD HERE AND IN 'db' SERVICE !!!
            VIKUNJA_DATABASE_PASSWORD: "YourStrongDatabasePassword"
            # !!! USE THE SAME STRONG JWT SECRET AS BEFORE OR GENERATE A NEW ONE !!!
            VIKUNJA_SERVICE_JWTSECRET: "YourExistingOrNewStrongJWTSecret"
            # !!! IMPORTANT: Set to your HTTPS domain !!!
            VIKUNJA_SERVICE_FRONTENDURL: "https://myvikunja.myuniversity.club"
            VIKUNJA_SERVICE_TRUSTPROXYHEADERS: "true" # Trust Nginx headers
            # Optional: Configure Mailer for user invites later
            # VIKUNJA_MAILER_ENABLED: "false"
          volumes:
            # Volume for file uploads
            - vikunja_ws_files:/app/vikunja/files
          restart: unless-stopped
          depends_on:
            - db # Depends on PostgreSQL service
          networks:
            - default
      
        frontend:
          image: vikunja/frontend:latest
          container_name: vikunja-ws-frontend-pg # New container name
          environment:
            # API URL uses internal service name 'api' and container port '3456'
            VIKUNJA_API_URL: "http://api:3456/api/v1"
          restart: unless-stopped
          depends_on:
            - api
          networks:
            - default
          # NO 'ports' section needed here - Nginx will handle external access
      
        db: # PostgreSQL service
          image: postgres:15
          container_name: vikunja-ws-db # New container name
          environment:
            POSTGRES_DB: "vikunja_workshop_db"
            POSTGRES_USER: "vikunja_workshop_user"
            # !!! USE THE SAME STRONG PASSWORD AS IN 'api' SERVICE !!!
            POSTGRES_PASSWORD: "YourStrongDatabasePassword"
          volumes:
            - vikunja_ws_postgres_data:/var/lib/postgresql/data # Persist DB data
          restart: unless-stopped
          networks:
            - default
      
      volumes:
        vikunja_ws_files: # Volume for files
        vikunja_ws_postgres_data: # Volume for PG data
      
      networks:
        default:
          driver: bridge
      
    • Replace Placeholders:

      • Replace YourStrongDatabasePassword in both the api and db services with a very strong password.
      • Replace YourExistingOrNewStrongJWTSecret with your JWT secret.
      • Replace https://myvikunja.myuniversity.club with your actual domain name (using HTTPS).
    • Save and close the file.
  3. Start Vikunja with PostgreSQL:

    • In ~/vikunja_workshop, run: docker-compose up -d
    • Check status: docker-compose ps. You should see vikunja-ws-api-pg, vikunja-ws-frontend-pg, and vikunja-ws-db running. Note that no ports are exposed to the host by Docker Compose this time.
  4. Configure Nginx:

    • Create the Nginx config file: sudo nano /etc/nginx/sites-available/vikunja-workshop
    • Paste the following, replacing myvikunja.myuniversity.club with your domain:

      # Temporary server block for Certbot validation
      server {
          listen 80;
          server_name myvikunja.myuniversity.club;
      
          root /var/www/html; # Default root for Certbot's ACME challenge
          location ~ /.well-known/acme-challenge/ {
              allow all;
          }
      
          location / {
               # Will be replaced by redirect after getting cert
               return 404;
          }
      }
      
    • Save and close.

    • Enable the site: sudo ln -s /etc/nginx/sites-available/vikunja-workshop /etc/nginx/sites-enabled/
    • Test Nginx config: sudo nginx -t
    • Reload Nginx: sudo systemctl reload nginx
  5. Obtain SSL Certificate:

    • Run Certbot: sudo certbot --nginx -d myvikunja.myuniversity.club
    • Follow the prompts. Choose the option to redirect HTTP traffic to HTTPS when asked. Certbot will automatically modify your Nginx configuration file (/etc/nginx/sites-available/vikunja-workshop) to include the necessary SSL settings and the proxy configuration.
  6. Adjust Nginx Proxy Configuration:

    • Certbot might not set up the proxy pass correctly. We need to edit the Nginx config again: sudo nano /etc/nginx/sites-available/vikunja-workshop
    • Find the server block listening on 443 ssl. It will already have ssl_certificate lines added by Certbot.
    • Inside this server block, find the location / { ... } block.
    • Replace the contents of the location / { ... } block with the correct proxy settings. We need Nginx to talk to the internal Docker IP of the frontend container.
    • First, find the frontend container's IP: Run docker inspect vikunja-ws-frontend-pg | grep IPAddress. Look for the IP address under the network vikunja_workshop_default (the name might vary slightly). Let's assume it's 172.20.0.4 for this example.
    • Modify the location / block in /etc/nginx/sites-available/vikunja-workshop to look like this (using the IP you found):

      server {
          listen 443 ssl http2;
          server_name myvikunja.myuniversity.club;
      
          # SSL settings added by Certbot (leave them here)
          ssl_certificate /etc/letsencrypt/live/myvikunja.myuniversity.club/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/myvikunja.myuniversity.club/privkey.pem;
          include /etc/letsencrypt/options-ssl-nginx.conf;
          ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
      
          # Increase max body size for file uploads (adjust as needed)
          client_max_body_size 100M;
      
          location / {
              # Proxy to the frontend container's internal IP and port 80
              proxy_pass http://172.20.0.4:80; # <-- Use the IP you found!
              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; # Crucial for HTTPS detection
      
              # WebSocket support
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
          }
      
          # Redirect HTTP to HTTPS (Certbot likely added this already in a separate block)
          # listen 80; (This might be in a separate server block added by Certbot)
          # server_name myvikunja.myuniversity.club;
          # return 301 https://$host$request_uri;
      }
      
    • Save and close the file.

    • Test the Nginx configuration again: sudo nginx -t
    • Reload Nginx for changes to take effect: sudo systemctl reload nginx
  7. Access Vikunja Securely:

    • Open your browser and navigate to https://myvikunja.myuniversity.club (using your actual domain).
    • You should be automatically redirected to HTTPS and see the Vikunja login/registration page.
    • Since you started with a fresh database, you will need to register a new admin user.
    • Log in and verify that Vikunja is working correctly.

Alternative Nginx Proxy Method (Using Docker Network): Instead of finding the container IP (which can change), you can attach Nginx (if run as a container) or use a specific host gateway IP (172.17.0.1 is often the default Docker bridge gateway) if networking allows. The most robust way when Nginx is on the host is often to expose the frontend port to a specific host IP (e.g., 127.0.0.1:8081:80 in docker-compose.yml) and then have Nginx proxy to http://127.0.0.1:8081. This avoids relying on dynamic container IPs. If you use this, remember to adjust the proxy_pass directive in Nginx accordingly.

Outcome: You now have a more robust Vikunja setup using PostgreSQL for data storage, secured with HTTPS via Nginx acting as a reverse proxy, and accessible through a clean domain name. You've successfully configured inter-container communication and proxied traffic securely.

3. Advanced Vikunja Management

With Vikunja running securely and using a robust database, we can now focus on long-term maintenance, automation, and leveraging more advanced features like the API.

Backup and Restore Strategies

Data loss can be catastrophic. Regularly backing up your self-hosted applications is non-negotiable. A good backup strategy protects you from hardware failure, accidental deletion, data corruption, or even ransomware attacks.

  • Importance of Backups: Your Vikunja instance contains valuable information – your tasks, project plans, deadlines, and potentially sensitive file attachments. Losing this data can severely impact your productivity or workflow. Regular, tested backups are your safety net.
  • What to Back Up: A complete Vikunja backup consists of two main parts:
    1. Database: Contains all your users, projects, lists, tasks, comments, tags, relations, etc. The method depends on the database you use:
      • PostgreSQL: Use the pg_dump utility.
      • MySQL/MariaDB: Use the mysqldump utility.
      • SQLite: Simply copy the .db file. Since the file can be actively written to, it's best practice to briefly stop the Vikunja API container before copying, or at least ensure the copy is consistent (some tools or filesystem snapshots might help).
    2. Files/Volumes: Vikunja stores configuration details and any file attachments within Docker volumes. You need to back up the contents of these volumes.
      • Configuration: While much configuration is done via environment variables, any settings stored in a config.yml file within a volume need backing up.
      • File Attachments: The volume mapped to /app/vikunja/files (or your configured VIKUNJA_FILES_BASEPATH) contains all user-uploaded files. This can grow quite large.
  • Backing Up Vikunja Data:

    • Database Dump (PostgreSQL Example): You can execute pg_dump from the host machine if the PostgreSQL port is exposed, or run it inside the PostgreSQL container using docker exec.

      # Command to run inside the PostgreSQL container
      # Replace 'vikunja-ws-db' with your actual DB container name
      # Replace 'vikunja_workshop_user' with your DB user
      # Replace 'vikunja_workshop_db' with your DB name
      docker exec <your_db_container_name> pg_dump -U <your_db_user> -d <your_db_name> -Fc > vikunja_db_backup_$(date +%Y%m%d_%H%M%S).dump
      
      # Example using workshop names:
      docker exec vikunja-ws-db pg_dump -U vikunja_workshop_user -d vikunja_workshop_db -Fc > /path/on/host/for/backups/vikunja_db_backup_$(date +%Y%m%d_%H%M%S).dump
      
      • -U <user>: Specifies the database user.
      • -d <dbname>: Specifies the database name.
      • -Fc: Specifies the custom format (compressed, suitable for pg_restore).
      • >: Redirects the output to a file on your host system. Name the file descriptively, perhaps with a timestamp.
    • Database Dump (MySQL/MariaDB Example):

      docker exec <your_db_container_name> mysqldump -u <your_db_user> -p'<your_db_password>' <your_db_name> > /path/on/host/for/backups/vikunja_db_backup_$(date +%Y%m%d_%H%M%S).sql
      
      Note: Including the password directly in the command can be a security risk (it might show in process lists). More secure methods involve configuration files or prompting.

    • SQLite Backup:

      # Optional: Stop the API container for consistency
      cd ~/vikunja_workshop && docker-compose stop api
      
      # Find the volume path on the host (can be tricky)
      # Method 1: Inspect the volume
      docker volume inspect vikunja_workshop_vikunja_ws_data # Or your SQLite volume name
      # Look for "Mountpoint": "/var/lib/docker/volumes/vikunja_workshop_vikunja_ws_data/_data"
      
      # Method 2: Copy directly from container path (Docker manages the mount)
      # This requires knowing the internal path set in docker-compose.yml
      # Let's assume the volume 'vikunja_ws_data' maps to '/app/vikunja/data'
      # and the DB is at '/app/vikunja/data/vikunja.db' inside the container
      docker cp <your_api_container_name>:/app/vikunja/data/vikunja.db /path/on/host/for/backups/vikunja_backup_$(date +%Y%m%d_%H%M%S).db
      
      # Example using basic setup names:
      docker cp vikunja-api:/app/vikunja/data/vikunja.db /path/on/host/for/backups/vikunja_backup_$(date +%Y%m%d_%H%M%S).db
      
      # Restart the API container if you stopped it
      cd ~/vikunja_workshop && docker-compose start api
      

    • Backing up Docker Volumes (Files/Config): You need to back up the contents of the named volumes (vikunja_files, vikunja_postgres_data, etc., depending on your setup). The actual data resides on the host filesystem, usually in a subdirectory under /var/lib/docker/volumes/.

      • Method 1: Find Mountpoint and use rsync or tar:
        # Find the mountpoint (as shown in SQLite example)
        VOLUME_PATH=$(docker volume inspect vikunja_ws_files | grep Mountpoint | awk '{print $2}' | sed 's/"//g') # Adjust volume name
        # Use rsync to copy the contents to a backup location
        rsync -avh $VOLUME_PATH/ /path/on/host/for/backups/vikunja_files_backup_$(date +%Y%m%d)/
        # Or use tar to create an archive
        tar czvf /path/on/host/for/backups/vikunja_files_backup_$(date +%Y%m%d).tar.gz -C $VOLUME_PATH .
        
      • Method 2: Use a temporary container to access the volume: This avoids needing sudo or figuring out the exact host path.
        # Back up 'vikunja_ws_files' volume
        docker run --rm -v vikunja_ws_files:/volume_data -v /path/on/host/for/backups:/backup_target alpine \
        tar czf /backup_target/vikunja_files_backup_$(date +%Y%m%d).tar.gz -C /volume_data .
        
        # Back up 'vikunja_ws_postgres_data' volume (while DB container is running)
        # It's generally SAFER to use pg_dump for live databases, but this backs up the raw files
        docker run --rm -v vikunja_ws_postgres_data:/volume_data -v /path/on/host/for/backups:/backup_target alpine \
        tar czf /backup_target/vikunja_postgres_data_backup_$(date +%Y%m%d).tar.gz -C /volume_data .
        
        Note: Backing up live database files directly from the volume can lead to inconsistent backups. pg_dump is the preferred method for PostgreSQL/MySQL. This volume backup method is primarily for the file attachments (vikunja_files) volume.
  • Automating Backups: Manually running backup commands is prone to being forgotten. Use cron (on Linux) or Task Scheduler (on Windows) to automate these commands.

    • Create a backup script (e.g., /opt/scripts/backup_vikunja.sh):
      #!/bin/bash
      
      BACKUP_DIR="/mnt/backups/vikunja" # Use a dedicated backup location (ideally separate disk/NAS)
      TIMESTAMP=$(date +%Y%m%d_%H%M%S)
      DB_CONTAINER="vikunja-ws-db" # Your DB container name
      DB_USER="vikunja_workshop_user" # Your DB user
      DB_NAME="vikunja_workshop_db" # Your DB name
      FILES_VOLUME="vikunja_ws_files" # Your files volume name
      
      # Create backup directory if it doesn't exist
      mkdir -p $BACKUP_DIR
      
      echo "Starting Vikunja backup at $(date)"
      
      # Backup PostgreSQL Database
      echo "Dumping database..."
      docker exec $DB_CONTAINER pg_dump -U $DB_USER -d $DB_NAME -Fc > $BACKUP_DIR/vikunja_db_$TIMESTAMP.dump
      if [ $? -ne 0 ]; then echo "Database dump failed!"; exit 1; fi
      
      # Backup Files Volume using temporary container
      echo "Backing up files volume..."
      docker run --rm -v $FILES_VOLUME:/volume_data -v $BACKUP_DIR:/backup_target alpine \
      tar czf /backup_target/vikunja_files_$TIMESTAMP.tar.gz -C /volume_data .
      if [ $? -ne 0 ]; then echo "Files volume backup failed!"; exit 1; fi
      
      # Optional: Prune old backups (e.g., keep last 7 days)
      echo "Pruning old backups..."
      find $BACKUP_DIR -type f -name 'vikunja_db_*.dump' -mtime +7 -delete
      find $BACKUP_DIR -type f -name 'vikunja_files_*.tar.gz' -mtime +7 -delete
      
      echo "Vikunja backup completed successfully."
      exit 0
      
    • Make the script executable: chmod +x /opt/scripts/backup_vikunja.sh
    • Edit the crontab: sudo crontab -e
    • Add a line to run the script daily (e.g., at 3:00 AM):
      0 3 * * * /opt/scripts/backup_vikunja.sh >> /var/log/vikunja_backup.log 2>&1
      
      This runs the script every day at 3:00 AM and logs output/errors to /var/log/vikunja_backup.log.
  • Restoring Vikunja from Backups: This is the critical second half – backups are useless if you can't restore them.

    1. Setup New Instance (if needed): If restoring to a new server or after a complete failure, set up Docker, Docker Compose, and create the docker-compose.yml file matching the configuration of the backed-up instance (same database type, volume names, etc.). Do not start the containers yet.
    2. Restore Database:
      • PostgreSQL: Create an empty database container first (docker-compose up -d db if using compose). Then use pg_restore.
        # Copy the backup file into the *new* DB container
        docker cp /path/to/your/vikunja_db_backup.dump <new_db_container_name>:/tmp/backup.dump
        
        # Execute pg_restore inside the new DB container
        docker exec <new_db_container_name> pg_restore -U <your_db_user> -d <your_db_name> --clean --if-exists /tmp/backup.dump
        
        # Example:
        # docker cp /mnt/backups/vikunja/vikunja_db_20231027_100000.dump vikunja-ws-db:/tmp/backup.dump
        # docker exec vikunja-ws-db pg_restore -U vikunja_workshop_user -d vikunja_workshop_db --clean --if-exists /tmp/backup.dump
        
        • --clean: Drops database objects before recreating them.
        • --if-exists: Avoids errors if objects don't exist during the clean phase.
      • MySQL/MariaDB: Start the DB container, then pipe the .sql file into the mysql client.
        docker exec -i <new_db_container_name> mysql -u <your_db_user> -p'<your_db_password>' <your_db_name> < /path/to/your/vikunja_db_backup.sql
        
      • SQLite: Stop the API container. Remove any existing .db file in the volume mountpoint. Copy the backup .db file into the volume mountpoint, ensuring it has the correct name expected by Vikunja (e.g., vikunja.db). Use docker cp or copy directly to the host path.
        # Example using docker cp
        docker cp /path/to/your/vikunja_backup.db <new_api_container_name_or_id>:/app/vikunja/data/vikunja.db
        
    3. Restore Files Volume:
      • Use the temporary container method, reversing the tar command. Ensure the target volume exists (Docker creates it automatically if defined in docker-compose.yml and a container using it is started, but it will be empty initially).
        # Make sure the target volume (e.g., vikunja_ws_files) exists
        # You might need to briefly start and stop a container using it:
        # cd ~/vikunja_workshop && docker-compose up -d api && docker-compose stop api
        
        # Restore from backup tarball
        docker run --rm -v <your_files_volume_name>:/volume_data -v /path/to/your/backups:/backup_target alpine \
        tar xzf /backup_target/<your_files_backup.tar.gz> -C /volume_data
        
        # Example:
        # docker run --rm -v vikunja_ws_files:/volume_data -v /mnt/backups/vikunja:/backup_target alpine \
        # tar xzf /backup_target/vikunja_files_20231027.tar.gz -C /volume_data
        
    4. Start Vikunja: Once the database and files are restored, start the full application stack: docker-compose up -d.
    5. Test Thoroughly: Log in and verify that your projects, tasks, and file attachments are present and correct.
  • Important Considerations:

    • Backup Storage: Store backups on a separate physical device or cloud storage. Backing up to the same disk your application runs on offers limited protection.
    • Testing Restores: Periodically test your restore procedure to ensure it works and that you know how to perform it under pressure.
    • Encryption: Encrypt sensitive backups, especially if storing them off-site or in the cloud.

Updating Vikunja

Keeping Vikunja up-to-date ensures you have the latest features, bug fixes, and security patches. Thanks to Docker, the process is usually straightforward.

  • Checking for New Releases: Monitor the Vikunja official website, blog, GitHub releases page, or community channels for announcements about new versions.
  • Reading Release Notes: Crucially, always read the release notes for the version you are upgrading to before performing the update. Release notes will highlight:
    • New features and improvements.
    • Bug fixes.
    • Breaking Changes: Any changes that might require manual intervention, configuration adjustments, or specific migration steps.
    • Database schema migrations (usually handled automatically by Vikunja on startup, but be aware).
  • The Update Process using Docker Compose:
    1. Backup First: Perform a full backup (database and volumes) before starting the update process. This allows you to roll back if anything goes wrong.
    2. Navigate to Compose Directory: cd ~/vikunja_workshop (or wherever your docker-compose.yml is).
    3. Pull New Images: Fetch the latest versions (or specific versions if you pinned them, e.g., vikunja/api:0.22.0) of the images defined in your docker-compose.yml:
      docker-compose pull
      
      This command checks the image tags specified in your docker-compose.yml (e.g., :latest, :0.22.0) and downloads newer versions if available from the registry (Docker Hub).
    4. Recreate Containers: Stop the existing containers and start new ones using the freshly pulled images. Docker Compose is smart enough to only recreate containers whose images have changed.
      docker-compose up -d
      
      This command will stop the running containers (like vikunja-ws-api-pg, vikunja-ws-frontend-pg), remove them, and create new ones based on the updated images, automatically re-attaching the existing volumes (vikunja_ws_files, vikunja_ws_postgres_data).
    5. Database Migrations: When the new API container starts, Vikunja will typically check the database schema version and automatically apply any necessary migrations. You can observe this process in the container logs: docker-compose logs -f api. Wait for messages indicating migrations are complete or that the API is ready.
    6. Test: Access Vikunja through your browser and verify that everything is working as expected. Check the version number in the settings or about page.
  • Rolling Back Updates: If the update causes problems:
    1. Modify docker-compose.yml: Change the image tags back to the previous working version (e.g., change vikunja/api:latest back to vikunja/api:0.21.0 if you know that was the last working version).
    2. Pull (Optional but good practice): docker-compose pull (to ensure the older image is present locally).
    3. Recreate Containers: docker-compose up -d. This will replace the problematic containers with ones using the older image version.
    4. Restore from Backup (If Necessary): If the newer version made incompatible database changes or corrupted data, you may need to stop the containers (docker-compose down), restore your database and potentially file volumes from the backup you took before the update, and then start the containers again (docker-compose up -d) using the older image versions.

Exploring the Vikunja API

Vikunja provides a powerful REST (Representational State Transfer) API that allows programmatic interaction with your tasks and projects. This opens up possibilities for automation, integration with other tools, or building custom interfaces.

  • Introduction to REST APIs: A REST API is a way for different software applications to communicate over a network (usually HTTP). You send requests to specific URLs (endpoints) using standard HTTP methods (GET, POST, PUT, DELETE) to retrieve, create, update, or delete data. Data is typically exchanged in a structured format like JSON (JavaScript Object Notation).
  • Enabling and Using the Vikunja API: The API is usually enabled by default and accessible via the /api/v1 path relative to your Vikunja API service URL.
  • Authentication (API Tokens): To use the API, you need to authenticate your requests. The standard way is using API tokens.
    1. Generate a Token: Log in to the Vikunja web interface. Go to Settings -> API Tokens. Create a new token, giving it a descriptive name (e.g., "backup-script", "mobile-app"). Vikunja will generate a long, random token string. Copy this token immediately and store it securely. You typically won't be able to see the token again after closing the creation dialog.
    2. Using the Token: Include the token in the Authorization header of your HTTP requests, prefixed with Bearer. Example Header: Authorization: Bearer <Your_Generated_API_Token>
  • API Documentation (Swagger UI): Vikunja provides interactive API documentation using Swagger UI. You can usually access this by navigating to /api/v1/docs on your Vikunja instance URL (e.g., https://myvikunja.myuniversity.club/api/v1/docs).
    • This interface lists all available API endpoints (e.g., /projects, /tasks/{task_id}, /users).
    • It details the required HTTP method (GET, POST, etc.), parameters (path, query, body), and expected request/response formats for each endpoint.
    • You can often even try out API calls directly from the Swagger UI by authorizing using your API token (look for an "Authorize" button).
  • Basic API Interactions using curl: curl is a command-line tool for making HTTP requests. It's great for testing API calls.

    Example 1: List Projects (Replace placeholders)

    curl -X GET "https://myvikunja.myuniversity.club/api/v1/projects" \
         -H "accept: application/json" \
         -H "Authorization: Bearer <Your_API_Token>"
    

    Example 2: Create a New Task (Replace placeholders)

    # First, find the ID of the list you want to add the task to (e.g., by listing lists or from the UI URL)
    LIST_ID=123 # Replace with actual list ID
    
    curl -X POST "https://myvikunja.myuniversity.club/api/v1/lists/${LIST_ID}/tasks" \
         -H "accept: application/json" \
         -H "Authorization: Bearer <Your_API_Token>" \
         -H "Content-Type: application/json" \
         -d '{
               "title": "New Task via API",
               "description": "This task was created using curl.",
               "due_date": "2023-12-31T23:59:59Z"
             }'
    

    • -X GET, -X POST: Specifies the HTTP method.
    • -H "Header-Name: Header Value": Adds HTTP headers (like Authorization, Content-Type, accept).
    • -d '{...}': Sends data in the request body (used for POST, PUT). Ensure it's valid JSON.
  • Tools like Postman/Insomnia: For more complex API interactions or frequent use, graphical API clients like Postman or Insomnia are highly recommended. They provide features like saving requests, managing environments (for different URLs or tokens), and better visualization of responses.

  • Potential Use Cases:
    • Automation: Create tasks automatically from emails, monitoring alerts, or other event sources.
    • Integration: Sync tasks with calendars, code repositories (e.g., create a task when a GitHub issue is assigned), or other project management tools.
    • Custom Reporting: Extract data via the API to generate custom reports or dashboards.
    • Mobile/Desktop Clients: The API enables the creation of alternative clients for Vikunja.

Customization and Theming Basic

While Vikunja aims for a clean and functional interface out-of-the-box, some customization is possible.

  • Configuration Options (config.yml): Vikunja primarily uses environment variables for configuration in Docker setups, as shown previously. However, it also supports configuration via a YAML file (typically config.yml). If you need to set options not available via environment variables, you can mount a configuration file into the API container.

    1. Create a config.yml file on your host.
    2. Add configuration directives according to the Vikunja documentation (check their official docs for available settings).
    3. Mount this file into the API container in your docker-compose.yml:
      services:
        api:
          # ... other settings
          volumes:
            - ./config.yml:/etc/vikunja/config.yml # Mount the config file
            - vikunja_ws_files:/app/vikunja/files
          # ...
      
      Note: Environment variables usually override settings in config.yml. Check the Vikunja documentation for the order of precedence.
  • Frontend Customization: Direct modification of the frontend code requires rebuilding the frontend image, which is an advanced topic beyond standard configuration. However, some aspects might be configurable:

    • Instance Message: You can often set a global message displayed to users (e.g., for maintenance notices) via environment variables or the config file (VIKUNJA_SERVICE_MOTD).
    • Legal Links: Configure links to custom Terms of Service or Privacy Policy pages (VIKUNJA_LEGAL_* variables).
  • Theme Adjustments: Vikunja's theming capabilities may vary between versions.

    • Dark/Light Mode: Usually selectable by the user in their profile settings.
    • Custom Themes: Check the official documentation or community resources. Some applications allow adding custom CSS files via volume mounts or configuration to override default styles, but this might not be officially supported or could break with updates. Advanced theming might require forking and modifying the frontend source code.
  • Logo: You might be able to replace the default Vikunja logo with your own by replacing the logo file within the frontend container (potentially via a volume mount if the structure allows, or by building a custom image). Again, check documentation for feasibility and recommended methods.

Customization often requires digging into the official Vikunja documentation for the specific version you are running, as available options can change.

Workshop Automated Backups and API Interaction

This workshop combines two advanced topics: setting up the automated backup script created earlier and performing basic task creation via the API.

Goal:

  1. Implement and schedule the automated backup script for the PostgreSQL database and file attachments volume.
  2. Use curl and the Vikunja API to create a new task in the "COMP SCI 101" project created in the first workshop.

Prerequisites:

  1. The Vikunja instance from the Intermediate workshop (using PostgreSQL, Nginx, HTTPS) should be running.
  2. Access to the server terminal where Vikunja is hosted.
  3. curl installed on the server.
  4. A designated directory on the server to store backups (e.g., /mnt/backups/vikunja). Ensure this directory exists and you have write permissions (sudo mkdir -p /mnt/backups/vikunja && sudo chown $USER:$USER /mnt/backups/vikunja - adjust ownership if needed).

Part 1: Backup Automation

  1. Create Backup Script:
    • Create the script file: nano ~/vikunja_workshop/backup_vikunja.sh
    • Paste the script content provided in the "Backup and Restore Strategies" section above.
    • Carefully review and modify the variables at the top of the script:
      • BACKUP_DIR="/mnt/backups/vikunja" (or your chosen backup path)
      • DB_CONTAINER="vikunja-ws-db" (Verify with docker ps)
      • DB_USER="vikunja_workshop_user" (From your docker-compose.yml)
      • DB_NAME="vikunja_workshop_db" (From your docker-compose.yml)
      • FILES_VOLUME="vikunja_ws_files" (Verify with docker volume ls)
    • Save and close (Ctrl+X, Y, Enter).
  2. Make Script Executable:
    • chmod +x ~/vikunja_workshop/backup_vikunja.sh
  3. Perform Manual Test Run:
    • Execute the script directly: ~/vikunja_workshop/backup_vikunja.sh
    • Check the output for any errors.
    • Verify that backup files (.dump and .tar.gz) have been created in your BACKUP_DIR. Check their size to ensure they are not empty.
    • ls -lh /mnt/backups/vikunja
  4. Schedule with Cron:
    • Open the crontab editor: crontab -e (If asked, choose an editor like nano).
    • Add the following line at the bottom, adjusting the script path if necessary:
      # Run Vikunja backup daily at 3:05 AM
      5 3 * * * /home/<your_username>/vikunja_workshop/backup_vikunja.sh >> /home/<your_username>/vikunja_workshop/vikunja_backup.log 2>&1
      
      • Replace <your_username> with your actual Linux username.
      • This runs the script at 3:05 AM daily. >> ... 2>&1 appends both standard output and errors to a log file in your workshop directory.
    • Save and close the crontab (Ctrl+X, Y, Enter in nano).
    • You can verify the cron job is listed: crontab -l

Part 2: API Task Creation

  1. Generate API Token:
    • Log in to your Vikunja instance (https://myvikunja.myuniversity.club).
    • Go to Settings (usually click your username/avatar in the top right) -> API Tokens.
    • Click "Create".
    • Enter a name: Workshop API Test
    • Click "Create".
    • Immediately copy the generated token string. Store it somewhere safe temporarily (like a local text file) – you'll need it for the curl commands. Let's call this token YOUR_API_TOKEN.
  2. Find Project and List IDs:
    • Navigate within Vikunja to your "COMP SCI 101" project.
    • Click on the "Assignments" list.
    • Look at the URL in your browser's address bar. It will likely look something like https://myvikunja.myuniversity.club/projects/1/lists/2.
    • The number after /projects/ is the Project ID (e.g., 1).
    • The number after /lists/ is the List ID for "Assignments" (e.g., 2).
    • Note down the List ID for "Assignments". Let's assume LIST_ID=2.
  3. Test API with curl - List Projects (Optional):
    • Open your server terminal.
    • Run the following curl command, replacing the URL and token:
      curl -X GET "https://myvikunja.myuniversity.club/api/v1/projects" \
           -H "accept: application/json" \
           -H "Authorization: Bearer YOUR_API_TOKEN" | jq . # Pipe to jq for pretty printing JSON if installed
      
    • You should see a JSON output listing your projects, including "COMP SCI 101".
  4. Create Task via API using curl:
    • Use the List ID you found in step 2 (LIST_ID=2 in our example).
    • Run the following curl command, replacing the URL, LIST_ID, and token:
      curl -X POST "https://myvikunja.myuniversity.club/api/v1/lists/2/tasks" \
           -H "accept: application/json" \
           -H "Authorization: Bearer YOUR_API_TOKEN" \
           -H "Content-Type: application/json" \
           -d '{
                 "title": "Programming Assignment 2 - API Created",
                 "description": "Submit the Python script via coursework portal.",
                 "priority": 1
               }' | jq .
      
    • This sends a POST request to create a task in list 2.
    • The -d '{...}' part contains the task details in JSON format.
    • You should receive a JSON response representing the newly created task.
  5. Verify in Vikunja UI:
    • Go back to your Vikunja browser tab.
    • Refresh the "COMP SCI 101" project page.
    • You should now see the new task "Programming Assignment 2 - API Created" listed under the "Assignments" list.

Outcome: You have successfully set up an automated backup routine for your Vikunja instance using a shell script and cron. You have also learned how to generate an API token, find necessary IDs, and use curl to interact with the Vikunja API to programmatically create a task. This demonstrates the power of automation and integration possible with Vikunja.

Conclusion

Throughout this guide, we've journeyed from understanding the core concepts of Vikunja and the benefits of self-hosting to deploying a basic instance, enhancing it with security and a robust database, and finally exploring advanced management techniques like backups, updates, and API interaction.

By self-hosting Vikunja, you gain unparalleled control over your project management data, ensuring privacy and tailoring the system to your specific needs. You avoid vendor lock-in and recurring subscription fees, while simultaneously gaining valuable technical experience in areas like Docker, Linux administration, networking, and database management.

We covered:

  • Basic Deployment: Using Docker Compose for a quick and easy setup with SQLite.
  • Intermediate Configuration: Securing your instance with Nginx/Traefik and Let's Encrypt for HTTPS, and migrating to a more scalable PostgreSQL database.
  • Advanced Management: Implementing crucial automated backup strategies, performing updates safely, and leveraging the power of the Vikunja API for automation and integration.

The workshops provided practical, step-by-step experience, transforming theoretical knowledge into tangible results – from creating your first project to automating backups and interacting with the API.

Your journey with self-hosted Vikunja doesn't end here. The world of self-hosting is vast and constantly evolving. We encourage you to:

  • Explore Further: Dive deeper into Vikunja's features like namespaces, Gantt charts, advanced filtering, and user collaboration.
  • Consult Official Documentation: The official Vikunja documentation is the definitive source for configuration options, API details, and troubleshooting.
  • Engage with the Community: Participate in forums, chat channels, or issue trackers to ask questions, share your experiences, and learn from others.
  • Experiment: Try different reverse proxies, explore advanced Docker networking, set up monitoring, or integrate Vikunja with other self-hosted tools you use.

Self-hosting is a rewarding endeavor that offers freedom, control, and continuous learning. By managing your own Vikunja instance, you've taken a significant step towards digital sovereignty and built a powerful tool to enhance your personal and professional productivity. Happy task managing!