Compare commits
10 Commits
54ddc0b902
...
b9d7383b21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9d7383b21 | ||
|
|
d312a33d9e | ||
|
|
3afd5c8445 | ||
|
|
9d5f060cbd | ||
|
|
3916dc8bee | ||
|
|
be7cd32d45 | ||
|
|
65c0e6145b | ||
|
|
9035da89ce | ||
|
|
ebd3aecdb5 | ||
|
|
5fc46a8148 |
18
.env.example
Normal file
18
.env.example
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# docker-compose Konfiguration
|
||||||
|
# Kopiere diese Datei nach .env und trage deine Werte ein
|
||||||
|
|
||||||
|
# IP oder Hostname des Servers auf dem du docker compose ausfuehrst
|
||||||
|
# (wird vom Browser genutzt um das Backend zu erreichen)
|
||||||
|
BACKEND_HOST=192.168.1.100
|
||||||
|
BACKEND_PORT=8443
|
||||||
|
|
||||||
|
# Datenbank-Passwort (frei waehlbar)
|
||||||
|
DB_PASSWORD=sicheres_db_passwort
|
||||||
|
|
||||||
|
# JWT Secret — langer zufaelliger String (min. 32 Zeichen)
|
||||||
|
# Beispiel: openssl rand -hex 32
|
||||||
|
JWT_SECRET=ZUFAELLIGER_STRING_MIN_32_ZEICHEN
|
||||||
|
|
||||||
|
# API Key — frei waehlbar, wird fuer Agent und Frontend benoetigt
|
||||||
|
# Beispiel: openssl rand -hex 16
|
||||||
|
API_KEY=SELBST_GEWAEHLTER_API_KEY
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@ -38,6 +38,12 @@ frontend/dist/
|
|||||||
frontend/src/config.js
|
frontend/src/config.js
|
||||||
!frontend/src/config.example.js
|
!frontend/src/config.example.js
|
||||||
|
|
||||||
|
# .env Dateien haben echte Credentials — nie einchecken
|
||||||
|
frontend/.env
|
||||||
|
!frontend/.env.example
|
||||||
|
.env
|
||||||
|
!.env.example
|
||||||
|
|
||||||
# ========================
|
# ========================
|
||||||
# OS / Editor
|
# OS / Editor
|
||||||
# ========================
|
# ========================
|
||||||
|
|||||||
182
README.md
182
README.md
@ -158,13 +158,179 @@ Client ──► Backend:ProxyPort ──► WebSocket (Binary) ──► Agent
|
|||||||
|
|
||||||
## Schnellstart
|
## Schnellstart
|
||||||
|
|
||||||
|
### Docker (empfohlen)
|
||||||
|
|
||||||
|
Voraussetzung: Docker installiert (`curl -fsSL https://get.docker.com | sh`).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make all # Backend + Agent + Updater bauen
|
git clone <repo-url> && cd rmm
|
||||||
make certs # TLS-Zertifikate generieren
|
git checkout release
|
||||||
make deploy-backend # Backend deployen
|
cp .env.example .env # .env anpassen (IP-Adresse, Passwörter, API-Key)
|
||||||
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Agent auf OPNsense installieren → siehe [agent-bsd/README.md](agent-bsd/README.md)
|
Fertig. Frontend unter `http://<BACKEND_HOST>`.
|
||||||
|
|
||||||
|
Vollständige Anleitung mit allen Details, Troubleshooting und Backup: **[docs/DOCKER.md](docs/DOCKER.md)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Manuell (ohne Docker)
|
||||||
|
|
||||||
|
|
||||||
|
### 1. Voraussetzungen
|
||||||
|
|
||||||
|
**Backend-Server** (Linux, Debian 12+ empfohlen):
|
||||||
|
```bash
|
||||||
|
# PostgreSQL 17 + TimescaleDB
|
||||||
|
apt install -y postgresql postgresql-client
|
||||||
|
# TimescaleDB: https://docs.timescale.com/self-hosted/latest/install/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Build-System** (macOS oder Linux):
|
||||||
|
```bash
|
||||||
|
# Go 1.24+
|
||||||
|
go version # muss >= 1.24 sein
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Konfiguration
|
||||||
|
|
||||||
|
**Backend:**
|
||||||
|
```bash
|
||||||
|
cp backend/config.yaml.example backend/config.yaml
|
||||||
|
```
|
||||||
|
```yaml
|
||||||
|
# backend/config.yaml (wichtigste Felder)
|
||||||
|
listen_addr: ":8443"
|
||||||
|
db_dsn: "postgres://rmm:PASSWORT@localhost:5432/rmm?sslmode=disable"
|
||||||
|
jwt_secret: "ZUFAELLIGER_STRING_MIN_32_ZEICHEN"
|
||||||
|
api_key: "SELBST_GEWAEHLTER_API_KEY"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Hinweis:** Den `api_key` legst du selbst fest — z.B. eine UUID oder ein langer zufaelliger String.
|
||||||
|
> Denselben Wert traegst du gleich in die Frontend-`.env` ein. Du brauchst kein laufendes
|
||||||
|
> System dafuer. Ueber die Einstellungen-Seite koennen spaeter weitere Keys (z.B. pro Agent)
|
||||||
|
> hinzugefuegt werden.
|
||||||
|
|
||||||
|
**Frontend:**
|
||||||
|
```bash
|
||||||
|
cp frontend/.env.example frontend/.env
|
||||||
|
```
|
||||||
|
```env
|
||||||
|
# frontend/.env
|
||||||
|
VITE_BACKEND_HOST=192.168.1.100 # IP/Hostname deines Backend-Servers
|
||||||
|
VITE_BACKEND_PORT=8443
|
||||||
|
VITE_API_KEY=SELBST_GEWAEHLTER_API_KEY # identisch mit api_key aus backend/config.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Datenbank anlegen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Als postgres-User auf dem Backend-Server:
|
||||||
|
sudo -u postgres psql << 'SQL'
|
||||||
|
CREATE USER rmm WITH PASSWORD 'PASSWORT';
|
||||||
|
CREATE DATABASE rmm OWNER rmm;
|
||||||
|
\c rmm
|
||||||
|
CREATE EXTENSION IF NOT EXISTS timescaledb;
|
||||||
|
SQL
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Tabellen werden beim ersten Backend-Start automatisch angelegt (Auto-Migration).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Bauen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Alles in einem Schritt:
|
||||||
|
make all
|
||||||
|
|
||||||
|
# Oder einzeln:
|
||||||
|
make backend # → build/rmm-backend (linux/amd64)
|
||||||
|
make agent-bsd # → build/rmm-agent-bsd (freebsd/amd64)
|
||||||
|
make agent-linux # → build/rmm-agent-linux (linux/amd64)
|
||||||
|
make frontend # → frontend/dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Backend deployen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Binary + Config auf den Server kopieren:
|
||||||
|
scp build/rmm-backend root@<backend-server>:/opt/rmm/
|
||||||
|
scp backend/config.yaml root@<backend-server>:/opt/rmm/
|
||||||
|
|
||||||
|
# Systemd-Service einrichten:
|
||||||
|
cat > /etc/systemd/system/rmm-backend.service << 'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=RMM Backend
|
||||||
|
After=network.target postgresql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/opt/rmm/rmm-backend
|
||||||
|
WorkingDirectory=/opt/rmm
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now rmm-backend
|
||||||
|
systemctl status rmm-backend
|
||||||
|
```
|
||||||
|
|
||||||
|
Der erste Start legt automatisch einen Admin-User an (Credentials werden ins Log geschrieben).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. Frontend deployen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build (mit .env-Konfiguration aus Schritt 2):
|
||||||
|
cd frontend && npm install && npm run build
|
||||||
|
|
||||||
|
# Auf Web-Server kopieren (z.B. Nginx):
|
||||||
|
scp -r frontend/dist/* root@<frontend-server>:/var/www/html/
|
||||||
|
|
||||||
|
# Nginx-Konfiguration (einfach):
|
||||||
|
cat > /etc/nginx/sites-available/rmm << 'EOF'
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /var/www/html;
|
||||||
|
index index.html;
|
||||||
|
location / { try_files $uri $uri/ /index.html; }
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
ln -s /etc/nginx/sites-available/rmm /etc/nginx/sites-enabled/
|
||||||
|
nginx -t && systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. Erste Anmeldung & 2FA
|
||||||
|
|
||||||
|
1. Frontend unter `http://<frontend-server>` aufrufen
|
||||||
|
2. Mit dem beim ersten Backend-Start erstellten Admin-Account anmelden
|
||||||
|
3. Einstellungen → **Zwei-Faktor-Authentifizierung** → Einrichten (empfohlen)
|
||||||
|
4. TOTP-Secret in Aegis / Google Authenticator eingeben, ersten Code bestätigen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
| Problem | Lösung |
|
||||||
|
|---------|--------|
|
||||||
|
| Backend startet nicht | `journalctl -u rmm-backend -f` — häufig DB-Verbindung oder Port belegt |
|
||||||
|
| Agent verbindet nicht | API-Key in `agent/config.yaml` prüfen, TLS-Zertifikat ggf. als trusted markieren |
|
||||||
|
| Frontend zeigt keine Daten | `VITE_BACKEND_HOST` und `VITE_API_KEY` in `.env` prüfen, neu bauen |
|
||||||
|
| TimescaleDB fehlt | `CREATE EXTENSION timescaledb` in der rmm-Datenbank ausführen |
|
||||||
|
|
||||||
## Dateistruktur
|
## Dateistruktur
|
||||||
|
|
||||||
@ -210,12 +376,12 @@ rmm/
|
|||||||
- **Persistente Agent-ID**: Ueberlebt Agent- und Backend-Neustarts
|
- **Persistente Agent-ID**: Ueberlebt Agent- und Backend-Neustarts
|
||||||
- **FreeBSD-kompatibel**: Volle Pfade (/usr/bin/netstat etc.), daemon statt nohup
|
- **FreeBSD-kompatibel**: Volle Pfade (/usr/bin/netstat etc.), daemon statt nohup
|
||||||
|
|
||||||
## Zugangsdaten
|
## Zugangsdaten (nach Installation)
|
||||||
|
|
||||||
```
|
```
|
||||||
Backend: https://your-backend:8443
|
Backend: https://<backend-ip>:8443
|
||||||
API-Key: YOUR_API_KEY
|
API-Key: in backend/config.yaml → api_key
|
||||||
Frontend: http://your-backend (admin / Start!123)
|
Frontend: https://<frontend-ip> (Login: admin / Passwort beim ersten Start gesetzt)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Lizenz
|
## Lizenz
|
||||||
|
|||||||
31
backend/Dockerfile
Normal file
31
backend/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o rmm-backend .
|
||||||
|
|
||||||
|
# ---
|
||||||
|
|
||||||
|
FROM debian:bookworm-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /build/rmm-backend .
|
||||||
|
COPY config.yaml.example config.yaml.example
|
||||||
|
|
||||||
|
RUN mkdir -p certs
|
||||||
|
|
||||||
|
EXPOSE 8443
|
||||||
|
|
||||||
|
# Umgebungsvariablen mit Standardwerten (koennen alle per ENV ueberschrieben werden)
|
||||||
|
ENV RMM_LISTEN_ADDR=":8443" \
|
||||||
|
RMM_DB_HOST="db" \
|
||||||
|
RMM_DB_PORT="5432" \
|
||||||
|
RMM_DB_USER="rmm" \
|
||||||
|
RMM_DB_NAME="rmm"
|
||||||
|
|
||||||
|
CMD ["./rmm-backend"]
|
||||||
@ -1,8 +1,23 @@
|
|||||||
# RMM Backend Konfiguration
|
# RMM Backend Konfiguration
|
||||||
|
# Kopiere diese Datei nach config.yaml und passe die Werte an.
|
||||||
|
# Alle Werte koennen auch als Umgebungsvariablen gesetzt werden (Docker).
|
||||||
|
|
||||||
listen_addr: ":8443"
|
listen_addr: ":8443"
|
||||||
tls_cert: "certs/server.crt"
|
tls_cert: "certs/server.crt"
|
||||||
tls_key: "certs/server.key"
|
tls_key: "certs/server.key"
|
||||||
db_path: "rmm.db"
|
|
||||||
|
|
||||||
api_keys:
|
# Datenbank
|
||||||
- "YOUR_API_KEY"
|
database:
|
||||||
|
host: "127.0.0.1" # ENV: RMM_DB_HOST
|
||||||
|
port: 5432 # ENV: RMM_DB_PORT
|
||||||
|
user: "rmm" # ENV: RMM_DB_USER
|
||||||
|
password: "" # ENV: RMM_DB_PASSWORD
|
||||||
|
dbname: "rmm" # ENV: RMM_DB_NAME
|
||||||
|
sslmode: "disable"
|
||||||
|
|
||||||
|
# Sicherheit — zufaellige Strings waehlen, nie die Beispielwerte verwenden!
|
||||||
|
jwt_secret: "ZUFAELLIGER_STRING_MIN_32_ZEICHEN" # ENV: RMM_JWT_SECRET
|
||||||
|
|
||||||
|
# API-Keys fuer Agent und Frontend-Zugriff
|
||||||
|
api_keys: # ENV: RMM_API_KEY (wird zusaetzlich angehaengt)
|
||||||
|
- "SELBST_GEWAEHLTER_API_KEY"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/cynfo/rmm-backend/db"
|
"github.com/cynfo/rmm-backend/db"
|
||||||
@ -41,7 +42,7 @@ func Load(path string) (*Config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Env overrides
|
// Env overrides — alle Werte koennen via ENV ueberschrieben werden (z.B. Docker)
|
||||||
if v := os.Getenv("RMM_LISTEN_ADDR"); v != "" {
|
if v := os.Getenv("RMM_LISTEN_ADDR"); v != "" {
|
||||||
cfg.ListenAddr = v
|
cfg.ListenAddr = v
|
||||||
}
|
}
|
||||||
@ -51,12 +52,32 @@ func Load(path string) (*Config, error) {
|
|||||||
if v := os.Getenv("RMM_TLS_KEY"); v != "" {
|
if v := os.Getenv("RMM_TLS_KEY"); v != "" {
|
||||||
cfg.TLSKey = v
|
cfg.TLSKey = v
|
||||||
}
|
}
|
||||||
|
if v := os.Getenv("RMM_JWT_SECRET"); v != "" {
|
||||||
|
cfg.JWTSecret = v
|
||||||
|
}
|
||||||
|
if v := os.Getenv("RMM_API_KEY"); v != "" {
|
||||||
|
cfg.APIKeys = append(cfg.APIKeys, v)
|
||||||
|
}
|
||||||
if v := os.Getenv("RMM_DB_HOST"); v != "" {
|
if v := os.Getenv("RMM_DB_HOST"); v != "" {
|
||||||
cfg.Database.Host = v
|
cfg.Database.Host = v
|
||||||
}
|
}
|
||||||
|
if v := os.Getenv("RMM_DB_PORT"); v != "" {
|
||||||
|
if port := 0; len(v) > 0 {
|
||||||
|
fmt.Sscanf(v, "%d", &port)
|
||||||
|
if port > 0 {
|
||||||
|
cfg.Database.Port = port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v := os.Getenv("RMM_DB_USER"); v != "" {
|
||||||
|
cfg.Database.User = v
|
||||||
|
}
|
||||||
if v := os.Getenv("RMM_DB_PASSWORD"); v != "" {
|
if v := os.Getenv("RMM_DB_PASSWORD"); v != "" {
|
||||||
cfg.Database.Password = v
|
cfg.Database.Password = v
|
||||||
}
|
}
|
||||||
|
if v := os.Getenv("RMM_DB_NAME"); v != "" {
|
||||||
|
cfg.Database.DBName = v
|
||||||
|
}
|
||||||
|
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -151,7 +151,7 @@ func ensureTLS(certPath, keyPath string) error {
|
|||||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("192.168.85.13")},
|
IPAddresses: localIPs(),
|
||||||
DNSNames: []string{"localhost", "rmm-backend"},
|
DNSNames: []string{"localhost", "rmm-backend"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,3 +182,28 @@ func ensureTLS(certPath, keyPath string) error {
|
|||||||
log.Printf("TLS-Zertifikat generiert: %s, %s", certPath, keyPath)
|
log.Printf("TLS-Zertifikat generiert: %s, %s", certPath, keyPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// localIPs sammelt alle lokalen IP-Adressen des Hosts für das TLS-Zertifikat
|
||||||
|
func localIPs() []net.IP {
|
||||||
|
ips := []net.IP{net.ParseIP("127.0.0.1")}
|
||||||
|
ifaces, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return ips
|
||||||
|
}
|
||||||
|
for _, iface := range ifaces {
|
||||||
|
addrs, _ := iface.Addrs()
|
||||||
|
for _, addr := range addrs {
|
||||||
|
var ip net.IP
|
||||||
|
switch v := addr.(type) {
|
||||||
|
case *net.IPNet:
|
||||||
|
ip = v.IP
|
||||||
|
case *net.IPAddr:
|
||||||
|
ip = v.IP
|
||||||
|
}
|
||||||
|
if ip != nil && !ip.IsLoopback() && ip.To4() != nil {
|
||||||
|
ips = append(ips, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ips
|
||||||
|
}
|
||||||
|
|||||||
@ -1,14 +1,24 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Frontend Build & Deploy
|
||||||
|
# Umgebungsvariablen setzen:
|
||||||
|
# REMOTE=root@<FRONTEND-SERVER>
|
||||||
|
# VITE_BACKEND_HOST=<BACKEND-IP-ODER-HOSTNAME>
|
||||||
|
# VITE_BACKEND_PORT=8443 (optional, default: 8443)
|
||||||
|
# VITE_API_KEY=<API-KEY> (optional)
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
FRONTEND_DIR="$(dirname "$0")/frontend"
|
|
||||||
REMOTE="root@192.168.85.20"
|
|
||||||
WEB_ROOT="/var/www/html"
|
|
||||||
|
|
||||||
echo "Building..."
|
REMOTE="${REMOTE:-root@localhost}"
|
||||||
cd "$FRONTEND_DIR" && npm run build
|
WEBROOT="${WEBROOT:-/var/www/html}"
|
||||||
|
|
||||||
echo "Deploying..."
|
echo "==> Baue Frontend..."
|
||||||
ssh "$REMOTE" "rm -rf ${WEB_ROOT}/assets/*"
|
VITE_BACKEND_HOST="${VITE_BACKEND_HOST}" \
|
||||||
scp -r dist/* "$REMOTE:${WEB_ROOT}/"
|
VITE_BACKEND_PORT="${VITE_BACKEND_PORT:-8443}" \
|
||||||
ssh "$REMOTE" "chmod -R 755 ${WEB_ROOT}/assets && chmod 644 ${WEB_ROOT}/assets/* ${WEB_ROOT}/index.html ${WEB_ROOT}/vite.svg 2>/dev/null; nginx -s reload"
|
VITE_API_KEY="${VITE_API_KEY}" \
|
||||||
echo "Done."
|
npm run build
|
||||||
|
|
||||||
|
echo "==> Deploye nach $REMOTE:$WEBROOT ..."
|
||||||
|
ssh "$REMOTE" "rm -rf ${WEBROOT}/assets/*"
|
||||||
|
scp -r dist/assets dist/index.html "$REMOTE:${WEBROOT}/"
|
||||||
|
ssh "$REMOTE" "chown -R www-data:www-data ${WEBROOT}/ && chmod -R 755 ${WEBROOT}/"
|
||||||
|
echo "==> Fertig"
|
||||||
|
|||||||
48
docker-compose.yml
Normal file
48
docker-compose.yml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: timescale/timescaledb:latest-pg17
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: rmm
|
||||||
|
POSTGRES_USER: rmm
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U rmm"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build: ./backend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8443:8443"
|
||||||
|
environment:
|
||||||
|
RMM_DB_HOST: db
|
||||||
|
RMM_DB_PASSWORD: ${DB_PASSWORD}
|
||||||
|
RMM_JWT_SECRET: ${JWT_SECRET}
|
||||||
|
RMM_API_KEY: ${API_KEY}
|
||||||
|
volumes:
|
||||||
|
- certs:/app/certs
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build: ./frontend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_HOST: ${BACKEND_HOST}
|
||||||
|
BACKEND_PORT: ${BACKEND_PORT:-8443}
|
||||||
|
API_KEY: ${API_KEY}
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
|
certs:
|
||||||
@ -291,7 +291,7 @@ Siehe [FIRMWARE.md](FIRMWARE.md) fuer Details.
|
|||||||
# Peer anlegen
|
# Peer anlegen
|
||||||
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
|
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
|
||||||
https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers \
|
https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers \
|
||||||
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"10.172.100.210"}'
|
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"<DNS-SERVER>"}'
|
||||||
|
|
||||||
# Peer mit eigenem Endpoint
|
# Peer mit eigenem Endpoint
|
||||||
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
|
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
|
||||||
|
|||||||
@ -620,7 +620,7 @@ Peer-Anlage: Keypair generiert auf Firewall, naechste freie IP automatisch, Endp
|
|||||||
# Peer anlegen
|
# Peer anlegen
|
||||||
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
|
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
|
||||||
https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers \
|
https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers \
|
||||||
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"10.172.100.210"}'
|
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"<DNS-SERVER>"}'
|
||||||
|
|
||||||
# Alle Peers
|
# Alle Peers
|
||||||
curl -sk -H "X-API-Key: YOUR_API_KEY" \
|
curl -sk -H "X-API-Key: YOUR_API_KEY" \
|
||||||
|
|||||||
221
docs/DOCKER.md
Normal file
221
docs/DOCKER.md
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
# Docker Installation
|
||||||
|
|
||||||
|
Diese Anleitung erklärt, wie du das RMM-System mit Docker auf einem Linux-Server installierst.
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- Linux-Server (Debian 12 / Ubuntu 22.04 oder neuer empfohlen)
|
||||||
|
- Mindestens 2 GB RAM, 10 GB freier Speicherplatz
|
||||||
|
- Docker und Docker Compose installiert
|
||||||
|
|
||||||
|
**Docker installieren** (falls noch nicht vorhanden):
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Das war es. Docker Compose ist seit Docker 2.x automatisch dabei (`docker compose`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Schritt 1 — Repository klonen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.cynfo.net/christian/rmm2.git
|
||||||
|
cd rmm2
|
||||||
|
git checkout release
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Schritt 2 — Konfigurationsdatei anlegen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Öffne `.env` mit einem Texteditor und trage deine Werte ein:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Datei sieht so aus:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# IP-Adresse oder Hostname dieses Servers
|
||||||
|
# (die Adresse über die du später im Browser das Frontend erreichst)
|
||||||
|
BACKEND_HOST=192.168.1.100
|
||||||
|
|
||||||
|
# Port des Backends — 8443 ist der Standard, nur ändern wenn nötig
|
||||||
|
BACKEND_PORT=8443
|
||||||
|
|
||||||
|
# Datenbank-Passwort — frei wählbar, wird nur intern verwendet
|
||||||
|
DB_PASSWORD=einSicheresPasswort123
|
||||||
|
|
||||||
|
# JWT-Secret — langer zufälliger String, mindestens 32 Zeichen
|
||||||
|
# Tipp: openssl rand -hex 32
|
||||||
|
JWT_SECRET=hierEinenLangenZufaelligenStringEintragen
|
||||||
|
|
||||||
|
# API-Key — frei wählbar, wird vom Frontend und den Agents verwendet
|
||||||
|
# Tipp: openssl rand -hex 16
|
||||||
|
API_KEY=hierEinenApiKeyEintragen
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Wichtig:** `BACKEND_HOST` ist die IP-Adresse oder der Hostname des Servers auf dem
|
||||||
|
> Docker läuft — nicht `localhost`. Der Browser muss diese Adresse erreichen können,
|
||||||
|
> um mit dem Backend zu kommunizieren.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Schritt 3 — Starten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Beim ersten Start lädt Docker die benötigten Basis-Images (postgres, nginx etc.) und
|
||||||
|
baut dann das Backend und das Frontend. Das dauert beim ersten Mal 3-5 Minuten.
|
||||||
|
|
||||||
|
Danach läuft das System und startet automatisch nach einem Server-Reboot neu.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Schritt 4 — Prüfen ob alles läuft
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Ausgabe sollte so aussehen:
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME STATUS PORTS
|
||||||
|
rmm-db-1 Up (healthy) 5432/tcp
|
||||||
|
rmm-backend-1 Up 0.0.0.0:8443->8443/tcp
|
||||||
|
rmm-frontend-1 Up 0.0.0.0:80->80/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
Alle drei Services müssen `Up` zeigen. Wenn `db` noch `starting` zeigt, warte
|
||||||
|
20-30 Sekunden — die Datenbank braucht beim allerersten Start etwas länger.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Schritt 5 — Erster Login
|
||||||
|
|
||||||
|
Rufe das Frontend im Browser auf:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://<BACKEND_HOST>
|
||||||
|
```
|
||||||
|
|
||||||
|
Beim ersten Start legt das Backend automatisch einen Admin-Account an.
|
||||||
|
Die Zugangsdaten stehen im Backend-Log:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose logs backend | grep -i "admin\|password\|passwort"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Häufige Aufgaben
|
||||||
|
|
||||||
|
### Logs anschauen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Alle Services
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Nur Backend
|
||||||
|
docker compose logs -f backend
|
||||||
|
|
||||||
|
# Nur die letzten 50 Zeilen
|
||||||
|
docker compose logs --tail=50 backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### System stoppen und neu starten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stoppen (Daten bleiben erhalten)
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# Starten
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Neu starten (z.B. nach Konfigurationsänderung)
|
||||||
|
docker compose restart backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### System aktualisieren
|
||||||
|
|
||||||
|
Nach einem `git pull` musst du die Images neu bauen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull
|
||||||
|
docker compose build
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Konfiguration ändern (`.env` wurde bearbeitet)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Nach Änderung von BACKEND_HOST, API_KEY etc.:
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker Compose erkennt automatisch, dass sich die ENV-Werte geändert haben
|
||||||
|
und startet die betroffenen Container neu.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Datensicherung
|
||||||
|
|
||||||
|
Die Datenbank liegt in einem Docker Volume (`pgdata`). Um ein Backup zu erstellen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup erstellen
|
||||||
|
docker compose exec db pg_dump -U rmm rmm > rmm-backup-$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Backup wiederherstellen
|
||||||
|
docker compose exec -T db psql -U rmm rmm < rmm-backup-20260101.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Backend startet nicht
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose logs backend
|
||||||
|
```
|
||||||
|
|
||||||
|
Häufige Ursachen:
|
||||||
|
- **Datenbank noch nicht bereit**: Warte 30 Sekunden, dann `docker compose restart backend`
|
||||||
|
- **Port 8443 belegt**: Prüfe mit `ss -tlnp | grep 8443` was den Port belegt
|
||||||
|
|
||||||
|
### Frontend zeigt „Verbindung fehlgeschlagen"
|
||||||
|
|
||||||
|
- Prüfe ob `BACKEND_HOST` in `.env` die richtige IP-Adresse ist
|
||||||
|
- Prüfe ob Port 8443 in der Firewall freigegeben ist
|
||||||
|
- Teste direkt: `curl -sk https://<BACKEND_HOST>:8443/api/v1/health`
|
||||||
|
|
||||||
|
### Datenbank-Volume zurücksetzen (Achtung: löscht alle Daten)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down -v # -v löscht auch Volumes
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ports
|
||||||
|
|
||||||
|
| Port | Service | Beschreibung |
|
||||||
|
|------|---------|-------------|
|
||||||
|
| 80 | Frontend | Web-Oberfläche (Browser) |
|
||||||
|
| 8443 | Backend | REST-API + WebSocket (Agents + Frontend) |
|
||||||
|
|
||||||
|
Port 80 und 8443 müssen von deinem Netzwerk erreichbar sein.
|
||||||
|
Port 5432 (Datenbank) ist nur intern verfügbar.
|
||||||
@ -51,7 +51,7 @@ Dann `config.js` anpassen:
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// frontend/src/config.js
|
// frontend/src/config.js
|
||||||
export const BACKEND_HOST = '192.168.85.13' // IP des Backend-Servers (für direkte Links, z.B. Tunnel-Ports)
|
export const BACKEND_HOST = '<BACKEND-IP>' // IP des Backend-Servers (für direkte Links, z.B. Tunnel-Ports)
|
||||||
export const BACKEND_URL = `https://${BACKEND_HOST}:8443`
|
export const BACKEND_URL = `https://${BACKEND_HOST}:8443`
|
||||||
export const API_KEY = 'DEIN_API_KEY' // aus backend/config.yaml → api_keys[0]
|
export const API_KEY = 'DEIN_API_KEY' // aus backend/config.yaml → api_keys[0]
|
||||||
```
|
```
|
||||||
@ -66,7 +66,7 @@ Für die **lokale Entwicklung** (`npm run dev`) muss zusätzlich `vite.config.js
|
|||||||
// vite.config.js → server.proxy
|
// vite.config.js → server.proxy
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'https://192.168.85.13:8443', // Backend-IP anpassen
|
target: 'https://<BACKEND-IP>:8443', // Backend-IP anpassen
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
ws: true, // WebSocket-Proxy aktivieren (Web Terminal, Agent-WS)
|
ws: true, // WebSocket-Proxy aktivieren (Web Terminal, Agent-WS)
|
||||||
@ -127,7 +127,7 @@ server {
|
|||||||
location /api/ {
|
location /api/ {
|
||||||
client_max_body_size 50m;
|
client_max_body_size 50m;
|
||||||
|
|
||||||
proxy_pass https://192.168.85.13:8443;
|
proxy_pass https://<BACKEND-IP>:8443;
|
||||||
proxy_ssl_verify off;
|
proxy_ssl_verify off;
|
||||||
|
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
@ -166,7 +166,7 @@ rm -f /etc/nginx/sites-enabled/default
|
|||||||
nginx -t && systemctl reload nginx
|
nginx -t && systemctl reload nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Backend-IP anpassen:** `192.168.85.13:8443` durch die tatsächliche Backend-Adresse ersetzen.
|
> **Backend-IP anpassen:** `<BACKEND-IP>:8443` durch die tatsächliche Backend-Adresse ersetzen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -228,7 +228,7 @@ API-Calls werden per Proxy an das Backend weitergeleitet — `vite.config.js` an
|
|||||||
// vite.config.js
|
// vite.config.js
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'https://192.168.85.13:8443', // Backend-IP anpassen
|
target: 'https://<BACKEND-IP>:8443', // Backend-IP anpassen
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
ws: true, // WebSocket-Proxy (Web Terminal, Agent-WS)
|
ws: true, // WebSocket-Proxy (Web Terminal, Agent-WS)
|
||||||
|
|||||||
@ -8,14 +8,28 @@ Einrichtung von PostgreSQL mit TimescaleDB auf dem RMM-Backend-Server (Debian 13
|
|||||||
|
|
||||||
## 1. PostgreSQL installieren
|
## 1. PostgreSQL installieren
|
||||||
|
|
||||||
|
> **Wichtig für Debian 13 (Trixie):** Das Standard-Debian-Repository liefert PostgreSQL 17.8,
|
||||||
|
> TimescaleDB benötigt aber mindestens 17.9. Deshalb muss zuerst das **offizielle
|
||||||
|
> PostgreSQL-Apt-Repository** eingerichtet werden — das liefert immer die aktuelle Version.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
apt update
|
apt update
|
||||||
apt install -y postgresql postgresql-contrib postgresql-common
|
apt install -y curl gnupg
|
||||||
|
|
||||||
|
# Offizielles PostgreSQL-Repository einrichten
|
||||||
|
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
|
||||||
|
| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
|
||||||
|
|
||||||
|
echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \
|
||||||
|
> /etc/apt/sources.list.d/pgdg.list
|
||||||
|
|
||||||
|
apt update
|
||||||
|
apt install -y postgresql-17
|
||||||
|
|
||||||
systemctl enable postgresql
|
systemctl enable postgresql
|
||||||
systemctl start postgresql
|
systemctl start postgresql
|
||||||
|
|
||||||
# Version prüfen (Trixie liefert PG17)
|
# Version prüfen — muss 17.9 oder neuer zeigen
|
||||||
psql --version
|
psql --version
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -24,17 +38,15 @@ psql --version
|
|||||||
## 2. TimescaleDB installieren
|
## 2. TimescaleDB installieren
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Repository einrichten
|
# TimescaleDB-Repository einrichten
|
||||||
apt install -y curl gnupg
|
|
||||||
echo "deb https://packagecloud.io/timescale/timescaledb/debian/ bookworm main" \
|
echo "deb https://packagecloud.io/timescale/timescaledb/debian/ bookworm main" \
|
||||||
> /etc/apt/sources.list.d/timescaledb.list
|
> /etc/apt/sources.list.d/timescaledb.list
|
||||||
curl -sL https://packagecloud.io/timescale/timescaledb/gpgkey | \
|
curl -sL https://packagecloud.io/timescale/timescaledb/gpgkey \
|
||||||
gpg --dearmor > /etc/apt/trusted.gpg.d/timescaledb.gpg
|
| gpg --dearmor > /etc/apt/trusted.gpg.d/timescaledb.gpg
|
||||||
apt update
|
apt update
|
||||||
|
|
||||||
# Passende Version zu PG17 installieren
|
# TimescaleDB für PostgreSQL 17 installieren
|
||||||
apt install -y timescaledb-2-loader-postgresql-17=2.25.1~debian12-1708 \
|
apt install -y timescaledb-2-postgresql-17
|
||||||
timescaledb-2-postgresql-17=2.25.1~debian12-1708
|
|
||||||
|
|
||||||
# In postgresql.conf aktivieren
|
# In postgresql.conf aktivieren
|
||||||
sed -i "s/#shared_preload_libraries = ''/shared_preload_libraries = 'timescaledb'/" \
|
sed -i "s/#shared_preload_libraries = ''/shared_preload_libraries = 'timescaledb'/" \
|
||||||
@ -43,6 +55,14 @@ sed -i "s/#shared_preload_libraries = ''/shared_preload_libraries = 'timescaledb
|
|||||||
systemctl restart postgresql
|
systemctl restart postgresql
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **Falls der Install mit einem Abhängigkeitsfehler fehlschlägt** (`postgresql-17 >= 17.9 required`):
|
||||||
|
> Das bedeutet, dass noch das Debian-eigene PostgreSQL 17.8 installiert ist.
|
||||||
|
> Lösung:
|
||||||
|
> ```bash
|
||||||
|
> apt remove -y postgresql* && apt autoremove -y
|
||||||
|
> # Dann Schritt 1 (PostgreSQL aus dem pgdg-Repo) wiederholen
|
||||||
|
> ```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Datenbank und User anlegen
|
## 3. Datenbank und User anlegen
|
||||||
|
|||||||
11
frontend/.env.example
Normal file
11
frontend/.env.example
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# RMM Frontend Konfiguration
|
||||||
|
# Kopiere diese Datei nach .env und trage deine Werte ein
|
||||||
|
|
||||||
|
# IP/Hostname des RMM Backends (ohne https://, ohne Port)
|
||||||
|
VITE_BACKEND_HOST=your-backend-host
|
||||||
|
|
||||||
|
# Port des RMM Backends
|
||||||
|
VITE_BACKEND_PORT=8443
|
||||||
|
|
||||||
|
# API-Key fuer den Frontend-Zugriff (aus den Backend-Einstellungen)
|
||||||
|
VITE_API_KEY=your-api-key-here
|
||||||
26
frontend/Dockerfile
Normal file
26
frontend/Dockerfile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
FROM node:22-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ---
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Konfiguration via ENV zur Laufzeit (kein Rebuild bei IP-Aenderung noetig)
|
||||||
|
ENV BACKEND_HOST=localhost \
|
||||||
|
BACKEND_PORT=8443 \
|
||||||
|
API_KEY=""
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
@ -265,7 +265,7 @@ DELETE /api/v1/agents/{id}/wireguard/peers/{uuid} Peer loeschen
|
|||||||
# Peer anlegen (Auto: Keypair, naechste freie IP, Endpoint)
|
# Peer anlegen (Auto: Keypair, naechste freie IP, Endpoint)
|
||||||
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
|
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
|
||||||
https://your-backend:8443/api/v1/agents/6beb8dfd.../wireguard/peers \
|
https://your-backend:8443/api/v1/agents/6beb8dfd.../wireguard/peers \
|
||||||
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"10.172.100.210"}'
|
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"<DNS-SERVER>"}'
|
||||||
# → {peer_config: "[Interface]\nPrivateKey=...\n[Peer]\n...", ...}
|
# → {peer_config: "[Interface]\nPrivateKey=...\n[Peer]\n...", ...}
|
||||||
|
|
||||||
# Alle Peers
|
# Alle Peers
|
||||||
|
|||||||
13
frontend/docker-entrypoint.sh
Normal file
13
frontend/docker-entrypoint.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Generiert /usr/share/nginx/html/runtime-config.js aus ENV-Variablen
|
||||||
|
# Wird beim Container-Start ausgefuehrt
|
||||||
|
|
||||||
|
cat > /usr/share/nginx/html/runtime-config.js << EOF
|
||||||
|
window.__RMM_CONFIG__ = {
|
||||||
|
backendHost: "${BACKEND_HOST:-localhost}",
|
||||||
|
backendPort: "${BACKEND_PORT:-8443}",
|
||||||
|
apiKey: "${API_KEY:-}"
|
||||||
|
};
|
||||||
|
EOF
|
||||||
|
|
||||||
|
exec nginx -g "daemon off;"
|
||||||
@ -1,6 +1,8 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<!-- Runtime-Konfiguration (Docker): wird von nginx aus ENV-Vars generiert -->
|
||||||
|
<script src="/runtime-config.js" onerror="window.__RMM_CONFIG__={}"></script>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|||||||
21
frontend/nginx.conf
Normal file
21
frontend/nginx.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# SPA-Routing: alle Pfade auf index.html
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Caching fuer Assets
|
||||||
|
location /assets/ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Kein Caching fuer index.html
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
}
|
||||||
|
}
|
||||||
3
frontend/public/runtime-config.js
Normal file
3
frontend/public/runtime-config.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Lokaler Entwicklungs-Fallback — in Docker wird diese Datei durch
|
||||||
|
// docker-entrypoint.sh mit echten Werten ueberschrieben
|
||||||
|
window.__RMM_CONFIG__ = {};
|
||||||
@ -1178,7 +1178,7 @@ function WireGuardTab({ agentId, sys }) {
|
|||||||
const [peers, setPeers] = useState([])
|
const [peers, setPeers] = useState([])
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [adding, setAdding] = useState(false)
|
const [adding, setAdding] = useState(false)
|
||||||
const [newPeer, setNewPeer] = useState({ name: '', dns: '10.172.100.210, 10.172.100.220' })
|
const [newPeer, setNewPeer] = useState({ name: '', dns: '' })
|
||||||
const [result, setResult] = useState(null)
|
const [result, setResult] = useState(null)
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
@ -1213,7 +1213,7 @@ function WireGuardTab({ agentId, sys }) {
|
|||||||
})
|
})
|
||||||
setResult(resp?.data || resp)
|
setResult(resp?.data || resp)
|
||||||
setAdding(false)
|
setAdding(false)
|
||||||
setNewPeer({ name: '', dns: '10.172.100.210, 10.172.100.220' })
|
setNewPeer({ name: '', dns: '' })
|
||||||
loadPeers()
|
loadPeers()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e.message)
|
setError(e.message)
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
// Frontend-Konfiguration — VOR dem Build anpassen, dann als config.js speichern
|
// Frontend-Konfiguration — wird automatisch aus .env gelesen
|
||||||
// config.js ist in .gitignore und wird NICHT eingecheckt
|
// Kopiere frontend/.env.example → frontend/.env und trage deine Werte ein
|
||||||
|
// config.js und .env sind in .gitignore und werden NICHT eingecheckt
|
||||||
|
|
||||||
export const BACKEND_HOST = 'BACKEND_IP_ODER_HOSTNAME'
|
export const BACKEND_HOST = import.meta.env.VITE_BACKEND_HOST || 'localhost'
|
||||||
export const BACKEND_URL = `https://${BACKEND_HOST}:8443`
|
export const BACKEND_PORT = import.meta.env.VITE_BACKEND_PORT || '8443'
|
||||||
export const API_KEY = 'DEIN_API_KEY'
|
export const BACKEND_URL = `https://${BACKEND_HOST}:${BACKEND_PORT}`
|
||||||
|
export const API_KEY = import.meta.env.VITE_API_KEY || ''
|
||||||
|
|||||||
@ -556,7 +556,7 @@ function SystemSettingsSection() {
|
|||||||
type="text"
|
type="text"
|
||||||
value={form.backend_url_internal || ''}
|
value={form.backend_url_internal || ''}
|
||||||
onChange={(e) => setForm({ ...form, backend_url_internal: e.target.value })}
|
onChange={(e) => setForm({ ...form, backend_url_internal: e.target.value })}
|
||||||
placeholder="https://192.168.85.13:8443"
|
placeholder="https://<BACKEND-IP>:8443"
|
||||||
className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-white text-sm focus:outline-none focus:border-orange-500 mt-1"
|
className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-white text-sm focus:outline-none focus:border-orange-500 mt-1"
|
||||||
/>
|
/>
|
||||||
<div className="text-[10px] text-gray-600 mt-0.5">Fuer Tunnel-Zugriff und lokale Verbindungen</div>
|
<div className="text-[10px] text-gray-600 mt-0.5">Fuer Tunnel-Zugriff und lokale Verbindungen</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user