Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A comprehensive guide to self host revolt #25

Open
Midou36O opened this issue Dec 27, 2021 · 76 comments
Open

A comprehensive guide to self host revolt #25

Midou36O opened this issue Dec 27, 2021 · 76 comments
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed

Comments

@Midou36O
Copy link

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!

@insertish insertish added the enhancement New feature or request label Jan 5, 2022
@yllekz
Copy link

yllekz commented Jan 15, 2022

I would love this as well. The current Docker setup does not work. Trying to create an account results in an unhelpful network error. Either the app needs to be fixed or the documentation needs to be updated.

@maxwelljens
Copy link

Unable to deploy it either. Stuck at nondescript "Network Error" when trying to log in remotely. Locally works just fine, however.

@sigaloid
Copy link

sigaloid commented Feb 4, 2022

@maxwelljens : You need to edit the .env config file. Otherwise it defaults to Screenshot from 2022-02-04 14-56-32

Which resolves to localhost. When you're using it locally, of course it resolves to localhost which is the server; outside of that network, though, would load to their localhost which the server is not hosted at. I'm not quite sure why it can't use relative URL's but it does mention that the default config only works for localhost in the readme

@maxwelljens
Copy link

@sigaloid Thanks for your reply.

I am aware of the .env file configuration. I changed every address accordingly, and port forwarded every relevant port. It doesn't work in spite of that.

@sigaloid
Copy link

sigaloid commented Feb 4, 2022

Try pressing F12 when logging in. That will let you see which network address it's going to. If it's still "local.revolt.chat:8000" then it's an issue with the config not being loaded correctly somehow. Otherwise it could be a bug in your web proxy

@sigaloid
Copy link

sigaloid commented Feb 4, 2022

Oops. I just tried deploying it and hit the same problem :p it seems my .env config is not being picked up in the docker-compose.

@maxwelljens
Copy link

@sigaloid Interesting. Good to know I am not the only one with this problem. Do let everyone know in this issue if you find a solution or workaround. Thanks.

@sigaloid
Copy link

sigaloid commented Feb 4, 2022

Okay so. Basic setup, just cloned the repo, edited .env to have different URL's for the API, but it still sends requests to http://local.revolt.chat:8000/auth/account/create. This seems to me like a problem with the environment variables because there's no configuration changes that are actually going through to the Delta server.

Basically, changing the API server in the .env has zero effect on the resulting containers. Did this on a fresh install. Looking like a bug in the docker compose setup to me at this point, maybe the env variables in the docker-compose.yml are not being properly retrieved?

Or maybe the ones in revoltchat/delta/docker-compose.yml supercede it... That would make sense because the ones there are the ones being used.

