Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save apeshand/e663c1dc1bb5ff41e43f00d7c6bb702c to your computer and use it in GitHub Desktop.
Save apeshand/e663c1dc1bb5ff41e43f00d7c6bb702c to your computer and use it in GitHub Desktop.

Revolt with voice chat | Windows desktop client

NOTE

Im using external S3 service(currently YandexCloud; Minio is disabled) and Traefik, multiple domain names for every service of Revolt. The range of voice ports in the d-compose file has been reduced from [10000, 11000] -> [10000, 10100] due to the resources of the VM: I have a VM with 2 processors and 4 RAM, enabling a range with 1k ports leads to a loooooong start of the voice container and high consumption of VM resources.

Self-hosted Revolt with voice chat

Firstly - create an external docker network with name traefik_external:

docker network create traefik_external

.env file content

Change the following variables:

  • DOMAIN;
  • REVOLT_APP_URL;
  • REVOLT_PUBLIC_URL;
  • VITE_API_URL;
  • REVOLT_EXTERNAL_WS_URL;
  • AUTUMN_PUBLIC_URL;
  • JANUARY_PUBLIC_URL;
  • REVOLT_HCAPTCHA_KEY;
  • REVOLT_HCAPTCHA_SITEKEY;
  • REVOLT_VAPID_PRIVATE_KEY & REVOLT_VAPID_PUBLIC_KEY - instruction How to generate Ur own pair of keys;
  • AUTUMN_S3_REGION;
  • AUTUMN_S3_ENDPOINT;
  • AWS_ACCESS_KEY_ID;
  • AWS_SECRET_ACCESS_KEY;
  • MANAGE_TOKEN & VOSO_MANAGE_TOKEN - I used the command pwgen -1 16, values are equal;
  • RTC_MIN_PORT & RTC_MAX_PORT - range start at 10000 and end is 10100;
  • RTC_IPS - strings with IP, delimited with colons, looks like 0.0.0.0,YOUR.VM.HOST.IP
.env content hided due to its size
##
## Quark configuration
##

# MongoDB
MONGODB=mongodb://database

# Redis
REDIS_URI=redis://redis/

# Domain name
DOMAIN=beautiful-domain.name

# 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://beautiful-domain.name

# URL to where the API is publicly accessible
REVOLT_PUBLIC_URL=https://api.beautiful-domain.name
VITE_API_URL=https://api.beautiful-domain.name

# URL to where the WebSocket server is publicly accessible
REVOLT_EXTERNAL_WS_URL=wss://events.beautiful-domain.name

# URL to where Autumn is publicly available
AUTUMN_PUBLIC_URL=https://files.beautiful-domain.name

# URL to where January is publicly available
JANUARY_PUBLIC_URL=https://metadata.beautiful-domain.name


##
## hCaptcha Settings
##

# If you are sure that you don't want to use hCaptcha, set to 1.
REVOLT_UNSAFE_NO_CAPTCHA=0

# hCaptcha API key (This is the "Secret key" from your User Settings page)
REVOLT_HCAPTCHA_KEY=YOUR_HCAPTCHA_KEY

# hCaptcha site key
REVOLT_HCAPTCHA_SITEKEY=YOUR_HCAPTCHA_SITEKEY


##
## Email Settings
##

# If you are sure that you don't want to use email verification, set to 1.
REVOLT_UNSAFE_NO_EMAIL=1

# SMTP host
# REVOLT_SMTP_HOST=smtp.example.com

# SMTP username
# [email protected]

# SMTP password
# REVOLT_SMTP_PASSWORD=CHANGEME

# SMTP From header
# REVOLT_SMTP_FROM=Revolt <[email protected]>


##
## Application Settings
##

# Whether to only allow users to sign up if they have an invite code
REVOLT_INVITE_ONLY=1

# Maximum number of people that can be in a group chat
REVOLT_MAX_GROUP_SIZE=250

