Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions .github/workflows/seismic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ jobs:
bash -n \
modules/seismic/mkosi.build \
modules/seismic/mkosi.postinst \
modules/seismic/mkosi.extra/usr/bin/persistent-luks-setup \
modules/seismic/mkosi.extra/usr/bin/seismic-persistent-luks-setup \
scripts/seismic/founding_inputs.sh \
scripts/seismic/image_json.sh
shellcheck -x \
modules/seismic/mkosi.build \
modules/seismic/mkosi.postinst \
modules/seismic/mkosi.extra/usr/bin/persistent-luks-setup \
modules/seismic/mkosi.extra/usr/bin/seismic-persistent-luks-setup \
scripts/seismic/founding_inputs.sh \
scripts/seismic/image_json.sh

Expand Down Expand Up @@ -168,31 +168,31 @@ jobs:
}
done <<'EOF'
etc/caddy/Caddyfile
etc/systemd/system/attestation.service
etc/systemd/system/caddy.service
etc/systemd/system/custodian.service
etc/systemd/system/persistent-luks-setup.service
etc/systemd/system/reth.service
etc/systemd/system/summit-keygen.service
etc/systemd/system/summit-persist.service
etc/systemd/system/summit.service
etc/systemd/system/summit.target
etc/systemd/system/tdx-init.service
etc/systemd/system/seismic-attestation.service
etc/systemd/system/seismic-caddy.service
etc/systemd/system/seismic-custodian.service
etc/systemd/system/seismic-persistent-luks-setup.service
etc/systemd/system/seismic-reth.service
etc/systemd/system/seismic-summit-keygen.service
etc/systemd/system/seismic-summit-persist.service
etc/systemd/system/seismic-summit.service
etc/systemd/system/seismic-summit.target
etc/systemd/system/seismic-tdx-init.service
etc/systemd/system/system.slice.d/deny-reth-rpc-port.conf
etc/systemd/system/minimal.target.wants/attestation.service
etc/systemd/system/minimal.target.wants/caddy.service
etc/systemd/system/minimal.target.wants/custodian.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
etc/systemd/system/minimal.target.wants/tdx-init.service
etc/systemd/system/minimal.target.wants/seismic-attestation.service
etc/systemd/system/minimal.target.wants/seismic-caddy.service
etc/systemd/system/minimal.target.wants/seismic-custodian.service
etc/systemd/system/minimal.target.wants/seismic-persistent-luks-setup.service
etc/systemd/system/minimal.target.wants/seismic-reth.service
etc/systemd/system/minimal.target.wants/seismic-summit.target
etc/systemd/system/minimal.target.wants/seismic-tdx-init.service
usr/bin/caddy
usr/bin/persistent-luks-setup
usr/bin/seismic-persistent-luks-setup
usr/bin/seismic-attestation-service
usr/bin/seismic-custodian-service
usr/bin/seismic-reth
usr/bin/summit
usr/bin/summit-persist
usr/bin/seismic-summit-persist
usr/bin/tdx-init
EOF

Expand Down
4 changes: 2 additions & 2 deletions modules/seismic/kernel/config.d/10-seismic
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y

# We use dm-integrity in persistent-luks-setup's authenticated FDE setup:
# cryptsetup luksFormat --integrity hmac-sha256 ...
# We use dm-integrity in seismic-persistent-luks-setup's authenticated FDE
# setup: cryptsetup luksFormat --integrity hmac-sha256 ...
CONFIG_DM_INTEGRITY=y
8 changes: 4 additions & 4 deletions modules/seismic/mkosi.conf
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ ImageId=seismic
#
# Prereqs before this is sane to land:
# 1. Signed-PCR-policy LUKS enrollment (the BLOCKER header in
# persistent-luks-setup) must land first — else every release
# seismic-persistent-luks-setup) must land first — else every release
# rebases roothash → PCR 11 → bricks unlock on first update.
# 2. Audit and relocate /usr/ writes from runtime scripts.

Expand All @@ -37,13 +37,13 @@ ExtraTrees=modules/seismic/mkosi.extra
PostInstallationScripts=modules/seismic/mkosi.postinst
BuildScripts=modules/seismic/mkosi.build

