Separate Containers Setup

For more control over your database — e.g. using an existing Postgres instance, custom tuning, or separate scaling — run PostgreSQL and heaper as separate containers.

This setup uses ghcr.io/janlunge/heaper-postgres:latest which includes the ULID extension required by heaper.

Docker Compose

services:
  postgres:
    image: ghcr.io/janlunge/heaper-postgres:latest
    platform: linux/amd64   # Required on ARM devices
    container_name: heaper-selfhost-postgres
    restart: unless-stopped
    environment:
      - POSTGRES_USER=heaper
      - POSTGRES_PASSWORD=change-me-please
      - POSTGRES_DB=heaper
    volumes:
      - ./heaper-data/postgres:/var/lib/postgresql/data
    # Uncomment to expose PostgreSQL externally:
    # ports:
    #   - "5432:5432"

  heaper:
    image: ghcr.io/janlunge/heaper:latest
    platform: linux/amd64   # Required on ARM devices
    container_name: heaper-selfhost
    restart: unless-stopped
    mem_limit: 4g
    memswap_limit: 4g
    depends_on:
      - postgres
    ports:
      - "3010:80"
    environment:
      - HOSTNAME=localhost
      - ENABLE_INTERNAL_POSTGRES=false
      - DB_HOST=postgres:5432
      - DB_USER=heaper
      - DB_PASS=change-me-please
      - DB_NAME=heaper
    volumes:
      - ./heaper-data/config:/usr/src/app/config
      - ./heaper-data/data:/usr/src/app/data
      - ./heaper-data/thumbnails:/mnt/thumbnails
      - ./heaper-data/storage:/mnt/storage
      - ./heaper-data/backups:/mnt/backups

Before first run: Change POSTGRES_PASSWORD and DB_PASS to the same secure password.

Start it:

docker-compose up -d

Access: http://localhost:3010

Docker Run

# Create network
docker network create heaper

# Run PostgreSQL
docker run -d --name heaper-selfhost-postgres --platform linux/amd64 \
  -e POSTGRES_USER=heaper \
  -e POSTGRES_PASSWORD=YOURPASSWORD \
  -e POSTGRES_DB=heaper \
  -p "5432:5432" \
  --volume /path/to/heaper/postgres:/var/lib/postgresql/data \
  --network heaper \
  ghcr.io/janlunge/heaper-postgres:latest

# Run Heaper
docker run -d --name heaper-selfhost --platform linux/amd64 \
  -p 3010:80 \
  -e HOSTNAME=your-domain.com \
  -e ENABLE_INTERNAL_POSTGRES=false \
  -e DB_HOST=heaper-selfhost-postgres:5432 \
  -e DB_USER=heaper \
  -e DB_PASS=YOURPASSWORD \
  -e DB_NAME=heaper \
  --volume /path/to/heaper/config:/usr/src/app/config \
  --volume /path/to/heaper/thumbnails:/mnt/thumbnails \
  --volume /path/to/heaper/storage:/mnt/storage \
  --network heaper \
  ghcr.io/janlunge/heaper:latest

Environment Variables

PostgreSQL Container

VariableDefaultDescription
POSTGRES_USERheaperPostgreSQL username
POSTGRES_PASSWORDPostgreSQL password
POSTGRES_DBheaperPostgreSQL database name

Heaper Container

VariableDefaultDescription
HOSTNAMElocalhostYour domain name
ENABLE_INTERNAL_POSTGRESfalseMust be false for this setup
DB_HOSTPostgres host and port (e.g. postgres:5432)
DB_USERPostgres username
DB_PASSPostgres password
DB_NAMEPostgres database name

Using an Existing PostgreSQL Instance

If you already have a PostgreSQL server, you can skip the postgres container entirely. Make sure your database has the ULID extension installed, then point the heaper container at your instance via the DB_* environment variables.

Next Steps