# VAPID keys for push notifications
# Generate using this guide: https://gitlab.insrt.uk/revolt/delta/-/wikis/vapid
# --> Please replace these keys before going into production! <--
REVOLT_VAPID_PRIVATE_KEY=YOUR_PRIVATE_KEY
REVOLT_VAPID_PUBLIC_KEY=YOUR_PUBLIC_KEY


##
## Autumn configuration
##

# S3 Region
AUTUMN_S3_REGION=ru-central1

# S3 Endpoint
AUTUMN_S3_ENDPOINT=https://some-bucket.storage.yandexcloud.net

# S3 Bucket prefix
# AUTUMN_S3_BUCKET_PREFIX=revolt-uploads

# MinIO Root User
# MINIO_ROOT_USER=minioautumn

# MinIO Root Password
# MINIO_ROOT_PASSWORD=minioautumn

# AWS Access Key ID
AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY_ID

# AWS Secret Key
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_ACCESS_KEY


##
## Vortex|Voso configuration
##

# The hostname to bind to.
HTTP_HOST=0.0.0.0:8080 # (default)

# The websocket URL to advertise.
WS_URL=wss://vortex.revolt.chat

# The token used for communication between Vortex and Delta.
MANAGE_TOKEN="Ahthoo8mosie5emo"
# The token used for communication between Vortex and Delta.
VOSO_MANAGE_TOKEN="Ahthoo8mosie5emo"

# The minimum port to use for WebRTC and RTP.
RTC_MIN_PORT=10000 # (default)

# The maximum port to use for WebRTC and RTP.
RTC_MAX_PORT=10100 # (not default)

# Disable RTP. The value 1 disables RTP, all other values or not set will enable RTP.
DISABLE_RTP=0 # (default)

# Semicolon separated list of IPs to use for WebRTC. Hostnames are not supported yet. Either combined or split listen and announce IPs.
RTC_IPS=0.0.0.0,256.257.258.259 # lol

Revolt.toml file

Change the following variables:

  • hosts.app;
  • hosts.api;
  • hosts.events;
  • hosts.autumn;
  • hosts.january;
  • hosts.voso_legacy;
  • hosts.voso_legacy_ws;
  • api.api.security.voso_legacy_token - same as MANAGE_TOKEN or VOSO_MANAGE_TOKEN in .env;
  • api.registration.invite_only - U can get instructions in Revolt self-hosted repository;
  • api.smtp.hosts - set it to "" if U have NO mail server;
  • files.encryption_key;
  • files.s3.endpoint;
  • files.s3.region;
  • files.s3.access_key_id;
  • files.s3.secret_access_key;
  • files.s3.default_bucket.
Revolt.toml content hided due to its size
# ⚠️ This configuration is intended for development environment.
# If you'd like to override anything, create a Revolt.override.toml

[database]
# MongoDB connection URL
# Defaults to the container name specified in self-hosted
mongodb = "mongodb://database"
# Redis connection URL
# Defaults to the container name specified in self-hosted
redis = "redis://redis/"

[hosts]
# Web locations of various services
# Defaults assume all services are reverse-proxied
# See https://github.com/revoltchat/self-hosted/blob/master/Caddyfile
#
# Remember to change these to https/wss where appropriate in production!
app = "https://beautiful-domain.name"
api = "https://api.beautiful-domain.name"
events = "wss://events.beautiful-domain.name"
autumn = "https://files.beautiful-domain.name"
january = "https://metadata.beautiful-domain.name"

# voice support
voso_legacy = "https://voso.beautiful-domain.name"
voso_legacy_ws = "wss://voso.beautiful-domain.name"

[api]

[api.security]
voso_legacy_token = "Ahthoo8mosie5emo"

[api.registration]
# Whether an invite should be required for registration
# See https://github.com/revoltchat/self-hosted#making-your-instance-invite-only
invite_only = true

[api.smtp]
# Email server configuration for verification
# Defaults to no email verification (host field is empty)
host = ""
username = "smtp"
password = "smtp"
from_address = "[email protected]"
reply_to = "[email protected]"
port = 14025
use_tls = false