# cryptsetup is used by persistent-luks-setup.service to format
# cryptsetup is used by seismic-persistent-luks-setup.service to format
# and open the LUKS volume (key supplied by the custodian via tmpfs).
# Flashbots builds cryptsetup from source with --with-crypto_backend=kernel to minimize deps;
# the Debian package works fine for us.
Packages=cryptsetup
# used by persistent-luks-setup.service to canonicalize the LUKS2
# header JSON before HMAC'ing it.
# used by seismic-persistent-luks-setup.service to canonicalize the
# LUKS2 header JSON before HMAC'ing it.
jq
# TPM2 libraries the attestation service links against
libtss2-esys-3.0.2-0t64
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Source-of-truth ownership/mode for the per-service /persistent subdirs.
# Applied by persistent-luks-setup.service's ExecStartPost after the LUKS
# volume is mounted at /persistent. Not in /etc/tmpfiles.d/ on purpose:
# Applied by seismic-persistent-luks-setup.service's ExecStartPost after the
# LUKS volume is mounted at /persistent. Not in /etc/tmpfiles.d/ on purpose:
# systemd-tmpfiles-setup.service runs at sysinit.target, well before
# persistent-luks-setup mounts /persistent, so the standard-path lookup
# would either error on the missing parent or — worse — create the dirs
# on the rootfs and have them shadowed once the LUKS volume mounts on top.
# seismic-persistent-luks-setup mounts /persistent, so the standard-path lookup
# would either error on the missing parent or — worse — create the dirs on the
# rootfs and have them shadowed once the LUKS volume mounts on top.
#
# Owners match the system users created in mkosi.postinst.

Expand All @@ -15,7 +15,7 @@ d /persistent/reth 0700 reth reth -

d /persistent/summit 0700 summit summit -
# summit's CLI doesn't auto-create its db/ path and expects it to exist.
# keys/ is written by summit-persist.service.
# keys/ is written by seismic-summit-persist.service.
# TODO: we should probably mimic reth and have summit create and manage its
# subdirs itself like reth does: `seismic-reth --datadir /persistent/reth`
# creates everything it needs underneath at runtime.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ Description=Seismic Attestation Service
# Starts at boot, before any configuration exists, so the founding harvest on
# :7879 can serve summit's public keys and the custodian's candidate
# tx_io_pk@0, and a quote over them, before the config POST. After
# summit-keygen, which writes the public-keys file the harvest serves;
# seismic-summit-keygen, which writes the public-keys file the harvest serves;
# network-online is for the IMDS round-trip in the quote path.
After=network-online.target summit-keygen.service
After=network-online.target seismic-summit-keygen.service
# The :7878 side reads its peers once tdx-init's done marker appears, so
# tdx-init is not an ordering dependency; Wants= only pulls it into the boot.
Wants=network-online.target tdx-init.service
Wants=network-online.target seismic-tdx-init.service
# Restarts with the custodian, so the root-key bootstrap runs again whenever
# the custodian loses root_key; see custodian.service for what a restart
# the custodian loses root_key; see seismic-custodian.service for what a restart
# reaches. After= orders that bootstrap after the restarted custodian's
# socket; the socket client retries regardless.
Requires=custodian.service
After=custodian.service
Requires=seismic-custodian.service
After=seismic-custodian.service

[Service]
Type=simple
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[Unit]
Description=Caddy, the node's public HTTPS proxy
# Starts only once persistent-luks-setup has finished, which implies both of
# its inputs exist: tdx-init's domain.env, and /persistent, where Caddy keeps
# its certificate and ACME account (see that unit). Nothing requires this
# unit: a node without a certificate has no public HTTPS, while reth and
# summit run regardless.
After=network-online.target persistent-luks-setup.service
# Starts only once seismic-persistent-luks-setup has finished, which implies
# both of its inputs exist: tdx-init's domain.env, and /persistent, where Caddy
# keeps its certificate and ACME account (see that unit). Nothing requires this
# unit: a node without a certificate has no public HTTPS, while reth and summit
# run regardless.
After=network-online.target seismic-persistent-luks-setup.service
Wants=network-online.target
Requires=persistent-luks-setup.service
Requires=seismic-persistent-luks-setup.service

[Service]
Type=notify
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ Description=Seismic Key Custodian
# stop custodian → custodian, attestation
# restart attestation → attestation (bootstrap: RootKeyAlreadyPresent)
#
# attestation.service's Requires= on this unit carries the first three rows:
# systemd (>= 254) passes an automatic Restart= along it as well as an explicit
# restart, but only under the default RestartMode=normal. BindsTo= in its
# place would stop the attestation service on a crash and never start it
# seismic-attestation.service's Requires= on this unit carries the first three
# rows: systemd (>= 254) passes an automatic Restart= along it as well as an
# explicit restart, but only under the default RestartMode=normal. BindsTo= in
# its place would stop the attestation service on a crash and never start it
# again, since the carried-over restart reaches only units still active.
#
# Nothing else may have Requires= or BindsTo= on either unit, or the restart
# reaches it too: re-running persistent-luks-setup on an open volume fails,
# or waits forever for the keyfile it already shredded, and takes reth and
# summit down with it.
# reaches it too: re-running seismic-persistent-luks-setup on an open volume
# fails, or waits forever for the keyfile it already shredded, and takes reth
# and summit down with it.

