Skip to content
OpenPostDocs
OpenPostDocs

Self-host OpenPost

Run OpenPost on your own server with Docker Compose.

This guide runs one OpenPost container with SQLite and local media storage. It is the shortest path for a personal or small-team instance. OpenPost runs its web and background work in the same container, so you do not need a separate queue service.

Before you start

  • Install Docker with the Compose plugin. Run the commands below on the server that will host OpenPost.
  • The published image supports linux/amd64. Other architectures need amd64 emulation.
  • For a public instance, point a domain at the server and put an HTTPS reverse proxy in front of port 8080. Forward all app requests, including /api/v1/ and /media/. Provider callbacks and media URLs must be reachable from outside your network.

You can test locally first. Set the final public URLs before connecting social accounts.

Install with Docker Compose

Create the data directories first:

mkdir -p openpost/data/db openpost/data/media
cd openpost

Create .env with fresh secrets:

cat > .env <<EOF
OPENPOST_APP_URL=http://localhost:8080
OPENPOST_PUBLIC_URL=http://localhost:8080
OPENPOST_MEDIA_URL=http://localhost:8080/media
OPENPOST_JWT_SECRET=$(openssl rand -base64 32)
OPENPOST_ENCRYPTION_KEY=$(openssl rand -base64 32)
EOF
chmod 600 .env

For a public deployment, replace all three URLs with the real HTTPS origin before connecting providers. For example, set OPENPOST_APP_URL=https://post.example.com, OPENPOST_PUBLIC_URL=https://post.example.com, and OPENPOST_MEDIA_URL=https://post.example.com/media. Keep both generated secrets stable across restarts and restores.

Create docker-compose.yml:

services:
  openpost:
    image: ghcr.io/getopenpost/openpost:latest
    platform: linux/amd64
    container_name: openpost
    restart: unless-stopped
    env_file: .env
    ports:
      - "8080:8080"
    volumes:
      - ./data:/data
    environment:
      OPENPOST_PORT: 8080
      OPENPOST_DATABASE_PATH: /data/db/openpost.db
      OPENPOST_MEDIA_PATH: /data/media

The example uses latest. For production, replace it with a release tag from GitHub Releases and record that tag with your backups. Read upgrades and backups before changing it.

Start it and check readiness:

docker compose up -d
curl http://localhost:8080/api/v1/ready

The ready response should show "status":"ready" and "database":"ok". It also reports storage when you use S3. If the request fails, inspect docker compose logs --tail=100 openpost. For a public server, check https://your-domain.example/api/v1/ready through the reverse proxy too.

Open http://localhost:8080 and create the first account. That account becomes the instance administrator. Create a workspace, then configure the provider integrations you need. Once a provider is configured, connect your social account and follow the first-post guide.

After setup, set OPENPOST_DISABLE_REGISTRATIONS=true in .env and run docker compose up -d if the instance should stop accepting new self-service registrations. Existing accounts can still sign in.

Production requirements

Keep the proxy's HTTPS certificate valid and forward the original host and scheme. OAuth callback URLs must match the public origin exactly. Use a versioned image tag for upgrades, then back up and test a restore. Back up data/db, data/media, the Compose file, and .env together. The .env file contains secrets, so protect the backup.

When several people use the instance, decide who can register and set up email delivery before requiring email verification. Set up each social provider in provider integrations; Bluesky and Discord webhooks need no developer app, while OAuth providers need their own credentials and often a public callback.

Choose a platform

Other install options

Next steps

On this page