Skip to content

Prepare repo for wider publication - #20

Merged
semistrict merged 9 commits into
mainfrom
claude/competent-lalande-013a08
Jul 6, 2026
Merged

Prepare repo for wider publication#20
semistrict merged 9 commits into
mainfrom
claude/competent-lalande-013a08

Conversation

@semistrict

Copy link
Copy Markdown
Owner

Pre-publicity pass over the repo ahead of sharing it more widely.

Licensing & metadata

  • Add Apache-2.0 LICENSE and NOTICE (upstream libkrun attribution); license/repository metadata in all Cargo manifests
  • GitHub repo description/topics updated to match the current libkrun-based implementation

CI fixes

  • tests.yml failed at 0s on every run since it was added (99/99 failures): ${{ runner.temp }} is not a valid context in job-level env. Moved to a $GITHUB_ENV step; also switched cargo test to bun run test (sets libclang env + codesign runner) and added podman/llvm to the deps install
  • release-binary.yml now triggers on v* tags, creates the GitHub Release, and uploads lnx-macos-arm64.tar.gz + sha256; optional Developer ID sign+notarize path activates when MACOS_SIGN_* secrets are configured (ad-hoc fallback otherwise)

Ingress CA hardening

  • Generated CA now carries critical nameConstraints (permitted DNS:.lnx/DNS:lnx, all IPv4/IPv6 excluded), basicConstraints CA:TRUE,pathlen:0, and keyUsage keyCertSign,cRLSign — trusting it cannot enable interception of any real domain
  • ingress disable now removes the trusted CA from the System keychain; new lnx ingress uninstall additionally deletes on-disk CA/cert state
  • trust_ca de-dupes stale trusted roots so repeated enables cannot accumulate old CAs
  • run_hidden bool soup refactored into a HiddenAction enum

Docs

  • README rewritten value-prop-first with measured timings (M5 Pro: ~0.9s exec via 4 GiB memory-snapshot restore, ~40ms on a live VM)
  • New docs/: architecture (moved from README), security (exactly what ingress installs and how to remove it), FAQ (positioning vs OrbStack/Lima/Apple container), troubleshooting, testing (absorbed TODO.txt)
  • CONTRIBUTING.md; Formula/lnx.rb so the repo doubles as a Homebrew tap; site copy refreshed
  • third_party/libkrun described as an in-tree vendored copy with snapshot patches; external fork references and copy.bara.sky removed

Cleanup

  • Removed the old Go implementation (old/, ~26k lines), its dead submodules and .gitmodules, TODO.txt, and the tracked results/ placeholder (now gitignored)

Testing

  • 137 host unit tests pass, including a new test asserting the CA's name constraints via openssl x509 -text
  • bun run test:ingress passes with new steps: CA files survive disable, uninstall removes CA/cert state
  • bun run test:system passes end-to-end (after refreshing a stale local image cache that predated images-v0.6.0)
  • actionlint clean on all workflows

- Add Apache-2.0 LICENSE, NOTICE, and license metadata in Cargo manifests
- Fix tests.yml: runner context is unavailable in job-level env, which
  failed every run at 0s since the workflow was added; use bun run test
  and install podman/llvm
- Name-constrain the ingress CA (critical nameConstraints permitting only
  .lnx DNS names, excluding all IPs, pathlen:0) and de-dupe stale trusted
  roots on enable; add lnx ingress uninstall to remove the trusted CA and
  ingress state, with unit and integration coverage
- Attach release binaries to GitHub Releases on v* tags, with an optional
  Developer ID sign+notarize path when MACOS_SIGN_* secrets are set
- Remove the old Go implementation, its dead submodules, and TODO.txt
  (content moved to docs/testing.md)
- Rewrite README value-prop-first with measured restore/exec timings and
  split details into docs/ (architecture, security, faq, troubleshooting,
  testing); add CONTRIBUTING.md and a Homebrew formula; refresh site copy
- ingress disable now removes the trusted lnx CA from the System keychain;
  uninstall additionally deletes the on-disk CA/certificate state
- Describe third_party/libkrun as an in-tree vendored copy with snapshot
  patches instead of pointing at an external fork; remove copy.bara.sky
- Delete leftover empty old/ directories
GitHub-hosted macOS runners do not support Apple nested virtualization, so
lnx tests can never boot VMs there. Depot's macos-26 runners are M4 hosts
with nested virtualization available, matching the existing Depot CI setup
used for kernel and rootfs builds. Also installs Go, which build.rs needs
for the embedded gvproxy bridge.
GitHub-hosted macOS runners do not support Apple nested virtualization, so
lnx tests can never boot VMs there. Depot CI (.depot/workflows) is
Linux-only, so keep the workflow on GitHub Actions but run it on Depot's
depot-macos-26 runners (M4, macOS 26, nested virtualization available).
Also installs Go, which build.rs needs for the embedded gvproxy bridge.
The system suite boots VMs, which requires Hypervisor.framework on
bare-metal macOS. Hosted macOS CI is always a VM and Apple only supports
nested virtualization for Linux guests, so no hosted provider can run it
(Depot CI is x86_64 Linux only; Depot managed runners do not support
personal accounts). Unit tests run on GitHub-hosted macos-26; the system
job targets a self-hosted Mac and is dispatch-only until one is
registered.
…work

test_vm_memory_init is the only unit test that creates a real HVF VM.
Hosted macOS CI runners are themselves VMs without HVF, so gate the test
on kern.hv_support instead of failing there.
The synthesized snapshot metadata still said dax:false, so the server
rejected the push with share_mismatch since host shares became
always-DAX. The import fixture got the same fix earlier; this one was
missed because the test workflow never ran.
The macOS virtiofs server faked lseek: SEEK_DATA always returned the
requested offset (never ENXIO at EOF) and SEEK_HOLE returned size+offset
via SEEK_END. macOS supports both seeks natively — the whence values are
just numbered opposite to Linux — so translate them instead. The fake
semantics made guest cp --sparse drop trailing holes, truncating copies
of pmem-aligned images. Add a sparse-geometry regression step to the
system suite.

The Linux snapshot fixture also kept the inner VM base on virtiofs,
where nested KVM cannot map DAX pages (vcpu EFAULT), and its shrunk
outer rootfs had no room for staging. Stage the inner base on
guest-local disk like the nested-kvm suite does and grow the outer
rootfs sparsely to 16 GiB.

Verified: system, snapshot-roundtrip, and nested-kvm suites pass;
snapshot-roundtrip previously failed fixture creation on every run.
Forks all restore the running browser stack and answer on noVNC; the
count is tunable with LNX_BROWSER_FORK_COUNT. Measured on an M5 Pro:
10 forks with verified endpoints in 1.16s.
@semistrict
semistrict merged commit e00b6ab into main Jul 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant