Deploy
Deploy Keenpix with Docker and verify the stateful parts.
Keenpix deploys as four focused Node applications plus Postgres and Dragonfly. The
default Compose file exposes the control plane on port 3000 and the standalone docs
site on 3003; the transform and worker services remain private on the Compose network.
Weighing self-host against the hosted option? See self-hosted vs managed image optimization.
Deploy a pinned release
git clone --branch v0.3.0 --depth 1 https://github.com/lord007tn/keenpix.git
cd keenpix
cp .env.example .env
# keep every service on the release you just checked out:
echo 'KEENPIX_APP_IMAGE=ghcr.io/lord007tn/keenpix-app:v0.3.0' >> .env
echo 'KEENPIX_TRANSFORM_IMAGE=ghcr.io/lord007tn/keenpix-transform:v0.3.0' >> .env
echo 'KEENPIX_WORKER_IMAGE=ghcr.io/lord007tn/keenpix-worker:v0.3.0' >> .env
echo 'KEENPIX_DOCS_IMAGE=ghcr.io/lord007tn/keenpix-docs:v0.3.0' >> .env
# set a strong secret:
# BETTER_AUTH_SECRET=$(openssl rand -hex 32)
# set POSTGRES_PASSWORD, KEENPIX_SUPER_ADMIN_EMAIL, and KEENPIX_SUPER_ADMIN_PASSWORD
docker compose pull
docker compose up -d
# dashboard → http://localhost:3000
# docs → http://localhost:3003docker-compose.yml ships the app, transform data plane, BullMQ worker with Workbench,
docs, Postgres, and Dragonfly. On boot the app runs prisma migrate deploy, optionally
seeds the default organization and super admin, then starts as a non-root user.
Check the release page before changing the four image variables; keeping explicit tags prevents a later pull from replacing only part of the running release.
After deploy
- Sign in as
KEENPIX_SUPER_ADMIN_EMAILwithKEENPIX_SUPER_ADMIN_PASSWORD. - Create a project pointed at your image origin.
- Add your source host under Settings → Security → Allowed hosts.
- Invite operators from the Admin console → Staff (
/admin/staff) and copy the invitation link. Transactional email is configured entirely through the environment (EMAIL_PROVIDER+ its provider vars) — there is no in-app email screen, and those env values are the only source. With email configured, the invite is also sent automatically. - Request
/img/https://your-origin.example/photo.jpg?project=ID&w=1200&fmt=webp— no API key required for transform URLs.
Architecture
Browser/CDN ──▶ app:3000 ──▶ transform:3002 ──▶ customer origin
│ │
│ └── memory + disk cache volume
├── Postgres
└── Dragonfly ──▶ worker:3001
Operator ──▶ docs:3003Scale the transform and worker independently. For multiple transform replicas, configure
a shared S3-compatible cache such as R2 or MaxIO. See
Docker Compose,
Coolify,
CDN setup for Cloudflare, Nginx, and Caddy caching rules,
Deployment presets for ready-made .env files, and
Configuration for every environment variable.