Vikunja is an open-source, self-hostable to-do app. It helps you organize your tasks and projects with features like list, kanban, gantt, and table views - all while keeping your data under your control.
| Port | 3456 |
| Registry | ghcr.io/daemonless/vikunja |
| Source | https://vikunja.io |
| Website | https://vikunja.io |
| Tag | Description | Best For |
|---|---|---|
pkg |
FreeBSD Quarterly. Uses stable, tested packages. | Production stability. |
latest / pkg-latest |
FreeBSD Latest. Rolling package updates. | Staying current. |
Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions.
Database. Where the app keeps its data. The default needs nothing else running.
A file in the app's config folder. Right for one person, nothing extra to run.
1. Save as .env and fill in what is empty:
PUID=1000
PGID=1000
TZ=UTC2. Save as compose.yaml:
name: vikunja
services:
vikunja:
image: ghcr.io/daemonless/vikunja:latest
container_name: vikunja
# "always", not "unless-stopped": FreeBSD's podman rc.d only auto-starts
# containers with restart-policy=always at boot (needs podman_enable=YES).
restart: always
environment:
- PUID=1000
- PGID=1000
- TZ=UTC
# Optional: the address Vikunja puts in the links it sends.
- VIKUNJA_SERVICE_PUBLICURL=
# The database, from the Database choice; sqlite needs nothing else.
- VIKUNJA_DATABASE_TYPE=${VIKUNJA_DATABASE_TYPE:-sqlite}
- VIKUNJA_DATABASE_HOST=${VIKUNJA_DATABASE_HOST:-}
- VIKUNJA_DATABASE_USER=${VIKUNJA_DATABASE_USER:-}
- VIKUNJA_DATABASE_PASSWORD=${VIKUNJA_DATABASE_PASSWORD:-}
- VIKUNJA_DATABASE_DATABASE=${VIKUNJA_DATABASE_DATABASE:-}
volumes:
- /containers/vikunja:/config
ports:
- 3456:3456Then run podman-compose up -d.
One more container, its data in its own folder. For a household, or an app that wants it.
1. Save as .env and fill in what is empty:
PUID=1000
PGID=1000
TZ=UTC
# Database: PostgreSQL
VIKUNJA_DATABASE_TYPE=postgres
VIKUNJA_DATABASE_HOST=postgres
VIKUNJA_DATABASE_USER=vikunja
VIKUNJA_DATABASE_PASSWORD= # set one
VIKUNJA_DATABASE_DATABASE=vikunja
DATABASE_LOCATION=/containers/vikunja/postgres2. Save as compose.yaml:
name: vikunja
services:
vikunja:
depends_on: [postgres]
image: ghcr.io/daemonless/vikunja:latest
container_name: vikunja
# "always", not "unless-stopped": FreeBSD's podman rc.d only auto-starts
# containers with restart-policy=always at boot (needs podman_enable=YES).
restart: always
environment:
- PUID=1000
- PGID=1000
- TZ=UTC
# Optional: the address Vikunja puts in the links it sends.
- VIKUNJA_SERVICE_PUBLICURL=
# The database, from the Database choice; sqlite needs nothing else.
- VIKUNJA_DATABASE_TYPE=${VIKUNJA_DATABASE_TYPE:-sqlite}
- VIKUNJA_DATABASE_HOST=${VIKUNJA_DATABASE_HOST:-}
- VIKUNJA_DATABASE_USER=${VIKUNJA_DATABASE_USER:-}
- VIKUNJA_DATABASE_PASSWORD=${VIKUNJA_DATABASE_PASSWORD:-}
- VIKUNJA_DATABASE_DATABASE=${VIKUNJA_DATABASE_DATABASE:-}
volumes:
- /containers/vikunja:/config
ports:
- 3456:3456
postgres:
image: ghcr.io/daemonless/postgres:17
restart: always
annotations:
org.freebsd.jail.allow.sysvipc: "true"
environment:
- POSTGRES_USER=${VIKUNJA_DATABASE_USER}
- POSTGRES_PASSWORD=${VIKUNJA_DATABASE_PASSWORD}
- POSTGRES_DB=${VIKUNJA_DATABASE_DATABASE}
volumes:
- "${DATABASE_LOCATION}:/var/lib/postgresql/data"Then run podman-compose up -d.
One more container, its data in its own folder. If you already know MariaDB, or the app prefers it.
1. Save as .env and fill in what is empty:
PUID=1000
PGID=1000
TZ=UTC
# Database: MariaDB
VIKUNJA_DATABASE_TYPE=mysql
VIKUNJA_DATABASE_HOST=mariadb
VIKUNJA_DATABASE_USER=vikunja
VIKUNJA_DATABASE_PASSWORD= # set one
VIKUNJA_DATABASE_DATABASE=vikunja
DATABASE_LOCATION=/containers/vikunja/mariadb2. Save as compose.yaml:
name: vikunja
services:
vikunja:
depends_on: [mariadb]
image: ghcr.io/daemonless/vikunja:latest
container_name: vikunja
# "always", not "unless-stopped": FreeBSD's podman rc.d only auto-starts
# containers with restart-policy=always at boot (needs podman_enable=YES).
restart: always
environment:
- PUID=1000
- PGID=1000
- TZ=UTC
# Optional: the address Vikunja puts in the links it sends.
- VIKUNJA_SERVICE_PUBLICURL=
# The database, from the Database choice; sqlite needs nothing else.
- VIKUNJA_DATABASE_TYPE=${VIKUNJA_DATABASE_TYPE:-sqlite}
- VIKUNJA_DATABASE_HOST=${VIKUNJA_DATABASE_HOST:-}
- VIKUNJA_DATABASE_USER=${VIKUNJA_DATABASE_USER:-}
- VIKUNJA_DATABASE_PASSWORD=${VIKUNJA_DATABASE_PASSWORD:-}
- VIKUNJA_DATABASE_DATABASE=${VIKUNJA_DATABASE_DATABASE:-}
volumes:
- /containers/vikunja:/config
ports:
- 3456:3456
mariadb:
image: ghcr.io/daemonless/mariadb:11.4
restart: always
environment:
- MYSQL_USER=${VIKUNJA_DATABASE_USER}
- MYSQL_PASSWORD=${VIKUNJA_DATABASE_PASSWORD}
- MYSQL_DATABASE=${VIKUNJA_DATABASE_DATABASE}
- MYSQL_ROOT_PASSWORD=${VIKUNJA_DATABASE_PASSWORD}
volumes:
- "${DATABASE_LOCATION}:/config"Then run podman-compose up -d.
A database you already run, here or on another machine. Nothing extra runs; you give the address and the account.
1. Save as .env and fill in Kind, Host, User, Password, Database:
PUID=1000
PGID=1000
TZ=UTC
# Database: Your own
VIKUNJA_DATABASE_TYPE= # Kind: postgres | mysql
VIKUNJA_DATABASE_HOST= # Host
VIKUNJA_DATABASE_USER= # User
VIKUNJA_DATABASE_PASSWORD= # Password
VIKUNJA_DATABASE_DATABASE= # Database2. Save as compose.yaml:
name: vikunja
services:
vikunja:
image: ghcr.io/daemonless/vikunja:latest
container_name: vikunja
# "always", not "unless-stopped": FreeBSD's podman rc.d only auto-starts
# containers with restart-policy=always at boot (needs podman_enable=YES).
restart: always
environment:
- PUID=1000
- PGID=1000
- TZ=UTC
# Optional: the address Vikunja puts in the links it sends.
- VIKUNJA_SERVICE_PUBLICURL=
# The database, from the Database choice; sqlite needs nothing else.
- VIKUNJA_DATABASE_TYPE=${VIKUNJA_DATABASE_TYPE:-sqlite}
- VIKUNJA_DATABASE_HOST=${VIKUNJA_DATABASE_HOST:-}
- VIKUNJA_DATABASE_USER=${VIKUNJA_DATABASE_USER:-}
- VIKUNJA_DATABASE_PASSWORD=${VIKUNJA_DATABASE_PASSWORD:-}
- VIKUNJA_DATABASE_DATABASE=${VIKUNJA_DATABASE_DATABASE:-}
volumes:
- /containers/vikunja:/config
ports:
- 3456:3456Then run podman-compose up -d.
.env:
# .env
DIRECTOR_PROJECT=vikunja
PUID=1000
PGID=1000
TZ=UTC
VIKUNJA_SERVICE_PUBLICURL=
VIKUNJA_DATABASE_TYPE=sqlite
VIKUNJA_DATABASE_HOST=
VIKUNJA_DATABASE_USER=
VIKUNJA_DATABASE_PASSWORD=<VIKUNJA_DATABASE_PASSWORD>
VIKUNJA_DATABASE_DATABASE=
appjail-director.yml:
# appjail-director.yml
options:
- virtualnet: ':<random> default'
- nat:
services:
vikunja:
name: vikunja
options:
- container: 'args:--pull'
- expose: '3456:3456 proto:tcp'
oci:
user: root
environment:
- PUID: !ENV '${PUID}'
- PGID: !ENV '${PGID}'
- TZ: !ENV '${TZ}'
- VIKUNJA_SERVICE_PUBLICURL: !ENV '${VIKUNJA_SERVICE_PUBLICURL}'
- VIKUNJA_DATABASE_TYPE: !ENV '${VIKUNJA_DATABASE_TYPE}'
- VIKUNJA_DATABASE_HOST: !ENV '${VIKUNJA_DATABASE_HOST}'
- VIKUNJA_DATABASE_USER: !ENV '${VIKUNJA_DATABASE_USER}'
- VIKUNJA_DATABASE_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
- VIKUNJA_DATABASE_DATABASE: !ENV '${VIKUNJA_DATABASE_DATABASE}'
volumes:
- vikunja: /config
volumes:
vikunja:
device: '/containers/vikunja'Makejail:
# Makejail
ARG tag=pkg
OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/vikunja:${tag}
Save the files above, then run appjail-director up.
.env:
# .env
DIRECTOR_PROJECT=vikunja
PUID=1000
PGID=1000
TZ=UTC
VIKUNJA_SERVICE_PUBLICURL=
VIKUNJA_DATABASE_TYPE=postgres
VIKUNJA_DATABASE_HOST=vikunja_postgres
VIKUNJA_DATABASE_USER=vikunja
VIKUNJA_DATABASE_PASSWORD=
VIKUNJA_DATABASE_DATABASE=vikunja
DATABASE_LOCATION=/containers/vikunja/postgres
appjail-director.yml:
# appjail-director.yml
options:
- virtualnet: ':<random> default'
- nat:
services:
vikunja:
name: vikunja
options:
- container: 'args:--pull'
- expose: '3456:3456 proto:tcp'
oci:
user: root
environment:
- PUID: !ENV '${PUID}'
- PGID: !ENV '${PGID}'
- TZ: !ENV '${TZ}'
- VIKUNJA_SERVICE_PUBLICURL: !ENV '${VIKUNJA_SERVICE_PUBLICURL}'
- VIKUNJA_DATABASE_TYPE: !ENV '${VIKUNJA_DATABASE_TYPE}'
- VIKUNJA_DATABASE_HOST: !ENV '${VIKUNJA_DATABASE_HOST}'
- VIKUNJA_DATABASE_USER: !ENV '${VIKUNJA_DATABASE_USER}'
- VIKUNJA_DATABASE_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
- VIKUNJA_DATABASE_DATABASE: !ENV '${VIKUNJA_DATABASE_DATABASE}'
volumes:
- vikunja: /config
vikunja-postgres:
name: vikunja_postgres
priority: 10
options:
- from: ghcr.io/daemonless/postgres:17
- template: !ENV '${PWD}/postgres-template.conf'
oci:
environment:
- POSTGRES_USER: !ENV '${VIKUNJA_DATABASE_USER}'
- POSTGRES_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
- POSTGRES_DB: !ENV '${VIKUNJA_DATABASE_DATABASE}'
volumes:
- database: /var/lib/postgresql/data
volumes:
vikunja:
device: '/containers/vikunja'
database:
device: !ENV '${DATABASE_LOCATION}'Makejail:
# Makejail
ARG tag=pkg
OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/vikunja:${tag}
postgres-template.conf:
# The jail PostgreSQL runs in: SysV shared memory, which a jail does not
# get by default. ip4/ip6 are set here because the director's ip4_inherit
# option is a no-op in AppJail 5.5.0.
exec.start: "/bin/sh /etc/rc"
exec.stop: "/bin/sh /etc/rc.shutdown jail"
sysvmsg: new
sysvsem: new
sysvshm: new
mount.devfs
persist
ip4: inherit
ip6: inherit
Save the files above, then run appjail-director up.
.env:
# .env
DIRECTOR_PROJECT=vikunja
PUID=1000
PGID=1000
TZ=UTC
VIKUNJA_SERVICE_PUBLICURL=
VIKUNJA_DATABASE_TYPE=mysql
VIKUNJA_DATABASE_HOST=vikunja_mariadb
VIKUNJA_DATABASE_USER=vikunja
VIKUNJA_DATABASE_PASSWORD=
VIKUNJA_DATABASE_DATABASE=vikunja
DATABASE_LOCATION=/containers/vikunja/mariadb
appjail-director.yml:
# appjail-director.yml
options:
- virtualnet: ':<random> default'
- nat:
services:
vikunja:
name: vikunja
options:
- container: 'args:--pull'
- expose: '3456:3456 proto:tcp'
oci:
user: root
environment:
- PUID: !ENV '${PUID}'
- PGID: !ENV '${PGID}'
- TZ: !ENV '${TZ}'
- VIKUNJA_SERVICE_PUBLICURL: !ENV '${VIKUNJA_SERVICE_PUBLICURL}'
- VIKUNJA_DATABASE_TYPE: !ENV '${VIKUNJA_DATABASE_TYPE}'
- VIKUNJA_DATABASE_HOST: !ENV '${VIKUNJA_DATABASE_HOST}'
- VIKUNJA_DATABASE_USER: !ENV '${VIKUNJA_DATABASE_USER}'
- VIKUNJA_DATABASE_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
- VIKUNJA_DATABASE_DATABASE: !ENV '${VIKUNJA_DATABASE_DATABASE}'
volumes:
- vikunja: /config
vikunja-mariadb:
name: vikunja_mariadb
priority: 10
options:
- from: ghcr.io/daemonless/mariadb:11.4
- template: !ENV '${PWD}/template.conf'
oci:
environment:
- MYSQL_USER: !ENV '${VIKUNJA_DATABASE_USER}'
- MYSQL_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
- MYSQL_DATABASE: !ENV '${VIKUNJA_DATABASE_DATABASE}'
- MYSQL_ROOT_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
volumes:
- database: /config
volumes:
vikunja:
device: '/containers/vikunja'
database:
device: !ENV '${DATABASE_LOCATION}'Makejail:
# Makejail
ARG tag=pkg
OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/vikunja:${tag}
Save the files above, then run appjail-director up.
.env:
# .env
DIRECTOR_PROJECT=vikunja
PUID=1000
PGID=1000
TZ=UTC
VIKUNJA_SERVICE_PUBLICURL=
VIKUNJA_DATABASE_TYPE=
VIKUNJA_DATABASE_HOST=
VIKUNJA_DATABASE_USER=
VIKUNJA_DATABASE_PASSWORD=
VIKUNJA_DATABASE_DATABASE=
appjail-director.yml:
# appjail-director.yml
options:
- virtualnet: ':<random> default'
- nat:
services:
vikunja:
name: vikunja
options:
- container: 'args:--pull'
- expose: '3456:3456 proto:tcp'
oci:
user: root
environment:
- PUID: !ENV '${PUID}'
- PGID: !ENV '${PGID}'
- TZ: !ENV '${TZ}'
- VIKUNJA_SERVICE_PUBLICURL: !ENV '${VIKUNJA_SERVICE_PUBLICURL}'
- VIKUNJA_DATABASE_TYPE: !ENV '${VIKUNJA_DATABASE_TYPE}'
- VIKUNJA_DATABASE_HOST: !ENV '${VIKUNJA_DATABASE_HOST}'
- VIKUNJA_DATABASE_USER: !ENV '${VIKUNJA_DATABASE_USER}'
- VIKUNJA_DATABASE_PASSWORD: !ENV '${VIKUNJA_DATABASE_PASSWORD}'
- VIKUNJA_DATABASE_DATABASE: !ENV '${VIKUNJA_DATABASE_DATABASE}'
volumes:
- vikunja: /config
volumes:
vikunja:
device: '/containers/vikunja'Makejail:
# Makejail
ARG tag=pkg
OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/vikunja:${tag}
Save the files above, then run appjail-director up.
Access at: http://localhost:3456
| Variable | Default | Description |
|---|---|---|
PUID |
1000 |
User ID for the application process |
PGID |
1000 |
Group ID for the application process |
TZ |
UTC |
Timezone for the container |
VIKUNJA_SERVICE_PUBLICURL |
`` | Address you open Vikunja at, e.g. http://192.168.1.10:3456/ (used in links and emails it sends) |
VIKUNJA_DATABASE_TYPE |
sqlite |
sqlite, postgres or mysql -- set by the Database choice |
VIKUNJA_DATABASE_HOST |
`` | Database host (the PostgreSQL and MariaDB choices fill this in) |
VIKUNJA_DATABASE_USER |
`` | Database user |
VIKUNJA_DATABASE_PASSWORD |
<VIKUNJA_DATABASE_PASSWORD> |
Database password |
VIKUNJA_DATABASE_DATABASE |
`` | Database name |
| Path | Description |
|---|---|
/config |
Database (vikunja.db), uploaded files and the login secret |
| Port | Protocol | Description |
|---|---|---|
3456 |
TCP | Web UI |
Architectures: amd64
User: bsd (UID/GID via PUID/PGID, defaults to 1000:1000)
Base: FreeBSD 15.1
Need help? Join our Discord community.