Compare commits
2
Commits
v0.2.5.7
...
8cc85c1fe1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cc85c1fe1 | ||
|
|
88036bcad3 |
@@ -825,17 +825,31 @@ Wer sich mit dem gleichen Token verbindet, landet im gleichen Room.
|
||||
|
||||
```bash
|
||||
cd rvs
|
||||
cp .env.example .env # PUBLIC_URL eintragen (Domain die auf den Server zeigt)
|
||||
cp .env.example .env # Modus waehlen (COMPOSE_PROFILES) + Werte eintragen
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**Zwei Modi** — in der `rvs/.env` per `COMPOSE_PROFILES`:
|
||||
|
||||
| Modus | `.env` | Wer macht TLS | Apps/Satelliten verbinden auf |
|
||||
|---|---|---|---|
|
||||
| **mit Caddy** | `COMPOSE_PROFILES=caddy` + `PUBLIC_URL` | Caddy im Stack (Let's Encrypt) | `PUBLIC_URL:CADDY_HTTPS_PORT` |
|
||||
| **ohne Caddy** | `COMPOSE_PROFILES=` (leer) | dein Reverse-Proxy (nginx, Traefik …) | Name + Port deines Proxys (meist 443) |
|
||||
|
||||
**Stack:**
|
||||
- `caddy` (TLS-Terminator + Let's Encrypt, lauscht auf 80+443)
|
||||
- `rvs` (WebSocket Relay + OAuth-Callback HTTP, nur intern auf Port 3000)
|
||||
- `rvs` (WebSocket Relay + OAuth-Callback HTTP). Unverschluesselter Port
|
||||
`RVS_HTTP_BIND:RVS_HTTP_PORT` (Default `127.0.0.1:3000`) — fuer den Reverse-Proxy.
|
||||
- `caddy` (nur Modus Caddy: TLS + Let's Encrypt auf 80 + `CADDY_HTTPS_PORT`)
|
||||
|
||||
Caddy holt automatisch ein Zertifikat fuer `PUBLIC_URL` via HTTP-01-Challenge.
|
||||
ACME-State persistent in `./data/caddy/` (gitignored) — kein Rate-Limit-Drama
|
||||
bei Container-Restart. WebSocket-Upgrades reicht Caddy transparent durch.
|
||||
Dafuer muss **Port 80 von aussen auf diesen Rechner** gehen — sonst schlaegt die
|
||||
Erneuerung still fehl und das Zertifikat laeuft nach 90 Tagen ab (Apps und
|
||||
Satelliten verbinden dann nicht mehr). ACME-State persistent in `./data/caddy/`
|
||||
(gitignored). WebSocket-Upgrades reicht Caddy transparent durch.
|
||||
|
||||
> **Bestehende Installation aktualisieren:** Caddy startet nur noch mit
|
||||
> `COMPOSE_PROFILES=caddy` in der `rvs/.env`. Wer Caddy weiter nutzt, traegt das
|
||||
> dort ein (sonst laeuft nach `git pull` + `up -d` kein TLS mehr).
|
||||
|
||||
**Features:**
|
||||
- WebSocket Relay (alle Message-Types: chat, audio, file, config, xtts, update, etc.)
|
||||
@@ -853,10 +867,56 @@ cp ARIA-v0.0.3.0.apk ~/ARIA-AGENT/rvs/updates/
|
||||
|
||||
**Multi-Instanz:** Mehrere ARIA-VMs koennen denselben RVS nutzen — jede mit eigenem Token.
|
||||
|
||||
**Ohne Caddy / eigener TLS-Terminator:** Wenn Du schon einen Reverse-Proxy
|
||||
(nginx/Traefik) davor hast, kommentier den `caddy`-Service in der
|
||||
`rvs/docker-compose.yml` aus und gib `rvs` wieder einen `ports`-Block
|
||||
(z.B. `["3000:3000"]`). Dein Reverse-Proxy macht dann TLS und reicht weiter.
|
||||
**Ohne Caddy — eigener Reverse-Proxy:** in der `rvs/.env`
|
||||
|
||||
```bash
|
||||
COMPOSE_PROFILES=
|
||||
RVS_HTTP_BIND=0.0.0.0 # Proxy auf anderem Rechner; gleicher Rechner: 127.0.0.1
|
||||
RVS_HTTP_PORT=3000
|
||||
```
|
||||
|
||||
Steht der Proxy auf einem anderen Rechner, den Port per Firewall **nur fuer den
|
||||
Proxy** freigeben.
|
||||
|
||||
**Strecke Proxy → RVS verschluesseln:** `RVS_HTTP_TLS=true` — der RVS spricht
|
||||
dann HTTPS auf `RVS_HTTP_PORT`, mit einem selbstsignierten Zertifikat (beim
|
||||
ersten Start in `rvs/data/rvs-tls/` erzeugt; eigenes `rvs.crt`/`rvs.key` darf
|
||||
dort liegen). Im Proxy als Ziel `https://<ip>:<port>`, das Zertifikat dabei
|
||||
**nicht** pruefen (nginx: Default; Nginx Proxy Manager: Scheme `https`,
|
||||
„Websockets Support" an). Nur ohne Caddy — der spricht den RVS per HTTP an.
|
||||
|
||||
Umstellen von Caddy:
|
||||
`docker compose rm -sf caddy && docker compose up -d`.
|
||||
|
||||
nginx-Beispiel (WebSocket braucht HTTP/1.1 + Upgrade-Header und lange Timeouts):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl; # Handys nehmen bevorzugt IPv6 — mit AAAA-Eintrag Pflicht
|
||||
server_name rvs.example.de;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/rvs.example.de/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/rvs.example.de/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.1.10:3000; # RVS_HTTP_BIND-IP : RVS_HTTP_PORT (https:// bei RVS_HTTP_TLS=true)
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_read_timeout 3600s; # WebSocket bleibt lange offen
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_buffering off;
|
||||
client_max_body_size 0; # APK-Download, Uploads
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Apps, Satelliten, KI-Boxen, Host-Agenten und die Bridge (`RVS_HOST`/`RVS_PORT`
|
||||
in deren `.env`) dann auf den Namen und Port des Proxys umstellen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+25
-4
@@ -3,12 +3,33 @@
|
||||
# Kopieren nach .env und Werte eintragen.
|
||||
# ════════════════════════════════════════════════════════
|
||||
|
||||
# ── Wer macht TLS? ──────────────────────────────────────
|
||||
# caddy = Caddy hier im Stack holt das Zertifikat selbst (Let's Encrypt)
|
||||
# (leer) = OHNE Caddy: ein vorhandener Reverse-Proxy (nginx, Traefik ...)
|
||||
# macht TLS und zeigt auf den RVS-Port unten
|
||||
COMPOSE_PROFILES=caddy
|
||||
|
||||
# ── Modus caddy ─────────────────────────────────────────
|
||||
# Oeffentlich erreichbarer DNS-Name dieses Servers. Caddy holt darauf ein
|
||||
# Let's Encrypt-Zertifikat (HTTP-01 Challenge ueber Port 80) und routet
|
||||
# WebSocket + HTTP weiter an den RVS-Container.
|
||||
#
|
||||
# WICHTIG:
|
||||
# - Die Domain muss per DNS-A-Record/AAAA auf diese Maschine zeigen
|
||||
# - Port 80 + 443 muessen vom Internet aus erreichbar sein
|
||||
# - Kein anderer Reverse-Proxy davor (sonst Cert-Konflikt)
|
||||
# - Port 80 muss von aussen HIERHER gehen (sonst laeuft das Zertifikat
|
||||
# nach 90 Tagen still ab — Fritzbox: Freigabe auf 80 pruefen!)
|
||||
PUBLIC_URL=rvs.example.de
|
||||
# Port, auf dem Caddy HTTPS anbietet (Apps/Satelliten: dieser Port)
|
||||
CADDY_HTTPS_PORT=444
|
||||
|
||||
# ── Modus ohne Caddy ────────────────────────────────────
|
||||
# Unverschluesselter RVS-Port, auf den der Reverse-Proxy zeigt.
|
||||
# 127.0.0.1 = nur von diesem Rechner. Steht der Proxy woanders:
|
||||
# 0.0.0.0 bzw. die interne IP — und den Port per Firewall NUR fuer
|
||||
# den Proxy freigeben (Klartext!).
|
||||
RVS_HTTP_BIND=127.0.0.1
|
||||
RVS_HTTP_PORT=3000
|
||||
# Auch die Strecke Proxy → RVS verschluesseln: der RVS spricht dann HTTPS
|
||||
# auf RVS_HTTP_PORT, mit selbstsigniertem Zertifikat (wird beim ersten Start
|
||||
# in ./data/rvs-tls/ erzeugt; eigenes rvs.crt/rvs.key darf dort liegen).
|
||||
# Im Proxy dann https://<ip>:<port> als Ziel, Zertifikat NICHT pruefen.
|
||||
# Nur ohne Caddy — der Caddy im Stack spricht den RVS per HTTP an.
|
||||
RVS_HTTP_TLS=false
|
||||
|
||||
@@ -2,6 +2,9 @@ FROM node:22-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# openssl: erzeugt bei RVS_HTTP_TLS=true das interne Zertifikat
|
||||
RUN apk add --no-cache openssl
|
||||
|
||||
# Erst package.json kopieren — Docker-Cache für npm install nutzen
|
||||
COPY package.json ./
|
||||
RUN npm install --production
|
||||
|
||||
+22
-15
@@ -1,30 +1,36 @@
|
||||
# ════════════════════════════════════════════════════════
|
||||
# ARIA RVS Stack — WebSocket Relay + OAuth Callback HTTP
|
||||
# Caddy davor terminiert TLS via Let's Encrypt (HTTP-01
|
||||
# Challenge ueber Port 80). OAuth-Provider wie Spotify
|
||||
# verlangen HTTPS fuer non-localhost Redirect-URIs.
|
||||
# Apps/Satelliten/Boxen brauchen TLS (wss://), OAuth-Provider
|
||||
# wie Spotify HTTPS. Wer TLS macht, waehlt die .env:
|
||||
#
|
||||
# A) COMPOSE_PROFILES=caddy — Caddy hier im Stack holt das
|
||||
# Zertifikat selbst (Let's Encrypt, HTTP-01 ueber Port 80).
|
||||
# Voraussetzung: Port 80 + CADDY_HTTPS_PORT von aussen auf
|
||||
# diese Maschine, PUBLIC_URL zeigt per DNS hierher.
|
||||
#
|
||||
# B) COMPOSE_PROFILES= — OHNE Caddy. Ein vorhandener
|
||||
# Reverse-Proxy (nginx, Traefik, ...) macht TLS und zeigt auf
|
||||
# den unverschluesselten RVS-Port (RVS_HTTP_BIND:RVS_HTTP_PORT).
|
||||
# nginx-Beispiel: README → RVS → "Ohne Caddy".
|
||||
# ════════════════════════════════════════════════════════
|
||||
#
|
||||
# Voraussetzungen:
|
||||
# - Port 80 + 443 frei (kein anderer Reverse-Proxy davor)
|
||||
# - Domain (PUBLIC_URL) zeigt per DNS auf diese Maschine
|
||||
# - .env mit PUBLIC_URL gesetzt
|
||||
#
|
||||
# Start: docker compose up -d
|
||||
# Wenn Du einen eigenen TLS-Terminator nutzt (z.B. nginx,
|
||||
# externer Caddy): caddy-service auskommentieren und
|
||||
# rvs-Container den ports-Block geben (3000 → public Port).
|
||||
|
||||
services:
|
||||
rvs:
|
||||
build: .
|
||||
restart: always
|
||||
# KEIN ports-Block — Caddy ist davor, RVS nur intern
|
||||
# via aria-rvs-net erreichbar. Wenn Du Caddy nicht nutzt,
|
||||
# diesen ports-Block reaktivieren: ports: ["${RVS_PORT:-443}:3000"]
|
||||
# Unverschluesselter RVS-Port fuer einen externen Reverse-Proxy (Modus B).
|
||||
# Default nur 127.0.0.1 — steht der Proxy auf einem ANDEREN Rechner,
|
||||
# RVS_HTTP_BIND=0.0.0.0 (oder die interne IP) setzen und den Port per
|
||||
# Firewall nur fuer den Proxy freigeben: hier laeuft alles im Klartext.
|
||||
ports:
|
||||
- "${RVS_HTTP_BIND:-127.0.0.1}:${RVS_HTTP_PORT:-3000}:3000"
|
||||
volumes:
|
||||
- ./updates:/updates # APK-Dateien fuer Auto-Update
|
||||
- ./data/rvs-tls:/certs # internes Zertifikat (RVS_HTTP_TLS)
|
||||
environment:
|
||||
- RVS_HTTP_TLS=${RVS_HTTP_TLS:-false}
|
||||
- MAX_SESSIONS=10
|
||||
# 4 GB V8-Heap — sonst OOM beim Empfang von 1 GB-Files
|
||||
# (base64 inflated ~1.34 GB plus WS-Frame-Margin).
|
||||
@@ -39,10 +45,11 @@ services:
|
||||
# damit Restart nicht jedes Mal ein neues Cert holt (Rate-Limit!).
|
||||
caddy:
|
||||
image: caddy:latest
|
||||
profiles: ["caddy"] # nur mit COMPOSE_PROFILES=caddy
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80"
|
||||
- "444:443"
|
||||
- "${CADDY_HTTPS_PORT:-444}:443"
|
||||
command: caddy reverse-proxy --from ${PUBLIC_URL} --to rvs:3000
|
||||
volumes:
|
||||
- ./data/caddy/data:/data # Zertifikate (PERSISTENT)
|
||||
|
||||
+28
-2
@@ -2,6 +2,8 @@
|
||||
|
||||
const { WebSocketServer } = require("ws");
|
||||
const http = require("http");
|
||||
const https = require("https");
|
||||
const { execFileSync } = require("child_process");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
@@ -9,6 +11,12 @@ const path = require("path");
|
||||
const PORT = parseInt(process.env.PORT || "3000", 10);
|
||||
const MAX_SESSIONS = parseInt(process.env.MAX_SESSIONS || "10", 10);
|
||||
const UPDATES_DIR = process.env.UPDATES_DIR || "/updates";
|
||||
// HTTPS statt HTTP auf PORT — fuer die Strecke externer Reverse-Proxy → RVS.
|
||||
// Das oeffentliche Zertifikat hat der Proxy; hier reicht ein selbstsigniertes
|
||||
// (wird beim ersten Start erzeugt). NICHT zusammen mit dem Caddy im Stack
|
||||
// (der spricht den RVS per HTTP an).
|
||||
const HTTP_TLS = /^(1|true|yes|ja)$/i.test(process.env.RVS_HTTP_TLS || "");
|
||||
const TLS_DIR = process.env.RVS_TLS_DIR || "/certs";
|
||||
// Kein Polling — APK wird manuell per git pull bereitgestellt
|
||||
|
||||
// Erlaubte Nachrichtentypen — alles andere wird verworfen
|
||||
@@ -274,7 +282,25 @@ function cleanupRooms() {
|
||||
// WICHTIG: Node-Default-Heap ist ~1.5 GB. Fuer 1 GB-Files muss der
|
||||
// Container mit --max-old-space-size=4096 (oder NODE_OPTIONS env var)
|
||||
// gestartet werden, sonst OOM-Crash beim Empfang.
|
||||
const httpServer = http.createServer(handleHttpRequest);
|
||||
/** Zertifikat fuer den internen HTTPS-Port: vorhandenes aus TLS_DIR nehmen
|
||||
* (eigenes darf man dort ablegen), sonst einmalig selbstsigniert erzeugen. */
|
||||
function loadInternalTls() {
|
||||
const key = path.join(TLS_DIR, "rvs.key");
|
||||
const crt = path.join(TLS_DIR, "rvs.crt");
|
||||
if (!fs.existsSync(key) || !fs.existsSync(crt)) {
|
||||
fs.mkdirSync(TLS_DIR, { recursive: true });
|
||||
execFileSync("openssl", ["req", "-x509", "-newkey", "rsa:2048", "-nodes", "-sha256",
|
||||
"-days", "3650", "-subj", "/CN=aria-rvs-intern", "-keyout", key, "-out", crt],
|
||||
{ stdio: "ignore" });
|
||||
fs.chmodSync(key, 0o600);
|
||||
log(`Internes TLS-Zertifikat erzeugt: ${crt} (selbstsigniert, 10 Jahre)`);
|
||||
}
|
||||
return { key: fs.readFileSync(key), cert: fs.readFileSync(crt) };
|
||||
}
|
||||
|
||||
const httpServer = HTTP_TLS
|
||||
? https.createServer(loadInternalTls(), handleHttpRequest)
|
||||
: http.createServer(handleHttpRequest);
|
||||
const wss = new WebSocketServer({ noServer: true, maxPayload: 1500 * 1024 * 1024 });
|
||||
|
||||
// HTTP-Upgrade-Pfad → an WebSocket-Server reichen
|
||||
@@ -285,7 +311,7 @@ httpServer.on("upgrade", (req, socket, head) => {
|
||||
});
|
||||
|
||||
httpServer.listen(PORT, () => {
|
||||
log(`RVS läuft auf Port ${PORT} (HTTP + WS) | Max Sessions: ${MAX_SESSIONS}`);
|
||||
log(`RVS läuft auf Port ${PORT} (${HTTP_TLS ? "HTTPS + WSS, internes Zertifikat" : "HTTP + WS"}) | Max Sessions: ${MAX_SESSIONS}`);
|
||||
// Beim Start pruefen ob eine APK da ist
|
||||
const apkInfo = getLatestAPK();
|
||||
if (apkInfo) log(`APK bereit: v${apkInfo.version} (${(fs.statSync(apkInfo.path).size / 1024 / 1024).toFixed(1)}MB)`);
|
||||
|
||||
Reference in New Issue
Block a user