Docker Compose
Run Probo and its dependencies on a single host with Docker Compose
The Probo repository includes a Compose definition that runs Probo, PostgreSQL, SeaweedFS, and headless Chrome on one host. Use it for evaluation, internal deployments, or small installations where a single-host failure is acceptable.
For workloads that require independent scaling, managed data services, or rolling updates, use the Kubernetes deployment.
Requirements
Section titled “Requirements”- A Linux host with Docker Engine and Docker Compose v2
- A DNS record for the hostname you will use
- A TLS-terminating reverse proxy or load balancer
- An SMTP relay if you want Probo to send email
- Enough memory for Probo and its dependencies; the supplied PostgreSQL configuration alone requests 4 GB of shared buffers
Install Probo
Section titled “Install Probo”-
Clone the repository
Terminal window git clone https://github.com/getprobo/probo.gitcd proboKeep
compose.prod.yamland thecompose/directory together. The Compose definition mounts the PostgreSQL initialization script and SeaweedFS configuration from that directory. -
Generate application secrets
Terminal window umask 077openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \-out oauth2-signing-key.pemexport PROBOD_ENCRYPTION_KEY="$(openssl rand -base64 32)"export PROBOD_AUTH_COOKIE_SECRET="$(openssl rand -base64 32)"export PROBOD_AUTH_PASSWORD_PEPPER="$(openssl rand -base64 32)"export PROBOD_TRUST_AUTH_TOKEN_SECRET="$(openssl rand -base64 32)"Preserve these values. Changing encryption, signing, or authentication secrets after users and data exist can invalidate sessions or make stored data inaccessible.
-
Create the environment file
Replace
probo.example.comand the SMTP values, then run:Terminal window cat > .env <<EOFPROBOD_ENCRYPTION_KEY=${PROBOD_ENCRYPTION_KEY}PROBOD_AUTH_COOKIE_SECRET=${PROBOD_AUTH_COOKIE_SECRET}PROBOD_AUTH_PASSWORD_PEPPER=${PROBOD_AUTH_PASSWORD_PEPPER}PROBOD_TRUST_AUTH_TOKEN_SECRET=${PROBOD_TRUST_AUTH_TOKEN_SECRET}PROBOD_BASE_URL=https://probo.example.comPROBOD_API_ADDR=0.0.0.0:8080PROBOD_API_CORS_ALLOWED_ORIGINS=https://probo.example.comPROBOD_SMTP_ADDR=smtp.example.com:587PROBOD_SMTP_USER=replace-with-smtp-userPROBOD_SMTP_PASSWORD=replace-with-smtp-passwordPROBOD_SMTP_TLS_REQUIRED=truePROBOD_MAILER_SENDER_EMAIL=no-reply@example.comEOFTerminal window chmod 600 .env oauth2-signing-key.pem -
Add the required OAuth signing key
The current
compose.prod.yamldoes not pass the OAuth signing key to Probo. Createcompose.local.yaml:services:probo:environment:PROBOD_OAUTH2_SERVER_SIGNING_KEY: ${PROBOD_OAUTH2_SERVER_SIGNING_KEY}PROBOD_SMTP_ADDR: ${PROBOD_SMTP_ADDR}PROBOD_SMTP_USER: ${PROBOD_SMTP_USER}PROBOD_SMTP_PASSWORD: ${PROBOD_SMTP_PASSWORD}PROBOD_SMTP_TLS_REQUIRED: ${PROBOD_SMTP_TLS_REQUIRED}PROBOD_MAILER_SENDER_EMAIL: ${PROBOD_MAILER_SENDER_EMAIL}Export the key before every Compose command:
Terminal window export PROBOD_OAUTH2_SERVER_SIGNING_KEY="$(cat oauth2-signing-key.pem)" -
Review the rendered configuration
Terminal window docker compose \-f compose.prod.yaml \-f compose.local.yaml \configDo not continue if a required value is empty. The rendered output contains secrets, so do not save or share it.
-
Start the services
Terminal window docker compose \-f compose.prod.yaml \-f compose.local.yaml \up -d -
Verify startup
Terminal window docker compose \-f compose.prod.yaml \-f compose.local.yaml \psdocker compose \-f compose.prod.yaml \-f compose.local.yaml \logs --tail=100 probocurl --fail http://127.0.0.1:8080/A successful HTTP response and a running
proboservice confirm that the application is reachable. Also test sign-in, file upload, and email delivery before inviting users.
Put Probo behind HTTPS
Section titled “Put Probo behind HTTPS”Terminate TLS at a reverse proxy or load balancer and forward requests to port 8080. Preserve the original Host, X-Forwarded-For, and X-Forwarded-Proto headers.
The supplied Compose definition publishes Probo, PostgreSQL, SeaweedFS, and Chrome ports on every host interface. Before making the server public:
- restrict inbound traffic with the host or cloud firewall;
- expose only ports
80and443through the reverse proxy; - prevent external access to ports
5432,8080,8081,8333,8443,9222, and9333; - replace the bundled PostgreSQL and SeaweedFS credentials, or use external managed services;
- pin the Probo image to a tested release instead of
latest.
Mounting a certificate into the Probo container does not configure TLS by itself.
Data and backups
Section titled “Data and backups”The deployment stores state in three named volumes:
probo-datafor local Probo data;postgres-datafor PostgreSQL;seaweedfs-datafor object storage.
Back up PostgreSQL and SeaweedFS as one recovery point. A database dump without its corresponding objects can leave document records whose files cannot be restored.
Create a database dump with:
docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ exec -T postgres \ pg_dump -U postgres -d probod --format=custom > probod.dumpUse a volume-aware backup tool or a storage snapshot for SeaweedFS. Stop writes while taking an offline volume backup, and test restoration on another host. Copy .env, oauth2-signing-key.pem, and any proxy configuration into your encrypted backup system separately.
Upgrade
Section titled “Upgrade”Read the release notes and take a tested backup first. Then pull and recreate the containers:
export PROBOD_OAUTH2_SERVER_SIGNING_KEY="$(cat oauth2-signing-key.pem)"
docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ pull
docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ up -dCheck the Probo logs and repeat the functional checks used during installation. Database migrations run when Probo starts; do not interrupt startup while a migration is running.
Troubleshooting
Section titled “Troubleshooting”Probo exits during startup
Section titled “Probo exits during startup”docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ logs --tail=200 proboIf the logs report a missing PROBOD_OAUTH2_SERVER_SIGNING_KEY, confirm that the key is exported in the current shell and that both Compose files are included in the command.
PostgreSQL is unhealthy
Section titled “PostgreSQL is unhealthy”docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ logs --tail=200 postgres
docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ exec postgres pg_isready -U postgres -d probodThe supplied PostgreSQL settings require considerably more than 4 GB of total host memory. If PostgreSQL is killed by the kernel, increase host memory or review its configuration before reducing limits.
Uploads or PDF generation fail
Section titled “Uploads or PDF generation fail”Inspect the Probo, SeaweedFS, and Chrome logs:
docker compose \ -f compose.prod.yaml \ -f compose.local.yaml \ logs --tail=200 probo seaweedfs chromeSee the environment variable reference when adding optional integrations or changing runtime behavior.