[Service]
Type=simple
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@ Description=Provision and unlock the persistent LUKS volume, mount /persistent
# once it holds root_key, which the attestation service fetches or confirms
# only after tdx-init's done marker, written after every other config file. So
# every unit ordered after this one finds /run/seismic/conf complete.
# After=tdx-init only keeps this unit queued, rather than polling, until the
# After=seismic-tdx-init only keeps this unit queued, rather than polling, until the
# config POST.
#
# Wants= rather than Requires= on all three: Requires= would restart this unit
# whenever one of them restarts (see custodian.service), and would cancel its
# queued start for good if tdx-init failed once, even when tdx-init's Restart=
# then recovers.
After=tdx-init.service
Wants=tdx-init.service custodian.service attestation.service
# whenever one of them restarts (see seismic-custodian.service), and would
# cancel its queued start for good if tdx-init failed once, even when
# tdx-init's Restart= then recovers.
After=seismic-tdx-init.service
Wants=seismic-tdx-init.service seismic-custodian.service seismic-attestation.service

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/usr/bin/persistent-luks-setup
ExecStart=/usr/bin/seismic-persistent-luks-setup
# Materialize per-service /persistent/<svc> ownership and mode now that /persistent is mounted.
ExecStartPost=/usr/bin/systemd-tmpfiles --create /etc/seismic/tmpfiles-persistent.conf

# Backstop for unforeseen failures only.
# A failure here — even one a restart later recovers — cancels the queued start
# jobs of every Requires= dependent (caddy/reth/summit-persist/summit),
# and systemd never re-enqueues them. If that stranding ever happens anyway,
# `systemctl start summit.target` pulls the whole chain back up.
# jobs of every Requires= dependent (seismic-caddy, seismic-reth,
# seismic-summit-persist, seismic-summit), and systemd never re-enqueues them. If that stranding ever happens anyway,
# `systemctl start seismic-summit.target` pulls the whole chain back up.
Restart=on-failure
RestartSec=5

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[Unit]
Description=Seismic Reth Node
After=network.target persistent-luks-setup.service
Requires=persistent-luks-setup.service
After=network.target seismic-persistent-luks-setup.service
Requires=seismic-persistent-luks-setup.service

[Service]
Type=simple
User=reth
# Own slice, outside system.slice's SocketBindDeny=tcp:8545, so reth is the
# only unit that can bind its RPC port. See system.slice.d/.
Slice=reth.slice
Slice=seismic-reth.slice
# Group= override is load-bearing here: the RuntimeDirectory= below creates
# /run/reth-engine/ with the unit's primary group. Without engine-api here,
# the dir would be reth:reth and summit couldn't open the IPC socket inside.
Expand All @@ -29,15 +29,15 @@ RuntimeDirectoryPreserve=restart
# peers, NAT extip) can't be hardcoded, so tdx-init emits them as flag
# fragments in reth-p2p.env, spliced in via $RETH_*_FLAG.

# Required (no `-`): persistent-luks-setup finishing implies tdx-init wrote
# reth-p2p.env (see that unit), so a missing file is a real boot failure, not
# something to tolerate.
# Required (no `-`): seismic-persistent-luks-setup finishing implies tdx-init
# wrote reth-p2p.env (see that unit), so a missing file is a real boot failure,
# not something to tolerate.
EnvironmentFile=/run/seismic/conf/reth-p2p.env

# --chain reth-genesis.json: tdx-init writes it each boot (/run is tmpfs);
# persistent-luks-setup finishing implies it exists.
# seismic-persistent-luks-setup finishing implies it exists.
# --datadir /persistent/reth: created by tmpfiles-persistent.conf via
# persistent-luks-setup's ExecStartPost.
# seismic-persistent-luks-setup's ExecStartPost.
# --http.api/--ws.api eth,net,web3 (not `all`): Caddy proxies /rpc+/ws wholesale,
# so this allowlist is what keeps admin/debug/txpool off the public surface. The
# seismic namespace and eth_ overrides register regardless;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ Description=Generate summit's consensus keys into tmpfs
# Runs at boot, before any configuration exists: the founding harvest quotes
# these keys' public halves, and the manifest pins them, before the config
# POST. It depends on nothing the POST produces.
PartOf=summit.target
PartOf=seismic-summit.target

