Skip to main content
Version: Next

Docker & Compose

Run Openbeehive as a single container for a self-host setup, or bring up the full cloud stack (Postgres and MinIO) with Docker Compose.

The image is published to the GitHub Container Registry on every release tag:

ghcr.io/openbeehive-org/openbeehive-app:latest # newest release
ghcr.io/openbeehive-org/openbeehive-app:X.Y.Z # a specific release
ghcr.io/openbeehive-org/openbeehive-app:X.Y # newest patch of a minor release

The same image serves both deployment profiles; the environment you pass in decides which one you get. Since 0.4.0 the container runs as the unprivileged user 65532 with /data as its working directory.

Verifying a release image​

Every release image is signed with cosign (keyless, bound to the release workflow's identity), carries a GitHub build-provenance attestation and ships an SBOM on the GitHub release. To check that the image you pull is the one the release workflow built:

cosign verify ghcr.io/openbeehive-org/openbeehive-app:X.Y.Z \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/openbeehive-org/openbeehive-app/\.github/workflows/release\.yml@.*'

gh attestation verify oci://ghcr.io/openbeehive-org/openbeehive-app:X.Y.Z --owner openbeehive-org

Both commands print the signing identity and the commit the image was built from. Images published before 0.4.0 are not signed.

tip

For a single-user instance on one machine the single binary is even simpler than Docker. Reach for Compose when you want Postgres and S3-style storage.

Run the single container​

One container with the selfhost profile keeps a SQLite database and the uploaded blobs on one mounted volume. Nothing else is required.

docker run -d \
--name openbeehive \
-p 8080:8080 \
-v openbeehive-data:/data \
-e BEEHIVE_DEPLOYMENT_PROFILE=selfhost \
-e BEEHIVE_PUBLIC_BASE_URL=https://bees.example.com \
-e 'BEEHIVE_DATABASE_DSN=file:/data/openbeehive.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)' \
-e BEEHIVE_BLOB_DIR=/data/blobs \
ghcr.io/openbeehive-org/openbeehive-app:latest
  • -p 8080:8080 maps the container's listen port (BEEHIVE_ADDR=:8080) to the host.
  • -v openbeehive-data:/data keeps your data on a named volume. Docker creates the volume with the ownership of /data in the image, so the unprivileged server user can write to it. If you bind-mount a host directory instead (-v /srv/openbeehive:/data), it must be owned by uid 65532: sudo chown -R 65532:65532 /srv/openbeehive.
  • The BEEHIVE_DATABASE_DSN and BEEHIVE_BLOB_DIR lines point the database and the uploaded photos at the volume explicitly. The defaults (openbeehive.db, ./data/blobs) are relative to the working directory, which is /data since 0.4.0, but spelling the paths out keeps the command unambiguous and matches the backup instructions.
  • BEEHIVE_PUBLIC_BASE_URL must be the address users reach, including scheme. The server uses it for OIDC redirect URLs and for invite and verification links.

With no login method enabled (the selfhost default) the instance runs in single-user mode. To add authentication, set BEEHIVE_SESSION_SECRET (generate it once with openssl rand -base64 32 and keep it stable; changing it signs everyone out) plus the variables for the method you want. Email/password login also needs BEEHIVE_ADMIN_EMAIL and BEEHIVE_ADMIN_PASSWORD, or the server refuses to start. See Authentication.

Using an env file​

docker run -d \
--name openbeehive \
-p 8080:8080 \
-v openbeehive-data:/data \
--env-file openbeehive.env \
ghcr.io/openbeehive-org/openbeehive-app:latest

The cloud profile with Compose​

The cloud profile pairs the server with PostgreSQL and MinIO. The repository's docker-compose.yml is a development stack: it builds the server from source and publishes the database and MinIO ports on the host.

git clone https://github.com/openbeehive-org/openbeehive-app.git
cd openbeehive-app
cp .env.example .env # then edit .env (see below)
docker compose up -d --build

The services​

ServiceImageRole
serverbuilt from the repository DockerfileBackend and web app on :8080
postgrespostgres:18-alpineDatabase; 5432 published on the host
miniominio/minio:latestS3-compatible blob storage; 9000 (API) and 9001 (console) published on the host

server depends on postgres and minio, so Compose starts them first.

What the compose file sets​

These values are hard-coded in docker-compose.yml and are not read from .env; change them by editing the file (and change the Postgres and MinIO credentials in the same place):

SettingValue in the compose file
BEEHIVE_DEPLOYMENT_PROFILEcloud
BEEHIVE_DATABASE_DSNpostgres://openbeehive:openbeehive@postgres:5432/openbeehive?sslmode=disable
BEEHIVE_MINIO_ENDPOINTminio:9000
BEEHIVE_MINIO_ACCESS_KEY / BEEHIVE_MINIO_SECRET_KEYminioadmin / minioadmin
BEEHIVE_OIDC_PROVIDERSgoogle

These come from your shell or .env:

# Required: the cloud profile enables password auth, which needs the instance admin.
# docker compose up fails immediately if either is missing.
BEEHIVE_ADMIN_EMAIL=you@example.com
BEEHIVE_ADMIN_PASSWORD=at-least-eight-characters

# Sessions; generate with: openssl rand -base64 32
BEEHIVE_SESSION_SECRET=

# Defaults to http://localhost:8080
BEEHIVE_PUBLIC_BASE_URL=https://bees.example.com

# Google is enabled as an OIDC provider in the compose file, so these are
# required too; without a client ID the server exits with
# "OIDC provider google: issuer/client id missing". Remove the BEEHIVE_OIDC_*
# lines from docker-compose.yml if you do not want Google sign-in.
BEEHIVE_OIDC_GOOGLE_CLIENT_ID=...
BEEHIVE_OIDC_GOOGLE_CLIENT_SECRET=...

:::note Service names are hostnames Inside the Compose network, containers reach each other by service name, which is why the DSN points at postgres and the MinIO endpoint at minio. :::

A production-shaped file​

docker-compose.demo.yml in the repository is the file behind the hosted instance: it uses the published image instead of building, publishes no database or MinIO ports, adds restart policies and healthchecks, takes every secret from .env, closes registration (invite-only) and enables the demo tenant. Its header comment lists the variables it needs. Use it as the starting point for your own production stack:

docker compose -f docker-compose.demo.yml up -d

For the full list of variables see Configuration.

Persisting your data​

  • Single container (selfhost): everything is under /data on the openbeehive-data volume, as long as the DSN and blob directory point there.
  • Cloud profile: records live in the pg volume (Postgres) and uploaded files in the minio volume. The server container is stateless and can be replaced freely.

:::danger Back up before you upgrade Named volumes survive docker compose up and image upgrades, but not docker compose down -v or a removed volume. Take a backup before any upgrade or destructive command. See Backups. :::

Common operations​

# Follow the server logs
docker compose logs -f server

# Rebuild from updated source and recreate (docker-compose.yml builds the image)
git pull && docker compose up -d --build

# Pull a newer published image and recreate (docker-compose.demo.yml or your own file)
docker compose -f docker-compose.demo.yml pull
docker compose -f docker-compose.demo.yml up -d

# Stop everything (volumes are kept)
docker compose down