If you want a simple and powerful task manager that stays entirely under your control, Vikunja is a great choice. This guide shows you how to host it on AlmaLinux 9 inside an LXC container, backed by PostgreSQL and served through Nginx with SSL under the hostname tasks.examplecorp.io
.

Why self-hosting your task manager matters
Setting up your own task manager like Vikunja is more than just a technical exercise – it’s about control, privacy, and flexibility. With tasks.examplecorp.io
, you now own your data, can adapt the system to your workflow, and avoid subscription lock-ins or third-party limitations.
By self-hosting, you can:
- Keep your tasks private — no external servers, no data leaks.
- Customize your setup — integrate with other tools or automate backups.
- Learn and experiment — hosting your own services strengthens your IT skills and knowledge.
In short, this isn’t just a server setup; it’s an investment in productivity and autonomy. Your tasks, your rules, your environment – all lightweight, secure, and fully yours.
Preparing the LXC Container
Before installing anything, it’s important to define the basic resources for your container. A minimal but balanced setup is sufficient for Vikunja.
Recommended resources:
- Base image: AlmaLinux 9 (LXC template)
- CPU: 2 cores
- Memory: 2 GB RAM
- Storage: 10 GB (local-lvm or similar)
- Networking: DHCP or static IP on
vmbr0
- Hostname:
tasks.examplecorp.io
Once the container is created, update the system and install basic tools:
dnf update -y
dnf install -y vim wget curl git unzip net-tools nginx postgresql-server
Setting up PostgreSQL
Vikunja relies on a database to store tasks and user information. We’ll use PostgreSQL for stability and performance.
Initialize and start PostgreSQL:
postgresql-setup --initdb
systemctl enable --now postgresql
Switch to the PostgreSQL user and create a database with its own user:
sudo -u postgres psql
Inside psql
:
CREATE DATABASE vikunja;
CREATE USER vikunja WITH PASSWORD 'your-strong-password';
GRANT ALL PRIVILEGES ON DATABASE vikunja TO vikunja;
\q
Adjusting PostgreSQL Authentication
By default, PostgreSQL uses ident authentication for local connections. Vikunja requires password authentication. Instead of changing defaults, we’ll add new rules specifically for the Vikunja database.
Edit pg_hba.conf
:
nano /var/lib/pgsql/data/pg_hba.conf
Add these lines above the defaults:
# Custom access rules for Vikunja
host vikunja vikunja 127.0.0.1/32 md5
host vikunja vikunja ::1/128 md5
Then restart PostgreSQL:
systemctl restart postgresql
Installing the Vikunja Backend
With the database ready, the next step is installing the backend service, which provides the API for tasks and projects.
Download and install the RPM:
wget https://dl.vikunja.io/vikunja/0.24.6/vikunja-0.24.6-x86_64.rpm
dnf install -y vikunja-0.24.6-x86_64.rpm
Backup and edit the configuration:
cp /etc/vikunja/config.yml /etc/vikunja/config.yml.default
nano /etc/vikunja/config.yml
Minimal config:
service:
frontendurl: https://tasks.examplecorp.io
database:
type: postgres
host: 127.0.0.1
user: vikunja
password: your-strong-password
database: vikunja
Enable and start Vikunja:
systemctl enable --now vikunja
Installing the Vikunja Frontend
The frontend delivers the user interface for your browser. We’ll place it in /var/www/vikunja
.
wget https://dl.vikunja.io/frontend/vikunja-frontend-0.24.6.zip
unzip vikunja-frontend-0.24.6.zip -d vikunja-frontend
mkdir -p /var/www/vikunja
cp -r -d vikunja-frontend/* /var/www/vikunja/
Configuring Nginx with SSL
To serve Vikunja securely, configure Nginx with SSL. In this example, we assume you already have your SSL certificate and key for tasks.examplecorp.io
.
Create the config file:
nano /etc/nginx/conf.d/vikunja.conf
Example configuration:
server {
listen 80;
server_name tasks.examplecorp.io;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name tasks.examplecorp.io;
ssl_certificate /etc/ssl/certs/tasks.examplecorp.io.crt;
ssl_certificate_key /etc/ssl/private/tasks.examplecorp.io.key;
root /var/www/vikunja;
index index.html;
location /api/v1/ {
proxy_pass http://127.0.0.1:3456/api/v1/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
try_files $uri $uri/ /index.html;
}
}
Enable Nginx:
systemctl enable --now nginx
Verifying the Installation
Once everything is running, it’s time to make sure your new task manager works.
Check listeners:
netstat -tulpen | grep -E "80|443|3456"
Verify the API:
curl -s https://tasks.examplecorp.io/api/v1/info | jq
Follow logs if needed:
journalctl -u vikunja.service -f
Bringing It All Together
Congratulations – you now have a fully functional, self-hosted task manager running at https://tasks.examplecorp.io
.
Your next steps? Start creating projects, invite your team if needed, and explore integrations or automation. Every task you manage here is truly yours – a small but meaningful step toward full control over your productivity.
Self-hosting is not just a technical achievement; it’s a mindset. And with this setup, you’ve already taken the first step.