Compare commits

...

12 Commits

Author SHA1 Message Date
Kevin B
531f7924b0 Working config 2026-02-15 15:59:21 +00:00
Kevin Bataille
f41d423936 Try production configuration 2026-02-15 18:21:04 +04:00
stoat-tofu[bot]
340484159e chore: modify .github/workflows/validate-pr-title.yml 2025-11-14 20:25:00 +00:00
Declan Chidlow
31ff9e81c0 chore: move to latest stoat stuff 2025-10-06 09:59:17 +08:00
Declan Chidlow
1a426356b5 docs: Switch name to Stoat 2025-10-06 09:03:07 +08:00
Paul Makles
8ffc55b96a docs: update README.md
closes #133
2025-07-18 11:06:50 +01:00
Kyle Kienapfel
21ef05770c fix: a few REVOLT_PUBLIC_URL references needed cleanup (#151)
Co-authored-by: Kyle Kienapfel <Docteh@users.noreply.github.com>
2025-07-18 11:05:38 +01:00
Kyle Kienapfel
db51161530 fix: have caddy apply url prefix to relative redirects from services (#150)
Co-authored-by: Kyle Kienapfel <Docteh@users.noreply.github.com>
2025-07-18 11:04:39 +01:00
BenV
d8d9721a16 fix(generate_config.sh): tail compatibility (#158) 2025-07-18 11:04:00 +01:00
Declan Chidlow
196900a6dd Merge pull request #154 from Docteh/minio-alias
fix: minio/mc deprecated config command, use alias set instead
2025-06-10 13:00:08 +08:00
Kyle Kienapfel
8e889598f5 fix: minio/mc deprecated config command, use alias set instead 2025-06-03 00:45:18 -07:00
Paul Makles
99b0d743af fix: 20240929-autumn-rewrite.mjs missing const 2025-05-12 11:28:34 +01:00
6 changed files with 141 additions and 59 deletions

20
.github/workflows/validate-pr-title.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: "Lint PR"
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
permissions:
pull-requests: read
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,22 +1,37 @@
{$HOSTNAME} { :80 {
route /api* { route /api* {
uri strip_prefix /api uri strip_prefix /api
reverse_proxy http://api:14702 reverse_proxy http://api:14702 {
header_down Location "^/" "/api/"
}
} }
route /ws { route /ws {
uri strip_prefix /ws uri strip_prefix /ws
reverse_proxy http://events:14703 reverse_proxy http://events:14703 {
header_down Location "^/" "/ws/"
}
} }
route /autumn* { route /autumn* {
uri strip_prefix /autumn uri strip_prefix /autumn
reverse_proxy http://autumn:14704 reverse_proxy http://autumn:14704 {
header_down Location "^/" "/autumn/"
}
} }
route /january* { route /january* {
uri strip_prefix /january uri strip_prefix /january
reverse_proxy http://january:14705 reverse_proxy http://january:14705 {
header_down Location "^/" "/january/"
}
}
route /gifbox* {
uri strip_prefix /gifbox
reverse_proxy http://gifbox:14706 {
header_down Location "^/" "/gifbox/"
}
} }
reverse_proxy http://web:5000 reverse_proxy http://web:5000

View File

