TLS-Gate: die Node als Ansible-Rolle â Handout fĂŒr Katze & Crew
Von: Branko â OZMAI / Ansible-Katze & Crew
Stand: 1. Oktober 2026
Typ: EXTERNAL_SOURCE (Inbox-Regel §3 â keine automatische Geltung, kein Brain-Status)
Charakter: HANDOUT / ĂBERGABE. Der Soll-Zustand ist belegt (đ§Ș, im Container); die Rolle selbst ist ⏠OPEN. Kein Deploy auf eine echte Node.
Quelle: Repo TLS-Gate-Mock-Pipeline (git.crumbforest.org), Commit 702afe3 (main): docs/HANDOUT_ANSIBLE.md, docker_vm/HANDBUCH.md,
docker_vm/provision/instance.sh, docker_vm/tests/{run,p3,p4,p5}.sh (52 + 43 + 54 + 31 PrĂŒfungen, am 1.10. grĂŒn), bin/TLS-doktor.bash (P6 Pool-Check, 90d6358).
Anschluss an: 2026-09-29_TLS-GATE-V3-STAND-HERKUNFT-NODE-CA-MIGRATION_BRANKO.md.
Legende: â real/gebaut · đ§Ș gebaut, getestet, nicht live · đ spezifiziert · ⏠OPEN · â UNKNOWN
Zugangsdaten, Kunden-Domains, Reseller-IDs und Inhalte der vertraulichen Anbieter-Doku stehen bewusst nicht hier. Alle Instanzen (ozm01, ozm02) und der Registrar sind Mock bzw. Fake.
Auftrag: Das, was heute docker_vm/provision/instance.sh im Container tut, wird eine Ansible-Rolle fĂŒr die echte Node.
Die Referenz steht fest und ist belegt: Der Container besteht vier Abnahme-Suiten (52 + 43 + 54 + 31 PrĂŒfungen), die Rolle soll dieselben ZustĂ€nde auf dem Zielhost erzeugen.
1. Was ihr ĂŒbernehmt (Skript-Schritt â Rollenteil)
instance.sh-Schritt |
Soll-Zustand | Ansible |
|---|---|---|
Pakete (Dockerfile) |
nginx, mariadb-server, php8.4-{fpm,cli,mysql,soap,mbstring,xml}, openssh-server; Standard-Pool www und Standard-Vhost aus |
package, command/file |
| Geheimnisse | je Instanz DB-, DDL-, Admin-Passwort und root.key (32 Byte, Format <id>:<base64>), nur root lesbar |
ansible.builtin.password-Lookup bzw. Vault; nie ins Repo/Log (no_log) |
| Benutzer | je Instanz User+Gruppe mit fester UID (ozm01 2001, ozm02 2002) |
user, group |
| Verzeichnisse | /home/<n>/{app,bin,state,logs}; /home/<n> 0710 <n>:www-data; state 0700 <n>; root.key 0400 <n>; app/, bin/ gehören root |
file |
| Code | native_php â app/, native_bash_cli â bin/ (root-eigen, nicht vom Web-User schreibbar) |
synchronize/copy |
| SSH | AllowGroups ssh-instances, nur SchlĂŒssel, kein root, keine Tunnel; authorized_keys gehört root |
lineinfile/Template (conf/sshd-tlsgate.conf), authorized_key mit root-Besitz |
| Datenbank | je Instanz Schema <n>, User <n>_ddl (alles auf das Schema, nur fĂŒr migrate) und <n>_app (nur SELECT, INSERT, UPDATE, DELETE) |
community.mysql.* |
| Pool + Vhost | aus provision/templates/pool.conf.tpl, vhost.conf.tpl |
template + Handler (reload) |
| App | user_cli.php migrate als <n>_ddl, Gruppe + Admin anlegen, Alltag nur als <n>_app |
command als Instanz-User, mit creates/StatusprĂŒfung |
| SelbstprĂŒfung | instance.sh endet mit PrĂŒfungen |
assert/uri/command |
2. Abnahme: wann ist die Rolle fertig
- Idempotenz: zweiter Lauf =
changed=0(Container: âkeine Aenderung (Sollstand erreicht)â). - Doktor grĂŒn, als root auf der Node, mit der Umgebung des Pools:
bash WEB_USER=<instanz> TLS_GATE_STATE_DIR=/home/<instanz>/state TLSGATE_ROOT_KEY_FILE=/home/<instanz>/state/root.key \ TLSGATE_DB_DRIVER=mysql TLSGATE_DB_NAME=<instanz> TLSGATE_DB_USER=<instanz>_app TLSGATE_DB_PASS=⊠\ /home/<instanz>/app/bin/TLS-doktor.bash
Erwartet: Exit 0, âAlles gruenâ. Er prĂŒft Erweiterungen, Schema,root.key,state/und den php-fpm-Pool (disable_functions,clear_env,open_basedir,display_errors). - Gegenproben bestehen (das ist der eigentliche Beweis): Die Suiten verĂ€ndern je eine Kleinigkeit und erwarten, dass etwas bricht â
root.key0644, ein Zeichen im DB-Passwort,popenausdisable_functions, ein Zeichen im ssh-SchlĂŒssel, Besitz vonstate/. SinngemÀà als Ansible-Verify-Playbook (--checkzeigt Drift) ĂŒbernehmen. - ZugĂ€nge: ssh nur mit SchlĂŒssel (falscher SchlĂŒssel, root und fremde Instanz â
Permission denied); Web-Login mit Passwort + TOTP;src/,bin/,state/,.gitper Web nicht ausgeliefert.
Die Suiten selbst (Repo: docker_vm/tests/*.sh) laufen per docker exec und sind nicht direkt auf einer Node nutzbar; sie sind die Spezifikation, kein Werkzeug fĂŒr den Zielhost.
3. Was auf der Node anders ist als im Container (nicht blind kopieren)
- TLS: Im Container keines. Auf der Node: Zertifikat und Vhost auf 443; dann
TLSGATE_COOKIE_SECUREentfernen (Vorlage setzt0nur fĂŒr die Testinstanz). - Registrar: Im Container nur der Fake (
soap.fake.test). Auf der Node echter Registrar ĂŒbercred add/cred test; Fake-Pool/-Vhost/-CA nicht ausrollen. - Zugangsdaten im Pool: Die Vorlage legt das DB-Passwort als
env[...]in die Pool-Datei (root-lesbar). FĂŒr den Betrieb besserLoadCredential/Secret-Mount â offen, bitte als Entscheidung festhalten. - systemd, cgroup, Ports 18080/2222: Container-Eigenheiten. Auf der Node regulĂ€re Ports und
systemctl. - Ein MariaDB, ein Schema je Instanz. Kein gemeinsames Mandantenschema; jede Instanz hat ihren eigenen
root.key(die Secrets sind daran gebunden).
4. Fallen (alle im Container schon aufgetreten)
<n>_ddlnie in den Pool. Der Web-Prozess bekommt nur<n>_app.authorized_keysundapp/gehören root. Sonst kann die Instanz ihre SchlĂŒssel bzw. ihren Code Ă€ndern.systemd-user-sessionsmuss laufen, sonst bleibt/run/nologinstehen und jeder ssh-Login scheitert (PAM âAccess deniedâ). Im Container Drop-inssh-user-sessions.conf.mbstringist Pflicht (ohne: HTTP 503 mit Paketnamen);pdo_mysqlbei Treibermysql.- IP-Rate-Limit der App: 10 Fehlversuche in 15 min sperren die IP. Verify-LĂ€ufe, die absichtlich falsche Passwörter senden, setzen vorher die ZĂ€hler zurĂŒck oder laufen von einer anderen IP.
- Neues Image/Host = neue ssh-HostschlĂŒssel â
ssh-keygen -R. dashboard.shper ssh:bash -lc dashboard.sh(nur die Login-Shell hat den PATH),ssh -nverhindert HĂ€nger.
5. Nicht Teil des Auftrags
Rust, Node-CA, TLS-Terminierung/ACME, ein gemeinsames Mandantenschema, Host-Doktoren (Backbone/Strato/Debian â siehe HANDBUCH §10). Offen aus dem Doktor: er prĂŒft nur den Pool des WEB_USER, nicht, ob ein anderer Pool im selben php-fpm schwĂ€cher ist.
6. Reihenfolge-Vorschlag
- Rolle
tlsgate_node(Pakete, sshd, MariaDB-Grundlage, nginx/php-fpm) â Verify: Doktor-Abschnitte Erweiterungen + Pool. - Rolle
tlsgate_instance(Parametername,uid,ssh_pubkey,mode: fake|real) â Verify: Idempotenz, ssh-/Web-Gegenproben. - Erst dann: zweite Instanz (
ozm02) und die Isolationsproben (ozm01 kann ozm02 nicht lesen â Datei, Socket, Schema).
Tipp: ansible-good-practices und ansible-zen auf die fertige Rolle laufen lassen, bevor sie auf die Node geht.