# Installation Diese Anleitung führt von einem leeren Server zu einer Anlage, die sichert und wiederherstellt. Sie beschreibt den Serverteil; die Agenten stehen in [agent-installation.md](agent-installation.md). ## Voraussetzungen | | | | --- | --- | | Betriebssystem | Linux (amd64 oder arm64). Der Server wird für Windows **nicht** ausgeliefert | | PostgreSQL | **15 oder neuer**, erreichbar vom Server. Geprüft gegen 17 (Entwicklung und CI) und 15 (Debian 12) | | Speicher für das Repository | eigener Datenträger oder eigene Freigabe — nicht dasselbe Gerät wie die zu sichernden Daten | | Reverse Proxy | optional, aber empfohlen, sofern der Dienst nicht selbst TLS bedient | **Das Repository gehört nicht auf denselben Datenträger wie die Quelle.** Ein Datenträgerausfall nähme sonst Original und Sicherung gemeinsam mit. Das ist keine Feinheit der Einrichtung, sondern der Zweck der Übung. ## Der kurze Weg: setup.sh Das Paket bringt ein Einrichtungsskript mit. Es geht genau die Schritte dieser Anleitung, und was es angelegt hat, baut es bei einem Abbruch wieder zurück. ```bash tar -xzf syncova--linux-amd64.tar.gz cd syncova--linux-amd64 sudo ./setup.sh ``` Es fragt nach Datenbank, Repository und dem ersten Administrator, installiert PostgreSQL auf Wunsch mit, erzeugt den Verschlüsselungsschlüssel und richtet den Dienst ein. Für einen unbeaufsichtigten Lauf: `sudo ./setup.sh --unbeaufsichtigt` mit den Werten aus der Umgebung (`./setup.sh --hilfe` zeigt sie). Später aktualisieren: `sudo ./update.sh` — es sichert vorher Datenbank und Konfiguration und nimmt sich selbst zurück, wenn der Dienst danach nicht hochkommt. Entfernen: `sudo ./uninstall.sh` — es lässt Datenbank, Repository und Konfiguration liegen, sofern man nicht ausdrücklich etwas anderes verlangt. **Eine bestehende Installation überschreibt `setup.sh` nicht.** Es bricht ab und verweist auf `update.sh`; der Unterschied ist, dass ein Update vorher sichert. Der Rest dieses Dokuments beschreibt dieselben Schritte von Hand — für alle, die wissen wollen, was das Skript tut, oder die davon abweichen müssen. ## 1. Paket auspacken ```bash tar -xzf syncova--linux-amd64.tar.gz cd syncova--linux-amd64 # Prüfsummen des Inhalts kontrollieren shasum -a 256 -c SHA256SUMS ./bin/syncova-api --version ``` Die Versionsabfrage braucht keine Konfiguration. Sie ist der schnellste Weg festzustellen, welche Fassung auf einem Server liegt. Der Paketinhalt: ```text bin/ Programme web/ Weboberfläche (statische Dateien) migrations/ SQL-Migrationen zum Nachlesen (sie stecken zusätzlich in den Programmen) docs/ diese Dokumentation deployment/ Beispiel für die Entwicklungsumgebung und die systemd-Einheit des Agenten ``` ## 2. Datenbank anlegen ```sql CREATE USER syncova WITH PASSWORD ''; CREATE DATABASE syncova OWNER syncova; ``` Syncova legt das Schema **nicht** beim Start an. Das ist Absicht: Ein Dienst, der beim Hochfahren stillschweigend das Schema ändert, macht aus einem versehentlichen Neustart eine Migration. ## 3. Verschlüsselungsschlüssel erzeugen ```bash ./bin/syncova-admin generate-key ``` Ausgegeben wird ein Wert der Form `v1:`. > **Ohne diesen Schlüssel sind die abgelegten Geheimnisse verloren** — MFA-Geheimnisse, > Zugangsdaten der Virtualisierungsverbünde und die Datenschlüssel der > Repositories. Er gehört an einen Ort **außerhalb** dieser Anlage: in einen > Passwortspeicher oder einen Tresor. In ein Backup, das Syncova selbst > erzeugt, gehört er ausdrücklich nicht — dann bräuchte man ihn, um an ihn > heranzukommen. ## 4. Konfiguration Syncova liest ausschließlich Umgebungsvariablen; eine Konfigurationsdatei gibt es nicht. Alle tragen das Präfix `SYNCOVA_`. ```bash # /etc/syncova/syncova.env — nur für root lesbar (chmod 0600) SYNCOVA_ENV=production SYNCOVA_DB_HOST=127.0.0.1 SYNCOVA_DB_PORT=5432 SYNCOVA_DB_NAME=syncova SYNCOVA_DB_USER=syncova SYNCOVA_DB_PASSWORD= SYNCOVA_DB_SSLMODE=require SYNCOVA_ENCRYPTION_KEYS=v1: SYNCOVA_ENCRYPTION_CURRENT_KEY=v1 SYNCOVA_HTTP_LISTEN_ADDRESS=127.0.0.1:8080 SYNCOVA_LOG_LEVEL=info SYNCOVA_LOG_FORMAT=json ``` Die wichtigsten weiteren Werte: | Variable | Vorgabe | Wozu | | --- | --- | --- | | `SYNCOVA_HTTP_TLS_CERT_FILE` / `_KEY_FILE` | leer | TLS im Dienst selbst. **Nur eines von beiden zu setzen verweigert den Start** — sonst liefe der Dienst im Klartext, obwohl der Betreiber Verschlüsselung eingerichtet zu haben glaubt | | `SYNCOVA_HTTP_REQUESTS_PER_MINUTE` | 600 | allgemeine Ratenbegrenzung | | `SYNCOVA_AUTH_REQUIRE_MFA_FOR_PRIVILEGED_USERS` | false | zweiter Faktor für Konten mit Benutzer-, Rollen- oder Sicherheitsrechten | | `SYNCOVA_RESTORE_ALLOWED_ROOTS` | leer | begrenzt Wiederherstellungsziele auf bestimmte Verzeichnisbäume | **Lauscht der Dienst ohne TLS auf allen Schnittstellen, warnt er beim Start in Großbuchstaben.** Der Betrieb hinter einem Reverse Proxy ist der Normalfall und völlig in Ordnung — solange der Dienst dann nur lokal erreichbar ist. ## 5. Schema anlegen ```bash set -a; . /etc/syncova/syncova.env; set +a ./bin/syncova-migrate up ./bin/syncova-migrate status ``` Passt das Schema später nicht zur Programmversion, verweigert `syncova-api` den Start mit einer erklärenden Meldung. Das ist kein Schikane, sondern der Schutz davor, dass eine neue Fassung auf ein altes Schema schreibt. ## 6. Ersten Administrator anlegen ```bash ./bin/syncova-admin create-admin --username admin ``` Das Passwort wird abgefragt und wiederholt — es steht **nicht** in einer Umgebungsvariablen und nicht in den Aufrufparametern. Beides landete sonst in der Prozessliste und in der Shell-Historie. In einem Skript geht es über die Standardeingabe: ```bash printf '%s\n%s\n' "$PASSWORD" "$PASSWORD" | ./bin/syncova-admin create-admin --username admin ``` **Es gibt kein Standardkonto im Programm.** Ein ausgeliefertes Kennwort wäre bekannt, sobald es einmal jemand nachschlägt. Das Kommando legt nur den **ersten** Administrator an; danach entstehen weitere Konten über die Oberfläche oder die API. ## 7. Dienst einrichten ```ini # /etc/systemd/system/syncova-api.service [Unit] Description=Syncova Control Plane After=network-online.target postgresql.service Wants=network-online.target [Service] Type=simple User=syncova Group=syncova EnvironmentFile=/etc/syncova/syncova.env ExecStart=/opt/syncova/bin/syncova-api Restart=on-failure RestartSec=5 # Härtung: Der Dienst braucht Netz und sein Repository, sonst nichts. NoNewPrivileges=yes PrivateTmp=yes ProtectSystem=strict ProtectHome=yes ReadWritePaths=/srv/syncova-repository ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes RestrictSUIDSGID=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX MemoryDenyWriteExecute=yes [Install] WantedBy=multi-user.target ``` `AF_UNIX` gehört in die Liste: Mit `systemd-resolved` läuft die Namensauflösung über einen Unix-Socket. Ohne diesen Eintrag findet der Dienst seine Datenbank nicht und meldet einen Netzfehler, während das Netz einwandfrei arbeitet. ```bash sudo systemctl daemon-reload sudo systemctl enable --now syncova-api curl -s http://127.0.0.1:8080/health/ready ``` ## 8. Oberfläche ausliefern Die Oberfläche ist ein Satz statischer Dateien unter `web/`. Sie braucht einen **SPA-Fallback**, sonst ergibt ein Neuladen auf `/recovery-points` einen 404: ```nginx server { listen 443 ssl; server_name syncova.example; root /opt/syncova/web; location / { try_files $uri /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; } } ``` ## 9. Erstes Repository Ein Repository entsteht **auf einem Datenträger**, nicht in einer Datenbankzeile: ```bash sudo install -d -o syncova -g syncova -m 0700 /srv/syncova-repository sudo -u syncova ./bin/syncova-repo create \ --path /srv/syncova-repository --name "Hauptziel" --hardened ``` `--hardened` setzt den Aufbewahrungsschutz: Manifeste, Blöcke, Schutzvermerke, Descriptor und Datenschlüssel bekommen das Unveränderlich-Kennzeichen des Dateisystems. **Ein so angelegtes Repository lässt sich nicht mit `rm -rf` entfernen** — auch nicht von root, ohne den Schutz vorher aufzuheben. Danach wird es in der Control Plane eingetragen: ```bash curl -X POST https://syncova.example/api/v1/repositories \ -H "Authorization: Bearer " -H 'Content-Type: application/json' \ -d '{"name":"Hauptziel","location":"/srv/syncova-repository"}' ``` Der Endpunkt **legt nichts an, sondern übernimmt**: Er öffnet das vorhandene Repository und liest dessen Kennung aus dem Descriptor. Liegt dort keines, lehnt er ab, statt einen Eintrag ohne Ablage dahinter zu erzeugen. Anschließend die Durchsetzungsstufe messen — sie wird gemessen, nicht behauptet: ```bash curl -X POST https://syncova.example/api/v1/repositories//enforcement/measure \ -H "Authorization: Bearer " ``` ## 10. Erster Auftrag Über die Oberfläche (Backup-Assistent, zehn Schritte) oder die API: ```bash curl -X POST https://syncova.example/api/v1/jobs \ -H "Authorization: Bearer " -H 'Content-Type: application/json' \ -H "Idempotency-Key: $(uuidgen)" -d '{ "name": "Dateiserver täglich", "repository_id": "", "schedule": {"type": "daily", "time": "02:00", "time_zone": "Europe/Berlin"}, "sources": [{"type": "filesystem", "id": "/srv/daten", "name": "Daten"}] }' ``` **Ohne Zeitzone rechnet der Server in UTC**, nicht in der Ortszeit des Servers. Sonst liefe dieselbe Konfiguration auf zwei Servern zu verschiedenen Zeiten. ## 11. Der Schritt, den die meisten auslassen ```bash # Eine Wiederherstellung durchführen, bevor man sie braucht curl -X POST https://syncova.example/api/v1/verification \ -H "Authorization: Bearer " -H 'Content-Type: application/json' \ -d '{"backup_id":"","verification_type":"restore_test"}' ``` Erst danach steigt ein Wiederherstellungspunkt auf `recoverable`. Alles davor ist ein Indiz, kein Nachweis. ## Aktualisierung auf eine neue Fassung ```bash # 1. Datenbank sichern — ein Rollback ersetzt keine Sicherung pg_dump -Fc syncova > syncova-vor-update.dump # 2. Dienst anhalten sudo systemctl stop syncova-api # 3. Programme austauschen sudo tar -xzf syncova--linux-amd64.tar.gz -C /opt/syncova --strip-components=1 # 4. Migrationen anwenden sudo -u syncova /opt/syncova/bin/syncova-migrate up # 5. Starten und nachsehen sudo systemctl start syncova-api curl -s http://127.0.0.1:8080/health/ready ``` Reihenfolge einhalten: Die Migrationen laufen mit dem **neuen** Programm, und der Dienst startet erst danach. Läuft er noch, während sich das Schema ändert, arbeitet er auf einem Stand, den er nicht kennt. Geht etwas schief: `syncova-migrate down` nimmt **genau eine** Migration zurück und verlangt in der Produktion `SYNCOVA_MIGRATE_CONFIRM_DOWN=yes`. Daten in Tabellen, die es vorher nicht gab, sind danach weg — deshalb Schritt 1. ## Was nach der Installation zu tun bleibt - **Zweiten Faktor einrichten**, mindestens für alle Konten mit Löschrecht. - **Benachrichtigungsweg einrichten**, sonst erfährt niemand von einem Ausfall. - **`syncova-dr export` regelmäßig laufen lassen** — die Konfigurationssicherung im Repository ist das, was nach einem Totalverlust des Servers übrig bleibt. - **Den Verschlüsselungsschlüssel außerhalb der Anlage hinterlegen.**