Skip to content

refactor: runtime pre-built images and remove node22-demo#35

Closed
angelorc wants to merge 23 commits intomainfrom
runtime-improvements
Closed

refactor: runtime pre-built images and remove node22-demo#35
angelorc wants to merge 23 commits intomainfrom
runtime-improvements

Conversation

@angelorc
Copy link
Copy Markdown
Owner

@angelorc angelorc commented Mar 4, 2026

Summary

  • Remove node22-demo runtime and all welcome-page generation code
  • Add pre-built runtime images (node22, node24, python3.13) built during vmsan install via Docker
  • --from-image now keeps the user image intact without injecting the agent
  • Fix cache key bug in resolveImageRootfs (minimal vs full builds)
  • Use proper error types instead of bare Error()
  • Clean up docs terminal examples (remove $ prefix)

Test plan

  • vmsan install builds 3 runtime images in ~/.vmsan/rootfs/
  • vmsan create --runtime node22 --connect works with agent
  • vmsan create --from-image node:22 creates VM without agent (with warning)
  • vmsan create --from-image node:22 --connect shows clear error
  • bun run build passes

Summary by CodeRabbit

Release Notes

  • New Features

    • Cloudflare Zero Trust tunnel integration for VM access with automatic DNS configuration
    • Node24 runtime environment support
    • Docker-based runtime image building pipeline with dynamic Dockerfile generation
    • --skip-dnat option to bypass port forwarding configuration
    • Tunnel hostname display in VM summary and list command
  • Improvements

    • Enhanced uninstall process with comprehensive cleanup of networks and resources
    • Better error handling and debug logging throughout
    • Improved validation for mutually exclusive command options
    • Removed welcome page feature
  • Deprecations

    • Node22-demo runtime replaced with Node24

angelorc and others added 23 commits March 4, 2026 09:40
- cloudflare-cleanup: only reload cloudflared if already running during cleanup
- cloudflare plugin: use full hostnames list for cleanup on partial setup failure
- cloudflare service: don't rethrow from finally in start() to avoid masking errors
- install.sh: kill only vmsan-managed cloudflared via PID file instead of killall
- install.sh: remove invalid JWT format validation for Cloudflare API tokens
When Cloudflare is configured, the cloudflare plugin sets skipDnat=true
via the beforeCreate hook. This skips DNAT iptables rules and port
conflict checks, allowing multiple VMs to use the same port since each
gets its own tunnel hostname. DNAT remains active when Cloudflare is
not configured.
Delete tunnel via API during uninstall and handle 409 conflict
in createTunnel by cleaning up stale tunnels before retrying.
…nfig updates

Use config_src: cloudflare instead of local. cloudflared runs with --token
and receives config updates via edge-push when pushConfig() is called.
No more restart/reload on VM create or stop.
Reorder uninstall: stop VMs first (while vmsan CLI is still available),
kill orphan VM processes, clean TAP/veth interfaces, delete vmsan-*
network namespaces, then remove iptables rules.
- Extract sleepSync/sleepAsync to shared utils, remove duplicate SharedArrayBuffer
- Fix removeDns inverted retry loop that polled when records didn't exist
- Add bulk addRoutes to avoid N+1 file I/O per hostname
- Deduplicate CNAME record payload in addDns
- Use cleanupCloudflareResources in vm:beforeStop instead of reimplementing
- Parallelize DNS cleanup with Promise.all
- Remove unused error factories (tokenInvalid, tokenInactive, noZoneForDomain)
- Remove unsafe Record<string,unknown> cast in plugin hook
- Merge duplicate uninstall loops in install.sh
- Validate PID ownership before killing cloudflared during uninstall
- Mask API token input with read -rs
- Guard against empty ports in setupTunnelRoutes and vm:afterStart
- Resolve account by domain zone first to avoid multi-account mismatch
Remove the node22-demo runtime, welcome page generation, and all
related dead code. Runtime images are now pre-built during install.
- Add findRuntimeRootfs() for node22, node24, python3.13 runtimes
- Build runtime ext4 images during vmsan install via Docker
- Disable agent injection for --from-image (keeps image intact)
- Fix cache key bug in resolveImageRootfs (minimal vs full)
- Use proper error types instead of bare Error()
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
vmsan Ignored Ignored Mar 4, 2026 5:40pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 4, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9d4f67a-4619-4997-b505-227d3e0cbbd3