[files]
# Encryption key for stored files
# Generate your own key using `openssl rand -base64 32`
encryption_key = "W6sL7QZigogvl5xFKdjR/DvaNuDA5GMHe4/98Qj0Lp8="
# Quality used for lossy WebP previews (set to 100 for lossless)
webp_quality = 80.0

[files.s3]
# S3 protocol endpoint
endpoint = "https://some-bucket.storage.yandexcloud.net"
# S3 region name
region = "ru-central1"
# S3 protocol key ID
access_key_id = "YOUR_ACCESS_KEY_ID"
# S3 protocol access key
secret_access_key = "YOUR_SECRET_ACCESS_KEY"
# Bucket to upload to by default
default_bucket = "some-bucket"

[files.limit]
# Minimum file size (in bytes)
min_file_size = 1
# Minimum image resolution
min_resolution = [1, 1]
# Maximum MP of images
max_mega_pixels = 40
# Maximum pixel side of an image
max_pixel_side = 10_000

[files.preview]
# Maximum image resolution
attachments = [1280, 1280]
avatars = [128, 128]
backgrounds = [1280, 720]
icons = [128, 128]
banners = [480, 480]
emojis = [128, 128]

[features]
# Feature gate options
webhooks_enabled = true

Revolt's compose.yml file

compose.yml content hided due to its size
services:
  # MongoDB database
  database:
    image: mongo
    restart: always
    networks:
      - revolt_nw
    volumes:
      - ./data/db:/data/db

  # Redis server
  redis:
    image: eqalpha/keydb
    restart: always
    networks:
      - revolt_nw

  # API server (delta)
  api:
    image: ghcr.io/revoltchat/server:20240929-1
    env_file: .env
    depends_on:
      - database
      - redis
    volumes:
      - ./Revolt.toml:/Revolt.toml
    restart: always
    networks:
      - revolt_nw
      - traefik_external
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_external"
      - "traefik.http.routers.rtr-revolt-api.entrypoints=websecure"
      - "traefik.http.routers.rtr-revolt-api.rule=Host(`api.${DOMAIN}`)"
      - "traefik.http.routers.rtr-revolt-api.tls=true"
      - "traefik.http.routers.rtr-revolt-api.tls.certResolver=letsencrypt"
      - "traefik.http.services.srv-revolt-api.loadbalancer.server.port=14702"

  # Events service (quark)
  events:
    image: ghcr.io/revoltchat/bonfire:20240929-1
    env_file: .env
    depends_on:
      - database
      - redis
    volumes:
      - ./Revolt.toml:/Revolt.toml
    restart: always
    networks:
      - revolt_nw
      - traefik_external
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_external"
      - "traefik.http.routers.rtr-revolt-events.rule=Host(`events.${DOMAIN}`)"
      - "traefik.http.routers.rtr-revolt-events.tls=true"
      - "traefik.http.routers.rtr-revolt-events.tls.certResolver=letsencrypt"
      - "traefik.http.services.srv-revolt-events.loadbalancer.server.port=9000"

  # Web App (revite)
  web:
    image: ghcr.io/revoltchat/client:master
    env_file: .env
    depends_on:
      - database
      - redis
    restart: always
    networks:
      - revolt_nw
      - traefik_external
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_external"
      - "traefik.http.routers.rtr-revolt-web.entrypoints=websecure"
      - "traefik.http.routers.rtr-revolt-web.rule=Host(`${DOMAIN}`)"
      - "traefik.http.routers.rtr-revolt-web.tls=true"
      - "traefik.http.routers.rtr-revolt-web.tls.certResolver=letsencrypt"
      - "traefik.http.services.srv-revolt-web.loadbalancer.server.port=5000"

  # File server (autumn)
  autumn:
    image: ghcr.io/revoltchat/autumn:1.1.11
    env_file: .env
    depends_on:
      - database
      - redis
    environment:
      - AUTUMN_MONGO_URI=mongodb://database
    restart: always
    networks:
      - revolt_nw
      - traefik_external
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_external"
      - "traefik.http.routers.rtr-revolt-files.rule=Host(`files.${DOMAIN}`)"
      - "traefik.http.routers.rtr-revolt-files.tls=true"
      - "traefik.http.routers.rtr-revolt-files.tls.certResolver=letsencrypt"
      - "traefik.http.services.srv-revolt-files.loadbalancer.server.port=3000"

  # Metadata and image proxy (january)
  january:
    image: ghcr.io/revoltchat/january:0.3.5
    depends_on:
      - database
      - redis
    restart: always
    networks:
      - revolt_nw
      - traefik_external
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_external"
      - "traefik.http.routers.rtr-revolt-metadata.rule=Host(`metadata.${DOMAIN}`)"
      - "traefik.http.routers.rtr-revolt-metadata.tls=true"
      - "traefik.http.routers.rtr-revolt-metadata.tls.certResolver=letsencrypt"
      - "traefik.http.services.srv-revolt-metadata.loadbalancer.server.port=7000"

  # Voice chat server (january)
  vortex:
    image: revoltchat/vortex:0.3.0-alpha.1
    env_file: .env
    depends_on:
      - database
      - redis
    restart: always
    networks:
      - revolt_nw
      - traefik_external
    ports:
      - "10000-10100:10000-10100"
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_external"
      - "traefik.http.routers.rtr-revolt-voso.rule=Host(`voso.${DOMAIN}`)"
      - "traefik.http.routers.rtr-revolt-voso.tls=true"
      - "traefik.http.routers.rtr-revolt-voso.tls.certResolver=letsencrypt"
      - "traefik.http.services.srv-revolt-voso.loadbalancer.server.port=8080"

