carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1# Recovery of an interrupted platform self-update (spec §6, "every run
2# begins with recovery"). Runs once per boot, BEFORE the edge, and on the
3# update oneshot's failure. It restores files only — carlos.prev over
4# carlos, the previous unit set — and never restarts or gates the edge
5# from inside a unit the edge is ordered after: at boot the edge's own
6# start IS the restart. At runtime (edge already started this boot) it
7# issues a non-blocking restart and exits.
8#
9# When a journal is open and carlos.prev exists, the recovery runs from
10# carlos.prev.
11# The moves protocol floor (moves spec §11) narrows that choice: once a
12# floor is armed (/data/.moves/floor.min-release is there and not empty),
13# carlos.prev runs only when its verdict file (/opt/carlos/carlos.prev.allowed,
14# written by root after comparing versions in Go) names that same floor,
15# byte for byte. A floor path that is a symlink or anything but a regular
16# file (a dangling link, a FIFO, a directory) never reads as "no floor":
17# the current binary runs (#267). carlos.prev's own floor gate (carlos
18# system floor-allows-prev) makes the comparison: it opens each file once,
19# without following a symlink or waiting on a FIFO, refuses anything but a
20# small single-link regular file with the expected owner, and exits 0 only
21# for a match. Not cmp: the agent owns /data and could swap the floor file
22# between the shell's tests and cmp's open.
23# Otherwise the current binary runs, and its own check refuses to restore a
24# carlos.prev below the floor. No floor file: the choice is exactly as
25# before. The line carries no percent sign and no dollar sign, both of which
26# systemd expands before the shell sees them.
27#
28# The seeds floor (seeded-instances spec §3.3) adds the same test for its
29# own files: once /data/.moves/seeds-floor.min-release is there and not
30# empty, carlos.prev runs only when /opt/carlos/carlos.prev.seeds-allowed
31# names that same floor, byte for byte.
32[Unit]
33Description=carlos platform self-update recovery
34Before=carlos-edge.service
35DefaultDependencies=yes
36
37[Service]
38Type=oneshot
39TimeoutStartSec=10min
40EnvironmentFile=-/etc/carlos/host.env
41ExecStart=/bin/sh -c 'if [ -x /opt/carlos/system/guard/carlos ] && { [ -e /var/lib/carlos-claims/authority/exec/census.json ] || [ -L /var/lib/carlos-claims/authority/exec/census.json ] || [ -e /opt/carlos/system/guard/moves ] || [ -L /opt/carlos/system/guard/moves ]; }; then exec /opt/carlos/system/guard/carlos system guard-exec recover; fi; if [ -f /opt/carlos/system/router/journal.json ] && [ -x /opt/carlos/carlos.prev ] && [ ! -L /data/.moves/floor.min-release ] && { [ ! -e /data/.moves/floor.min-release ] || [ -f /data/.moves/floor.min-release ]; } && { ! [ -s /data/.moves/floor.min-release ] || /opt/carlos/carlos.prev system floor-allows-prev /data/.moves/floor.min-release /opt/carlos/carlos.prev.allowed; } && [ ! -L /data/.moves/seeds-floor.min-release ] && { [ ! -e /data/.moves/seeds-floor.min-release ] || [ -f /data/.moves/seeds-floor.min-release ]; } && { ! [ -s /data/.moves/seeds-floor.min-release ] || /opt/carlos/carlos.prev system floor-allows-prev /data/.moves/seeds-floor.min-release /opt/carlos/carlos.prev.seeds-allowed; }; then exec /opt/carlos/carlos.prev system apply --recover; fi; exec /opt/carlos/carlos system apply --recover'
42
43ProtectHome=yes
44PrivateTmp=yes
45PrivateDevices=yes
46ProtectClock=yes
47ProtectHostname=yes
48ProtectKernelTunables=yes
49ProtectKernelModules=yes
50ProtectKernelLogs=yes
51RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
52RestrictNamespaces=yes
53RestrictRealtime=yes
54LockPersonality=yes
55MemoryDenyWriteExecute=yes
56MemoryMax=256M
57TasksMax=64
58
59[Install]
60WantedBy=multi-user.target
61