[Service]
Type=oneshot
# Stays active after it exits, so it runs once per boot: summit-persist's
# Requires= then finds it satisfied instead of starting it again.
# Stays active after it exits, so it runs once per boot:
# seismic-summit-persist's Requires= then finds it satisfied instead of
# starting it again.
RemainAfterExit=yes
User=summit

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Copy summit's tmpfs keys into its keystore, or confirm the keystore
After=seismic-persistent-luks-setup.service seismic-summit-keygen.service
Requires=seismic-persistent-luks-setup.service seismic-summit-keygen.service
PartOf=seismic-summit.target

[Service]
Type=oneshot
RemainAfterExit=yes
User=summit

# Its own unit rather than seismic-summit.service's ExecStartPre=, so it runs
# once per boot rather than at every summit restart, and so only it writes the
# keystore.
ExecStart=/usr/bin/seismic-summit-persist

StandardOutput=journal
StandardError=journal
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[Unit]
Description=Summit Consensus Server
After=network.target persistent-luks-setup.service reth.service summit-persist.service
Requires=persistent-luks-setup.service reth.service summit-persist.service
PartOf=summit.target
After=network.target seismic-persistent-luks-setup.service seismic-reth.service seismic-summit-persist.service
Requires=seismic-persistent-luks-setup.service seismic-reth.service seismic-summit-persist.service
PartOf=seismic-summit.target

[Service]
Type=simple
Expand All @@ -17,17 +17,17 @@ UMask=0002
# and will start working once summit's EnvFilter construction is updated.
Environment=RUST_LOG=info

# summit-persist.service is the only writer of the keystore, and summit only
# reads it. It must never gain a keygen step of its own, even as a fallback:
# that would mint fresh keys the manifest never pinned, turning a loud startup
# failure into a launch-check mismatch. The public-keys file the attestation
# service serves is read-only here for the same reason.
# seismic-summit-persist.service is the only writer of the keystore, and summit
# only reads it. It must never gain a keygen step of its own, even as a
# fallback: that would mint fresh keys the manifest never pinned, turning a
# loud startup failure into a launch-check mismatch. The public-keys file the
# attestation service serves is read-only here for the same reason.
ReadOnlyPaths=/persistent/summit/keys /run/seismic/summit
InaccessiblePaths=/run/seismic/summit/keys

# Required (no `-`): persistent-luks-setup finishing implies tdx-init wrote
# summit.env (see that unit), so a missing file is a real boot failure, not
# something to tolerate.
# Required (no `-`): seismic-persistent-luks-setup finishing implies tdx-init
# wrote summit.env (see that unit), so a missing file is a real boot failure,
# not something to tolerate.
EnvironmentFile=/run/seismic/conf/summit.env

# --rpc-ip 127.0.0.1: Caddy fronts the public RPC at /summit
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[Unit]
Description=Summit and the setup units that carry its keys into the keystore
# A name for the group, not a dependency: nothing orders after this target.
# It pulls its members into the boot, and gives operators one handle to
# restart, stop or inspect them by (`systemctl restart seismic-summit.target`)
# without knowing which member the others hang off.
#
# Members, in start order:
#
# seismic-summit-keygen oneshot, at boot keys into
# │ /run/seismic/summit/keys, the
# │ public halves beside them
# ▼
# seismic-summit-persist oneshot, after tmpfs keys into
# │ /persistent mounts /persistent/summit/keys, or
# │ confirms the keystore
# ▼
# seismic-summit long-running only reads the keystore
#
# What a restart reaches. A restart propagates to the units that depend on the
# restarted one, never to its dependencies, and a start leaves an active unit
# alone: both oneshots stay active (RemainAfterExit=yes), so each runs once per
# boot unless restarted explicitly.
#
# restart seismic-summit.target → keygen, persist, summit (PartOf= on each)
# restart seismic-summit-keygen → keygen, persist, summit (Requires= chain)
# restart seismic-summit-persist → persist, summit (summit Requires= it)
# restart seismic-summit.service → summit
#
# Keygen is a no-op on a re-run (--no-overwrite), so no restart can replace
# the keys the manifest pins.
Wants=seismic-summit-keygen.service seismic-summit-persist.service seismic-summit.service

[Install]
WantedBy=minimal.target
Loading
Loading