networks:
  traefik_external:
    name: traefik_external
    external: true
  revolt_nw:
    name: revolt_nw

Traefik's docker-compose.yml file

Traefik is located in a separate directory, because I use it not only for the Revolt service. Change label certificatesresolvers.letsencrypt.acme with Ur real email address.

docker-compose.yml
version: '3'

services:
  traefik:
    image: traefik:v2.11.10
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "[email protected]"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      # - "--log.level=DEBUG" if nessecary
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - traefik_nw
      - traefik_external

networks:
  traefik_nw:
    name: traefik_nw
  traefik_external:
    name: traefik_external
    external: true

Windows Desktop client for self-hosted Revolt

Clone the repository of Revolt Desktop.

Change URLs in:

./src/lib/config.ts:

export function getBuildURL() {
    const build: "stable" | "nightly" | "dev" = getConfig().build;

    switch (build) {
        case "dev":
            return "http://local.revolt.chat:3001";
        case "nightly":
            return "https://nightly.revolt.chat";
        default:
            return "https://app.revolt.chat"; // change it to Ur domain name.
    }
}
  • ./src/lib/discordRPC.ts

    export async function connectRPC() {
        if (!getConfig().discordRPC) return;
    
        try {
            rpc = new Client({ transport: "ipc" });
    
            rpc.on("ready", () =>
                rpc.setActivity({
                    state: "revolt.chat",
                    details: "Chatting with others",
                    largeImageKey: "qr",
                    largeImageText: "Communication is critical – use Revolt.",
                    buttons: [
                        {
                            label: "Join Revolt",
                            url: "https://app.revolt.chat/", // change it Ur domain name, preserving slash symbol.
                        },
                        { label: "Website", url: "https://revolt.chat" },
                    ],
                }),
            );
    
            // @ts-ignore
            rpc.on("disconnected", reconnect);
    
            rpc.login({ clientId: "872068124005007420" });
        } catch (err) {
            reconnect();
        }
    }

Thats all. Now - just build the app.

@exababy
Copy link

exababy commented Dec 24, 2024

revoltchat/backend#318
revoltchat/backend#313

Can we use this instead of the vortex?

@apeshand
Copy link
Author

apeshand commented Jan 9, 2025

revoltchat/backend#318 revoltchat/backend#313

Can we use this instead of the vortex?

Oh, hi there :-)
I have no idea bout livekit. U can try it on your own ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment