Use Docker Compose
This guide explains how to run the PERSEUS platform using Docker Compose. A Podman workflow is included below.
Prerequisites
Section titled “Prerequisites”Docker Engine and Docker-Compose v2 or Podman (see Podman section).
A .env file next to your Compose file with the required PERSEUS settings (database, secrets, etc.).
Create a folder backup next to your docker-compose.yml file. This folder will be mounted into the perseus-core container and holds the daily backups of all PERSEUS data. Read more about this mechanism in the documentation.
You can change the path to the mounted backup directory in the docker-compose.yml.
Optional local folders for custom content:
./custom-services→ mounted into the core container./custom-states→ mounted into the core container
Docker Compose file
Section titled “Docker Compose file”Create docker-compose.yml with the following content (identical to what we ship, with inline comments). If you run Podman on SELinux systems (e.g., Fedora), add :Z to bind mounts (see the Podman tips below).
services: perseus-core: image: docker.io/pc2upb/perseus-core:latest pull_policy: always ports: - "8000:8000" # Core listens on 8000 inside the container networks: - database_network volumes: - core-rsa:/home/perseus/perseus/security/keys - ./backups:/home/perseus/perseus/backups - ./custom-services:/home/perseus/perseus/services/custom - ./custom-states:/home/perseus/perseus/states/custom env_file: - .env restart: unless-stopped
perseus-frontend: image: docker.io/pc2upb/perseus-frontend:latest pull_policy: always ports: - "8001:80" # Frontend is served on port 80 inside the container environment: - CORE_URL=<HOST>/api # Replace <HOST> with your host, i.e. https://perseus.pc2.uni-paderborn.de restart: unless-stopped
mongodb: image: docker.io/library/mongo:latest networks: - database_network volumes: - mongodb-data:/mongodb restart: unless-stopped
networks: database_network:
volumes: core-rsa: mongodb-data:Start with Docker-Compose
Section titled “Start with Docker-Compose”# 1) Pull images (optional; docker compose will pull on demand)docker compose pull
# 2) Start in the backgrounddocker compose up -d
# 3) Check logs (useful during first start)docker compose logs -f perseus-coredocker compose logs -f perseus-frontendVerify locally (without a proxy)
Section titled “Verify locally (without a proxy)”- Core: http://localhost:8000
- Frontend: http://localhost:8001 (Make sure CORE_URL points to your public BASEURL/api once you add a proxy)
Update to latest images
Section titled “Update to latest images”docker compose pulldocker compose up -ddocker compose downAdd a reverse proxy (example snippets)
Section titled “Add a reverse proxy (example snippets)”You can use any reverse proxy. Below are minimal configs that route BASEURL/ → frontend and BASEURL/api → core.
Nginx (example)
Section titled “Nginx (example)”server { listen 80; server_name perseus.example.org;
# If you terminate TLS elsewhere, keep this on 80; otherwise use 'listen 443 ssl' and add certs.
location / { proxy_pass http://127.0.0.1:8001/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; }
location /api/ { proxy_pass http://127.0.0.1:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; }}Caddy (example)
Section titled “Caddy (example)”perseus.example.org { route /api* { uri strip_prefix /api reverse_proxy 127.0.0.1:8000 } reverse_proxy 127.0.0.1:8001}Running with Podman
Section titled “Running with Podman”You have two main options:
Option A — podman-compose (Compose-compatible)
Section titled “Option A — podman-compose (Compose-compatible)”If you prefer to keep using the same docker-compose.yml:
# Install podman-compose (package name may vary by distro)sudo dnf install podman-compose # Fedora# orsudo apt-get install podman-compose # Debian/Ubuntu (may require pipx/pip if not packaged)
# Startpodman-compose up -d
# Logspodman-compose logs -f perseus-corepodman-compose logs -f perseus-frontend
# Stoppodman-compose downSELinux tip (Fedora/RHEL): For bind mounts like ./custom-services:… add :Z to the end so Podman can relabel the content.
Option B — Native Podman + systemd (advanced)
Section titled “Option B — Native Podman + systemd (advanced)”You can convert a running container set into systemd units for auto‑start:
# Start once with podman-compose up -d (or podman run ... per service)# Then generate systemd units:podman generate systemd --name --files --new --restart-policy=always perseus-corepodman generate systemd --name --files --new --restart-policy=always perseus-frontendpodman generate systemd --name --files --new --restart-policy=always mongodb
# Copy units to your user systemd dir and enable themmkdir -p ~/.config/systemd/usercp *.service ~/.config/systemd/user/systemctl --user daemon-reloadsystemctl --user enable --now container-perseus-core.service container-perseus-frontend.service container-mongodb.serviceCommon pitfalls & tips
Section titled “Common pitfalls & tips”- CORE_URL mismatch: Ensure the frontend CORE_URL exactly matches your public API route (including /api), otherwise the browser will call the wrong origin.
- CORS: Using a reverse proxy with BASEURL/ and BASEURL/api keeps everything on the same origin and avoids most CORS issues.
- Firewall: Open inbound 80/443 on your host if you expect external access.
- Updating images: Always pull and then up -d to apply new versions without losing volumes.
- Backups: Backup the named volumes mongodb-data and core-rsa regularly. PERSEUS also creates daily backups of all data.