Open Midou36O opened 2 years ago
@zicklag anything to add from your self-hosting experience?
I can see how people can have a hard time with hosting Revolt. It's actually pretty simple, but the more services there are, the more confusing things get, especially if you're not used to server stuff.
It was pretty easy for me, but I've had years to get my self-hosting setup refined.
I used Traefik for a reverse proxy, and Traefik made it super easy to setup.
Here's a best-effort, as quick as I coud write it guide for setting it up, just in case it helps anybody:
https://gist.github.com/zicklag/c5adbf9bf4c5adb7640ed3e752c9eb28
It ended up including some bonuses including a Portainer web UI and backup system, but again, this is all best effort and the guide might not quite work exactly if you try to follow it. I'm not sure!
I'm also trying to setup revolt behind nginx reverse proxy, I followed the instructions in the readme and now the custom port (9008) just redirects me to 443.
I can't understand writing everywhere here for the sake of a custom port ":80" or not? If not, what should be written here?
Sorry in advance for not the best English
P.S. the page in the browser was painted before, but now it is empty
I have finally solved this. This is my configuration
# Redis
REDIS_URI=redis://redis/
# Hostname used for Caddy
# This should in most cases match REVOLT_APP_URL
HOSTNAME=:80
# URL to where the Revolt app is publicly accessible
REVOLT_APP_URL=https://revolt.mydomain.net
# URL to where the API is publicly accessible
REVOLT_PUBLIC_URL=https://revolt.mydomain.net/api
VITE_API_URL=https://revolt.mydomain.net/api
# URL to where the WebSocket server is publicly accessible
REVOLT_EXTERNAL_WS_URL=wss://revolt.mydomain.net/ws
# URL to where Autumn is publicly available
AUTUMN_PUBLIC_URL=https://revolt.mydomain.net/autumn
# URL to where January is publicly available
JANUARY_PUBLIC_URL=https://revolt.mydomain.net/january
...
(revolt.mydomain.net
is a placeholder, i changed it to my actual domain)
So my first attempt was with my Nginx proxy manager, I was routing traffic straight to the revolt_web_1
on port 5000 with scheme https
which was a mistake and also the HOSTNAME
env variable was https://revolt.mydomain.net
version: "3.8"
services:
database: image: mongo restart: always volumes:
redis: image: eqalpha/keydb restart: always networks:
minio: image: minio/minio command: server /data env_file: .env volumes:
caddy: image: caddy restart: always env_file: .env volumes:
api: image: ghcr.io/revoltchat/server:20220715-1 env_file: .env depends_on:
events: image: ghcr.io/revoltchat/bonfire:20220715-1 env_file: .env depends_on:
web: image: ghcr.io/revoltchat/client:master env_file: .env depends_on:
autumn: image: ghcr.io/revoltchat/autumn:1.1.5 env_file: .env depends_on:
january: image: ghcr.io/revoltchat/january:master depends_on:
createbuckets: image: minio/mc depends_on:
Note the ``
networks:
I routed all traffic to the caddy server using the hostname feature with the scheme http
and port 80
(I have not tested routing traffic through using scheme https
and 443
yet)
Instead of deleting all containers and doing docker-compose up -d
, I have just done docker-compose up -d
and it updated the .env for the containers. If this does not work for you then just delete the containers, volumes etc and then do docker-compose up -d
for a fresh install
In cloudflare, I purged all cache and purged cache for the browser and it works!
I hope this guide helps you guys out.
This is all the settings i've done
I have finally solved this. This is my configuration
# Redis REDIS_URI=redis://redis/ # Hostname used for Caddy # This should in most cases match REVOLT_APP_URL HOSTNAME=:80 # URL to where the Revolt app is publicly accessible REVOLT_APP_URL=https://revolt.mydomain.net # URL to where the API is publicly accessible REVOLT_PUBLIC_URL=https://revolt.mydomain.net/api VITE_API_URL=https://revolt.mydomain.net/api # URL to where the WebSocket server is publicly accessible REVOLT_EXTERNAL_WS_URL=wss://revolt.mydomain.net/ws # URL to where Autumn is publicly available AUTUMN_PUBLIC_URL=https://revolt.mydomain.net/autumn # URL to where January is publicly available JANUARY_PUBLIC_URL=https://revolt.mydomain.net/january ...
(
revolt.mydomain.net
is a placeholder, i changed it to my actual domain)So my first attempt was with my Nginx proxy manager, I was routing traffic straight to the
revolt_web_1
on port 5000 with schemehttps
which was a mistake and also theHOSTNAME
env variable was https://revolt.mydomain.netHow I got it working
1. I put all the containers on the nginx proxy manager network using this config:
version: "3.8" services: # MongoDB database database: image: mongo restart: always volumes: - ./data/db:/data/db networks: - nginx-proxy-manager_default # Redis server redis: image: eqalpha/keydb restart: always networks: - nginx-proxy-manager_default # S3-compatible storage server minio: image: minio/minio command: server /data env_file: .env volumes: - ./data/minio:/data restart: always networks: - nginx-proxy-manager_default # Caddy web server caddy: image: caddy restart: always env_file: .env volumes: - ./Caddyfile:/etc/caddy/Caddyfile - ./data/caddy-data:/data - ./data/caddy-config:/config networks: - nginx-proxy-manager_default hostname: caddy # API server (delta) api: image: ghcr.io/revoltchat/server:20220715-1 env_file: .env depends_on: - database - redis - caddy restart: always networks: - nginx-proxy-manager_default # Events service (quark) events: image: ghcr.io/revoltchat/bonfire:20220715-1 env_file: .env depends_on: - database - redis - caddy restart: always networks: - nginx-proxy-manager_default # Web App (revite) web: image: ghcr.io/revoltchat/client:master env_file: .env depends_on: - caddy restart: always networks: - nginx-proxy-manager_default # File server (autumn) autumn: image: ghcr.io/revoltchat/autumn:1.1.5 env_file: .env depends_on: - database - createbuckets - caddy environment: - AUTUMN_MONGO_URI=mongodb://database restart: always networks: - nginx-proxy-manager_default # Metadata and image proxy (january) january: image: ghcr.io/revoltchat/january:master depends_on: - caddy restart: always networks: - nginx-proxy-manager_default # Create buckets for minio. createbuckets: image: minio/mc depends_on: - minio env_file: .env entrypoint: > /bin/sh -c " while ! curl -s --output /dev/null --connect-timeout 1 http://minio:9000; do echo 'Waiting minio...' && sleep 0.1; done; /usr/bin/mc alias set minio http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD; /usr/bin/mc mb minio/attachments; /usr/bin/mc mb minio/avatars; /usr/bin/mc mb minio/backgrounds; /usr/bin/mc mb minio/icons; /usr/bin/mc mb minio/banners; /usr/bin/mc mb minio/emojis; exit 0; " networks: - nginx-proxy-manager_default networks: nginx-proxy-manager_default: external: true
Note the
networks: - nginx-proxy-manager_default
on each service2. I routed all traffic to the caddy server using the hostname feature with the scheme `http` and port `80` (I have not tested routing traffic through using scheme `https` and `443` yet) 3. Instead of deleting all containers and doing `docker-compose up -d`, I have just done `docker-compose up -d` and it updated the .env for the containers. If this does not work for you then just delete the containers, volumes etc and then do `docker-compose up -d` for a fresh install 4. In cloudflare, I purged all cache and purged cache for the browser and it works!
I hope this guide helps you guys out.
@markiemm first of all I followed your guide and it was very helpful.
The main takeaway is that if you are using a reverse proxy you must set your hostname to :80, I'm using traefik, and using :433 did not work unfortunately.
Since everything goes through Caddy anyways, you only need to have it in the reverse proxy network.
I have a similar config but with traefik, and only Caddy is in the traefik_default
network.
I didn't need to set any header middlewares, but I do have insecureSkipVerify
enabled in the traefik.yml
file.
I'm interested about pure minimal config without Cloudfare and using certificate from Letsencrypt and nginx as a reverse proxy. I'm using no-ip.com DDNS as a domain.
Managed to get rid of NETWORKERROR message, when registering an account - now it's working, but now I have UNKNOWNERROR when logging in with existing account. Console showing problems while connecting to wss Websocket endpoint.
I have very similar config to : https://github.com/revoltchat/self-hosted/issues/25#issuecomment-1467010464 But without proxy managers (which shouldn't be a part of the game) + caddy config based on the official manual ("1234:80")
Nginx location points to: http://localhost:1234
I assume, the problem is very obvious, but I can't figure out. Trying to guess the solution for 2 days already.
I'm interested about pure minimal config without Cloudfare and using certificate from Letsencrypt and nginx as a reverse proxy. I'm using no-ip.com DDNS as a domain.
Managed to get rid of NETWORKERROR message, when registering an account - now it's working, but now I have UNKNOWNERROR when logging in with existing account. Console showing problems while connecting to wss Websocket endpoint.
I have very similar config to : #25 (comment) But without proxy managers (which shouldn't be a part of the game) + caddy config based on the official manual ("1234:80")
Nginx location points to: http://localhost:1234
I assume, the problem is very obvious, but I can't figure out. Trying to guess the solution for 2 days already.
Despite the readme stating how to do it correctly I removed the caddy entry from docker-compose and exposed the ports again. My nginx config uses subdomains maybe that somehows works better on your setup as well. I'll just leave my setup here maybe it can help you a bit.
Despite the readme stating how to do it correctly I removed the caddy entry from docker-compose and exposed the ports again. My nginx config uses subdomains maybe that somehows works better on your setup as well. I'll just leave my setup here maybe it can help you a bit.
Thanks a lot for your config. After 1 more hour I've managed to launch the instance without Cloudfare, additional domain mappings, using Letsencrypt cert and no-ip secondary level domain.
In docker-compose.yml I've changed only these lines for caddy initially (removed https):
ports:
- "1234:80"
#- "443:443"
My .env file header:
HOSTNAME=:80
REVOLT_APP_URL=https://mynoipdomain.org
REVOLT_PUBLIC_URL=https://mynoipdomain.org/api
VITE_API_URL=https://mynoipdomain.org/api
REVOLT_EXTERNAL_WS_URL=wss://mynoipdomain.org/ws
AUTUMN_PUBLIC_URL=https://mynoipdomain.org/autumn
JANUARY_PUBLIC_URL=https://mynoipdomain.org/january
But, the problem was in Nginx (location part) actually (I guess).
Instead of
proxy_set_header Connection upgrade;
I've put
proxy_set_header Connection $http_connection;
as per your sample:
location / {
proxy_pass http://localhost:1234/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_http_version 1.1;
}
I still have some errors in console, but those are really minor comparing to that challenge I had.
Thanks!
Also, I would like to document all the steps for beginners (and myself too for the future purpose) to configure secured self-hosted instance in a very detailed way (including domain, VPS registration and especially Nginx part)
I'm trying to make an invite-only server. Got the .env editing done, I proceed to the next step:
~/revolt# docker compose exec database mongosh
service "database" is not running container #1
Something tells me I haven't installed Mongo to the app's satisfaction, but I'm not sure how that's done. This is on a VPS running Debian 11.
Try running docker compose up -d
first. That is required to start the containers before the docker compose exec database mongosh
command executes the mongosh
command in the database
container.
That worked perfectly, thank you.
anyone experiencing revolt redirecting to itself?
here is my nginx config
server {
listen 80;
server_name chat.hbigroup.org;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name chat.hbigroup.org;
ssl_certificate /etc/letsencrypt/live/hbigroup.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hbigroup.org/privkey.pem;
location / {
proxy_pass http://127.0.0.1:46395;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
I've been struggling to self-host Revolt in docker with my NGINX reverse proxy for days now. I can't get it working via https.
No matter what I change I get some variant of this error. Replacing mydomain.com with my actual domain...
xhr.js:210 Mixed Content: The page at 'https://mydomain.com/login' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://mydomain.com/'. This request has been blocked; the content must be served over HTTPS.
All URLs that I can find have been adjusted for HTTPS, so what gives?
I tried changing all my environment variables to HTTPS instead of HTTP. Changed WS to WSS. I'm using a reverse proxy, so I set HOSTNAME to :80.
Maybe I need to do some work in NGINX proxy manager, but I can't figure out what's going on... Any tips?
@Fifthdread I fixed that by moving each service to its own subdomain
It's pain! Well documented! Im outside docker network with nginx. Must work too. Basicly the same . No Errors in Network / console, till i try to start voice chat........
i get:
Request URL: https://revolt.domain.com/api/channels/01HC3QM8FZT4WZS4M8V8KZMNPJ/join_call
Request Method: POST
Status Code: 400 Bad Request
Remote Address: 1.2.3.4:443
Referrer Policy: strict-origin-when-cross-origin
# Caddy web server
caddy:
image: caddy
restart: always
env_file: .env
ports:
- "88:80"
#- "443:443"
# Hostname used for Caddy
# This should in most cases match REVOLT_APP_URL
HOSTNAME=:80
# URL to where the Revolt app is publicly accessible
REVOLT_APP_URL=https://revolt.domain.com
# URL to where the API is publicly accessible
REVOLT_PUBLIC_URL=https://revolt.domain.com/api
VITE_API_URL=https://revolt.domain.com/api
# URL to where the WebSocket server is publicly accessible
REVOLT_EXTERNAL_WS_URL=wss://revolt.domain.com/ws
# URL to where Autumn is publicly available
AUTUMN_PUBLIC_URL=https://revolt.domain.com/autumn
# URL to where January is publicly available
JANUARY_PUBLIC_URL=https://revolt.domain.com/january
server {
listen 443 ssl;
server_name revolt.domain.com;
include ssl.conf;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
client_max_body_size 10G;
client_body_timeout 6000m;
fastcgi_buffers 64 4K;
client_header_timeout 6000m;
proxy_connect_timeout 6000m;
proxy_read_timeout 6000m;
proxy_send_timeout 6000m;
if ($http_upgrade) {
rewrite ^(.*)$ /ws_78dd759593f041bc970fd7eef8b0c4af$1;
}
location / {
proxy_pass http://localhost:88;
proxy_set_header Host $host;
}
location /ws_78dd759593f041bc970fd7eef8b0c4af/ {
proxy_pass http://localhost:88/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
# Important, to prevent ws from sending data for a long time and causing timeout disconnection.
proxy_read_timeout 24h;
}
}
somone got voice running? must be possible...i asked in the official supoprt channel from revolt and got the answer that voice is not running at the moment. but i tried it on the official webapp, not self hosted, it is working...so it must work selfhosted too. maybe without docker? I already tried it directly with port 80 and 443, no chance.
Cant generate api keys, cause gitlab.insrt.uk timed out. A Nightmare. https://gitlab.insrt.uk/revolt/delta/-/wikis/vapid
Took this, seems to work but smaller generated keys: https://tools.reactpwa.com/vapid?
somone got voice running? must be possible...i asked in the official supoprt channel from revolt and got the answer that voice is not running at the moment. but i tried it on the official webapp, not self hosted, it is working...so it must work selfhosted too. maybe without docker? I already tried it directly with port 80 and 443, no chance.
Same, I get an API error for vortex but I can't figure out why, the API seems to work for the rest.
Hello it is impossible for me to send a content whether it is photo or video I have a 422 error return. Do you have a solution thank you
This is all the settings i've done
![]()
![]()
![]()
@markiemm What is that second picture of? Is it a network device that you named nginx-proxy-manager_default?
I'm interested about pure minimal config without Cloudfare and using certificate from Letsencrypt and nginx as a reverse proxy. I'm using no-ip.com DDNS as a domain. Managed to get rid of NETWORKERROR message, when registering an account - now it's working, but now I have UNKNOWNERROR when logging in with existing account. Console showing problems while connecting to wss Websocket endpoint. I have very similar config to : #25 (comment) But without proxy managers (which shouldn't be a part of the game) + caddy config based on the official manual ("1234:80") Nginx location points to: http://localhost:1234 I assume, the problem is very obvious, but I can't figure out. Trying to guess the solution for 2 days already.
Despite the readme stating how to do it correctly I removed the caddy entry from docker-compose and exposed the ports again. My nginx config uses subdomains maybe that somehows works better on your setup as well. I'll just leave my setup here maybe it can help you a bit.
docker-compose.yml
version: "3.8" services: # MongoDB database database: image: mongo restart: always volumes: - ./data/db:/data/db # Redis server redis: image: eqalpha/keydb restart: always # S3-compatible storage server minio: image: minio/minio command: server /data env_file: .env volumes: - ./data/minio:/data restart: always ports: - "10000:9000" # API server (delta) api: image: ghcr.io/revoltchat/server:20230421-3 env_file: .env depends_on: - database - redis restart: always ports: - "8000:8000" # Events service (quark) events: image: ghcr.io/revoltchat/bonfire:20230421-3 env_file: .env depends_on: - database - redis restart: always ports: - "9000:9000" # Web App (revite) web: image: ghcr.io/revoltchat/client:master env_file: .env restart: always ports: - "5000:5000" # File server (autumn) autumn: image: ghcr.io/revoltchat/autumn:1.1.8 env_file: .env depends_on: - database - createbuckets environment: - AUTUMN_MONGO_URI=mongodb://database restart: always ports: - "3000:3000" # Metadata and image proxy (january) january: image: ghcr.io/revoltchat/january:master restart: always ports: - "7000:7000" # Create buckets for minio. createbuckets: image: minio/mc depends_on: - minio env_file: .env entrypoint: > /bin/sh -c " while ! curl -s --output /dev/null --connect-timeout 1 http://minio:9000; do echo 'Waiting minio...' && sleep 0.1; done; /usr/bin/mc alias set minio http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD; /usr/bin/mc mb minio/attachments; /usr/bin/mc mb minio/avatars; /usr/bin/mc mb minio/backgrounds; /usr/bin/mc mb minio/icons; /usr/bin/mc mb minio/banners; /usr/bin/mc mb minio/emojis; exit 0; "
.env nginx
map $http_host $revolt_upstream { revolt.YOUR.DOMAIN http://127.0.0.1:5000; api.revolt.YOUR.DOMAIN http://127.0.0.1:8000; ws.revolt.YOUR.DOMAIN http://127.0.0.1:9000; autumn.revolt.YOUR.DOMAIN http://127.0.0.1:3000; january.revolt.YOUR.DOMAIN http://127.0.0.1:7000; } server { server_name revolt.YOUR.DOMAIN api.revolt.YOUR.DOMAIN ws.revolt.YOUR.DOMAIN autumn.revolt.YOUR.DOMAIN january.revolt.YOUR.DOMAIN; listen 80; add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; client_max_body_size 10G; client_body_timeout 6000m; fastcgi_buffers 64 4K; client_header_timeout 6000m; proxy_connect_timeout 6000m; proxy_read_timeout 6000m; proxy_send_timeout 6000m; if ($http_upgrade) { rewrite ^(.*)$ /ws_78dd759593f041bc970fd7eef8b0c4af$1; } location / { proxy_pass $revolt_upstream; proxy_set_header Host $host; } location /ws_78dd759593f041bc970fd7eef8b0c4af/ { proxy_pass $revolt_upstream/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Connection $http_connection; proxy_set_header Upgrade $http_upgrade; # Important, to prevent ws from sending data for a long time and causing timeout disconnection. proxy_read_timeout 24h; } }
Using this has helped immensely, and I have now been able to get past the initial error on registering, but when I try to sign in after onboarding, I get the following error:
Trying to connect to the websocket locally results in it dropping the connection immediately
Any help would be greatly appreciated!
Edit: I missed the trailing the slash in proxy_pass $revolt_upstream/;
, adding that and removing the add_header Access-Control-Allow-Origin
that I tried adding to fix another issue did the trick!
Guide updated and improved with https://github.com/revoltchat/self-hosted/pull/97
Hello, i tried self hosting revolt through docker, sure enough the guide provided on readme worked. The problem is when creating an account on localhost i always get an error, furthermore, trying to proxying through nginx (using my own knowledge, which isn't really this advanced) made things worse as i didn't even knew what to proxy and what not. Would it be possible to write an actual complete guide to self host revolt? This defenitely would help people decentralize the service!