# appServer Portal UI Übersichts-Webserver für **`server.schooltech.ch`**. Er fasst eine Reihe von Web-Diensten (Roboter-Steuerungen, Guacamole-Remotedesktops, Portainer, VS Code, Nextcloud …) unter **einer Domain** zusammen und macht sie über sprechende Subdomains erreichbar. Alle Dienste laufen als Subdomain von `.server.schooltech.ch` – egal ob sie auf dem Server selbst, auf einem Gerät im LAN oder hinter einem SSH-Tunnel stehen. Ein nginx-Reverse-Proxy nimmt jede Subdomain auf 443 entgegen, terminiert TLS (Let's Encrypt) und leitet an den passenden Upstream weiter. --- ## Inhalt - [Architektur-Übersicht](#architektur-übersicht) - [Die Portal-Seite (`server.schooltech.ch`)](#die-portal-seite-serverschooltechch) - [Die Dienste / Subdomains](#die-dienste--subdomains) - [`forwarding.conf` – das Herzstück](#forwardingconf--das-herzstück) - [`connect-proxies.sh` – Konfig-Generator](#connect-proxiessh--konfig-generator) - [Authentifizierung](#authentifizierung) - [TLS / Let's Encrypt](#tls--lets-encrypt) - [Container & Betrieb](#container--betrieb) - [Neuen Dienst hinzufügen](#neuen-dienst-hinzufügen) - [Dateiübersicht](#dateiübersicht) --- ## Architektur-Übersicht Alles hängt unter `*.server.schooltech.ch`. Der Unterschied zwischen den Diensten ist nicht die Domain, sondern **wohin der Upstream zeigt**: ![Architektur-Übersicht](doc/Architektur.svg) > Diagramm-Quelle: [`doc/Architektur.svg`](doc/Architektur.svg) — auch als > [`doc/Architektur.png`](doc/Architektur.png) (für Viewer ohne SVG-Support). **Bausteine (Docker-Container, siehe `docker-compose.yaml`):** | Container | Image | Rolle | |---|---|---| | `appServer_PortalUI` | `nginx:alpine` | Reverse-Proxy + Auslieferung der Portal-Seite (Ports 80/443) | | `AppServerAuth` | `node:24-alpine` | Login-/Session-Service (`auth/auth.js`, Port 3000 intern) | | `appServer_TunnelHead` | `linuxserver/openssh-server` | SSH-Hub: entfernte Geräte bauen Reverse-Tunnel hierher auf | | `appServer_guacamole` | `abesnier/guacamole` | Lokaler Guacamole-Remotedesktop | | `appServer_LetsEncryptFetcher` | `certbot/certbot` | Holt/erneuert die TLS-Zertifikate | Alle Container hängen im Docker-Netzwerk **`appRobotNet`** und sprechen sich per Container-Namen an (z. B. `appserverauth:3000`). --- ## Die Portal-Seite (`server.schooltech.ch`) Ruft man die nackte Domain `server.schooltech.ch` auf, erscheint die **Portal-Oberfläche** – eine schlanke Single-Page-App aus `public/`: - **`public/index.html`** – Grundgerüst: oben eine **Navigationsleiste** (`
` mit Logo *„schooltech“*, der Service-Navigation `#services` und einem Login/Logout-Button), darunter ein **`