Repository navigation
Add Hetzner bare-metal provisioning for the public demo - #15
Merged
Merged
Conversation
Move the demo off the expired Azure VM onto a Hetzner bare-metal (Server
Auction) host. Bare metal is required because Hetzner Cloud (every tier,
including ARM) exposes no nested virtualization, so QEMU would fall back to
TCG; the demo boots real x86 KVM guests on each validation.
Mirrors the existing azure-* scripts but runs over plain SSH (Hetzner has no
az run-command equivalent):
- scripts/hetzner-bootstrap-vm.sh: toolchain + qemu-kvm, hard-fails if
/dev/kvm is missing, builds bpfcompat + static validator + examples, creates
the bpfcompat-demo service user (in the kvm group), installs the serve unit.
- scripts/hetzner-configure-tls.sh: Caddy + Let's Encrypt; ufw opens only
22/80/443 (bare metal has no cloud firewall/NSG); backend stays on
127.0.0.1:8080.
- packaging/systemd/bpfcompat-serve.{service,env.example}: first systemd unit
for the demo web server (Azure ran serve by hand). Hardening is deliberately
looser than the agent unit since qemu needs /dev/kvm and the TCG JIT needs
W^X.
- docs/hetzner-runbook.md: end-to-end runbook.
- Makefile: hetzner-bootstrap-vm / hetzner-configure-tls targets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a credentials section so deploy secrets never land in the repo: real *.env files (BPFCOMPAT_API_WRITE_KEY etc.; .example templates stay tracked), SSH private keys (id_rsa/id_ed25519/*_rsa/*_ed25519), TLS material (*.pem/*.key/*.ppk), known_hosts, and local deploy scratch (/.hetzner/, /.secrets/). Verified the .example templates and existing *-secret* docs/scripts remain tracked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two corrections found during the live deploy: - bootstrap installed apt golang (1.22), but the project needs Go 1.25 (go.mod). Install the official toolchain pinned via GO_VERSION instead. - the serve unit's WorkingDirectory was the empty state dir, so relative data paths (matrices/, vm profiles) did not resolve. Point WorkingDirectory at the cloned repo and pass --matrix; run artifacts still go to the writable --workdir state dir. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Hetzner demo is served at bpfcompat.kernelguard.net; update the README live-demo link and the runbook references accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The serve unit runs as bpfcompat-demo with WorkingDirectory=/opt/bpfcompat-src (root-owned). It writes UI report copies to reports/ and API state to .bpfcompat-api/ relative to that dir; create both owned by the service user so validations can finalize. Found via a live end-to-end run where all 8 profiles passed but the final report write hit permission denied. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The Azure credit expired, so the public demo (
demo.kernelguard.net) needs a new home. This adds the tooling to host it on a Hetzner bare-metal (Server Auction) box.Why bare metal, not Hetzner Cloud: the demo boots real x86 QEMU/KVM guests on each validation. Hetzner Cloud — every tier, including dedicated-vCPU and ARM/CAX — exposes no nested virtualization (no
/dev/kvm), so QEMU would fall back to TCG (~10× slower). Only dedicated/auction bare metal gives native KVM.What
Mirrors the existing
azure-*scripts but runs over plain SSH (Hetzner has noaz run-commandequivalent):scripts/hetzner-bootstrap-vm.sh(make hetzner-bootstrap-vm) — installs toolchain +qemu-kvm, hard-fails if/dev/kvmis missing, buildsbpfcompat+ static validator + examples, creates thebpfcompat-demoservice user (in thekvmgroup), installs the serve unit.scripts/hetzner-configure-tls.sh(make hetzner-configure-tls) — Caddy + Let's Encrypt;ufwopens only 22/80/443 (bare metal has no cloud firewall/NSG); backend stays on127.0.0.1:8080.packaging/systemd/bpfcompat-serve.{service,env.example}— first systemd unit for the demo web server (Azure ranserveby hand). Hardening is deliberately looser than the agent unit since qemu needs/dev/kvmand the TCG JIT needs W^X.docs/hetzner-runbook.md— end-to-end runbook.Makefile—hetzner-bootstrap-vm/hetzner-configure-tlstargets.Security posture (unchanged from the demo today)
--addr 127.0.0.1:8080behind Caddy +ufw.BPFCOMPAT_API_ENABLE_RUNTIME_EXECUTE=false— no host eBPF loading.internal/api/sanitize.go)..bpfcompat/runs/**(per-run SSH keys) stays under/var/lib/bpfcompat-demo.Test plan
Scripts are
shellcheck-clean andbash -n-valid. Full validation is the live deploy once the auction box is ordered (manual, Robot panel) and its IP is known.🤖 Generated with Claude Code