# 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**: 
                          Internet  (HTTPS :443 / HTTP :80)
                                     │
              ┌────────────────────────────────────────────────┐
              │  nginx Reverse-Proxy   (Container: appServer_PortalUI)
              │  ein vHost pro Subdomain  *.server.schooltech.ch
              │  TLS-Terminierung (Let's Encrypt) · 80→443 Redirect
              └────────────────────────────────────────────────┘
                                     │
        ┌───────────────┬───────────┼──────────────┬────────────────────┐
        ▼               ▼           ▼              ▼
  server.          rp5*.        nextcloud.   inf*/rp3*/tc*/robot*/fluidnc*
  schooltech.ch    schooltech.  schooltech.   .server.schooltech.ch
  Portal-UI        lokale        Gerät im LAN  über SSH-Tunnel-Hub
  (diese App)      Container     (direkte IP)  appServer_TunnelHead
        │               │           │              │
        ▼               ▼           ▼              ▼
  public/          appServer_    192.168.0.210  appServer_TunnelHead (SSH-Reverse-Tunnels)
  index.html       guacamole /                  ├─ 99xx InformatikWeb (inf*)
  + Auth-API       portainer                    ├─ 81xx RP3/SCARA (rp3*, fluidnc*)
                                                └─ 97xx ThinkCentre (tc*, robot*)
> Bild: [`doc/Architektur.png`](doc/Architektur.png) · Vektor-Quelle: > [`doc/Architektur.svg`](doc/Architektur.svg) (für PDF/beliebige Skalierung). **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 **`