carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1# Proves the S3 replicas actually restore: pulls every database named in
2# /etc/litestream.yml back from S3 into a private tmp, opens it, and runs an
3# integrity check. An un-restored backup is not a backup. Runs daily via
4# carlos-restore-verify.timer; a failure leaves this unit in state 'failed',
5# where fleet sweeps see it loudly. Ported from titogo's
6# deploy/systemd/titogo-restore-verify.service.
7[Unit]
8Description=carlos restore-verify (restore every S3 replica, integrity-check it)
9After=network-online.target carlos-litestream.service
10Wants=network-online.target
11
12[Service]
13Type=oneshot
14ExecStart=/opt/carlos/carlos ops restore-verify -config /etc/litestream.yml
15EnvironmentFile=/data/litestream.env
16# Restore into a DISK-backed directory, not the PrivateTmp tmpfs. Both are
17# charged to this cgroup — page cache is accounted just like tmpfs, so the
18# reported peak barely moves (flagship: 485.6M on tmpfs, 494.4M on disk, for a
19# 412M tenant). What changes is what the ceiling DOES when the restore does not
20# fit, and that is the whole point:
21#
22# tmpfs pages are unevictable -> hitting MemoryMax KILLS the drill
23# page cache is reclaimable -> hitting MemoryMax THROTTLES it
24#
25# Measured on the flagship 2026-08-16, same 412M database, MemoryMax=128M:
26# on tmpfs, oom-killed after 8.3s; on disk, still running after 10 minutes
27# under reclaim (stopped by hand). So the restored file no longer has to FIT
28# in the cgroup's memory — a tenant outgrowing the ceiling degrades instead of
29# failing.
30#
31# It does NOT make size irrelevant: a badly undersized ceiling makes the drill
32# crawl. Keep MemoryMax comfortably above the largest tenant. systemd creates
33# and cleans %C/carlos-verify and binds it writable despite
34# ProtectSystem=strict.
35CacheDirectory=carlos-verify
36Environment=TMPDIR=%C/carlos-verify
37User=carlos
38Group=carlos
39CapabilityBoundingSet=
40NoNewPrivileges=yes
41ProtectSystem=strict
42ProtectHome=yes
43PrivateTmp=yes
44PrivateDevices=yes
45RestrictAddressFamilies=AF_INET AF_INET6
46MemoryDenyWriteExecute=yes
47# Sized to sit ABOVE the largest single database, not to bound the process:
48# restored bytes are charged here either way (see the TMPDIR note). Measured
49# after the move to disk: a fleet of ~30 small replicas peaks around 150M,
50# a single ~400M tenant database around 500M. Two earlier lessons are
51# load-bearing and kept: the service was OOM-killed at a ~256M peak when
52# restored copies ACCUMULATED (RestoreVerify now deletes each once checked
53# — see its comment), and tmpfs is why unfitting files were fatal rather
54# than slow.
55#
56# WATCH: a single database approaching this ceiling will throttle, not
57# fail, when it crosses — raise this then.
58MemoryMax=512M
59