Skip to content

Mount host /private via VirtioFS and rewrite Docker bind paths#249

Open
PeronGH wants to merge 4 commits intomasterfrom
feat/private-virtiofs
Open

Mount host /private via VirtioFS and rewrite Docker bind paths#249
PeronGH wants to merge 4 commits intomasterfrom
feat/private-virtiofs

Conversation

@PeronGH
Copy link
Copy Markdown
Contributor

@PeronGH PeronGH commented Apr 15, 2026

Summary

  • Add a VirtioFS share for host /private (macOS-only) so the guest can access /private/tmp, /private/var/folders, etc. Guest /tmp and /var remain isolated tmpfs — no host pollution.
  • Resolve top-level symlinks in Docker bind-mount source paths (HostConfig.Binds, HostConfig.Mounts) before forwarding to guest dockerd. Uses readlink on the first path component rather than a hardcoded prefix list, so it handles any macOS system symlink and is a no-op on Linux.

Fixes docker run -v /tmp/foo:/app and -v /var/folders/...:/app which previously silently mounted empty directories.

Test plan

  • cargo clippy --all-targets and cargo test pass
  • Boot VM — mount | grep virtiofs in guest shows private on /private type virtiofs
  • Guest /tmp is still tmpfs (mount | grep /tmp shows tmpfs)
  • docker run --rm -v /tmp/test-arcbox:/mnt alpine ls /mnt sees host files
  • docker run --rm -v /private/tmp/test-arcbox:/mnt alpine ls /mnt same
  • docker run --rm -v /Users/...:/mnt alpine ls /mnt still works (no regression)

…aths

On macOS, /tmp → /private/tmp and /var → /private/var are symlinks.
Docker bind mounts to these paths failed because the guest had no
/private mount and its /tmp and /var are isolated tmpfs.

Add a VirtioFS share for host /private (macOS-only, gated by is_dir
check) so the guest can access /private/tmp, /private/var/folders, etc.
Guest /tmp and /var remain isolated tmpfs — no host pollution.

In the Docker API proxy, resolve top-level symlinks in bind-mount
source paths (HostConfig.Binds and HostConfig.Mounts) before
forwarding to guest dockerd. Uses readlink on the first path component
rather than a hardcoded prefix list, so it automatically handles any
macOS system symlink and is a no-op on Linux.
Copilot AI review requested due to automatic review settings April 15, 2026 11:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds macOS-specific support for Docker bind-mounts that go through top-level system symlinks (e.g. /tmp/private/tmp) by (1) exposing host /private into the guest via VirtioFS and (2) rewriting Docker container-create bind mount sources to use the resolved /private/... path before proxying to guest dockerd.

Changes:

  • Add /private VirtioFS share (tag + mountpoint) and mount it in the guest (both PID1 init path and standard agent startup path).
  • Introduce a Docker-proxy-side path resolver that follows the top-level symlink for bind-mount sources in HostConfig.Binds and HostConfig.Mounts.
  • Replace the generic create-container proxy handler with a custom handler that rewrites the request body before forwarding.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
guest/arcbox-agent/src/mount.rs Mounts the new private VirtioFS share at /private when available.
guest/arcbox-agent/src/init.rs Mounts /private early during PID1 init so it exists before tmpfs mounts.
common/arcbox-constants/src/virtiofs.rs Adds TAG_PRIVATE / MOUNT_PRIVATE constants.
app/arcbox-docker/src/lib.rs Exposes the new host_path module.
app/arcbox-docker/src/host_path.rs Implements top-level symlink resolution + JSON request body rewriting for binds/mounts.
app/arcbox-docker/src/handlers/container.rs Rewrites container-create request body before proxying to guest dockerd.
app/arcbox-core/src/machine.rs Adds host /private to VM shared directories when present.

Comment thread app/arcbox-docker/src/handlers/container.rs
Comment thread app/arcbox-docker/src/host_path.rs
Comment thread app/arcbox-core/src/machine.rs
Comment thread app/arcbox-core/src/machine.rs
- Gate symlink resolution to target_os = "macos" so Linux top-level
  symlinks (/bin → /usr/bin, etc.) are never rewritten.
- Remove Content-Length header after body rewrite so the proxy does
  not forward a stale value when the rewritten JSON differs in size.
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 15, 2026

Greptile Summary

This PR fixes docker run -v /tmp/foo:/app and -v /var/folders/...:/app on macOS by (1) adding a VirtioFS share that exposes the host's /private directory to the guest at /private, and (2) intercepting Docker container-create requests to rewrite symlinked top-level paths (/tmp/…/private/tmp/…, /var/…/private/var/…) before forwarding to guest dockerd.

