15 Commits
main ... main

Author SHA1 Message Date
82913d7f83 Update docker-compose2.yml
update for reverse proxy
2026-02-28 01:55:53 -06:00
6d6a3cceb6 Update .env.web
update for reverse proxy
2026-02-28 01:55:23 -06:00
3f716efe70 Update .gitignore
commented out the gitignore.
2026-02-28 01:28:48 -06:00
5b753f6762 added docker-compose2.yml 2026-02-28 01:21:11 -06:00
97367d1f41 Update docker-compose.yml
changed 4443 to 8443
2026-02-28 01:09:38 -06:00
bd52dc4688 Update docker-compose.yml
added &env and *env entries instead of using .env.web
2026-02-28 01:07:18 -06:00
0992048935 Update docker-compose.yml 2026-02-28 00:50:33 -06:00
e21d86d3fa Upload files to "/" 2026-02-28 00:49:19 -06:00
cbff098301 Upload files to "/" 2026-02-28 00:46:18 -06:00
eb7787a851 Update .env 2026-02-28 00:45:33 -06:00
c01603c51a merge upstream 2026-02-28 00:38:43 -06:00
d241581856 Stupid Caddyfile 2026-02-04 22:21:43 -06:00
ddcf2b3634 Update to new stoat name new docker config options 2026-02-04 22:11:11 -06:00
bd354e4e29 Added docker-compose.yml 2026-02-04 22:06:37 -06:00
490ff5686a Add .env 2026-02-04 22:05:55 -06:00
11 changed files with 577 additions and 306 deletions

6
.env Normal file
View File

@@ -0,0 +1,6 @@
HOSTNAME=https://chat.kofal.net
REVOLT_PUBLIC_URL=https://chat.kofal.net/api
VITE_API_URL=https://chat.kofal.net/api
VITE_WS_URL=wss://chat.kofal.net/ws
VITE_MEDIA_URL=https://chat.kofal.net/autumn
VITE_PROXY_URL=https://chat.kofal.net/january

6
.env.web Normal file
View File

@@ -0,0 +1,6 @@
HOSTNAME=:80
REVOLT_PUBLIC_URL=https://chat.kofal.net/api
VITE_API_URL=https://chat.kofal.net/api
VITE_WS_URL=wss://chat.kofal.net/ws
VITE_MEDIA_URL=https://chat.kofal.net/autumn
VITE_PROXY_URL=https://chat.kofal.net/january

10
.gitignore vendored
View File

@@ -1,12 +1,10 @@
data*
.env
.env.web
Revolt.toml
livekit.yml
#.env
#.env.web
#Revolt.toml
#livekit.yml
Revolt.toml.old
livekit.yml.old
secrets.env
compose.override.yml
compose.override.yml.old

108
README.md
View File

