fix(smolmachines): Linux compat for TSI networking and git-gate paths
Three fixes for Linux smolvm support: 1. Skip force_allowlist DB patch on Linux — patching allowed_cidrs into smolvm's state DB crashes TSI boot on Linux. Per-bottle CIDR isolation is not enforced on Linux until smolvm fixes the --allow-cidr + TSI interaction (known limitation). 2. Patch /etc/git-gate/ references in the staged entrypoint to /bot-bottle-data/git-gate/ so git-daemon finds its hooks and access-hook at the new consolidated mount path. 3. Drop explicit --net-backend tsi — the default on this smolvm build is already TSI; explicitly requesting it is incompatible with -p port mappings on Linux. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -406,15 +406,13 @@ def _stage_sidecar_data(plan: SmolmachinesBottlePlan) -> Path:
|
||||
for name in ("entrypoint.sh", "pre-receive", "access-hook"):
|
||||
(scripts_dir / name).chmod(0o755)
|
||||
|
||||
# Patch credential paths: the rendered entrypoint hardcodes
|
||||
# /git-gate/creds/; rewrite to the in-VM git-gate subdir.
|
||||
# Patch paths: the rendered entrypoint hardcodes /git-gate/creds/
|
||||
# and /etc/git-gate/ for hooks; rewrite both to the in-VM subdir.
|
||||
ep_path = scripts_dir / "entrypoint.sh"
|
||||
ep_path.write_text(
|
||||
ep_path.read_text().replace(
|
||||
"/git-gate/creds/",
|
||||
f"{_GIT_GATE_SCRIPTS_DIR_IN_VM}/creds/",
|
||||
)
|
||||
)
|
||||
text = ep_path.read_text()
|
||||
text = text.replace("/git-gate/creds/", f"{_GIT_GATE_SCRIPTS_DIR_IN_VM}/creds/")
|
||||
text = text.replace("/etc/git-gate/", f"{_GIT_GATE_SCRIPTS_DIR_IN_VM}/")
|
||||
ep_path.write_text(text)
|
||||
|
||||
creds_dir = scripts_dir / "creds"
|
||||
creds_dir.mkdir(exist_ok=True)
|
||||
|
||||
@@ -152,23 +152,31 @@ def force_allowlist(machine_name: str, allowed_cidrs: list[str]) -> None:
|
||||
"""Ensure the machine's persisted TSI allowlist equals
|
||||
`allowed_cidrs`, failing **closed** if that can't be confirmed.
|
||||
|
||||
Runs on both macOS and Linux. It exists because smolvm 0.8.0
|
||||
silently drops `--allow-cidr` when combined with `--from`, so
|
||||
the allowlist has to be written into smolvm's persistent state
|
||||
DB before `machine start`. Rather than assume the flag was
|
||||
dropped, we read the persisted row and only patch when it
|
||||
doesn't already match — so a newer smolvm that honors the flag
|
||||
is left untouched.
|
||||
macOS only. On Linux, smolvm's TSI defaults to full loopback
|
||||
access and patching `allowed_cidrs` into the state DB crashes
|
||||
TSI boot (the VM fails with "boot process exited (code 1)").
|
||||
Per-bottle CIDR isolation is therefore not enforced on Linux
|
||||
until smolvm fixes the `--allow-cidr` + TSI interaction. This
|
||||
is a known limitation — the agent VM can reach all of host
|
||||
loopback, not just its bottle's forwarder ports.
|
||||
|
||||
On macOS, smolvm 0.8.0 silently drops `--allow-cidr` when
|
||||
combined with `--from`, so the allowlist has to be written
|
||||
into smolvm's persistent state DB before `machine start`.
|
||||
Rather than assume the flag was dropped, we read the persisted
|
||||
row and only patch when it doesn't already match — so a newer
|
||||
smolvm that honors the flag is left untouched.
|
||||
|
||||
Must run AFTER `smolvm machine create` (the row has to exist)
|
||||
and BEFORE `smolvm machine start` (smolvm reads the row on
|
||||
start; in-flight VMs don't pick up changes).
|
||||
|
||||
Fail-closed: if the state DB is missing, the row is missing, or
|
||||
the allowlist still doesn't match after patching, we `die()`
|
||||
rather than boot a VM whose egress confinement we can't verify
|
||||
— an unconfirmed allowlist is a sandbox-escape risk (the agent
|
||||
VM could reach all of host loopback)."""
|
||||
Fail-closed (macOS): if the state DB is missing, the row is
|
||||
missing, or the allowlist still doesn't match after patching,
|
||||
we `die()` rather than boot a VM whose egress confinement we
|
||||
can't verify."""
|
||||
if not _is_macos():
|
||||
return
|
||||
want = list(allowed_cidrs)
|
||||
if not _SMOLVM_DB_PATH.is_file():
|
||||
die(
|
||||
|
||||
@@ -313,9 +313,9 @@ class TestForceAllowlist(unittest.TestCase):
|
||||
self.assertEqual(4, cfg["cpus"])
|
||||
self.assertTrue(cfg["network"])
|
||||
|
||||
def test_patches_on_linux_too(self):
|
||||
# force_allowlist no longer no-ops on Linux — the TSI
|
||||
# allowlist must be enforced there as well.
|
||||
def test_skips_patch_on_linux(self):
|
||||
# On Linux, patching allowed_cidrs into the smolvm state DB
|
||||
# crashes TSI boot. force_allowlist is a no-op on Linux.
|
||||
with patch.object(loopback_alias, "_is_macos", return_value=False), \
|
||||
patch.object(loopback_alias, "_SMOLVM_DB_PATH", self.db):
|
||||
loopback_alias.force_allowlist("demo-vm", ["127.0.0.16/32"])
|
||||
@@ -324,7 +324,7 @@ class TestForceAllowlist(unittest.TestCase):
|
||||
"SELECT data FROM vms WHERE name='demo-vm'",
|
||||
).fetchone()[0])
|
||||
con.close()
|
||||
self.assertEqual(["127.0.0.16/32"], cfg["allowed_cidrs"])
|
||||
self.assertIsNone(cfg["allowed_cidrs"])
|
||||
|
||||
def test_skips_write_when_already_matching(self):
|
||||
# A newer smolvm that honors --allow-cidr at create leaves the
|
||||
|
||||
Reference in New Issue
Block a user