Key changes:

  • arcbox-constants: New TAG_PRIVATE / MOUNT_PRIVATE constants for the /private VirtioFS share.
  • machine.rs: Both new() (load persisted VMs) and create() (new VMs) now conditionally add the /private host share, guarded by is_dir() — safe no-op on Linux.
  • host_path.rs (new): resolve() uses read_link on the first path component to dynamically follow macOS system symlinks; rewrite_create_body() rewrites both HostConfig.Binds entries and HostConfig.Mounts structured objects; non-macOS builds get a no-op stub; well-covered by tests.
  • container.rs: The create_container handler now reads the full request body, calls rewrite_create_body, strips Content-Length (since the body may have grown), and re-proxies — the rest of the container API is untouched.
  • init.rs / mount.rs: Guest agent mounts /private VirtioFS early in PID-1 init and in mount_standard_shares(), both idempotent via is_mounted() checks; previous hard-coded string literals replaced with constants (prior review concern resolved).

The approach is dynamic (reads the actual symlink on-disk) rather than a hardcoded prefix list, so it naturally handles /etc/private/etc and any future macOS system symlinks without code changes.

Confidence Score: 5/5

Safe to merge — all prior review concerns addressed, implementation is clean and well-tested, remaining findings are non-blocking P2 style suggestions.

Both previously flagged issues (hardcoded string literals, pub module visibility) are resolved. The new host_path module has comprehensive tests covering macOS symlink resolution, the non-macOS no-op path, invalid JSON, empty bodies, and both Binds/Mounts formats. The two remaining comments are cosmetic: a misleading ordering comment in init.rs and a defensive to_str() suggestion in resolve(). Neither affects correctness.

No files require special attention; host_path.rs is the most novel file but is well-covered by tests.

Important Files Changed

Filename Overview
app/arcbox-docker/src/host_path.rs New module: dynamic top-level symlink resolution for Docker bind-mount host paths; handles Binds strings and structured Mounts objects; comprehensive tests for macOS and Linux; uses to_string_lossy() which could silently corrupt non-UTF-8 paths (P2 suggestion to switch to to_str()).
app/arcbox-docker/src/handlers/container.rs Replaces proxy_handler! macro for create_container with a custom handler that reads the body, rewrites bind-mount paths via host_path::rewrite_create_body, strips Content-Length, and re-proxies; approach is correct.
app/arcbox-core/src/machine.rs Adds /private VirtioFS share (guarded by is_dir()) in both new() and create() paths; follows existing pattern for the /Users share; uses constants from arcbox-constants.
guest/arcbox-agent/src/init.rs Mounts /private VirtioFS share early in PID-1 init, before tmpfs mounts; uses constants (prior concern resolved); ordering comment is misleading — no technical dependency on tmpfs mount ordering.
guest/arcbox-agent/src/mount.rs Imports updated to use constants; mount_standard_shares() now mounts /private with is_mounted() idempotency guard; consistent with /Users share handling.
common/arcbox-constants/src/virtiofs.rs Adds TAG_PRIVATE = "private" and MOUNT_PRIVATE = "/private" constants; clear doc comments.
app/arcbox-docker/src/lib.rs Adds pub(crate) mod host_path; — narrowed from pub per prior review feedback.

Sequence Diagram

sequenceDiagram
    participant CLI as Docker CLI (host)
    participant Proxy as arcbox-docker proxy
    participant HostPath as host_path::rewrite_create_body
    participant GuestD as guest dockerd
    participant VirtioFS as VirtioFS /private

    CLI->>Proxy: POST /containers/create
    Proxy->>HostPath: rewrite_create_body(body)
    HostPath->>HostPath: resolve("/tmp")
    Note over HostPath: read_link("/tmp") → "private/tmp"
    HostPath-->>Proxy: Binds rewritten to /private/tmp/foo
    Note over Proxy: Strip Content-Length header
    Proxy->>GuestD: POST /containers/create (rewritten)
    GuestD->>VirtioFS: bind mount /private/tmp/foo
    Note over VirtioFS: Backed by host /private/tmp/foo
    VirtioFS-->>GuestD: mount OK
    GuestD-->>Proxy: 201 Created
    Proxy-->>CLI: 201 Created
Loading

Reviews (3): Last reviewed commit: "docs(mount): update mount_standard_share..." | Re-trigger Greptile

Comment thread guest/arcbox-agent/src/init.rs Outdated
Comment thread app/arcbox-docker/src/lib.rs Outdated
Replace hardcoded "private"/"/private" and "users"/"/Users" strings in
guest init with TAG_PRIVATE/MOUNT_PRIVATE and TAG_USERS/MOUNT_USERS
constants to prevent silent drift from host-side config.

Narrow host_path module visibility to pub(crate) — it's an internal
implementation detail of the Docker proxy.
Copilot AI review requested due to automatic review settings April 15, 2026 11:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread guest/arcbox-agent/src/mount.rs
@PeronGH PeronGH requested a review from AprilNEA April 15, 2026 11:50
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.

2 participants