@@ -16,7 +16,7 @@ Self-hosting Stoat using Docker
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]
> If you are updating an instance from before February 28, 2026, please consult the [notices section](#notices) at the bottom.
> If you are updating an instance from before February 20, 2026, please consult the [notices section](#notices) at the bottom.
> [!IMPORTANT]
> A list of security advisories is [provided at the bottom](#security-advisories).
@@ -27,20 +27,13 @@ This repository contains configurations and instructions that can be used for de
## Table of Contents
- [Deployment](#deployment)
- [Secure your server](#secure-your-server)
- [Configure your domain](#configure-your-domain)
- [Install Required Dependencies](#install-required-dependencies)
- [Configuration](#configuration)
- [Updating](#updating)
- [Additional Notes](#additional-notes)
- [Creating an Account](#creating-an-account)
- [Placing Behind Another Reverse-Proxy or Another Port](#placing-behind-another-reverse-proxy-or-another-port)
- [Insecurely Expose the Database](#insecurely-expose-the-database)
- [Mongo Compatibility](#mongo-compatibility)
- [KeyDB Compatibility](#keydb-compatibility)
- [Making Your Instance Invite-only](#making-your-instance-invite-only)
- [Why ports 7881 and 50000-50100/udp aren't in the Caddyfile](#why-ports-7881-and-50000-50100udp-arent-in-the-caddyfile)
- [Getting kicked on video enabled instances when turning on video](#getting-kicked-on-video-enabled-instances-when-turning-on-video)
- [Notices](#notices)
- [Security Advisories](#security-advisories)
@@ -92,7 +85,7 @@ ssh root@<ip address>
ssh root@<ip address> -i path/to/id_rsa
```
### Securing your server
And now we can proceed with some basic configuration and securing the system:
```bash
# update the system
@@ -116,9 +109,7 @@ reboot
```
> [!NOTE]
> If you are using another cloud provider, or you are doing this on a physical machine, you will need to forward ports 80, 443, 7881 and 50000-50100/udp.
### Configuring your domain
> If you are using another cloud provider, or you are doing this on a physical machine, you will need to forwards ports 80, 443, 7881 and 50000-50100/udp.
Your system is now ready to proceed with installation, but before we continue, you should configure your domain.
@@ -126,7 +117,7 @@ Your system is now ready to proceed with installation, but before we continue, y
Your domain (or a subdomain) should point to the server's IP (A and AAAA records) or CNAME to the hostname provided.
### Install required dependencies
Next, we must install the required dependencies:
```bash
# ensure Git and Docker are installed
@@ -145,8 +136,6 @@ apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
## Configuration
Now, we can pull in the configuration for Stoat:
```bash
@@ -161,8 +150,6 @@ chmod +x ./generate_config.sh
./generate_config.sh your.domain
```
The generate_config.sh script will create the neccessary secrets required to create a Stoat instance, and the secrets will be inserted into a file named `secrets.env`. You should back up this file, as losing it may result in you losing access to all files on your Stoat instance.
You can find [more options here](https://github.com/stoatchat/stoatchat/blob/main/crates/core/config/Revolt.toml), some noteworthy configuration options:
- Email verification
@@ -198,13 +185,7 @@ Pull the latest version of this repository:
git pull
```
Ensure that your secrets in `Revolt.toml` and `secrets.env` match. If your secrets don't match, copy the secrets from `Revolt.toml` to `secrets.env`. The following step will **overwrite** your existing configuration. If you have custom configuration settings you will need to copy them over afterwards. Alternatively, you can forgo running the configurator, but you may miss out on new features.
Run the configuration script with your domain and pass the overwrite flag:
```bash
./generate_config.sh --overwrite your.domain
```
Check if your configuration file is correct by opening [the reference config file](https://github.com/stoatchat/stoatchat/blob/main/crates/core/config/Revolt.toml) and your `Revolt.toml` to compare changes.
Then pull all the latest images:
@@ -220,14 +201,33 @@ docker compose up -d
## Additional Notes
### Creating an Account
By default, email verification is disabled.
However, when you sign up for an account on your Stoat instance, you are still required to submit an email address and will see a prompt to "Check your mail!" for a verification email. You can simply return to the login page and log in using the email address and password you just set.
### Placing Behind Another Reverse-Proxy or Another Port
During configuration using `generate_config.sh` you will be asked if you'd like to place Stoat behind another reverse proxy. Enter `y` to configure for reverse proxy. This will expose your caddy on port 8880, and you can reverse proxy to <http://localhost:8880>
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`:
```yml
# compose.yml
services:
caddy:
ports:
- "1234:80"
# - "443:443"
```
> [!WARNING]
> This file is not included in `.gitignore`. It may be sufficient to use an override file, but that will not remove port `80` / `443` allocations.
Update the hostname used by the web server:
```diff
# .env.web
- HOSTNAME=http://example.com
+ HOSTNAME=:80
```
You can now reverse proxy to <http://localhost:1234>.
> [!NOTE]
> If you are using nginx as your reverse proxy, you will need to add the upgrade header configuration to allow websockets on /ws and /livekit, which are required for Stoat.
@@ -285,7 +285,7 @@ services:
- "27017:27017"
```
Docker will bypass your ufw rules when you do this. This means that if the port is open, the database will be publically accessible and anyone will be able to modify it.
For obvious reasons, be careful doing this.
### Mongo Compatibility
@@ -304,13 +304,13 @@ services:
### KeyDB Compatibility
Some systems (including ARM systems) may not support the latest KeyDB version; you may use redis or valkey instead as such:
Some systems may not support the latest KeyDB version; you may pin to KeyDB 6.3.3 as such:
```yml
# compose.override.yml
services:
redis:
image: valkey/valkey:8
image: docker.io/eqalpha/keydb:v6.3.3
```
### Making Your Instance Invite-only
@@ -319,7 +319,7 @@ Add the following section to your `Revolt.toml` file:
```toml
[api.registration]
# Whether an invite should be required for registration
# See https://github.com/stoatchat/self-hosted#making-your-instance-invite-only
# See https://github.com/revoltchat/self-hosted#making-your-instance-invite-only
invite_only = true
```
@@ -334,25 +334,16 @@ use revolt
db.invites.insertOne({ _id: "enter_an_invite_code_here" })
```
### Why ports 7881 and 50000-50100/udp aren't in the Caddyfile
Livekit requires ports 7881/tcp and 50000-50100/udp to be openly accessible on the internet. These ports are used for the RTC protocol. Caddy does not support RTC without significant configuration changes that are out of scope of this repo.
### Getting kicked on video enabled instances when turning on video
Due to an incomplete implementation, Stoat will kick any user that attempts to stream a video that is larger than the maximum size defined in `Revolt.toml`. If you would like to increase the maximum size allowed on your Stoat instance, you can do so by modifying the `video_resolution` field under `[features.limits.new_user]` and `[features.limits.default]` to a larger value in your `Revolt.toml`. For example, 4k would be : `[3996, 2160]`.
## Notices
<details>
<summary>If you deployed Stoat before October 5, 2025...</summary>
> [!IMPORTANT]
> 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
> image: minio/minio:RELEASE.2022-10-24T18-35-07Z
> ```
> [!IMPORTANT]
> If you deployed Stoat before [2023-04-21](https://github.com/stoatchat/stoatchat/commit/32542a822e3de0fc8cc7b29af46c54a9284ee2de), you may have to flush your Redis database.
>
> ```bash
@@ -365,6 +356,7 @@ Due to an incomplete implementation, Stoat will kick any user that attempts to s
> FLUSHDB
> ```
> [!IMPORTANT]
> As of 30th September 2024, Autumn has undergone a major refactor, which requires a manual migration.
>
> To begin, add a temporary container that we can work from:
@@ -394,6 +386,7 @@ Due to an incomplete implementation, Stoat will kick any user that attempts to s
> node ./20240929-autumn-rewrite.mjs
> ```
> [!IMPORTANT]
> As of November 28, 2024, the following breaking changes have been applied:
>
> - Rename config section `api.vapid` -> `pushd.vapid`
@@ -406,6 +399,7 @@ Due to an incomplete implementation, Stoat will kick any user that attempts to s
>
> - Added `rabbit` (RabbitMQ) and `pushd` (Stoat push daemon)
> [!IMPORTANT]
> As of October 5, 2025, the following breaking changes have been applied:
>
> - Rename docker compose project from revolt to stoat
@@ -413,26 +407,28 @@ Due to an incomplete implementation, Stoat will kick any user that attempts to s
> These will NOT automatically be applied to your environment.
>
> You must run the environment with the old revolt name to apply the update. After you run `docker compose pull` during the upgrade procedure, you must run `docker compose -p revolt down`. You may then continue with the upgrade procedure.
</details>
<br />
> [!IMPORTANT]
> As of February 28, 2026, the configuration script will load secrets into `secrets.env`. You must copy your existing secrets into secrets.env to prevent `generate_config.sh` from overwriting your secrets. If your secrets are overwritten you will lose access to all files on your Stoat instance.
> As of February 18, 2026, livekit support and the new web app was added to the self host repo. In order to utilize the new voice features and the new web app, you must add a valid livekit configuration.
>
> Copy secrets.env.example to secrets.env
> Before beginning the upgrade process, please do the following:
>
> ```bash
> cp secrets.env.example secrets.env
> git pull
> chmod +x migrations/20260218-voice-config.sh
> ./migrations/20260218-voice-config.sh your.domain
> ```
>
> Begin the process of copying your secrets to secrets.env. You can view where each secret is located by reading the `secrets.env` file. Open the file with micro and read the instructions.
> This should append the new configurations to your existing configuration. Only run this migration once, as if you run it more than once your instance will fail to start. You may then continue with the upgrade procedure.
> [!IMPORTANT]
> As of February 20, 2026, there was an error in the `generate_config.sh` script. Please apply the following changes to your configuration:
>
> ```bash
> micro secrets.env
> ```
> In `Revolt.toml`, under the section `[api.livekit.nodes.worldwide]`, change the url value to `http://livekit:7880`
>
> All of your secrets can be found in `Revolt.toml` and should be copied to your `secrets.env` file. After all 5 secrets are copied over, you are safe to run `generate_config.sh` to get new configuration options.
> In `livekit.yml`, under the section `webhook`, change the first line under `url` to `http://voice-ingress:8500/worldwide`
>
> Please note that these say `http` and not `https`. That is intentional.
## Security Advisories

23
Revolt.toml Normal file
View File

@@ -0,0 +1,23 @@
[hosts]
app = "https://chat.kofal.net"
api = "https://chat.kofal.net/api"
events = "wss://chat.kofal.net/ws"
autumn = "https://chat.kofal.net/autumn"
january = "https://chat.kofal.net/january"
[hosts.livekit]
worldwide = "wss://chat.kofal.net/livekit"
[pushd.vapid]
private_key = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUVEQmZCeDl6WitaQlVoZzI3TjNHM1REQ2xzM084Qkk0K2lrT1A5cXJ2UmlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFamUrMU92YjUrYkwzS3BtOXJ2cWhxbTNtMHlMa1g2dDhiTGVDVW9pQ044Wmp0ZjRTNmJRRgptYVhiWUVHQWVDTEphdmxVdUh3SVZpZWFmSjJFVEFTNnd3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo"
public_key = "BI3vtTr2-fmy9yqZva76oapt5tMi5F-rfGy3glKIgjfGY7X-Eum0BZml22BBgHgiyWr5VLh8CFYnmnydhEwEusM"
[files]
encryption_key = "KcOMrR6lTE5wcHvL3z7aB/0tj2+4rJD2KNDnB/tjp3I="
[api.livekit.nodes.worldwide]
url = "http://livekit:7880"
lat = 0.0
lon = 0.0
key = "317d0847b3a2"
secret = "5a25b201ae80573c064e01b7387e7ac6fa99b0039a128dff"

View File

@@ -70,10 +70,6 @@ services:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data/caddy-data:/data
- ./data/caddy-config:/config
networks:
default:
aliases:
- "${STOAT_DOMAIN:-caddy}"
# API server
api:
@@ -213,6 +209,6 @@ services:
# Web App
web:
image: ghcr.io/stoatchat/for-web:103d2bf
image: ghcr.io/stoatchat/for-web:addb6b7
restart: always
env_file: .env.web

221
docker-compose.yml Normal file
View File

@@ -0,0 +1,221 @@
name: stoat
services:
# MongoDB: Database
database:
image: docker.io/mongo
restart: always
environment: &env
- HOSTNAME=https://chat.kofal.net
- REVOLT_PUBLIC_URL=https://chat.kofal.net/api
- VITE_API_URL=https://chat.kofal.net/api
- VITE_WS_URL=wss://chat.kofal.net/ws
- VITE_MEDIA_URL=https://chat.kofal.net/autumn
- VITE_PROXY_URL=https://chat.kofal.net/january
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
# Caddy: Web server
caddy:
image: docker.io/caddy
restart: always
environment: *env
ports:
- "8880:80"
- "8443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data/caddy-data:/data
- ./data/caddy-config:/config
# API server
api:
image: ghcr.io/stoatchat/api:v0.11.1
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
# Events service
events:
image: ghcr.io/stoatchat/events:v0.11.1
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# File server
autumn:
image: ghcr.io/stoatchat/file-server:v0.11.1
depends_on:
database:
condition: service_healthy
createbuckets:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Metadata and image proxy
january:
image: ghcr.io/stoatchat/proxy:v0.11.1
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Tenor proxy
gifbox:
image: ghcr.io/stoatchat/gifbox:v0.11.1
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Regular task daemon
crond:
image: ghcr.io/stoatchat/crond:v0.11.1
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/stoatchat/pushd:v0.11.1
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
# Voice ingress daemon
voice-ingress:
image: ghcr.io/stoatchat/voice-ingress:v0.11.1
restart: always
depends_on:
database:
condition: service_healthy
rabbit:
condition: service_healthy
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
livekit:
image: ghcr.io/stoatchat/livekit-server:v1.9.6
depends_on:
redis:
condition: service_started
command: --config /etc/livekit.yml
ports:
- "7881:7881"
- "50000-50100:50000-50100/udp"
restart: always
volumes:
- type: bind
source: ./livekit.yml
target: /etc/livekit.yml
# 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;
"
# Web App
web:
image: ghcr.io/stoatchat/for-web:addb6b7
restart: always
environment: *env

214
docker-compose2.yml Normal file
View File

@@ -0,0 +1,214 @@
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
# Caddy: Web server
caddy:
image: docker.io/caddy
restart: always
env_file: .env.web
ports:
- "8880:80"
#- "8443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data/caddy-data:/data
- ./data/caddy-config:/config
# API server
api:
image: ghcr.io/stoatchat/api:v0.11.1
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
# Events service
events:
image: ghcr.io/stoatchat/events:v0.11.1
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# File server
autumn:
image: ghcr.io/stoatchat/file-server:v0.11.1
depends_on:
database:
condition: service_healthy
createbuckets:
condition: service_started
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Metadata and image proxy
january:
image: ghcr.io/stoatchat/proxy:v0.11.1
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Tenor proxy
gifbox:
image: ghcr.io/stoatchat/gifbox:v0.11.1
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
restart: always
# Regular task daemon
crond:
image: ghcr.io/stoatchat/crond:v0.11.1
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/stoatchat/pushd:v0.11.1
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
# Voice ingress daemon
voice-ingress:
image: ghcr.io/stoatchat/voice-ingress:v0.11.1
restart: always
depends_on:
database:
condition: service_healthy
rabbit:
condition: service_healthy
volumes:
- type: bind
source: ./Revolt.toml
target: /Revolt.toml
livekit:
image: ghcr.io/stoatchat/livekit-server:v1.9.6
depends_on:
redis:
condition: service_started
command: --config /etc/livekit.yml
ports:
- "7881:7881"
- "50000-50100:50000-50100/udp"
restart: always
volumes:
- type: bind
source: ./livekit.yml
target: /etc/livekit.yml
# 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;
"
# Web App
web:
image: ghcr.io/stoatchat/for-web:addb6b7
restart: always
env_file: .env.web

View File

@@ -1,196 +1,51 @@
#!/usr/bin/env bash
SECRETS_FOUND=0
IS_OVERWRITING=0
DOMAIN=
VIDEO_ENABLED=
usage() {
echo "Usage: ./generate_config.sh [--overwrite] DOMAIN"
exit 1
}
loadSecrets() {
SECRETS_FOUND=1
set -a && source secrets.env && set +a
}
# Check args to ensure correct usage
# No args is not valid
if [[ $# -eq 1 ]]; then
if [[ $1 = --* ]]; then
usage
fi
DOMAIN=$1
elif [[ $# -eq 2 ]]; then
if [[ $1 != --overwrite ]]; then
usage
fi
if [[ $2 = --* ]]; then
usage
fi
DOMAIN=$2
IS_OVERWRITING=1
else
usage
fi
if test -f "secrets.env"; then
loadSecrets
fi
if test -f "Revolt.toml"; then
if [[ $IS_OVERWRITING -eq 1 ]]; then
if [ "$SECRETS_FOUND" -eq "0" ]; then
echo "Overwrite flag passed, but secrets.env not found. This script will refuse to execute an overwrite without secrets.env."
echo "If you are absolutely sure you want to overwrite your secrets with new secrets, copy the secrets.env.example file without modifying it's contents using command 'cp secrets.env.example secrets.env'."
echo "If you do not copy your existing secrets into secrets.env you WILL lose access to ALL of your files store in your Stoat instance."
exit 1
fi
echo "Overwriting existing config."
echo "Renaming Revolt.toml to Revolt.toml.old"
mv Revolt.toml Revolt.toml.old
echo "Renaming livekit.yml to livekit.yml.old"
mv livekit.yml livekit.yml.old
echo "Renaming compose.override.yml to compose.override.yml.old"
mv compose.override.yml compose.override.yml.old
else
echo "Existing config found, in caution, this script will refuse to execute if you have existing config."
if [ "$SECRETS_FOUND" -eq "0" ]; then
echo "Please configure secrets.env with your existing secrets to prevent losing access to your saved files in your Stoat instance. You can see instructions on how to configure it by reading the file secrets.env.example. You can do this by running the command 'cat secrets.env.example'."
echo "Overwriting your existing config will result in you losing access to all current files stored on your Stoat instance unless you copy your old secrets into secrets.env."
else
echo "secrets.env found, please ensure it matches what is currently in your Revolt.toml."
fi
echo "This script will back up your old config if you choose to overwrite."
echo "To overwrite the existing config, run the script again with the --overwrite flag"
usage
fi
fi
if [ "$SECRETS_FOUND" -eq "0" ]; then
cp secrets.env.example secrets.env
loadSecrets
fi
echo "Configuring Stoat with hostname $DOMAIN"
STOAT_HOSTNAME="https://$DOMAIN"
read -rp "Would you like to place Stoat behind another reverse proxy? [y/N]: "
if [ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ]; then
echo "Yes received. Configuring for reverse proxy."
STOAT_HOSTNAME=':80'
echo "Writing compose.override.yml..."
echo "services:" > compose.override.yml
echo " caddy:" >> compose.override.yml
echo " ports: !override" >> compose.override.yml
echo " - \"8880:80\"" >> compose.override.yml
echo "caddy is configured to host on :8880. If you need a different port, modify the compose.override.yml."
echo "STOAT_DOMAIN=" > .env
else
echo "No received. Configuring with built in caddy as primary reverse proxy."
echo "STOAT_DOMAIN=$DOMAIN" > .env
fi
read -rp "Would you like to enable camera and screen sharing? [Y/n]: "
if [ "$REPLY" = "n" ] || [ "$REPLY" = "N" ]; then
echo "No received. Not configuring video."
else
echo "Yes received. Configuring video."
VIDEO_ENABLED=true
fi
# Generate secrets
echo "Generating secrets..."
if [ "$PUSHD_VAPID_PRIVATEKEY" = "" ]; then
if [ "$PUSHD_VAPID_PUBLICKEY" != "" ]; then
echo "VAPID public key is defined when private key isn't?"
echo "Did you forget to copy the PUSHD_VAPID_PRIVATEKEY secret?"
echo "Try removing PUSHD_VAPID_PUBLICKEY if you do not have a private key."
exit 1
fi
echo "Generating Pushd VAPID secrets..."
openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
PUSHD_VAPID_PRIVATEKEY=$(base64 -i vapid_private.pem | tr -d '\n' | tr -d '=')
PUSHD_VAPID_PUBLICKEY=$(openssl ec -in vapid_private.pem -outform DER|tail --bytes 65|base64|tr '/+' '_-'|tr -d '\n'|tr -d '=')
rm vapid_private.pem
echo "" >> secrets.env
printf "PUSHD_VAPID_PRIVATEKEY='%s'\n" $PUSHD_VAPID_PRIVATEKEY >> secrets.env
printf "PUSHD_VAPID_PUBLICKEY='%s'\n" $PUSHD_VAPID_PUBLICKEY >> secrets.env
elif [ "$PUSHD_VAPID_PUBLICKEY" = "" ]; then
echo "VAPID private key is defined when public key isn't?"
echo "Did you forget to copy the PUSHD_VAPID_PUBLICKEY secret?"
echo "Try removing PUSHD_VAPID_PRIVATEKEY if you do not have a public key."
exit 1
else
echo "Using old Pushd VAPID secrets..."
fi
if [ "$FILES_ENCRYPTION_KEY" = "" ]; then
echo "Generating files encryption secret..."
FILES_ENCRYPTION_KEY=$(openssl rand -base64 32)
echo "" >> secrets.env
printf "FILES_ENCRYPTION_KEY='%s'\n" $FILES_ENCRYPTION_KEY >> secrets.env
else
echo "Using old files encryption secret..."
fi
if [ "$LIVEKIT_WORLDWIDE_SECRET" = "" ]; then
if [ "$LIVEKIT_WORLDWIDE_KEY" != "" ]; then
echo "Livekit public key is defined when secret isn't?"
echo "Did you forget to copy the LIVEKIT_WORLDWIDE_SECRET secret?"
echo "Try removing LIVEKIT_WORLDWIDE_KEY if you do not have a secret."
exit 1
fi
echo "Generating Livekit secrets..."
LIVEKIT_WORLDWIDE_SECRET=$(openssl rand -hex 24)
LIVEKIT_WORLDWIDE_KEY=$(openssl rand -hex 6)
echo "" >> secrets.env
printf "LIVEKIT_WORLDWIDE_SECRET='%s'\n" $LIVEKIT_WORLDWIDE_SECRET >> secrets.env
printf "LIVEKIT_WORLDWIDE_KEY='%s'\n" $LIVEKIT_WORLDWIDE_KEY >> secrets.env
elif [ "$LIVEKIT_WORLDWIDE_KEY" = "" ]; then
echo "Livekit secret is defined when public key isn't?"
echo "Did you forget to copy the LIVEKIT_WORLDWIDE_KEY secret?"
echo "Try removing LIVEKIT_WORLDWIDE_SECRET if you do not have a public key."
exit 1
else
echo "Using old Livekit secrets..."
echo "Existing config found, running this script will overwrite your existing config and make your previously uploaded files innaccesible. Are you sure you'd like to reconfigure?"
select yn in "Yes" "No"; do
case $yn in
No ) exit;;
Yes ) mv Revolt.toml Revolt.toml.old && mv livekit.yml livekit.yml.old && break;;
esac
done
fi
# set hostname for Caddy and vite variables
echo "HOSTNAME=$STOAT_HOSTNAME" > .env.web
echo "REVOLT_PUBLIC_URL=https://$DOMAIN/api" >> .env.web
echo "VITE_API_URL=https://$DOMAIN/api" >> .env.web
echo "VITE_WS_URL=wss://$DOMAIN/ws" >> .env.web
echo "VITE_MEDIA_URL=https://$DOMAIN/autumn" >> .env.web
echo "VITE_PROXY_URL=https://$DOMAIN/january" >> .env.web
echo "VITE_CFG_ENABLE_VIDEO=$VIDEO_ENABLED" >> .env.web
echo "HOSTNAME=https://$1" > .env.web
echo "REVOLT_PUBLIC_URL=https://$1/api" >> .env.web
echo "VITE_API_URL=https://$1/api" >> .env.web
echo "VITE_WS_URL=wss://$1/ws" >> .env.web
echo "VITE_MEDIA_URL=https://$1/autumn" >> .env.web
echo "VITE_PROXY_URL=https://$1/january" >> .env.web
# hostnames
echo "[hosts]" > Revolt.toml
echo "app = \"https://$DOMAIN\"" >> Revolt.toml
echo "api = \"https://$DOMAIN/api\"" >> Revolt.toml
echo "events = \"wss://$DOMAIN/ws\"" >> Revolt.toml
echo "autumn = \"https://$DOMAIN/autumn\"" >> Revolt.toml
echo "january = \"https://$DOMAIN/january\"" >> Revolt.toml
echo "app = \"https://$1\"" >> Revolt.toml
echo "api = \"https://$1/api\"" >> Revolt.toml
echo "events = \"wss://$1/ws\"" >> Revolt.toml
echo "autumn = \"https://$1/autumn\"" >> Revolt.toml
echo "january = \"https://$1/january\"" >> Revolt.toml
# livekit hostname
echo "" >> Revolt.toml
echo "[hosts.livekit]" >> Revolt.toml
echo "worldwide = \"wss://$DOMAIN/livekit\"" >> Revolt.toml
echo "worldwide = \"wss://$1/livekit\"" >> Revolt.toml
# VAPID keys
echo "" >> Revolt.toml
echo "[pushd.vapid]" >> Revolt.toml
echo "private_key = \"$PUSHD_VAPID_PRIVATEKEY\"" >> Revolt.toml
echo "public_key = \"$PUSHD_VAPID_PUBLICKEY\"" >> Revolt.toml
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 "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
# encryption key for files
echo "" >> Revolt.toml
echo "[files]" >> Revolt.toml
echo "encryption_key = \"$FILES_ENCRYPTION_KEY\"" >> Revolt.toml
echo "encryption_key = \"$(openssl rand -base64 32)\"" >> Revolt.toml
livekit_key=$(openssl rand -hex 6)
livekit_secret=$(openssl rand -hex 24)
# livekit yml
echo "rtc:" > livekit.yml
@@ -206,10 +61,10 @@ echo "turn:" >> livekit.yml
echo " enabled: false" >> livekit.yml
echo "" >> livekit.yml
echo "keys:" >> livekit.yml
echo " $LIVEKIT_WORLDWIDE_KEY: $LIVEKIT_WORLDWIDE_SECRET" >> livekit.yml
echo " $livekit_key: $livekit_secret" >> livekit.yml
echo "" >> livekit.yml
echo "webhook:" >> livekit.yml
echo " api_key: $LIVEKIT_WORLDWIDE_KEY" >> livekit.yml
echo " api_key: $livekit_key" >> livekit.yml
echo " urls:" >> livekit.yml
echo " - \"http://voice-ingress:8500/worldwide\"" >> livekit.yml
@@ -219,23 +74,5 @@ echo "[api.livekit.nodes.worldwide]" >> Revolt.toml
echo "url = \"http://livekit:7880\"" >> Revolt.toml
echo "lat = 0.0" >> Revolt.toml
echo "lon = 0.0" >> Revolt.toml
echo "key = \"$LIVEKIT_WORLDWIDE_KEY\"" >> Revolt.toml
echo "secret = \"$LIVEKIT_WORLDWIDE_SECRET\"" >> Revolt.toml
# Video config
# We need to address issue https://github.com/stoatchat/stoatchat/issues/588 until we adopt a backend version later than 0.12.0
# We'll enable 1080p video by default, that should be high enough for most users.
if [[ -n "$VIDEO_ENABLED" ]]; then
echo "" >> Revolt.toml
echo "[features.limits.new_user]" >> Revolt.toml
echo "video_resolution = [1920, 1080]" >> Revolt.toml
echo "video_aspect_ratio = [0.3, 10]" >> Revolt.toml
echo "" >> Revolt.toml
echo "[features.limits.default]" >> Revolt.toml
echo "video_resolution = [1920, 1080]" >> Revolt.toml
echo "video_aspect_ratio = [0.3, 10]" >> Revolt.toml
fi
if [[ $IS_OVERWRITING -eq 1 ]]; then
echo "Overwrote existing config. If any custom configuration was present in old Revolt.toml, you may now copy it over from Revolt.toml.old."
fi
echo "key = \"$livekit_key\"" >> Revolt.toml
echo "secret = \"$livekit_secret\"" >> Revolt.toml

19
livekit.yml Normal file
View File

@@ -0,0 +1,19 @@
rtc:
use_external_ip: true
port_range_start: 50000
port_range_end: 50100
tcp_port: 7881
redis:
address: redis:6379
turn:
enabled: false
keys:
317d0847b3a2: 5a25b201ae80573c064e01b7387e7ac6fa99b0039a128dff
webhook:
api_key: 317d0847b3a2
urls:
- "http://voice-ingress:8500/worldwide"

View File

@@ -1,45 +0,0 @@
# DO NOT EDIT secrets.env.example - copy it to secrets.env then edit it as
# instructed.
#
# This file is for storing secrets for your Stoat instance safely. To use the
# secrets file, copy secrets.env.example to secrets.env with the command:
# cp secrets.env.example secrets.env
#
# Secrets must be stored in .env format, and will never be overwritten by the
# generate_config.sh script. The generate_config.sh script will first check
# secrets.env for secrets, and if a secret exists it will use that secret. If
# it does not exist, it will generate a new one and write it to secrets.env. If
# generate_config.sh creates new secrets, they will be added to the end of the
# file.
#
# You should only need to modify secrets.env manually once, then after that
# generate_config.sh will manage it. If you need to add a secret, uncomment the
# line the secret is on by removing the # and the space before the name of the
# secret and paste the secret after the equals sign, with single quote marks
# surrounding the secret. Example secrets are provided to demonstrate.
#
# This is an example secret
VALID_SECRET_EXAMPLE='example_secret'
#
# This is also an example secret
VALID_SECRET_EXAMPLE_2='This is an example secret'
#
# Pushd VAPID private key is the value stored in the [pushd.vapid] section of
# Revolt.toml for the private_key line.
# PUSHD_VAPID_PRIVATEKEY=
#
# Pushd VAPID public key is the value stored in the [pushd.vapid] section of
# Revolt.toml for the public_key line.
# PUSHD_VAPID_PUBLICKEY=
#
# Files encryption key is the value stored in the [files] section of
# Revolt.toml for the encryption_key line.
# FILES_ENCRYPTION_KEY=
#
# Livekit worldwide key is the value stored in the
# [api.livekit.nodes.worldwide] section of Revolt.toml for the key line.
# LIVEKIT_WORLDWIDE_KEY=
#
# Livekit worldwide secret is the value stored in the
# [api.livekit.nodes.worldwide] section of Revolt.toml for the secret line.
# LIVEKIT_WORLDWIDE_SECRET=