Self-Hosting Kaneo on a Raspberry Pi with Docker Compose
Kaneo is a clean, self-hostable project management tool — think a lightweight Trello alternative you actually own. This post walks through getting it running on a Raspberry Pi (or any ARM64 Linux box) via Docker Compose, accessible from any machine on your LAN.
Prerequisites
- Raspberry Pi running Linux (tested on
aarch64) - Docker and Docker Compose installed
opensslavailable on the Pi
Project structure
Create a dedicated folder for Kaneo:
1
mkdir ~/containers/kaneo && cd ~/containers/kaneo
You’ll end up with two files in here: compose.yml and .env.
compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# compose.yml
services:
postgres:
image: postgres:16-alpine
env_file:
- .env
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U kaneo -d kaneo"]
interval: 10s
timeout: 5s
retries: 5
kaneo:
image: ghcr.io/usekaneo/kaneo:latest
ports:
- "5173:5173"
env_file:
- .env
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
volumes:
postgres_data:
.env
Generate a secret first:
1
openssl rand -hex 32
Then create the .env file, replacing the placeholders:
1
2
3
4
5
6
# .env
KANEO_CLIENT_URL=http://YOUR_HOSTNAME_OR_IP:5173
POSTGRES_USER=kaneo
POSTGRES_DB=kaneo
POSTGRES_PASSWORD=yourpasswordhere
AUTH_SECRET=paste-openssl-output-here
Warning:
KANEO_CLIENT_URLmust match the hostname or IP you use to access Kaneo from other machines on your LAN. Setting it tolocalhostwill cause the frontend to fail for any device that isn’t the Pi itself — the value gets baked into the built frontend at container startup.
For example, if your Pi is reachable at hermes on your network:
1
KANEO_CLIENT_URL=http://hermes:5173
Tip: Docker commands on a Pi typically require
sudounless your user has been added to thedockergroup (sudo usermod -aG docker $USER).
Why POSTGRES_USER and POSTGRES_DB matter
The Kaneo container expects to connect as a kaneo database user. The default postgres:16-alpine image only creates the postgres superuser unless you explicitly set POSTGRES_USER. Without these two variables, the Kaneo container will crash on startup with role "kaneo" does not exist and restart-loop indefinitely.
| Variable | Purpose |
|---|---|
POSTGRES_USER |
Creates this role on first init |
POSTGRES_DB |
Creates a database owned by that role |
POSTGRES_PASSWORD |
Sets the password for that role |
KANEO_CLIENT_URL |
Baked into the frontend — must be your LAN address |
AUTH_SECRET |
Signs auth tokens — generate with openssl rand -hex 32 |
Start it up
1
sudo docker compose up -d
Docker will pull both images (this may take a few minutes on a Pi) and start the stack. Postgres initialises first, passes its healthcheck, then Kaneo starts.
Watch the logs to confirm it’s healthy:
1
sudo docker compose logs -f
You should see Kaneo complete its environment variable replacement and database migration without errors. Once you see the API ready message, open a browser on any machine on your LAN:
1
http://YOUR_HOSTNAME_OR_IP:5173
Managing the stack
| Command | What it does |
|---|---|
sudo docker compose up -d |
Start in background |
sudo docker compose down |
Stop containers (data preserved) |
sudo docker compose down -v |
Stop and wipe the database volume |
sudo docker compose logs -f |
Tail live logs |
sudo docker compose pull |
Pull latest images |
sudo docker compose up -d --force-recreate |
Restart with latest pulled images |
Re-initialising from scratch
If you need to start fresh (e.g. you changed POSTGRES_USER after a first run), you must wipe the volume so postgres re-initialises with the new credentials:
1
2
sudo docker compose down -v
sudo docker compose up -d
The -v flag removes the named postgres_data volume. This deletes all data — only use it when you want a clean slate.
