Docker
Run the backend in a container.
The backend publishes a multi-arch Docker image at ghcr.io/cookiepal/backend. The image runs as the non-root node user and exposes port 8080.
Pull
docker pull ghcr.io/cookiepal/backend:latest
# or pin a specific version
docker pull ghcr.io/cookiepal/backend:1.0.0Tags: latest tracks the most recent stable release; every release also lands under its X.Y.Z tag. Use X.Y.Z in production.
Run
docker run -d \
--name cookiepal-backend \
-p 8080:8080 \
-e SITE=https://example.com \
-e ORIGINS=https://example.com,https://www.example.com \
-e DATABASE_URL=postgres://user:pass@db-host:5432/cookiepal \
ghcr.io/cookiepal/backend:latestAll configuration is via environment variables — see Configuration for the full list.
docker-compose
The repo ships a docker-compose.yml in packages/backend/ that bundles the backend with a Postgres 16 container:
services:
backend:
image: ghcr.io/cookiepal/backend:latest
ports: ['8080:8080']
environment:
SITE: https://example.com
ORIGINS: https://example.com
DATABASE_URL: postgres://cookiepal:cookiepal@db:5432/cookiepal
depends_on: [db]
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: cookiepal
POSTGRES_PASSWORD: cookiepal
POSTGRES_DB: cookiepal
volumes:
- cookiepal-pg:/var/lib/postgresql/data
volumes:
cookiepal-pg:cd packages/backend && docker compose up -dCORS is exact-match
ORIGINS values are compared verbatim against the Origin request header. No wildcards, no regex, no subdomain matching. List every domain your banner loads from explicitly:
ORIGINS=https://example.com,https://www.example.com,https://staging.example.comhttp:// vs https:// and trailing-slash differences will fail the match.
Deploying to a managed platform
Railway
- New project → Deploy from GitHub → select
cookiepal/cookiepal-oss. - Root Directory blank; Dockerfile Path
packages/backend/Dockerfile. - Add a Postgres plugin — Railway wires
DATABASE_URLinto the service. - Set
SITEandORIGINSenv vars. - Deploy. Railway issues a public HTTPS URL; use it as
backendURLin the banner config.
Fly.io
fly launch --dockerfile packages/backend/Dockerfile --no-deploy
fly postgres create --name cookiepal-db
fly postgres attach cookiepal-db # sets DATABASE_URL
fly secrets set SITE=https://yoursite.com ORIGINS=https://yoursite.com
fly deployYour own VPS
Any box with Docker and a reachable Postgres. Put Caddy or nginx in front for TLS.
Port mapping
The image listens on 8080 inside. Map it to whatever you want outside (-p 443:8080 behind a TLS-terminating proxy is common). Set PORT only if you need to change the in-container port.