Anyway I am yet to find a solution. Unfortunately this is blocking me from deploying this awesome software ;(

@mirkoRainer
Copy link

I just cloned the repo and am able to get a local version up and running just using docker compose up.
I did have to adjust some of the port binding for my host machine due to conflicts but that was obvious in the logs.
i.e. I changed 5000 to 42069 for the web app 5000:5000 became 42069:5000 and I can access Revolt using 127.0.0.1:42069 or local.revolt.chat:42069.

What do logs look like when you run docker compose up?

@sigaloid
Copy link

sigaloid commented Feb 5, 2022

For example, try changing REVOLT_APP_URL in the .env to some random domain and see if that's where the network requests go when you restart it. (Press F12 and try registering)

This is the scenario I had trouble with

@Razorback360
Copy link

@sigaloid Thanks for your reply.

I am aware of the .env file configuration. I changed every address accordingly, and port forwarded every relevant port. It doesn't work in spite of that.

Same issue over here, nothing I do is working. Tried adding URLs in the docker-compose.yml environment but to no avail

@sigaloid
Copy link

sigaloid commented Feb 6, 2022

https://asciinema.org/a/fqCutcwDYY2jK4mMcI6ewj1W8

Okay, so I re-pulled the docker container on my local PC rather than my VPS (sudo docker pull revoltchat/server:master) and did this to the .env file (even though it's gibberish). Oddly enough, when I attempted to register, it successfully sent it to the new domain I entered in the .env file. This means that I did succeed in making my config changes save.

I don't even know what I did differently (i did basically everything the same). And I still cannot make it work on the server.

I've been trying to fix this and running against a wall about this for days now. It's gotta be something really basic I'm overlooking.

@sigaloid
Copy link

sigaloid commented Feb 6, 2022

Starting from a fresh Docker install, my Fedora box can follow the directuions and persist config changes, but my Debian box cannot. Side by side, completely brand new environment... What OS are you on, @Razorback360 @mirkoRainer @maxwelljens ?

@maxwelljens
Copy link

@sigaloid My server is on Fedora 34.

@mirkoRainer
Copy link

mirkoRainer commented Feb 6, 2022 via email

@Razorback360
Copy link

Starting from a fresh Docker install, my Fedora box can follow the directuions and persist config changes, but my Debian box cannot. Side by side, completely brand new environment... What OS are you on, @Razorback360 @mirkoRainer @maxwelljens ?

I'm on Ubuntu.

@Ikun886-cxk
Copy link

https://asciinema.org/a/fqCutcwDYY2jK4mMcI6ewj1W8

Okay, so I re-pulled the docker container on my local PC rather than my VPS (sudo docker pull revoltchat/server:master) and did this to the .env file (even though it's gibberish). Oddly enough, when I attempted to register, it successfully sent it to the new domain I entered in the .env file. This means that I did succeed in making my config changes save.

I don't even know what I did differently (i did basically everything the same). And I still cannot make it work on the server.

I've been trying to fix this and running against a wall about this for days now. It's gotta be something really basic I'm overlooking.

I think you need to refresh the cache. I tried to open the website in the browser's traceless mode, and the problem was successfully solved.

@Ikun886-cxk
Copy link

Here is an example of nginx.

map $http_host $revolt_upstream {
  example.com http://127.0.0.1:5000;
  api.example.com http://127.0.0.1:8000;
  ws.example.com http://127.0.0.1:9000;
  autumn.example.com http://127.0.0.1:3000;
  january.example.com http://127.0.0.1:7000;
  vortex.example.com http://127.0.0.1:8080;
}

server {
  listen 80;
  listen 443 ssl http2;
  server_name example.com *.example.com;

  # SSL 

  if ($http_upgrade) {
    # Here, the path is used to reverse the generation of ws. Just roll the keyboard to prevent conflicts with other services.
    rewrite ^(.*)$ /ws_78dd759593f041bc970fd7eef8b0c4af$1;
  }

  location / {
    proxy_pass $revolt_upstream;
    proxy_set_header Host $host;
  }

  location /ws_78dd759593f041bc970fd7eef8b0c4af/ {
    # Note that here is the trailing slash.
    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;
  }
}

@sigaloid
Copy link

sigaloid commented Feb 7, 2022

asciinema.org/a/fqCutcwDYY2jK4mMcI6ewj1W8
Okay, so I re-pulled the docker container on my local PC rather than my VPS (sudo docker pull revoltchat/server:master) and did this to the .env file (even though it's gibberish). Oddly enough, when I attempted to register, it successfully sent it to the new domain I entered in the .env file. This means that I did succeed in making my config changes save.
I don't even know what I did differently (i did basically everything the same). And I still cannot make it work on the server.
I've been trying to fix this and running against a wall about this for days now. It's gotta be something really basic I'm overlooking.

I think you need to refresh the cache. I tried to open the website in the browser's traceless mode, and the problem was successfully solved.

Wow. My goodness. Is this some sort of caching issue? I disabled cache, refreshed, rebooted, etc and nothing fixed the issue. Are these resources aggressively cached?

Regardless, the fix is to NOT START THE DOCKER CONTAINER until you've set up the env file. I started the docker container to make sure the images were downloaded, then I stopped it to configure it. Thank you so much @SurpriseLon that saved me from a few more days of confusion!!

@Razorback360
Copy link

Regardless, the fix is to NOT START THE DOCKER CONTAINER until you've set up the env file. I started the docker container to make sure the images were downloaded, then I stopped it to configure it. Thank you so much @SurpriseLon that saved me from a few more days of confusion!!

Solution mentioned here does not work for me. I have completely deleted the docker compose, removed all containers and their data, configured the .env, then deployed the compose and yet it is still the same issue. I am running on Ubuntu 20.04.3 LTS

@sigaloid
Copy link

sigaloid commented Feb 7, 2022

A few things I can think of: Are you editing the .env.example? Make sure you cp .env.example .env and change the config in .env. Then, try in incognito mode or in a fresh browser - the javascript containing the server is heavily cached and the filename isn't dynamically changed based on its hash, so it will never re-request it. I even did F12 - disable cache and it didn't help. Only trying in incognito + Ctrl+F5'ing helped.

@Alauraa
Copy link

Alauraa commented Feb 10, 2022

Here is an example of nginx.

map $http_host $revolt_upstream {
  example.com http://127.0.0.1:5000;
  api.example.com http://127.0.0.1:8000;
  ws.example.com http://127.0.0.1:9000;
  autumn.example.com http://127.0.0.1:3000;
  january.example.com http://127.0.0.1:7000;
  vortex.example.com http://127.0.0.1:8080;
}

server {
  listen 80;
  listen 443 ssl http2;
  server_name example.com *.example.com;

  # SSL 

  if ($http_upgrade) {
    # Here, the path is used to reverse the generation of ws. Just roll the keyboard to prevent conflicts with other services.
    rewrite ^(.*)$ /ws_78dd759593f041bc970fd7eef8b0c4af$1;
  }

  location / {
    proxy_pass $revolt_upstream;
    proxy_set_header Host $host;
  }

  location /ws_78dd759593f041bc970fd7eef8b0c4af/ {
    # Note that here is the trailing slash.
    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;
  }
}

On this nginx config, would i need to make all those domains? As well as, can i not just reverse proxy those domains to the ports that they are on?

@Ikun886-cxk
Copy link

Here is an example of nginx.

map $http_host $revolt_upstream {
  example.com http://127.0.0.1:5000;
  api.example.com http://127.0.0.1:8000;
  ws.example.com http://127.0.0.1:9000;
  autumn.example.com http://127.0.0.1:3000;
  january.example.com http://127.0.0.1:7000;
  vortex.example.com http://127.0.0.1:8080;
}

server {
  listen 80;
  listen 443 ssl http2;
  server_name example.com *.example.com;

  # SSL 

  if ($http_upgrade) {
    # Here, the path is used to reverse the generation of ws. Just roll the keyboard to prevent conflicts with other services.
    rewrite ^(.*)$ /ws_78dd759593f041bc970fd7eef8b0c4af$1;
  }

  location / {
    proxy_pass $revolt_upstream;
    proxy_set_header Host $host;
  }

  location /ws_78dd759593f041bc970fd7eef8b0c4af/ {
    # Note that here is the trailing slash.
    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;
  }
}

On this nginx config, would i need to make all those domains? As well as, can i not just reverse proxy those domains to the ports that they are on?

Yes,you can

@Alauraa
Copy link

Alauraa commented Feb 14, 2022

Here is an example of nginx.

map $http_host $revolt_upstream {
  example.com http://127.0.0.1:5000;
  api.example.com http://127.0.0.1:8000;
  ws.example.com http://127.0.0.1:9000;
  autumn.example.com http://127.0.0.1:3000;
  january.example.com http://127.0.0.1:7000;
  vortex.example.com http://127.0.0.1:8080;
}

server {
  listen 80;
  listen 443 ssl http2;
  server_name example.com *.example.com;

  # SSL 

  if ($http_upgrade) {
    # Here, the path is used to reverse the generation of ws. Just roll the keyboard to prevent conflicts with other services.
    rewrite ^(.*)$ /ws_78dd759593f041bc970fd7eef8b0c4af$1;
  }

  location / {
    proxy_pass $revolt_upstream;
    proxy_set_header Host $host;
  }

  location /ws_78dd759593f041bc970fd7eef8b0c4af/ {
    # Note that here is the trailing slash.
    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;
  }
}

On this nginx config, would i need to make all those domains? As well as, can i not just reverse proxy those domains to the ports that they are on?

Yes,you can

So this doesn't exactly answer my question, there was 2 in the sentence, just a yes doesn't help. Sorry for any confusion or etc.

@Cocam123
Copy link

Hello everyone.

Sorry for the inactivity I had here (I had no pc). But I put HTTPS on my server. Problem, now it's giving me "network error". Could my other site (also in https) cause this problem?

@whiskeytangofoxy
Copy link

whiskeytangofoxy commented Mar 15, 2022

Hello everyone.

Sorry for the inactivity I had here (I had no pc). But I put HTTPS on my server. Problem, now it's giving me "network error". Could my other site (also in https) cause this problem?

I'm also running into a myriad of issues when trying to convert a insecure instance of Revolt to https. I'm using the nginx config detailed in this same thread. Other than that, I've made no changes to my .env or docker-compose.yml beyond those that were required to get the insecure http-hosted version of my Revolt chat running. Any ideas? There seems to be an issue with an HTTP GET and a "Blocked loading mixed active content “http://[domain]:[port]/” error in the web dev console I cannot resolve.

@josealonso
Copy link

josealonso commented Apr 4, 2022

@maxwelljens : You need to edit the .env config file. Otherwise it defaults to Screenshot from 2022-02-04 14-56-32

Which resolves to localhost. When you're using it locally, of course it resolves to localhost which is the server; outside of that network, though, would load to their localhost which the server is not hosted at. I'm not quite sure why it can't use relative URL's but it does mention that the default config only works for localhost in the readme

I can see this screen, but I get this error message even before entering the password.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://local.revolt.chat:8000/.

That's on Firefox. On Chrome I don't exactly the same error messages

Failed to load resource: net::ERR_SOCKET_NOT_CONNECTED    :8000/1:

Uncaught (in promise) Error: Network Error         createError.js:16 
    at Np (vendor.aeef7222.js:12)
    at XMLHttpRequest.u.onerror (vendor.aeef7222.js:13)

I use Ubuntu 20.04.2 LTS

@zicklag
Copy link

zicklag commented Feb 5, 2023

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!

@TheToady
Copy link

TheToady commented Feb 5, 2023

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.

@YukiKras
Copy link

YukiKras commented Mar 6, 2023

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
image
P.S. the page in the browser was painted before, but now it is empty

@markiemm
Copy link

markiemm commented Mar 13, 2023

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

How 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 service

  1. 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)

  2. 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

  3. In cloudflare, I purged all cache and purged cache for the browser and it works!

I hope this guide helps you guys out.

@markiemm
Copy link

This is all the settings i've done
4
3
2
1

@MatveyMirman
Copy link

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

How 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 service

2. 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.

@demetera
Copy link

demetera commented Jun 3, 2023

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.

@Crashdummyy
Copy link

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
REVOLT_APP_URL=https://revolt.YOUR.DOMAIN
REVOLT_PUBLIC_URL=https://api.revolt.YOUR.DOMAIN
VITE_API_URL=https://api.revolt.YOUR.DOMAIN
REVOLT_EXTERNAL_WS_URL=wss://ws.revolt.YOUR.DOMAIN
AUTUMN_PUBLIC_URL=https://autumn.revolt.YOUR.DOMAIN
JANUARY_PUBLIC_URL=https://january.revolt.YOUR.DOMAIN
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;
  }
    
}

@demetera
Copy link

demetera commented Jun 4, 2023

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!

@demetera
Copy link

demetera commented Jun 4, 2023

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)

