Deployment
PicFast provides several deployment paths. For most users, Docker Compose with a reverse proxy is the best balance of simplicity and production readiness.
Docker Compose (recommended)
Download the compose file and environment template, no cloning needed:
mkdir picfast && cd picfast
wget https://raw.githubusercontent.com/atbeta/picfast/main/docker/docker-compose.yml
wget https://raw.githubusercontent.com/atbeta/picfast/main/docker/.env.example -O .env Edit .env with your domain, secrets, and configuration, then:
docker compose up -d The compose file includes PostgreSQL 16 and PicFast. By default PicFast binds to 127.0.0.1:18080 — put a reverse proxy (Nginx, Caddy, NPM) in front for HTTPS. Set PICFAST_HTTP_BIND=0.0.0.0 in .env to bind to all interfaces.
On first startup, open your site and follow the setup wizard. Set PICFAST_APP_ADMIN_EMAIL and PICFAST_APP_ADMIN_PASSWORD in .env to auto-create the admin and skip the wizard.
Data is stored under the current directory:
- Postgres:
./data/postgres - Uploads:
./data/uploads - Thumbnails:
./data/thumbnails
Traefik (auto-SSL)
If you already run a Traefik instance with pre-configured TLS certificates, use this variant:
mkdir picfast && cd picfast
wget https://raw.githubusercontent.com/atbeta/picfast/main/docker/docker-compose.traefik.yml
wget https://raw.githubusercontent.com/atbeta/picfast/main/docker/.env.traefik.example -O .env
vim .env # set domain, database password, JWT secret
docker compose -f docker-compose.traefik.yml up -d Make sure TRAEFIK_DOCKER_NETWORK in .env matches your Traefik's network.
Docker Hub image (docker run)
Prebuilt images are on Docker Hub. Useful for quick testing or custom setups:
docker network create picfast-net
docker run -d --name picfast-db --network picfast-net \
-e POSTGRES_PASSWORD=devonly \
-v picfast-pgdata:/var/lib/postgresql/data \
postgres:16-alpine
docker run -d --name picfast --network picfast-net -p 18080:8080 \
-e PICFAST_DATABASE_URL='postgres://postgres:devonly@picfast-db:5432/postgres?sslmode=disable' \
-e PICFAST_JWT_SECRET='change-me-in-production' \
-e PICFAST_SERVER_BASE_URL='http://localhost:18080' \
-v picfast-uploads:/app/data/uploads \
-v picfast-thumbnails:/app/data/thumbnails \
xbeta/picfast:latest See Docker Hub for available tags.
Pre-flight checklist
- JWT secret: set to a strong random value (
openssl rand -hex 32) - Server base URL: your actual HTTPS domain
- Admin credentials: set for headless deployments, or use the setup wizard
- Database password: don't use example values in production
- Reverse proxy passes
HostandX-Forwarded-Protoheaders - Upload size limits in reverse proxy match your needs (default 50 MB per file)
Environment variables
All configuration can be set via PICFAST_ prefixed environment variables (they take precedence over config.yaml). See Configuration for the full reference.
PICFAST_SERVER_PORT=8080
PICFAST_SERVER_BASE_URL=https://picfast.example.com
PICFAST_JWT_SECRET=your-strong-secret
PICFAST_DATABASE_URL=postgres://picfast:picfast@localhost:5432/picfast?sslmode=disable
PICFAST_STORAGE_LOCAL_ROOT=./data/uploads
PICFAST_STORAGE_THUMBNAIL_DIR=./data/thumbnails Reverse proxy
Nginx
server {
listen 443 ssl;
server_name picfast.example.com;
ssl_certificate /etc/ssl/certs/pics.crt;
ssl_certificate_key /etc/ssl/private/pics.key;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:18080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
} Caddy
picfast.example.com {
reverse_proxy 127.0.0.1:18080
request_body {
max_size 100MB
}
} Observability (Prometheus)
PicFast exposes Prometheus metrics on a dedicated internal port (:9190). In Docker Compose, this port is not published to the host — Prometheus scrapes it within the Docker network:
scrape_configs:
- job_name: picfast
metrics_path: /metrics
static_configs:
- targets: ["app:9190"] The /health endpoint returns 200 when the database and storage are reachable. Metrics include HTTP request counts, upload throughput, database pool stats, and business counters (storage usage, cleanup, auth, and moderation).
Backup & maintenance
For full-instance archives (database + optional objects), checksum verification, restore preflight, and consistency checks, use the built‑in picfast maintenance CLI — see Backup & Maintenance.
Quick SQL‑only dump from Postgres (example; container and DB names vary):
docker exec picfast-db pg_dump -U picfast picfast > backup.sql Updating
docker compose pull
docker compose up -d Migrations run automatically on startup.
Serverless & PaaS
Render, Fly.io, Railway, Koyeb and Zeabur give you a single container with an ephemeral disk and no host access. Since 0.26 PicFast ships a slim image for these platforms — pure Go, no libvips, about 13 MB compressed, and much faster cold starts.
Before the first upload you need external PostgreSQL, S3-compatible object storage and an external job trigger. The full guide — Render one-click deploy, per-platform commands, image limitations, free-tier notes and troubleshooting — is on Serverless & Container PaaS.
Home network & NAS
For Synology, QNAP, TrueNAS, Unraid, or Raspberry Pi — with Cloudflare/Tailscale/FRP tunnels — see Home Network & NAS.