diff --git a/.github/workflows/seismic.yml b/.github/workflows/seismic.yml index 3b57ae3..c6ff4b8 100644 --- a/.github/workflows/seismic.yml +++ b/.github/workflows/seismic.yml @@ -170,7 +170,10 @@ jobs: } done <<'EOF' etc/systemd/system/attestation.service + etc/systemd/system/certbot-renew.service + etc/systemd/system/certbot-renew.timer etc/systemd/system/custodian.service + etc/systemd/system/nginx-ssl-setup.service etc/systemd/system/persistent-luks-setup.service etc/systemd/system/reth.service etc/systemd/system/summit-keygen.service @@ -179,7 +182,9 @@ jobs: etc/systemd/system/summit.target etc/systemd/system/tdx-init.service etc/systemd/system/minimal.target.wants/attestation.service + etc/systemd/system/minimal.target.wants/certbot-renew.timer etc/systemd/system/minimal.target.wants/custodian.service + etc/systemd/system/minimal.target.wants/nginx-ssl-setup.service etc/systemd/system/minimal.target.wants/persistent-luks-setup.service etc/systemd/system/minimal.target.wants/reth.service etc/systemd/system/minimal.target.wants/summit.target diff --git a/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.service b/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.service index a2254cf..c494b7f 100644 --- a/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.service +++ b/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.service @@ -2,6 +2,9 @@ Description=Certbot SSL Certificate Renewal After=network-online.target persistent-luks-setup.service Requires=persistent-luks-setup.service +# The timer is enabled in every image, but only a node whose nginx-ssl-setup +# obtained a certificate has anything to renew. +ConditionPathExists=/persistent/nginx/.certbot-done [Service] Type=oneshot diff --git a/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.timer b/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.timer index c7f96ac..d70802f 100644 --- a/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.timer +++ b/modules/seismic/mkosi.extra/etc/systemd/system/certbot-renew.timer @@ -7,4 +7,4 @@ RandomizedDelaySec=1h Persistent=true [Install] -WantedBy=timers.target +WantedBy=minimal.target diff --git a/modules/seismic/mkosi.extra/etc/systemd/system/nginx-ssl-setup.service b/modules/seismic/mkosi.extra/etc/systemd/system/nginx-ssl-setup.service index 216396a..c0615eb 100644 --- a/modules/seismic/mkosi.extra/etc/systemd/system/nginx-ssl-setup.service +++ b/modules/seismic/mkosi.extra/etc/systemd/system/nginx-ssl-setup.service @@ -11,4 +11,4 @@ StandardOutput=journal StandardError=journal [Install] -WantedBy=multi-user.target +WantedBy=minimal.target diff --git a/modules/seismic/mkosi.extra/etc/systemd/system/reth.service b/modules/seismic/mkosi.extra/etc/systemd/system/reth.service index a53f8ed..842e88e 100644 --- a/modules/seismic/mkosi.extra/etc/systemd/system/reth.service +++ b/modules/seismic/mkosi.extra/etc/systemd/system/reth.service @@ -1,7 +1,7 @@ [Unit] Description=Seismic Reth Node -After=network.target persistent-luks-setup.service nginx-ssl-setup.service attestation.service -Requires=persistent-luks-setup.service nginx-ssl-setup.service attestation.service +After=network.target persistent-luks-setup.service attestation.service +Requires=persistent-luks-setup.service attestation.service [Service] Type=simple diff --git a/modules/seismic/mkosi.extra/etc/systemd/system/summit.service b/modules/seismic/mkosi.extra/etc/systemd/system/summit.service index 04f6dbe..2d577c0 100644 --- a/modules/seismic/mkosi.extra/etc/systemd/system/summit.service +++ b/modules/seismic/mkosi.extra/etc/systemd/system/summit.service @@ -1,7 +1,7 @@ [Unit] Description=Summit Consensus Server -After=network.target persistent-luks-setup.service nginx-ssl-setup.service attestation.service reth.service summit-persist.service -Requires=persistent-luks-setup.service nginx-ssl-setup.service attestation.service reth.service summit-persist.service +After=network.target persistent-luks-setup.service attestation.service reth.service summit-persist.service +Requires=persistent-luks-setup.service attestation.service reth.service summit-persist.service PartOf=summit.target [Service] diff --git a/modules/seismic/mkosi.extra/usr/bin/nginx-ssl-setup b/modules/seismic/mkosi.extra/usr/bin/nginx-ssl-setup index 6c34fbb..e5c0d62 100644 --- a/modules/seismic/mkosi.extra/usr/bin/nginx-ssl-setup +++ b/modules/seismic/mkosi.extra/usr/bin/nginx-ssl-setup @@ -85,12 +85,7 @@ if [ ! -f "$CERTBOT_DONE" ]; then # Mark as done touch "$CERTBOT_DONE" - # Enable automatic renewal timer - systemctl enable certbot-renew.timer - systemctl start certbot-renew.timer - echo "SSL certificate obtained successfully" - echo "Automatic renewal enabled" else echo "Certbot already run, skipping (remove $CERTBOT_DONE to re-run)" fi diff --git a/modules/seismic/mkosi.postinst b/modules/seismic/mkosi.postinst index c3f4ee6..f0bbf24 100755 --- a/modules/seismic/mkosi.postinst +++ b/modules/seismic/mkosi.postinst @@ -32,19 +32,16 @@ chmod +x "$BUILDROOT/usr/bin/nginx-ssl-setup" chmod +x "$BUILDROOT/usr/bin/persistent-luks-setup" chmod +x "$BUILDROOT/usr/bin/summit-persist" -# Enable services -mkdir -p "$BUILDROOT/etc/systemd/system/minimal.target.wants" -for service in \ +# Enable services: `systemctl enable` creates the symlink each unit's +# [Install] WantedBy= names, here minimal.target.wants/, so the boot +# target pulls it in. It must happen at build time: the rootfs is a tmpfs, +# so a unit enabled on a running node is disabled again after a reboot. +mkosi-chroot systemctl enable \ persistent-luks-setup.service \ tdx-init.service \ nginx-ssl-setup.service \ + certbot-renew.timer \ reth.service \ custodian.service \ attestation.service \ summit.target -do - mkosi-chroot systemctl enable "$service" - ln -sf "/etc/systemd/system/$service" "$BUILDROOT/etc/systemd/system/minimal.target.wants/" -done - -# Note: certbot-renew.timer is enabled by nginx-ssl-setup after initial certbot run diff --git a/modules/seismic/readme.md b/modules/seismic/readme.md index ea4daac..0eb8d8f 100644 --- a/modules/seismic/readme.md +++ b/modules/seismic/readme.md @@ -195,10 +195,13 @@ write the override at provisioning time. `nginx-ssl-setup` templates [`node-template.conf`](mkosi.extra/etc/nginx/node-template.conf) with -the domain, obtains a Let's Encrypt certificate, and enables -`certbot-renew.timer`. reth and summit both `Requires=` it, so a failed -certificate keeps them down, though neither needs public HTTPS to run. +the domain and obtains a Let's Encrypt certificate. Nothing depends on +it: a failed certificate leaves the node without public HTTPS, while +reth and summit run regardless. +`certbot-renew.timer` is enabled in the image, since the rootfs is tmpfs +and an enablement made at runtime would not survive a reboot. Its +service is skipped until `nginx-ssl-setup` has obtained a certificate. The timer renews monthly with `RandomizedDelaySec=1h`, so a fleet does not hit Let's Encrypt in the same minute. Renewal can race a disk snapshot (TODO in the service file).