@@ -1,6 +1,6 @@
<div align="center"> <div align="center">
<h1> <h1>
Revolt Self-Hosted Stoat Self-Hosted
[![Stars](https://img.shields.io/github/stars/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/stargazers) [![Stars](https://img.shields.io/github/stars/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/stargazers)
[![Forks](https://img.shields.io/github/forks/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/network/members) [![Forks](https://img.shields.io/github/forks/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/network/members)
@@ -9,20 +9,20 @@
[![Contributors](https://img.shields.io/github/contributors/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/graphs/contributors) [![Contributors](https://img.shields.io/github/contributors/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/graphs/contributors)
[![License](https://img.shields.io/github/license/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/blob/main/LICENSE) [![License](https://img.shields.io/github/license/revoltchat/self-hosted?style=flat-square&logoColor=white)](https://github.com/revoltchat/self-hosted/blob/main/LICENSE)
</h1> </h1>
Self-hosting Revolt using Docker Self-hosting Stoat using Docker
</div> </div>
<br/> <br/>
This repository contains configurations and instructions that can be used for deploying Revolt. This repository contains configurations and instructions that can be used for deploying a full instance of Stoat, including the back-end, web front-end, file server, and metadata and image proxy.
> [!WARNING] > [!WARNING]
> If you are updating an instance from before November 28, 2024, please see the [notices section](#notices) at the bottom of this README! > If you are updating an instance from before November 28, 2024, please consult the [notices section](#notices) at the bottom.
> [!IMPORTANT] > [!IMPORTANT]
> A list of security advisories is [provided at the bottom](#security-advisories). > A list of security advisories is [provided at the bottom](#security-advisories).
> [!NOTE] > [!NOTE]
> Please consult _[What can I do with Revolt, and how do I self-host?](https://developers.revolt.chat/faq.html#admonition-what-can-i-do-with-revolt-and-how-do-i-self-host)_ on our developer site for information about licensing and brand use. > Please consult _[What can I do with Stoat, and how do I self-host?](https://developers.revolt.chat/faq.html#admonition-what-can-i-do-with-revolt-and-how-do-i-self-host)_ on our developer site for information about licensing and brand use.
> [!NOTE] > [!NOTE]
> amd64 builds are not currently available for the web client. > amd64 builds are not currently available for the web client.
@@ -31,6 +31,7 @@ This repository contains configurations and instructions that can be used for de
> This guide does not include working voice channels ([#138](https://github.com/revoltchat/self-hosted/pull/138#issuecomment-2762682655)). A [rework](https://github.com/revoltchat/backend/issues/313) is currently in progress. > This guide does not include working voice channels ([#138](https://github.com/revoltchat/self-hosted/pull/138#issuecomment-2762682655)). A [rework](https://github.com/revoltchat/backend/issues/313) is currently in progress.
## Table of Contents ## Table of Contents
- [Deployment](#deployment) - [Deployment](#deployment)
- [Updating](#updating) - [Updating](#updating)
- [Advanced Deployment](#advanced-deployment) - [Advanced Deployment](#advanced-deployment)
@@ -137,11 +138,11 @@ apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
``` ```
Now, we can pull in the configuration for Revolt: Now, we can pull in the configuration for Stoat:
```bash ```bash
git clone https://github.com/revoltchat/self-hosted revolt git clone https://github.com/revoltchat/self-hosted stoat
cd revolt cd stoat
``` ```
Generate a configuration file by running: Generate a configuration file by running:
@@ -151,7 +152,7 @@ chmod +x ./generate_config.sh
./generate_config.sh your.domain ./generate_config.sh your.domain
``` ```
You can find [more options here](https://github.com/revoltchat/backend/blob/df074260196f5ed246e6360d8e81ece84d8d9549/crates/core/config/Revolt.toml), some noteworthy configuration options: You can find [more options here](https://github.com/revoltchat/backend/blob/stable/crates/core/config/Revolt.toml), some noteworthy configuration options:
- Email verification - Email verification
- Captcha - Captcha
@@ -164,7 +165,7 @@ If you'd like to edit the configuration, just run:
micro Revolt.toml micro Revolt.toml
``` ```
Finally, we can start up Revolt. First, run it in the foreground with: Finally, we can start up Stoat. First, run it in the foreground with:
```bash ```bash
docker compose up docker compose up
@@ -212,8 +213,8 @@ Prerequisites before continuing:
Clone this repository. Clone this repository.
```bash ```bash
git clone https://github.com/revoltchat/self-hosted revolt git clone https://github.com/revoltchat/self-hosted stoat
cd revolt cd stoat
``` ```
Create `.env.web` and download `Revolt.toml`, then modify them according to your requirements. Create `.env.web` and download `Revolt.toml`, then modify them according to your requirements.
@@ -222,12 +223,12 @@ Create `.env.web` and download `Revolt.toml`, then modify them according to your
> The default configurations are intended exclusively for testing and will only work locally. If you wish to deploy to a remote server, you **must** edit the URLs in `.env.web` and `Revolt.toml`. Please reference the section below on [configuring a custom domain](#custom-domain). > The default configurations are intended exclusively for testing and will only work locally. If you wish to deploy to a remote server, you **must** edit the URLs in `.env.web` and `Revolt.toml`. Please reference the section below on [configuring a custom domain](#custom-domain).
```bash ```bash
echo "HOSTNAME=http://local.revolt.chat" > .env.web echo "HOSTNAME=http://local.stoat.chat" > .env.web
echo "REVOLT_PUBLIC_URL=http://local.revolt.chat/api" >> .env.web echo "REVOLT_PUBLIC_URL=http://local.stoat.chat/api" >> .env.web
wget -O Revolt.toml https://raw.githubusercontent.com/revoltchat/backend/main/crates/core/config/Revolt.toml wget -O Revolt.toml https://raw.githubusercontent.com/revoltchat/backend/main/crates/core/config/Revolt.toml
``` ```
Then start Revolt: Then start Stoat:
```bash ```bash
docker compose up -d docker compose up -d
@@ -237,21 +238,29 @@ docker compose up -d
### Custom Domain ### Custom Domain
To configure a custom domain, you will need to replace *all* instances of `local.revolt.chat` in `Revolt.toml` and `.env.web` to your chosen domain (here represented as `example.com`), like so: To configure a custom domain, you can either generate a config for https by running:
```
chmod +x ./generate_config.sh
./generate_config.sh your.domain
```
Or alternatively do it manually, you will need to replace _all_ instances of `local.stoat.chat` in `Revolt.toml` and `.env.web` to your chosen domain (here represented as `example.com`), like so:
```diff ```diff
# .env.web # .env.web
- REVOLT_PUBLIC_URL=http://local.revolt.chat/api - REVOLT_PUBLIC_URL=http://local.stoat.chat/api
+ REVOLT_PUBLIC_URL=http://example.com + REVOLT_PUBLIC_URL=http://example.com/api
``` ```
```diff ```diff
# Revolt.toml # Revolt.toml
- app = "http://local.revolt.chat" - app = "http://local.stoat.chat"
+ app = "http://example.com" + app = "http://example.com"
``` ```
In the case of `HOSTNAME`, you must strip the protocol prefix: In the case of `HOSTNAME`, you must strip the protocol prefix:
```diff ```diff
# .env.web # .env.web
- HOSTNAME=http://example.com - HOSTNAME=http://example.com
@@ -262,8 +271,8 @@ You will likely also want to change the protocols to enable HTTPS:
```diff ```diff
# .env.web # .env.web
- REVOLT_PUBLIC_URL=http://example.com - REVOLT_PUBLIC_URL=http://example.com/api
+ REVOLT_PUBLIC_URL=https://example.com + REVOLT_PUBLIC_URL=https://example.com/api
``` ```
```diff ```diff
@@ -277,7 +286,7 @@ You will likely also want to change the protocols to enable HTTPS:
### Placing Behind Another Reverse-Proxy or Another Port ### Placing Behind Another Reverse-Proxy or Another Port
If you'd like to place Revolt behind another reverse proxy or on a non-standard port, you'll need to edit `compose.yml`. If you'd like to place Stoat behind another reverse proxy or on a non-standard port, you'll need to edit `compose.yml`.
Override the port definitions on `caddy`: Override the port definitions on `caddy`:
@@ -345,14 +354,14 @@ db.invites.insertOne({ _id: "enter_an_invite_code_here" })
## Notices ## Notices
> [!IMPORTANT] > [!IMPORTANT]
> If you deployed Revolt before [2022-10-29](https://github.com/minio/docs/issues/624#issuecomment-1296608406), you may have to tag the `minio` image release if it's configured in "fs" mode. > If you deployed Stoat before [2022-10-29](https://github.com/minio/docs/issues/624#issuecomment-1296608406), you may have to tag the `minio` image release if it's configured in "fs" mode.
> >
> ```yml > ```yml
> image: minio/minio:RELEASE.2022-10-24T18-35-07Z > image: minio/minio:RELEASE.2022-10-24T18-35-07Z
> ``` > ```
> [!IMPORTANT] > [!IMPORTANT]
> If you deployed Revolt before [2023-04-21](https://github.com/revoltchat/backend/commit/32542a822e3de0fc8cc7b29af46c54a9284ee2de), you may have to flush your Redis database. > If you deployed Stoat before [2023-04-21](https://github.com/revoltchat/backend/commit/32542a822e3de0fc8cc7b29af46c54a9284ee2de), you may have to flush your Redis database.
> >
> ```bash > ```bash
> # for stock Redis and older KeyDB images: > # for stock Redis and older KeyDB images:
@@ -396,15 +405,16 @@ db.invites.insertOne({ _id: "enter_an_invite_code_here" })
> [!IMPORTANT] > [!IMPORTANT]
> As of November 28, 2024, the following breaking changes have been applied: > As of November 28, 2024, the following breaking changes have been applied:
>
> - Rename config section `api.vapid` -> `pushd.vapid` > - Rename config section `api.vapid` -> `pushd.vapid`
> - Rename config section `api.fcm` -> `pushd.fcm` > - Rename config section `api.fcm` -> `pushd.fcm`
> - Rename config section `api.apn` -> `pushd.apn` > - Rename config section `api.apn` -> `pushd.apn`
> >
> These will NOT automatically be applied to your config and must be changed/added manually. > These will NOT automatically be applied to your config and must be changed/added manually.
> >
>
> The following components have been added to the compose file: > The following components have been added to the compose file:
> - Added `rabbit` (RabbitMQ) and `pushd` (Revolt push daemon) >
> - Added `rabbit` (RabbitMQ) and `pushd` (Stoat push daemon)
## Security Advisories ## Security Advisories

View File

@@ -1,14 +1,19 @@
name: revolt name: stoat
networks:
web:
external: true
name: web
services: services:
# MongoDB: Database # MongoDB: Database
database: database:
image: docker.io/mongo image: docker.io/mongo:4.4
restart: always restart: unless-stopped
volumes: volumes:
- ./data/db:/data/db - ./data/db:/data/db
healthcheck: healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet test: echo 'db.runCommand("ping").ok' | mongo localhost:27017/test --quiet
interval: 10s interval: 10s
timeout: 10s timeout: 10s
retries: 5 retries: 5
@@ -16,13 +21,13 @@ services:
# Redis: Event message broker & KV store # Redis: Event message broker & KV store
redis: redis:
image: docker.io/eqalpha/keydb image: docker.io/redis:6-alpine
restart: always restart: unless-stopped
# RabbitMQ: Internal message broker # RabbitMQ: Internal message broker
rabbit: rabbit:
image: docker.io/rabbitmq:4 image: docker.io/rabbitmq:4
restart: always restart: unless-stopped
environment: environment:
RABBITMQ_DEFAULT_USER: rabbituser RABBITMQ_DEFAULT_USER: rabbituser
RABBITMQ_DEFAULT_PASS: rabbitpass RABBITMQ_DEFAULT_PASS: rabbitpass
@@ -37,7 +42,7 @@ services:
# MinIO: S3-compatible storage server # MinIO: S3-compatible storage server
minio: minio:
image: docker.io/minio/minio image: minio/minio:RELEASE.2022-10-24T18-35-07Z
command: server /data command: server /data
volumes: volumes:
- ./data/minio:/data - ./data/minio:/data
@@ -56,24 +61,46 @@ services:
- icons.minio - icons.minio
- banners.minio - banners.minio
- emojis.minio - emojis.minio
restart: always restart: unless-stopped
# Caddy: Web server # Caddy: Web server
caddy: caddy:
image: docker.io/caddy image: docker.io/caddy
restart: always restart: unless-stopped
env_file: .env.web env_file: .env.web
ports:
- "80:80"
- "443:443"
volumes: volumes:
- ./Caddyfile:/etc/caddy/Caddyfile - ./Caddyfile:/etc/caddy/Caddyfile
- ./data/caddy-data:/data - ./data/caddy-data:/data
- ./data/caddy-config:/config - ./data/caddy-config:/config
labels:
# Explicitly tell Traefik to expose this container
- traefik.enable=true
- traefik.docker.network=web
# HTTPS
- traefik.http.services.stoat-service-secure.loadbalancer.server.port=80
- traefik.http.routers.stoat-secure.service=stoat-service-secure
- traefik.http.routers.stoat-secure.entrypoints=websecure
- traefik.http.routers.stoat-secure.tls.certresolver=le
- traefik.http.routers.stoat-secure.rule=Host(`stoat.mistergeek.fr`)
- traefik.http.middlewares.stoat-secure-cache.compress=true
# HTTP
- traefik.http.services.stoat-service-insecure.loadbalancer.server.port=80
- traefik.http.routers.stoat-insecure.service=stoat-service-insecure
- traefik.http.routers.stoat-insecure.entrypoints=web
- traefik.http.routers.stoat-insecure.rule=Host(`stoat.mistergeek.fr`)
- traefik.http.middlewares.stoat-insecure-cache.compress=true
- traefik.http.routers.traefik.tls=true
- traefik.http.routers.traefik.tls.certresolver=le
# GZIP
- traefik.http.routers.traefik.middlewares=traefik-compress
- traefik.http.middlewares.traefik-compress.compress=true
networks:
- default
- web
# API server # API server
api: api:
image: ghcr.io/revoltchat/server:20250210-1 image: ghcr.io/revoltchat/server:20250930-2
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
@@ -85,11 +112,11 @@ services:
- type: bind - type: bind
source: ./Revolt.toml source: ./Revolt.toml
target: /Revolt.toml target: /Revolt.toml
restart: always restart: unless-stopped
# Events service # Events service
events: events:
image: ghcr.io/revoltchat/bonfire:20250210-1 image: ghcr.io/revoltchat/bonfire:20250930-2
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
@@ -99,17 +126,17 @@ services:
- type: bind - type: bind
source: ./Revolt.toml source: ./Revolt.toml
target: /Revolt.toml target: /Revolt.toml
restart: always restart: unless-stopped
# Web App # Web App
web: web:
image: ghcr.io/revoltchat/client:master image: ghcr.io/revoltchat/client:master
restart: always restart: unless-stopped
env_file: .env.web env_file: .env.web
# File server # File server
autumn: autumn:
image: ghcr.io/revoltchat/autumn:20250210-1 image: ghcr.io/revoltchat/autumn:20250930-2
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
@@ -119,20 +146,29 @@ services:
- type: bind - type: bind
source: ./Revolt.toml source: ./Revolt.toml
target: /Revolt.toml target: /Revolt.toml
restart: always restart: unless-stopped
# Metadata and image proxy # Metadata and image proxy
january: january:
image: ghcr.io/revoltchat/january:20250210-1 image: ghcr.io/revoltchat/january:20250930-2
volumes: volumes:
- type: bind - type: bind
source: ./Revolt.toml source: ./Revolt.toml
target: /Revolt.toml target: /Revolt.toml
restart: always restart: unless-stopped
# Tenor proxy
gifbox:
image: ghcr.io/revoltchat/gifbox:20250930-2
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: unless-stopped
# Regular task daemon # Regular task daemon
crond: crond:
image: ghcr.io/revoltchat/crond:20250210-1-debug image: ghcr.io/revoltchat/crond:20250930-2
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
@@ -142,11 +178,11 @@ services:
- type: bind - type: bind
source: ./Revolt.toml source: ./Revolt.toml
target: /Revolt.toml target: /Revolt.toml
restart: always restart: unless-stopped
# Push notification daemon # Push notification daemon
pushd: pushd:
image: ghcr.io/revoltchat/pushd:20250210-1 image: ghcr.io/revoltchat/pushd:20250930-2
depends_on: depends_on:
database: database:
condition: service_healthy condition: service_healthy
@@ -158,7 +194,7 @@ services:
- type: bind - type: bind
source: ./Revolt.toml source: ./Revolt.toml
target: /Revolt.toml target: /Revolt.toml
restart: always restart: unless-stopped
# Create buckets for minio. # Create buckets for minio.
createbuckets: createbuckets:
@@ -168,7 +204,7 @@ services:
entrypoint: > entrypoint: >
/bin/sh -c " /bin/sh -c "
while ! /usr/bin/mc ready minio; do while ! /usr/bin/mc ready minio; do
/usr/bin/mc config host add minio http://minio:9000 minioautumn minioautumn; /usr/bin/mc alias set minio http://minio:9000 minioautumn minioautumn;
echo 'Waiting minio...' && sleep 1; echo 'Waiting minio...' && sleep 1;
done; done;
/usr/bin/mc mb minio/revolt-uploads; /usr/bin/mc mb minio/revolt-uploads;

2
generate_config.sh Normal file → Executable file
View File

@@ -17,7 +17,7 @@ echo "" >> Revolt.toml
echo "[pushd.vapid]" >> Revolt.toml echo "[pushd.vapid]" >> Revolt.toml
openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
echo "private_key = \"$(base64 -i vapid_private.pem | tr -d '\n' | tr -d '=')\"" >> Revolt.toml echo "private_key = \"$(base64 -i vapid_private.pem | tr -d '\n' | tr -d '=')\"" >> Revolt.toml
echo "public_key = \"$(openssl ec -in vapid_private.pem -outform DER|tail -c 65|base64|tr '/+' '_-'|tr -d '\n'|tr -d '=')\"" >> Revolt.toml echo "public_key = \"$(openssl ec -in vapid_private.pem -outform DER|tail --bytes 65|base64|tr '/+' '_-'|tr -d '\n'|tr -d '=')\"" >> Revolt.toml
rm vapid_private.pem rm vapid_private.pem
# encryption key for files # encryption key for files

View File

@@ -28,6 +28,7 @@ const BUCKET_MAP = {
*/ */
const CONNECTION_URL = "mongodb://database"; const CONNECTION_URL = "mongodb://database";
const objectLookup = {};
const mongo = new MongoClient(CONNECTION_URL); const mongo = new MongoClient(CONNECTION_URL);
await mongo.connect(); await mongo.connect();