Skip to content

Instantly share code, notes, and snippets.

@paigeadelethompson
Created November 21, 2025 03:03
Show Gist options
  • Select an option

  • Save paigeadelethompson/902b10eaf33b40bc860b4d115f65ba3b to your computer and use it in GitHub Desktop.

Select an option

Save paigeadelethompson/902b10eaf33b40bc860b4d115f65ba3b to your computer and use it in GitHub Desktop.
HOSTNAME=https://stoat.netcrave.io
REVOLT_PUBLIC_URL=https://api.stoat.netcrave.network
FORCE_DEBUG=1
name: stoat
services:
# MongoDB: Database
database:
image: docker.io/mongo
restart: always
volumes:
- ./data/db:/data/db
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
interval: 10s
timeout: 10s
retries: 5
start_period: 10s
# Redis: Event message broker & KV store
redis:
image: docker.io/eqalpha/keydb
restart: always
# RabbitMQ: Internal message broker
rabbit:
image: docker.io/rabbitmq:4
restart: always
environment:
RABBITMQ_DEFAULT_USER: rabbituser
RABBITMQ_DEFAULT_PASS: rabbitpass
volumes:
- ./data/rabbit:/var/lib/rabbitmq
healthcheck:
test: rabbitmq-diagnostics -q ping
interval: 10s
timeout: 10s
retries: 3
start_period: 20s
# MinIO: S3-compatible storage server
minio:
image: docker.io/minio/minio
command: server /data
volumes:
- ./data/minio:/data
environment:
MINIO_ROOT_USER: minioautumn
MINIO_ROOT_PASSWORD: minioautumn
MINIO_DOMAIN: minio
networks:
default:
aliases:
- revolt-uploads.minio
# legacy support:
- attachments.minio
- avatars.minio
- backgrounds.minio
- icons.minio
- banners.minio
- emojis.minio
restart: always
# API server
api:
image: ghcr.io/revoltchat/server:20250930-2
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
rabbit:
condition: service_healthy
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
networks:
default:
traefik-public:
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.middlewares.stoat-api-cors.headers.customResponseHeaders.Access-Control-Allow-Origin=https://stoat.netcrave.io,https://*.stoat.netcrave.network"
- "traefik.http.middlewares.stoat-api-cors.headers.customResponseHeaders.Access-Control-Allow-Methods=*"
- "traefik.http.middlewares.stoat-api-cors.headers.customResponseHeaders.Access-Control-Allow-Headers=*"
- "traefik.http.routers.stoat-web-https.middlewares=stoat-api-cors@docker"
- "traefik.http.routers.stoat-api.rule=Host(`api.stoat.netcrave.network`)"
- "traefik.http.services.stoat-api.loadbalancer.server.port=14702"
- "traefik.http.routers.stoat-api.entrypoints=web"
- "traefik.http.routers.stoat-api.service=stoat-api"
- "traefik.http.routers.stoat-api-https.rule=Host(`api.stoat.netcrave.network`)"
- "traefik.http.routers.stoat-api-https.tls=true"
- "traefik.http.services.stoat-api-https.loadbalancer.server.port=14702"
- "traefik.http.routers.stoat-api-https.entrypoints=websecure"
- "traefik.http.routers.stoat-api-https.service=stoat-api"
- "traefik.http.routers.stoat-api-https.tls.certresolver=myresolver"
# Events service
events:
image: ghcr.io/revoltchat/bonfire:20250930-2
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
networks:
default:
traefik-public:
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.middlewares.stoat-event-cors.headers.customResponseHeaders.Access-Control-Allow-Origin=https://stoat.netcrave.io,https://*.stoat.netcrave.network"
- "traefik.http.middlewares.stoat-event-cors.headers.customResponseHeaders.Access-Control-Allow-Methods=*"
- "traefik.http.middlewares.stoat-event-cors.headers.customResponseHeaders.Access-Control-Allow-Headers=*"
- "traefik.http.routers.stoat-web-https.middlewares=stoat-event-cors@docker"
- "traefik.http.routers.stoat-events.rule=Host(`events.stoat.netcrave.network`)"
- "traefik.http.services.stoat-events.loadbalancer.server.port=14703"
- "traefik.http.routers.stoat-events.entrypoints=web"
- "traefik.http.routers.stoat-events.service=stoat-events"
- "traefik.http.routers.stoat-events-https.rule=Host(`events.stoat.netcrave.network`)"
- "traefik.http.routers.stoat-events-https.tls=true"
- "traefik.http.services.stoat-events-https.loadbalancer.server.port=14703"
- "traefik.http.routers.stoat-events-https.entrypoints=websecure"
- "traefik.http.routers.stoat-events-https.service=stoat-events"
- "traefik.http.routers.stoat-events-https.tls.certresolver=myresolver"
# Web App
web:
image: ghcr.io/revoltchat/client:latest
restart: always
env_file: .env.web
networks:
default:
traefik-public:
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.middlewares.stoat-web-cors.headers.customResponseHeaders.Access-Control-Allow-Origin=https://stoat.netcrave.io,https://*.stoat.netcrave.network"
- "traefik.http.middlewares.stoat-web-cors.headers.customResponseHeaders.Access-Control-Allow-Methods=*"
- "traefik.http.middlewares.stoat-web-cors.headers.customResponseHeaders.Access-Control-Allow-Headers=*"
- "traefik.http.routers.stoat-web-https.middlewares=stoat-web-cors@docker"
- "traefik.http.routers.stoat-web.rule=Host(`stoat.netcrave.io`)"
- "traefik.http.services.stoat-web.loadbalancer.server.port=5000"
- "traefik.http.routers.stoat-web.entrypoints=web"
- "traefik.http.routers.stoat-web.service=stoat-web"
- "traefik.http.routers.stoat-web-https.rule=Host(`stoat.netcrave.io`)"
- "traefik.http.routers.stoat-web-https.tls=true"
- "traefik.http.services.stoat-web-https.loadbalancer.server.port=5000"
- "traefik.http.routers.stoat-web-https.entrypoints=websecure"
- "traefik.http.routers.stoat-web-https.service=stoat-web"
- "traefik.http.routers.stoat-web-https.tls.certresolver=myresolver"
# File server
autumn:
image: ghcr.io/revoltchat/autumn:20250930-2
depends_on:
database:
condition: service_healthy
createbuckets:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
networks:
default:
traefik-public:
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.middlewares.stoat-autumn-cors.headers.customResponseHeaders.Access-Control-Allow-Origin=https://stoat.netcrave.io,https://*.stoat.netcrave.network"
- "traefik.http.middlewares.stoat-autumn-cors.headers.customResponseHeaders.Access-Control-Allow-Methods=*"
- "traefik.http.middlewares.stoat-autumn-cors.headers.customResponseHeaders.Access-Control-Allow-Headers=*"
- "traefik.http.routers.stoat-web-https.middlewares=stoat-autumn-cors@docker"
- "traefik.http.routers.stoat-autumn.rule=Host(`autumn.stoat.netcrave.network`)"
- "traefik.http.services.stoat-autumn.loadbalancer.server.port=14704"
- "traefik.http.routers.stoat-autumn.entrypoints=web"
- "traefik.http.routers.stoat-autumn.service=stoat-autumn"
- "traefik.http.routers.stoat-autumn-https.rule=Host(`autumn.stoat.netcrave.network`)"
- "traefik.http.routers.stoat-autumn-https.tls=true"
- "traefik.http.services.stoat-autumn-https.loadbalancer.server.port=14704"
- "traefik.http.routers.stoat-autumn-https.entrypoints=websecure"
- "traefik.http.routers.stoat-autumn-https.service=stoat-autumn"
- "traefik.http.routers.stoat-autumn-https.tls.certresolver=myresolver"
# Metadata and image proxy
january:
image: ghcr.io/revoltchat/january:20250930-2
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
networks:
default:
traefik-public:
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.middlewares.stoat-january-cors.headers.customResponseHeaders.Access-Control-Allow-Origin=https://stoat.netcrave.io,https://*.stoat.netcrave.network"
- "traefik.http.middlewares.stoat-january-cors.headers.customResponseHeaders.Access-Control-Allow-Methods=*"
- "traefik.http.middlewares.stoat-january-cors.headers.customResponseHeaders.Access-Control-Allow-Headers=*"
- "traefik.http.routers.stoat-web-https.middlewares=stoat-january-cors@docker"
- "traefik.http.routers.stoat-january.rule=Host(`january.stoat.netcrave.network`)"
- "traefik.http.services.stoat-january.loadbalancer.server.port=14705"
- "traefik.http.routers.stoat-january.entrypoints=web"
- "traefik.http.routers.stoat-january.service=stoat-january"
- "traefik.http.routers.stoat-january-https.rule=Host(`january.stoat.netcrave.network`)"
- "traefik.http.routers.stoat-january-https.tls=true"
- "traefik.http.services.stoat-january-https.loadbalancer.server.port=14705"
- "traefik.http.routers.stoat-january-https.entrypoints=websecure"
- "traefik.http.routers.stoat-january-https.service=stoat-january"
- "traefik.http.routers.stoat-january-https.tls.certresolver=myresolver"
# Tenor proxy
gifbox:
image: ghcr.io/revoltchat/gifbox:20250930-2
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
networks:
default:
traefik-public:
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.middlewares.stoat-gifbox-cors.headers.customResponseHeaders.Access-Control-Allow-Origin=https://stoat.netcrave.io,https://*.stoat.netcrave.network"
- "traefik.http.middlewares.stoat-gifbox-cors.headers.customResponseHeaders.Access-Control-Allow-Methods=*"
- "traefik.http.middlewares.stoat-gifbox-cors.headers.customResponseHeaders.Access-Control-Allow-Headers=*"
- "traefik.http.routers.stoat-web-https.middlewares=stoat-gifbox-cors@docker"
- "traefik.http.routers.stoat-gifbox.rule=Host(`gifbox.stoat.netcrave.network`)"
- "traefik.http.services.stoat-gifbox.loadbalancer.server.port=14706"
- "traefik.http.routers.stoat-gifbox.entrypoints=web"
- "traefik.http.routers.stoat-gifbox.service=stoat-gifbox"
- "traefik.http.routers.stoat-gifbox-https.rule=Host(`gifbox.stoat.netcrave.network`)"
- "traefik.http.routers.stoat-gifbox-https.tls=true"
- "traefik.http.services.stoat-gifbox-https.loadbalancer.server.port=14706"
- "traefik.http.routers.stoat-gifbox-https.entrypoints=websecure"
- "traefik.http.routers.stoat-gifbox-https.service=stoat-gifbox"
- "traefik.http.routers.stoat-gifbox-https.tls.certresolver=myresolver"
# Regular task daemon
crond:
image: ghcr.io/revoltchat/crond:20250930-2
depends_on:
database:
condition: service_healthy
minio:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Push notification daemon
pushd:
image: ghcr.io/revoltchat/pushd:20250930-2
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
rabbit:
condition: service_healthy
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
extra_hosts:
- "stoat.netcrave.io:192.168.72.250"
- "api.stoat.netcrave.network:192.168.72.250"
- "events.stoat.netcrave.network:192.168.72.250"
- "autumn.stoat.netcrave.network:192.168.72.250"
- "january.stoat.netcrave.network:192.168.72.250"
# Create buckets for minio.
createbuckets:
image: docker.io/minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
while ! /usr/bin/mc ready minio; do
/usr/bin/mc alias set minio http://minio:9000 minioautumn minioautumn;
echo 'Waiting minio...' && sleep 1;
done;
/usr/bin/mc mb minio/revolt-uploads;
exit 0;
"
networks:
traefik-public:
external: true
[hosts]
app = "https://stoat.netcrave.io"
api = "https://api.stoat.netcrave.network/"
events = "wss://events.stoat.netcrave.network/"
autumn = "https://autumn.stoat.netcrave.network/"
january = "https://january.stoat.netcrave.network/"
[pushd.vapid]
private_key = "xxxxxxxxx"
public_key = "BGinrv1GI3KcSS-u7ZDTG6fVgUFMhtLnfvmXsuH3OJL2srcQ1f-_NMG6GvpLMyAabq8jidX6nHLUcg7smzF4ed8"
[files]
encryption_key = "xxxxxxxxxx"
[api]
[api.registration]
# Whether an invite should be required for registration
# See https://github.com/revoltchat/self-hosted#making-your-instance-invite-only
invite_only = true
[sentry]
# Configuration for Sentry error reporting
api = ""
events = ""
voice_ingress = ""
files = ""
proxy = ""
pushd = ""
crond = ""
gifbox = ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment