Hosting a server

There are a lot of different ways to host a server, but the absolute easiest is to start up a Docker Compose stack with everything in it.

🔗Docker Compose

The example below will set up a minimal server:

# Create the stack directory
mkdir refrain
cd refrain
mkdir tls jwks
touch docker-compose.yml

Next, copy the YAML below into refrain/docker-compose.yml file:

volumes:
  postgres-data:
  rabbitmq-data:
  minio-data:
services:
  postgres:
    image: postgres:18.3
    shm_size: 128mb
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: refrain
      PGDATA: /var/lib/postgresql
    volumes:
      - postgres-data:/var/lib/postgresql
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -U postgres -d refrain" ]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 5s
  rabbitmq:
    image: rabbitmq:4.3-management
    environment:
      RABBITMQ_DEFAULT_USER: rabbitmq
      RABBITMQ_DEFAULT_PASS: refrain
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    healthcheck:
      test: [ "CMD-SHELL", "rabbitmq-diagnostics -q check_running && rabbitmq-diagnostics -q check_local_alarms" ]
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 5s
  minio:
    image: pgsty/minio:RELEASE.2026-04-17T00-00-00Z
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin-secret
    command: server /data --console-address ":9001"
    volumes:
      - minio-data:/data
    healthcheck:
      test: [ "CMD", "mc", "ready", "local" ]
      interval: 5s
      timeout: 5s
      retries: 10
  init-minio:
    image: pgsty/mc:RELEASE.2026-04-17T00-00-00Z
    entrypoint: >
      /bin/bash -c "
          while true; do
              mc alias set local http://minio:9000 minioadmin minioadmin-secret
              if [[ $? == 0 ]]; then
                  break
              fi
              sleep 1
          done
          mc mb --ignore-existing local/refrain
          mc admin user add local refrain-client refrain-client-secret
          mc admin policy attach local readwrite --user refrain-client
          echo 'Bucket and client user created successfully.'      
      "
  refrain:
    image: monitorjbl/refrain
    restart: always
    command:
      - standalone
    depends_on:
      postgres:
        condition: service_healthy
      rabbitmq:
        condition: service_healthy
      minio:
        condition: service_healthy
    ports:
      - "8443:8443/tcp"
      - "8443:8443/udp"
    environment:
      REFRAIN__DATABASE__URL: "postgres://postgres:postgres@postgres:5432/refrain"
      REFRAIN__RABBITMQ__URL: "amqp://rabbitmq:refrain@rabbitmq:5672"
      REFRAIN__OBJECT_STORAGE__URL: "http://minio:9000"
    volumes:
      # Mount your configuration file into the server (optional, omitting it will use the default config)
      # - ./refrain.toml:/opt/refrain/refrain.toml
      # Mount your JWKS dir into the server (optional, but not doing this means your server will have a different signing key at each startup)
      - ./jwks:/opt/refrain/jwks
      # Mount your TLS dir into the server (optional, but not doing this means your server will have a different TLS key at each boot) 
      - ./tls:/opt/refrain/tls

Now, start your server!

docker compose up

This will start a server with the default configuration and self-signed keys. Once everything boots up, you can access your server at https://localhost:8443. The default username/password is "admin/refrain1234!".

More example deployments with Docker can be found here.

🔗Kubernetes

Kubernetes is a great deployment platform, though not too many people have it in their homelab these days. If you are one of the crazy, brilliant few that both want to host your own services and maintain a k8s installation, you can use the example deployments found here. No Helm chart yet, but good ol' kubectl apply -f still works just fine!

🔗Barebones

This is an example of starting the refrain-server binary yourself. The external dependencies are still required, and in this example we are going to start them with Docker. However, the configuration TOML can be updated to point to any properly-configured Postgres/RabbitMQ/S3 service. There isn't much of a good reason to do this in most cases, but it is a useful illustration of how the service actually runs. For more customized deployments, hopefully this helps!

curl -o refrain-server.zip -L https://s3.us-east-1.amazonaws.com/refrain.gg/releases/latest/server/refrain-server-linux-amd64.zip
unzip refrain-server.zip -d ./refrain
cd ./refrain
touch docker-compose.yml

Now, copy the following into the docker-compose.yml file:

volumes:
  postgres-data:
  rabbitmq-data:
  minio-data:
services:
  postgres:
    image: postgres:18.3
    shm_size: 128mb
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: refrain
      PGDATA: /var/lib/postgresql
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql
  rabbitmq:
    image: rabbitmq:4.3-management
    environment:
      RABBITMQ_DEFAULT_USER: rabbitmq
      RABBITMQ_DEFAULT_PASS: refrain
    ports:
      - "5672:5672"
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
  minio:
    image: pgsty/minio:RELEASE.2026-04-17T00-00-00Z
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin-secret
    ports:
      - "9000:9000"
    command: server /data --console-address ":9001"
    volumes:
      - minio-data:/data
    healthcheck:
      test: [ "CMD", "mc", "ready", "local" ]
      interval: 5s
      timeout: 5s
      retries: 10
  init-minio:
    image: pgsty/mc:RELEASE.2026-04-17T00-00-00Z
    entrypoint: >
      /bin/bash -c "
          while true; do
              mc alias set local http://minio:9000 minioadmin minioadmin-secret
              if [[ $? == 0 ]]; then
                  break
              fi
              sleep 1
          done
          mc mb --ignore-existing local/refrain
          mc admin user add local refrain-client refrain-client-secret
          mc admin policy attach local readwrite --user refrain-client
          echo 'Bucket and client user created successfully.'      
      "

Boot up the dependencies with docker compose up -d and wait for them to finish starting. Finally, start the server:

./refrain-server standalone

You can now access Refrain at https://localhost:8443! This is not a great way to host refrain, but it can be done relatively painlessly.