Skip to content

Self host with Coolify

Alien edited this page Oct 18, 2026 · 1 revision

Run Dossier on a Coolify server from a Compose file made for Coolify: the app and PostgreSQL in one resource. Coolify generates the database password and DOSSIER_SECRET, and its proxy serves Dossier over HTTPS. These steps are for Coolify 4.4.

Why not the README's Compose file? Coolify reads ${VAR:?message} as a default value, so the database password would be the message itself, and the file's ports entry would skip Coolify's proxy. The file below avoids both.

What you need

  • A Coolify server. To start one, see Coolify's installation guide.
  • 4 GB of memory is safer: Coolify itself needs 2 GB, and Dossier about 1 GB. The server needs an Intel or AMD processor (x86-64), since the image isn't built for ARM. A local model needs much more: see Get a VPS in the README.
  • A domain name, such as dossier.example.com, with a DNS A record pointing at the server.

1. Create the resource

In your project and environment, choose New resource → Docker Compose (the one without a Git repository). Paste this as the Docker Compose file, then press Create service:

services:
  db:
    image: postgres:18-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: dossier
      POSTGRES_PASSWORD: ${SERVICE_PASSWORD_POSTGRES}
      POSTGRES_DB: dossier
    volumes:
      - pgdata:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dossier -d dossier"]
      interval: 5s
      timeout: 5s
      retries: 10

  app:
    image: ghcr.io/aientech/dossier:latest
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      DATABASE_URL: postgresql://dossier:${SERVICE_PASSWORD_POSTGRES}@db:5432/dossier
      DOSSIER_SECRET: ${SERVICE_PASSWORD_64_SECRET}
      DOSSIER_PASSWORD: ${DOSSIER_PASSWORD:?}
      TZ: ${TZ:-}
      DOSSIER_BACKUP_RETENTION_DAYS: ${DOSSIER_BACKUP_RETENTION_DAYS:-}
      DOSSIER_TELEMETRY: ${DOSSIER_TELEMETRY:-}
      DOSSIER_AI_PROVIDER: ${DOSSIER_AI_PROVIDER:-}
      DOSSIER_AI_URL: ${DOSSIER_AI_URL:-}
      DOSSIER_AI_MODEL: ${DOSSIER_AI_MODEL:-}
      DOSSIER_AI_KEY: ${DOSSIER_AI_KEY:-}
      DOSSIER_AI_TIMEOUT_SECONDS: ${DOSSIER_AI_TIMEOUT_SECONDS:-}
      DOSSIER_JOBS_SOURCE: ${DOSSIER_JOBS_SOURCE:-}
      DOSSIER_JSEARCH_KEY: ${DOSSIER_JSEARCH_KEY:-}
      DOSSIER_JSEARCH_HOST: ${DOSSIER_JSEARCH_HOST:-}
      DOSSIER_ADZUNA_APP_ID: ${DOSSIER_ADZUNA_APP_ID:-}
      DOSSIER_ADZUNA_KEY: ${DOSSIER_ADZUNA_KEY:-}
      DOSSIER_GOOGLE_CLIENT_ID: ${DOSSIER_GOOGLE_CLIENT_ID:-}
      DOSSIER_GOOGLE_CLIENT_SECRET: ${DOSSIER_GOOGLE_CLIENT_SECRET:-}
      DOSSIER_PUBLIC_URL: ${DOSSIER_PUBLIC_URL:-}
    volumes:
      - data:/data
    # Room for Chromium, which prints the PDFs.
    mem_limit: 1g
    # Lets http://host.docker.internal:11434 reach an Ollama on the server.
    extra_hosts:
      - "host.docker.internal:host-gateway"

volumes:
  pgdata:
  data:

Coolify fills in SERVICE_PASSWORD_POSTGRES and SERVICE_PASSWORD_64_SECRET with random values and keeps them across deploys.

2. Set your password

Dossier takes a hash of the password you'll sign in with, never the password itself. On the server, or anywhere with Docker, run this and type your password twice:

docker run --rm -it ghcr.io/aientech/dossier hash-password

It prints one line that starts with argon2id:. In the resource's Environment Variables, set DOSSIER_PASSWORD to it; Coolify won't deploy while it's empty. While you're there, set TZ to your time zone, such as Europe/Berlin.

Every other variable is listed there too, empty until you need it. What each one does: Environment variables in the README. SERVICE_PASSWORD_64_SECRET is DOSSIER_SECRET: read its row there before you change it.

3. Add the domain

In Domains, press Add domain, pick the app service, choose https, enter your domain and port 3000, and save. Coolify's proxy gets a certificate for it once the DNS record points at the server.

The proxy sets the headers Dossier relies on (X-Forwarded-Proto, and the visitor's address added to X-Forwarded-For), so don't add a ports entry to the Compose file: requests that skip the proxy could set those headers themselves.

4. Deploy

Press Deploy. Coolify pulls the images, starts the database, waits until it's ready, then starts Dossier. On every start, Dossier applies the database migrations and loads its built-in themes before it serves; Runtime Logs shows each step.

Open your domain and sign in. Then pick an AI model in Settings → AI provider (see Choosing an AI provider) and, if you like, a job source in Settings → Job search (see Choosing a job source).

Optional: Ollama for a local model

With a local model, your profile and documents never leave your server. To run Ollama in the same resource, press Edit Compose file in General, add this service under services: and ollama: under volumes:, then save and deploy again:

  ollama:
    image: ollama/ollama:0.34.4
    restart: unless-stopped
    volumes:
      - ollama:/root/.ollama

Give it no domain. Then open Terminal, pick the ollama container and pull a model:

ollama pull qwen2.5:7b

In Dossier, open Settings → AI provider → Local model, set the server address to http://ollama:11434, pick the model and press Test connection. Which model to pick, and how fast it is: Local model with Ollama.

Day to day

  • Change a setting: edit it in Environment Variables, then press Restart.

  • Upgrade: take an export and a database dump first (see Back up), then choose Pull latest and restart from the Restart menu. To pin a version instead, change latest in the Compose file to it, such as v1.6.0, and change it again for each upgrade. Coolify stops the old containers before it starts the new ones, so Dossier is away for a moment; if a migration fails, it stays away until you restore the dump. See Upgrading.

  • Back up: export from Settings → Your data, and take database dumps. On the server, docker ps --format '{{.Names}}' lists the containers: Dossier's name starts with app-, the database's with db-. Then:

    docker exec <the database's container> pg_dump -U dossier -Fc dossier > dossier.dump
    docker cp <Dossier's container>:/data/backups ./backups

    To restore a dump, stop Dossier, load the dump, and start Dossier again:

    docker stop <Dossier's container>
    docker exec -i <the database's container> pg_restore --clean --if-exists -U dossier -d dossier < dossier.dump
    docker start <Dossier's container>

    More in Backups and restore.

  • Something's wrong: Runtime Logs, and Troubleshooting.

Clone this wiki locally