Does a to-do app deserve a whole server?
On its own, often not, and it is worth being honest about that. Vikunja's documentation gives no processor or memory figures, and its sizing advice is simply this: past a handful of users, move from SQLite to MySQL or PostgreSQL. Where a whole machine pays off is when your lists sit next to the other tools your team relies on, say Plane for bigger projects or Joplin Server for shared notes, on hardware nobody else touches.
Our dedicated servers give you exactly that: the whole computer, a root login, a port with no traffic meter and the freedom to stop any month, handed over within 30 minutes of payment approval for a ready server. For one small team with nothing else to run, a micro server is the modest end of the range. If a firewall rule ever locks you out, the remote console that rack servers and blades include still shows you the screen and lets you press power; two cartridge models, m510 and m710x, have it too, while other cartridges offer power control alone.
Three ways to install it
Vikunja ships as a single program that serves the app and its interface together, so whichever route you choose, you install one thing.
| Route | What you get | Suits you when |
|---|---|---|
| Debian/Ubuntu package | apt repository from release 2.4.0 (amd64, arm64, armhf); config in /etc/vikunja/config.yml; a systemd unit | You want updates through apt |
| Docker image | vikunja/vikunja, running as user 1000; settings through VIKUNJA_ variables | Your server already runs containers |
| Plain binary | GPG-signed zip you unpack into /opt/vikunja and start with your own systemd unit | Your distribution has no package |
RPM, Arch and Alpine repositories exist too. This guide follows the Debian package on Ubuntu with SQLite, which is built in. If your team will grow, set database.type to postgres or mysql from day one; MySQL needs 8.0 or newer, because 5.7 lacks features Vikunja relies on.
Before you begin
- A fresh Ubuntu or Debian server and your own SSH login with sudo.
- A domain name, here tasks.example.com, already pointing at the server, so Caddy can fetch its certificate.
- A few minutes to choose usernames for the people who will use it.
Up and running in an evening
- Turn the firewall on with IPv6 set first, so every rule covers both address families, and open 80 and 443 for Caddy, which runs as a normal program and is blocked without that rule.
- Add Vikunja's signed repository and install it with Caddy. A fresh package install stays stopped, so nothing listens yet.
- Create the service user the docs' hardening guide recommends, with its own data folder.
sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw
ufw allow OpenSSH
ufw allow 80,443/tcp
ufw --force enable
curl -fsSL https://dl.vikunja.io/repos/gpg.key | gpg --dearmor -o /usr/share/keyrings/vikunja.gpg
echo "deb [signed-by=/usr/share/keyrings/vikunja.gpg] https://dl.vikunja.io/repos/apt stable main" > /etc/apt/sources.list.d/vikunja.list
apt update && apt install -y vikunja caddy
useradd --system --user-group --home-dir /var/lib/vikunja --shell /usr/sbin/nologin vikunja
install -d -m 700 -o vikunja -g vikunja /var/lib/vikunja /var/lib/vikunja/files
printf 'tasks.example.com {\n reverse_proxy 127.0.0.1:3456\n}\n' > /etc/caddy/Caddyfile
systemctl reload caddy
Next, write the configuration and start the service. The heredoc fills in the secret inside the shell, so it never shows in ps or your history, and the file ends up readable by the vikunja user alone at mode 600.
SECRET=$(openssl rand -hex 32)
install -m 600 -o vikunja -g vikunja /dev/null /etc/vikunja/config.yml
cat > /etc/vikunja/config.yml <<EOF
service:
secret: "$SECRET"
publicurl: "https://tasks.example.com/"
interface: "127.0.0.1:3456"
enableregistration: false
ipextractionmethod: xff
trustedproxies: 127.0.0.1/32,::1/128
database:
type: sqlite
path: /var/lib/vikunja/vikunja.db
files:
basepath: /var/lib/vikunja/files
EOF
unset SECRET
mkdir -p /etc/systemd/system/vikunja.service.d
printf '[Service]\nUser=vikunja\nGroup=vikunja\nWorkingDirectory=/var/lib/vikunja\nProtectHome=true\nPrivateTmp=true\nProtectSystem=strict\nReadWritePaths=/var/lib/vikunja\n' > /etc/systemd/system/vikunja.service.d/user.conf
systemctl daemon-reload
systemctl start vikunja
sudo -u vikunja vikunja user create --config /etc/vikunja/config.yml -u alex -e alex@example.com
- secret signs everyone's login tokens. Leave it out and Vikunja picks a random one at each start, logging your whole team out on every restart. Older guides call it
JWTSecret, which is deprecated and copied across. - publicurl is the address your team types. It is required here because cross-origin checks (CORS) are on by default.
- interface keeps Vikunja on 127.0.0.1, so the only way in from outside is through Caddy.
- enableregistration: false closes the sign-up form. It is on by default, which would let any visitor make an account.
- ipextractionmethod and trustedproxies let logs and rate limits see real visitors instead of Caddy.
The last line makes your own account while the site is still closed to the outside world. Vikunja asks for the password, which keeps it off the command line. Run the same command for each colleague. Every key also works as an environment variable, such as VIKUNJA_SERVICE_PUBLICURL, and a variable beats the file.
Run Vikunja commands as the vikunja user, as above. The docs warn that running them as root leaves root-owned files, including SQLite's write-ahead log, in the data folder, and the service then fails to start.
Keeping your lists safe
Your data lives in two places, in the database and among the uploaded attachments, and deleted projects are gone for good: Vikunja has no trash and no undo. The built-in vikunja dump command packs the configuration, the version, every attachment and the full database into one zip. That zip includes your config file and its secret, so the backup folder stays private to the vikunja user.
This writes the cron file with printf; the log folder exists before the first run:
install -d -m 700 -o vikunja -g vikunja /var/backups/vikunja /var/log/vikunja-dump
printf '%s\n' \
'SHELL=/bin/sh' \
'10 3 * * * vikunja umask 077; /usr/local/bin/vikunja dump --config /etc/vikunja/config.yml -p /var/backups/vikunja > /var/log/vikunja-dump/dump-$(date +\%F).log 2>&1' \
'40 3 * * * vikunja find /var/backups/vikunja -name "vikunja-dump_*.zip" -mtime +14 -delete' \
> /etc/cron.d/vikunja-dump
chmod 644 /etc/cron.d/vikunja-dump
Fourteen days of zips is our example, not a rule. Copy them off the server regularly, to a machine somewhere else: you manage the server; we keep the hardware and the network running. To bring an archive back, vikunja restore takes the zip, and --preserve-config keeps today's settings rather than the ones inside it. Try it once on a spare install so the first restore is not a real emergency.
Updating without surprises
- Take a fresh dump first, as the docs ask.
- Read the changelog for the new release in case it lists a manual step.
- Run
apt update && apt upgrade. The package restarts Vikunja on the new version, and Vikunja applies any database migrations on its own as it starts. - If apt asks about /etc/vikunja/config.yml, keep your version; your secret and settings live there.
Stay on the stable channel. Jumping to an unstable build is easy, but the docs advise against going back; you would hold on until a newer stable version ships.
The licence, and what Pro adds
Vikunja is free software: most of its code is under AGPL-3.0-or-later. You can run it for your team at no cost. If you change the code and let people use your changed version over the network, the AGPL asks you to make that source available to them.
Vikunja Pro is optional. A licence key adds a panel for managing every user, per-task time tracking and audit logs, and it funds the project. Without a key your server never contacts the licence service; with one, it checks in when it starts and daily after that, sending user counts and similar details but none of your tasks.
Questions people ask
- Can people sign themselves up?
- Only if you let them. Sign-up is on by default, and this guide turns it off with
enableregistration: false. You then add each person withvikunja user create, run as the vikunja user. - Do I need Docker to run Vikunja?
- No. The Debian package used here installs the program and a systemd service, and there are RPM, Arch and Alpine packages plus a plain binary. Docker is a good choice when your server already runs containers; the image takes the same settings as environment variables.
- Where does Vikunja keep my tasks?
- In the database you configure. With this guide that is a SQLite file at /var/lib/vikunja/vikunja.db, with attachments in /var/lib/vikunja/files. Both go into the nightly dump zip.
- Will an update delete anything?
- It should not: Vikunja runs its own database migrations when the new version starts. Still, take a dump before every upgrade and read the changelog, since a release can ask for a manual step. If something goes wrong,
vikunja restorebrings the zip back. - Can a company use Vikunja for free?
- Yes. The AGPL lets you run it for any number of colleagues without paying. The licence only adds obligations when you modify the code and offer your version to users over a network. Pro is a paid add-on if you want instance-wide user management, logged hours per task or an audit trail.