# MDM Server — Technische Architektur

## Server

- **Hostname:** rebreak-mdm
- **IP:** 178.105.101.137
- **Provider:** Hetzner Cloud
- **OS:** Ubuntu 24.04
- **SSH:** `ssh rebreak-mdm` (via ~/.ssh/config Alias)

## DNS

- **Domain:** mdm.rebreak.org
- **Registrar:** IONOS
- **Record:** A-Record, 178.105.101.137
- **TTL:** Standard (300-3600s)

## Stack-Komponenten

### nginx (System-Service)
- Version: nginx/1.24.0
- Port 80: HTTP-zu-HTTPS-Redirect (301)
- Port 443: SSL/TLS mit HTTP/2, reverse proxy zu nanomdm
- Config: `/etc/nginx/sites-available/mdm.rebreak.org` (symlinked in sites-enabled)
- TLS: Let's Encrypt via certbot, auto-renewal via systemd-Timer

### NanoMDM (Docker-Container)
- Image: `ghcr.io/micromdm/nanomdm:latest` (v0.9.0 zum Zeitpunkt Setup)
- Container-Name: `nanomdm`
- Compose-File: `/opt/nanomdm/docker-compose.yml`
- Netzwerk-Mode: `host` (kein Bridge-Netzwerk — direkter Zugriff auf localhost:5432)
- Lauscht: `127.0.0.1:9000` (nur localhost, nginx proxiet)
- Restart-Policy: `unless-stopped`
- Volumes:
  - `/opt/nanomdm/certs:/certs:ro` (CA-cert + Push-cert)
  - `nanomdm-data:/data` (Docker-Volume)

### PostgreSQL (System-Service)
- Version: PostgreSQL 16
- Socket: `127.0.0.1:5432` (localhost only)
- Datenbank: `nanomdm`
- User: `nanomdm`
- Passwort: in `/root/.nanomdm_db_pass` (chmod 600)
- pg_hba: scram-sha-256 für localhost + 172.17.0.0/16 + 172.18.0.0/16 (Docker-Netze)

### Certbot (System-Service)
- Cert-Pfad: `/etc/letsencrypt/live/mdm.rebreak.org/`
- Auto-Renewal: systemd-Timer (certbot.timer), prüft 2x täglich
- Renewal: nginx-Reload nach Renewal via Hook

## Port-Übersicht

| Port | Bind         | Service   | Beschreibung                       |
|------|--------------|-----------|------------------------------------|
| 80   | 0.0.0.0      | nginx     | HTTP → HTTPS redirect              |
| 443  | 0.0.0.0      | nginx     | HTTPS, TLS termination, MDM-proxy  |
| 9000 | 127.0.0.1    | nanomdm   | MDM-Protokoll (intern only)        |
| 5432 | 127.0.0.1    | postgres  | DB (intern only)                   |
| 22   | 0.0.0.0      | sshd      | Admin-SSH                          |

UFW-Regeln: 22/tcp, 80/tcp, 443/tcp erlaubt. Alles andere denied by default.

## Zertifikat-Pfade

| Datei                              | Inhalt              | Permissions |
|------------------------------------|---------------------|-------------|
| `/opt/nanomdm/certs/ca.crt`       | MDM CA (self-signed)| 644         |
| `/opt/nanomdm/certs/ca.key`       | MDM CA Private Key  | 600         |
| `/opt/nanomdm/certs/push.csr`     | Apple Push CSR      | 644         |
| `/opt/nanomdm/certs/push.key`     | Apple Push Priv-Key | 600         |
| `/opt/nanomdm/certs/push.pem`     | Apple Push Cert (*)  | 600 geplant |
| `/root/.nanomdm_db_pass`          | Postgres-Passwort   | 600         |

(*) `push.pem` existiert noch nicht — warte auf Apple-Portal-Upload (Phase D.1)

## Apple Push Zertifikat — Ablauf

Apple-Geräte erhalten MDM-Befehle via Apple Push Notification Service (APNS). Dafür braucht NanoMDM ein von Apple signiertes Push-Zertifikat.

Ablauf (einmal jährlich zu erneuern):

```
1. Server generiert push.key + push.csr (einmalig, Key bleibt gleich bei Renewal)
2. Admin lädt push.csr auf identity.apple.com/pushcert hoch
3. Apple signiert und stellt push.pem aus (Download)
4. push.pem wird auf Server kopiert: /opt/nanomdm/certs/push.pem
5. nanomdm via -apns-cert oder Umgebungsvariable konfigurieren
6. docker compose restart nanomdm
```

Wichtig: Bei Renewal (jährlich) den GLEICHEN push.key verwenden. Wenn ein neuer Key generiert wird, müssen alle enrollten Geräte re-enrollen.

## Trust-Modell

```
Chahine (Device-Owner)
  - enrolled freiwillig
  - hat KEINEN MDM-Admin-Zugriff
  - kann Profil NICHT selbst entfernen

Olfa (Co-Admin)
  - hat SSH-Zugriff auf rebreak-mdm
  - kennt MDM-Admin-API-Key (nach Phase E generiert)
  - kann Profil entfernen via nanomdm API

Ina Wittek (Trustee, ina.wittek@gmx.de)
  - bekommt Notfall-Credentials per Email (Phase E)
  - kann Profil entfernen wenn weder Chahine noch Olfa erreichbar
  - hat kein Server-Zugriff, nur Credentials für nanomdm-Endpoint
```

## Recovery-Szenarien

| Szenario                          | Lösung                                                      |
|-----------------------------------|-------------------------------------------------------------|
| Profil-Entfernung nötig           | Olfa oder Ina nutzen MDM-API oder nanomdm-UI                |
| Server down                       | `ssh rebreak-mdm` → `docker compose -f /opt/nanomdm/docker-compose.yml up -d` |
| Apple Push Cert abgelaufen        | Neues Push Cert via identity.apple.com, gleicher push.key   |
| DB korrupt                        | Backup einspielen (pg_dump), dann nanomdm restart           |
| Server kompromittiert             | Apple Push Cert revoken auf identity.apple.com, neuer Server, neues Enrollment |
| Device verloren (gestohlen)       | MDM-remote-wipe triggern (löscht Gerät), nicht MDM-Profil  |
| Factory-Reset vom User            | Nuclear option: alle Daten weg, aber MDM-Profil auch weg. Dann re-enroll. |
