Files
SilverMetal/linux
SysAdmin b20e568b19
Some checks failed
Build SilverMetal Linux ISO (reproducibility-gated) / build-and-verify (push) Failing after 1m14s
fix(linux/build): run derivative-maker as unprivileged builder user (M1.1)
Run #4251 advanced past checkout and into derivative-maker, then died
immediately:

    ERROR: This must NOT be run as root (sudo)!
    ERROR: Exiting ./derivative-maker with non-zero exit code 1.
           Errors Detected: 0. Execution Time: 00:00:00.

Kicksecure's derivative-maker explicitly refuses to run as root — it
expects a regular user with passwordless sudo and uses sudo internally
for the privileged operations (debootstrap, mksquashfs, chroot mounts).
Our minimal debian-slim builder image had a `builder` user (uid 1000)
but no sudo, no sudoers entry, and the container ran as root.

Aligns with the upstream Kicksecure container pattern at
linux/build/derivative-maker/docker/derivative-maker-docker-setup
(uses USER=user with `${USER} ALL=(ALL) NOPASSWD:ALL`).

Changes:
- Dockerfile.builder: install `sudo` (and `fakeroot` while we're here —
  upstream sanity-tests pulls this in via apt at build time, but having
  it baked avoids a snapshot.debian.org round-trip every run); add
  passwordless sudoers entry for builder; correct the misleading
  comment that claimed root was needed.
- New scripts/build-inner.sh: the inner derivative-maker invocation
  pulled out of build.sh's heredoc. Once we needed to drop privileges
  via runuser, the nested-heredoc / nested-quoting situation became
  unmaintainable; a regular script with normal quoting is far cleaner.
- build.sh: inner heredoc now just chowns the workspace to builder and
  runuser's into build-inner.sh. ${REPO_ROOT} and ${BUILD_DIR} continue
  to be forwarded into the container via -e.
- build.sh: BUILDER_IMAGE digest re-pinned to sha256:f8f0db37…1bedc
  (rebuilt and pushed natively on 10.0.0.51 — never on the WSL/aarch64
  dev box, see reference_silvermetal_runner.md memory).

Verified: bash -n on both scripts; image builds and pushes cleanly.
Pushing this commit triggers a fresh CI run that will exercise it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:09:42 +01:00
..

SilverMetal OS — Linux

Status: Phase 1 (planning) → moving to milestone 1.1 (reproducible Kicksecure fork build)

🔒 SilverMetal OS product line — we ship the operating system.

The reference SilverMetal flavour. Tier A — full kernel-level hardening, verified boot we control, Debian/Kicksecure-based.

Scope (v1)

See ../docs/roadmap.md Phase 1.

Hardening must-haves

  • Kicksecure base (Debian-derived, hardened upstream)
  • linux-hardened kernel + KSPP sysctl/build flags
  • Secure Boot with our shim/MOK
  • TPM2 PCR-bound LUKS2 unlock (Argon2id), full-disk encryption mandatory
  • AppArmor strict profiles for browsers, mail, viewers, networked daemons
  • GrapheneOS hardened_malloc as system allocator
  • bubblewrap + Flatpak primary; firejail for legacy .deb
  • nftables default-deny inbound, encrypted DNS, SilverVPN always-on default
  • Zero upstream telemetry — verified by integration test
  • SilverBrowser default (ungoogled-chromium-rebranded v1)
  • SilverVPN integrated from existing SilverLABS/SilverVPN (Linux client + tunnel service)
  • SilverSync v1 (Nextcloud-backed, client-side encryption)
  • A/B updates with rollback, signed by our keys
  • Optional amnesic session mode

Out of scope (v1)

  • Atomic / immutable root (v1.1 — ostree experiment)
  • dm-verity on / (v1.1)
  • ARM64 / Apple Silicon (v2)
  • Tor-by-default variant (sibling product later)

Directory layout

linux/
├── build/             # live-build pipeline, reproducible-build config
├── kernel/            # config fragments, linux-hardened pinning
├── overlay/           # /etc + /usr/share/silvermetal + skel hardening overlay
├── packages/
│   ├── include.list   # what's installed
│   └── exclude.list   # what's purged (snap, telemetry, etc.)
├── apparmor/          # custom strict profiles
├── nftables/          # default ruleset
├── installer/         # Calamares branding + hardened defaults
├── update-server/     # signing + repo hosting (infra-as-code)
└── tests/
    ├── lynis-baseline/
    ├── kspp-check/
    └── telemetry-leak/

Verification gates (must pass before public alpha)

  • Two clean builds from same commit → identical SHA256
  • kconfig-hardened-check passes
  • Lynis hardening score ≥ 90
  • 30-min idle telemetry capture: zero packets to MS/Google/Apple/Mozilla/Canonical/Debian/analytics
  • TPM tamper test: LUKS correctly falls back to passphrase
  • AppArmor: every networked binary confined or documented
  • Independent privacy-engineering review

Upstream we depend on

  • Kicksecure — fork base
  • linux-hardened — kernel patchset
  • GrapheneOS hardened_malloc — allocator
  • KSPP — kernel config authority
  • secureblue — reference for v1.1 immutable design
  • SilverLABS/SilverVPN — VPN client + tunnel service (existing, integrated)