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
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ All Alloy sysext images are cryptographically signed. The instance verifies sign
before installing updates via systemd-sysupdate.

- **Signing Key:** `Alloy Sysext Signing Key <alloy-sysext@separationofconcerns.dev>`
- **Public Key Location:** `/etc/sysupdate.alloy.d/alloy.gpg`
- **Public Key Location:** `/etc/systemd/import-pubring.gpg`
- **Sysupdate Config:** `/etc/sysupdate.alloy.d/alloy.conf` with `Verify=true`
- **Signature Files:** `.asc` files stored alongside images in R2

Expand Down Expand Up @@ -438,7 +438,7 @@ cat /etc/sysupdate.alloy.d/alloy.conf
systemd-sysupdate -C alloy list

# Check the public key
cat /etc/sysupdate.alloy.d/alloy.gpg
cat /etc/systemd/import-pubring.gpg
```

**Note:** Changing the Butane configuration (including the Alloy version) will cause
Expand Down
89 changes: 87 additions & 2 deletions opentofu/modules/vultr/instance/userdata/ghost.bu
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ storage:
Path=/opt/extensions/alloy/
CurrentSymlink=/etc/extensions/alloy.raw

# GPG public key for verifying Alloy sysext signatures
# GPG public key for verifying Alloy sysext signatures (SHA256SUMS.gpg)
# This key is merged into /etc/systemd/import-pubring.gpg by the
# sysupdate-import-pubring.service at boot time. The merge preserves
# any existing keys from the base image (e.g., Fedora/Ubuntu legacy keys).
# Key: Alloy Sysext Signing Key <alloy-sysext@separationofconcerns.dev>
- path: /etc/sysupdate.alloy.d/alloy.gpg
- path: /etc/systemd/alloy-sysext.gpg.pub
mode: 0644
contents:
inline: |
Expand Down Expand Up @@ -96,6 +99,69 @@ storage:
=8FOV
-----END PGP PUBLIC KEY BLOCK-----

# Script to merge system GPG keyring with Alloy signing key
# Checks for .pgp (newer systemd) first, then falls back to .gpg (legacy)
- path: /usr/local/bin/sysupdate-merge-keyring.sh
mode: 0755
contents:
inline: |
#!/bin/bash
# Merge system import-pubring with Alloy sysext signing key
# systemd-sysupdate checks /etc/systemd/ first, then /usr/lib/systemd/
# We copy the system keyring to /etc and append our key to preserve both
set -euo pipefail

SYS_KEYRING=""
ETC_KEYRING="/etc/systemd/import-pubring.gpg"
ALLOY_KEY="/etc/systemd/alloy-sysext.gpg.pub"

# Check for system keyring (.pgp preferred, .gpg fallback)
if [[ -f /usr/lib/systemd/import-pubring.pgp ]]; then
SYS_KEYRING="/usr/lib/systemd/import-pubring.pgp"
ETC_KEYRING="/etc/systemd/import-pubring.pgp"
elif [[ -f /usr/lib/systemd/import-pubring.gpg ]]; then
SYS_KEYRING="/usr/lib/systemd/import-pubring.gpg"
ETC_KEYRING="/etc/systemd/import-pubring.gpg"
fi

# Create /etc/systemd directory if needed
mkdir -p /etc/systemd

if [[ -n "$SYS_KEYRING" ]]; then
echo "Copying system keyring from $SYS_KEYRING to $ETC_KEYRING"
cp "$SYS_KEYRING" "$ETC_KEYRING"
else
echo "No system keyring found, creating new keyring at $ETC_KEYRING"
touch "$ETC_KEYRING"
fi

# Import Alloy signing key into the keyring
if [[ -f "$ALLOY_KEY" ]]; then
echo "Importing Alloy signing key into $ETC_KEYRING"
# Use gpg to import key into keyring file
GNUPGHOME=$(mktemp -d)
export GNUPGHOME
trap 'rm -rf "$GNUPGHOME"' EXIT

# Import existing keyring if it has content
if [[ -s "$ETC_KEYRING" ]]; then
gpg --batch --quiet --import "$ETC_KEYRING" 2>/dev/null || true
fi

# Import Alloy key
gpg --batch --quiet --import "$ALLOY_KEY"

# Export merged keyring
gpg --batch --quiet --export > "$ETC_KEYRING"

echo "Keyring merge complete"
else
echo "Warning: Alloy signing key not found at $ALLOY_KEY"
fi

chmod 0644 "$ETC_KEYRING"
echo "Keyring ready at $ETC_KEYRING"

- path: /etc/systemd/system/ghost-compose.service
mode: 0644
contents:
Expand Down Expand Up @@ -400,6 +466,25 @@ systemd:
- name: locksmithd.service
enabled: true

# Merge system GPG keyring with Alloy signing key before sysupdate runs
# This ensures systemd-sysupdate can verify both system packages and Alloy sysext
# The merge preserves existing keys from the base image while adding our key
- name: sysupdate-import-pubring.service
enabled: true
contents: |
[Unit]
Description=Merge GPG keyring for systemd-sysupdate
Before=systemd-sysupdate.service
ConditionPathExists=/etc/systemd/alloy-sysext.gpg.pub

[Service]
Type=oneshot
ExecStart=/usr/local/bin/sysupdate-merge-keyring.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

- name: systemd-sysupdate.timer
enabled: true

Expand Down
Loading