📥 Commits

Reviewing files that changed from the base of the PR and between a32bd94 and 82cfb1d.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • docs/content/index.md
  • install.sh
  • package.json
  • src/commands/create.ts
  • src/commands/create/args.ts
  • src/commands/create/cleanup.ts
  • src/commands/create/environment.ts
  • src/commands/create/image-rootfs.ts
  • src/commands/create/input.ts
  • src/commands/create/state.ts
  • src/commands/create/summary.ts
  • src/commands/create/types.ts
  • src/commands/create/validation.ts
  • src/commands/list.ts
  • src/context.ts
  • src/errors/cloudflare.ts
  • src/errors/codes.ts
  • src/errors/index.ts
  • src/errors/vm.ts
  • src/index.ts
  • src/lib/agent-service.ts
  • src/lib/cloudflare-cleanup.ts
  • src/lib/file-lock.ts
  • src/lib/jailer.ts
  • src/lib/network.ts
  • src/lib/utils.ts
  • src/lib/vm-state.ts
  • src/lib/welcome-page.ts
  • src/plugins/cloudflare.ts
  • src/services/cloudflare.ts
  • src/services/vm.ts

📝 Walkthrough

Walkthrough

This PR introduces Cloudflare Tunnel integration for VM networking with tunnel lifecycle management, adds support for pre-built runtime images (node22, node24, python3.13), extends the installation script with interactive cloudflared setup, and removes the welcome page feature. It also implements skipDnat for selective DNAT rule bypassing and enhances error handling throughout.

Changes