@GreaterJoe
Copy link

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.

@zicklag
Copy link

zicklag commented Jul 1, 2023

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.

@GreaterJoe
Copy link

That worked perfectly, thank you.

@GNUGradyn
Copy link

anyone experiencing revolt redirecting to itself?
image
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";
    }
}

@Fifthdread
Copy link

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?

@0dragosh
Copy link

0dragosh commented Aug 4, 2023

@Fifthdread I fixed that by moving each service to its own subdomain

@steel4me
Copy link

steel4me commented Oct 7, 2023

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;
        }
		
}

@steel4me
Copy link

steel4me commented Oct 8, 2023

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.

@steel4me
Copy link

steel4me commented Oct 9, 2023

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?

@Brandters
Copy link

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.
image

@killforby
Copy link

image
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

@NoahMoyer
Copy link

This is all the settings i've done 4 3 2 1

@markiemm What is that second picture of? Is it a network device that you named nginx-proxy-manager_default?

@mlclns
Copy link

mlclns commented Mar 23, 2024

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:

Screenshot 2024-03-23 at 13 01 42 Screenshot 2024-03-23 at 12 53 25

Trying to connect to the websocket locally results in it dropping the connection immediately

Screenshot 2024-03-23 at 12 59 44 Screenshot 2024-03-23 at 12 59 34

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!

@insertish insertish added good first issue Good for newcomers help wanted Extra attention is needed and removed enhancement New feature or request labels Mar 28, 2024
@DeclanChidlow
Copy link
Member

Guide updated and improved with #97

@GaMeRaM
Copy link

GaMeRaM commented Oct 8, 2024

Seems like vortex is missing from this configuration, which makes voice calls broken (400 VosoUnavailable). I've been logging my experience here revoltchat/revite#989 (sorry if its in unrelated repo)

UPD: Sorry. Read the whole conversation. Seems like vortex is not recommended for selfhosting and thus voice is not deployable at this time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed
Projects
Status: 🕒 Backlog
Development

No branches or pull requests