# Root's half of joining (region HA spec 2 ยง5 step 5.3): `carlos system # join` verifies this box's signed invitation, writes the enrollment it # names, and arms the host lifecycle guard (guard-arm) with the release # identity `carlos system install-channel` kept. On a box that is armed # already, has no invitation yet, or has CARLOS_HOST_CLAIM or # CARLOS_REGION_HA off, it does nothing. Started only by # carlos-system-join.path; no [Install] section, because nothing else # should want it. # # Root, with no filesystem sandboxing, like carlos-system-update.service: # guard-arm writes /opt/carlos/system/guard, /etc/carlos/host-actor.json and # the guarded units' drop-ins under /etc/systemd/system. # StartLimitIntervalSec=0 because the path unit can fire in bursts. [Unit] Description=carlos joining (root: arm the host lifecycle guard) After=network-online.target Wants=network-online.target StartLimitIntervalSec=0 [Service] Type=oneshot TimeoutStartSec=5min EnvironmentFile=-/etc/carlos/host.env ExecStart=/opt/carlos/carlos system join # --- hardening (the carlos-system-update.service set) --- ProtectHome=yes PrivateTmp=yes PrivateDevices=yes ProtectClock=yes ProtectHostname=yes ProtectKernelTunables=yes ProtectKernelModules=yes ProtectKernelLogs=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX RestrictNamespaces=yes RestrictRealtime=yes LockPersonality=yes MemoryDenyWriteExecute=yes MemoryMax=256M TasksMax=64