Docker Compose on any VPS
Hetzner, DigitalOcean, Vultr, a box in your office. If it runs Docker, this is the guide.
1. Install Docker
On a fresh Ubuntu or Debian server:
curl -fsSL https://get.docker.com | sh2. Create the compose file
Make a folder, and put this in docker-compose.yml:
services:
piqo:
image: ghcr.io/mddanishyusuf/piqo-selfhost:0
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- piqo-data:/app/data
environment:
AUTH_SECRET: ${AUTH_SECRET}
APP_URL: ${APP_URL}
PIQO_LICENSE_KEY: ${PIQO_LICENSE_KEY:-}
MAXMIND_LICENSE_KEY: ${MAXMIND_LICENSE_KEY:-}
SMTP_URL: ${SMTP_URL:-}
EMAIL_FROM: ${EMAIL_FROM:-}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/api/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
volumes:
piqo-data:3. Set the two required variables
Next to it, a .env file:
echo "AUTH_SECRET=$(openssl rand -base64 48)" > .env
echo "APP_URL=https://analytics.example.com" >> .env
echo "PIQO_LICENSE_KEY=PIQOSH-XXXXX-XXXXX-XXXXX-XXXXX" >> .envAPP_URL must be the public HTTPS address people will reach the install at. Its hostname is what the license registers.
4. Start it
docker compose up -d
docker compose logs -f piqo # wait for "[piqo] ready on http://0.0.0.0:3000"5. Put HTTPS in front
The container speaks plain HTTP on port 3000. Terminate TLS with any reverse proxy. Caddy is the least work because it fetches certificates itself. Install it, then in /etc/caddy/Caddyfile:
analytics.example.com {
reverse_proxy localhost:3000
}Point the DNS A record at the server, reload Caddy, and open the URL. Caddy forwards the client IP, which the collector uses for country lookups. Nginx works the same way with proxy_pass and the usualX-Forwarded-For header.
6. Finish in the app
Create the owner account on /setup. If you set PIQO_LICENSE_KEY you go straight to the dashboard; otherwise paste the key on /activate. Add a site and drop the script tag on your pages.
piqo-data holds the SQLite database, nightly backups and the optional GeoLite2 file. docker compose down keeps it; only docker compose down -v deletes it. See Updates & backups.