Cohort / File(s) Summary
Cloudflare Integration
src/services/cloudflare.ts, src/plugins/cloudflare.ts, src/errors/cloudflare.ts
Introduces CloudflareService for Cloudflare Tunnel lifecycle (create, push config, manage DNS/routes), CloudflareError with factory functions for Cloudflare-specific error scenarios, and cloudflarePlugin that hooks into VM lifecycle (beforeCreate, afterCreate, afterStart, beforeStop) to configure tunnels and manage resources.
Cloudflare Setup & Exports
src/errors/codes.ts, src/errors/index.ts, src/index.ts, src/lib/cloudflare-cleanup.ts
Adds CloudflareErrorCode type union, exports CloudflareError and related factory functions, and introduces cleanupCloudflareResources utility for removing Cloudflare routes and DNS entries during VM cleanup.
Installation & Dependencies
install.sh, package.json
Extends install.sh with VMSAN_REF and CLOUDFLARED_VERSION variables, go_arch() helper for architecture mapping, interactive Cloudflare configuration flow, cloudflared binary installation, docker-based runtime image build pipeline (node22, node24, python3.13), and comprehensive uninstall cleanup including Cloudflare tunnel deletion and network interface cleanup. Adds cloudflare (v5.2.0) and p-retry (v7.1.1) dependencies.
Runtime & Image Management
src/commands/create/environment.ts, src/commands/create/image-rootfs.ts
Introduces findRuntimeRootfs() to resolve pre-built runtime rootfs files, adds minimal mode support to image-rootfs building with cache suffix handling, and extends rootfs resolution to support both custom images and pre-built runtimes.
DNAT & Network Configuration
src/lib/network.ts, src/lib/vm-state.ts, src/services/vm.ts, src/commands/create/state.ts, src/commands/create/validation.ts
Adds skipDnat field to NetworkConfig and VmNetwork, conditionally skips DNAT rule application when enabled, validates published ports only when DNAT is active, and threads skipDnat through VM creation and network initialization.
VM Create Command Updates
src/commands/create.ts, src/commands/create/args.ts, src/commands/create/types.ts, src/commands/create/summary.ts, src/commands/create/input.ts
Replaces node22-demo with node24 in VALID_RUNTIMES, adds mutually-exclusive check for --from-image and --connect flags, includes tunnelHostnames in summary output (rendering as https:// URLs), updates runtime and from-image descriptions, and removes port validation call from parseCreateInput.
VM List & State
src/commands/list.ts, src/commands/create/cleanup.ts
Extends list command to display TUNNEL column computed from tunnelHostnames or fallback to tunnelHostname, and hardens cleanup error handling with detailed debug logging via consola and toError utilities.
Error Handling & Logging
src/lib/jailer.ts, src/errors/vm.ts
Removes welcome page injection logic and related PrepareChrootConfig field, updates vmNoAgentTokenError metadata to reflect custom image mode limitations (no agent support for connect/exec/cp).
Utilities & Sync Primitives
src/lib/utils.ts, src/lib/file-lock.ts
Adds sleepSync() and sleepAsync() utilities for synchronous and asynchronous delays, replaces Atomics.wait usage in FileLock with sleepSync for retry logic.
Plugin System & Context
src/context.ts
Initializes a builtin cloudflarePlugin alongside user-supplied plugins, ensuring all plugins have setup() called in a unified loop.
Documentation & Comments
docs/content/index.md, src/lib/agent-service.ts
Removes shell prompts from code blocks in documentation examples and removes non-functional header comment from agent-service.
Welcome Page Removal
src/lib/welcome-page.ts
Deletes entire module containing generateWelcomeHtml, generateWelcomeServer, and generateWelcomeService functions for node22-demo runtime.

Sequence Diagram

sequenceDiagram
    participant VM as VM Lifecycle
    participant Plugin as Cloudflare Plugin
    participant Service as CloudflareService
    participant CF as Cloudflare API
    participant DNS as DNS Provider

    Note over VM,DNS: VM Creation Flow with Cloudflare Tunnel

    VM->>Plugin: vm:beforeCreate
    activate Plugin
    Plugin->>Service: isConfigured()
    Plugin->>Service: isInstalled()
    alt Cloudflare configured
        Plugin->>Service: Validate cloudflared present
        Plugin->>VM: Set skipDnat=true
    end
    deactivate Plugin

    VM->>VM: Create VM with ports
    
    VM->>Plugin: vm:afterCreate
    activate Plugin
    Plugin->>Service: createTunnel()
    activate Service
    Service->>CF: Create Cloudflare tunnel
    CF-->>Service: tunnelId, tunnelToken
    Service->>Service: Store tunnel config
    deactivate Service
    
    Plugin->>Service: setupTunnelRoutes()
    activate Service
    Service->>Service: addRoutes() for VM ports
    Service->>Service: pushConfigWithRetry()
    activate Service
    Service->>CF: Update tunnel ingress config
    CF-->>Service: OK
    deactivate Service
    Service->>DNS: addDns() for hostnames
    DNS-->>Service: CNAME created
    Service->>VM: Update state.tunnelHostnames
    deactivate Service
    deactivate Plugin

    VM->>Plugin: vm:afterStart
    activate Plugin
    alt Cloudflare configured
        Plugin->>Service: Restore tunnelHostnames from state
    end
    deactivate Plugin

    VM->>Plugin: vm:beforeStop
    activate Plugin
    alt Cloudflare configured
        Plugin->>Service: cleanupCloudflareResources()
        activate Service
        Service->>Service: removeRoute(vmId)
        Service->>CF: pushConfigWithRetry()
        CF-->>Service: OK
        Service->>DNS: removeDns() for each hostname
        DNS-->>Service: CNAME removed
        deactivate Service
    end
    deactivate Plugin

    Note over VM,DNS: VM Cleanup Complete
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly Related PRs

Poem

🐰 Through tunnels of Cloudflare, our VMs now dash,
Hostnames resolve with a tunneling splash!
Node24 replaces the demo of yore,
While DNAT skips dance on the networking floor.
A rabbits' delight—these tunnels so bright!

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch runtime-improvements

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@angelorc angelorc closed this Mar 4, 2026
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