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 | sh

2. 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" >> .env

APP_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.

Where the data is. The named volume 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.
NextRender