Workload · Running a team to-do app

Your own Vikunja: a self-hosted to-do app on a server only you use

You can self-host Vikunja by installing one program, which carries both the task app and the web pages your team opens, then giving it a secret, its public address and a place to keep data, with HTTPS in front. This guide uses the official Debian package with SQLite, runs it under its own user, keeps sign-ups closed so only the people you add get in, and saves everything to a zip every night.

The short version
  1. Installed from the project's own signed apt repository
  2. Listens on 127.0.0.1 only; Caddy handles HTTPS
  3. No public sign-up: you add each person from the command line
  4. One nightly zip holds tasks, attachments and settings

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.

RouteWhat you getSuits you when
Debian/Ubuntu packageapt repository from release 2.4.0 (amd64, arm64, armhf); config in /etc/vikunja/config.yml; a systemd unitYou want updates through apt
Docker imagevikunja/vikunja, running as user 1000; settings through VIKUNJA_ variablesYour server already runs containers
Plain binaryGPG-signed zip you unpack into /opt/vikunja and start with your own systemd unitYour 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

  1. 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.
  2. Add Vikunja's signed repository and install it with Caddy. A fresh package install stays stopped, so nothing listens yet.
  3. 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

  1. Take a fresh dump first, as the docs ask.
  2. Read the changelog for the new release in case it lists a manual step.
  3. 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.
  4. 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 with vikunja 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 restore brings 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.

Give your team's tasks a home of their own

Choose a dedicated server, install Vikunja tonight, and keep every list on hardware that only answers to you.

Get a server for your to-do app

Read next