Installation
Self-host omnipaper with Docker Compose.
Create the Compose file
Generate two secrets — run this twice, once for each:
openssl rand -base64 32Paste the values into docker-compose.yml:
services:
postgres:
image: postgres:18
restart: unless-stopped
environment:
POSTGRES_USER: omnipaper
POSTGRES_PASSWORD: pg-password-change-me
POSTGRES_DB: omnipaper
volumes:
- postgres-data:/var/lib/postgresql/data
app:
image: ghcr.io/omnipaper/omnipaper:0
restart: unless-stopped
depends_on:
- postgres
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://omnipaper:pg-password-change-me@postgres:5432/omnipaper
# Paste a separate `openssl rand -base64 32` value into each
AUTH_SECRET: replace-me
ENCRYPTION_KEY: replace-me
volumes:
postgres-data:Image tags
0— the latest pre-1.0 release (tracks the0.xline).0.x— the latest patch within the minor line.0.x.y— a specific, pinned version.
Pin a specific 0.x.y version (as in the file above). The rolling 0 and 0.x tags move
as new builds ship and may be unstable before 1.0.
Start it
docker compose up -dOpen http://localhost:3000 and create your first account. See First run
for what happens next.
Storage is not configured at deploy time. After your first login, connect an S3-compatible bucket (AWS S3, Cloudflare R2, MinIO, …) from the app's settings. See Storage.
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL | ✅ | — | PostgreSQL connection string. |
AUTH_SECRET | ✅ | — | Signs auth sessions and cookies. Use a random 32-byte value. |
ENCRYPTION_KEY | ✅ | — | See Environment variables. |
APP_URL | — | derived from request | Public URL of your instance. See Custom domain. |
PORT | — | 3000 | Port the app listens on inside the container. |
See Environment variables for the full reference.
Custom domain
omnipaper runs behind a reverse proxy (Caddy, Traefik, nginx, …) with no extra
configuration: when APP_URL is unset it derives its origin from the incoming request.
Just make sure your proxy forwards X-Forwarded-Host and X-Forwarded-Proto.
To pin the origin to a fixed value, add APP_URL to the app service's environment
services:
app:
environment:
DATABASE_URL: postgres://omnipaper:change-me@postgres:5432/omnipaper
AUTH_SECRET: replace-me
ENCRYPTION_KEY: replace-me
APP_URL: https://omnipaper.example.com # add this lineInclude the scheme (https://) and no trailing slash.
Terminate TLS at your reverse proxy and forward to the app's port 3000. omnipaper serves
plain HTTP inside the container.
Updating
docker compose pull
docker compose up -dMigrations run automatically on start, so pull-and-up is all that's needed.