Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
77f76b0
refactor: cross-platform foundation for macOS support
rgarcia Feb 10, 2026
e34cae0
feat: add macOS VM support via Apple Virtualization.framework
rgarcia Feb 10, 2026
3cb9760
fix: embed vz.entitlements and fix macOS runtime issues
rgarcia Feb 10, 2026
f5498ff
fix: remove stale disk platform files from rebase
rgarcia Feb 11, 2026
f60d8fa
fix: vsock proxy data loss, zombie reaping, and remove vz-shim from i…
rgarcia Feb 11, 2026
8785860
fix: e2e test config sourcing and missing CLI handling
rgarcia Feb 11, 2026
a20c6eb
fix: remove unused registry-push flag from gen-jwt
rgarcia Feb 11, 2026
916e4f3
fix: remove unnecessary .gitkeep for vz-shim embed dir
rgarcia Feb 11, 2026
6c3dc8d
feat: add VM lifecycle smoke test to e2e install test
rgarcia Feb 11, 2026
2da6eb4
fix: create vz-shim embed directory in Makefile before copying
rgarcia Feb 11, 2026
732dea9
Fix macOS CLI install missing $SUDO prefix
cursoragent Feb 12, 2026
1f345c4
fix: CLI install on macOS and make CLI a hard requirement in e2e
rgarcia Feb 12, 2026
9360854
fix: remove nonexistent 'hypeman images' from e2e test
rgarcia Feb 12, 2026
b795e9c
fix: retry hypeman run after async pull in e2e test
rgarcia Feb 12, 2026
86858a0
fix: clean up macOS development docs and Makefile comment
rgarcia Feb 12, 2026
c42aad6
fix: README treats Linux and macOS as equal platforms
rgarcia Feb 12, 2026
7d29895
Address PR review: fix shutdown semantics, reduce timeout, add vz int…
rgarcia Feb 13, 2026
5d4a5fc
fix(vz): fix guest-agent exec format error on instance restart
rgarcia Feb 13, 2026
f93aa64
Address hiroTamada review nits
rgarcia Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .air.darwin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
args_bin = []
bin = "./tmp/main"
# Build for macOS with vz support, then sign with entitlements
# Also builds and signs vz-shim (subprocess that hosts vz VMs)
cmd = "make build-embedded && go build -o ./tmp/vz-shim ./cmd/vz-shim && codesign --sign - --entitlements vz.entitlements --force ./tmp/vz-shim && mkdir -p lib/hypervisor/vz/vz-shim && cp ./tmp/vz-shim lib/hypervisor/vz/vz-shim/vz-shim && go build -tags containers_image_openpgp -o ./tmp/main ./cmd/api && codesign --sign - --entitlements vz.entitlements --force ./tmp/main"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata", "bin", "scripts", "data", "kernel"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
# No sudo needed on macOS - vz doesn't require root
full_bin = "./tmp/main"
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "yaml"]
include_file = []
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
kill_delay = '1s'
rerun = false
rerun_delay = 500
send_interrupt = true
stop_on_error = false

[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"

[log]
main_only = false
time = false

[misc]
clean_on_exit = false

[screen]
clear_on_rebuild = false
keep_scroll = true
122 changes: 122 additions & 0 deletions .env.darwin.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# =============================================================================
# macOS (Darwin) Configuration for Hypeman
# =============================================================================
# Copy this file to .env and customize for your environment.
#
# Key differences from Linux (.env.example):
# - DEFAULT_HYPERVISOR: Use "vz" (Virtualization.framework) instead of cloud-hypervisor/qemu
# - DATA_DIR: Uses macOS conventions (~/Library/Application Support)
# - Network settings: BRIDGE_NAME, SUBNET_CIDR, etc. are IGNORED (vz uses NAT)
# - Rate limiting: Not supported on macOS (no tc/HTB equivalent)
# - GPU passthrough: Not supported on macOS
# =============================================================================

# Required
JWT_SECRET=dev-secret-change-me

# Data directory - use macOS conventions
# Note: ~ expands to $HOME at runtime
DATA_DIR=~/Library/Application Support/hypeman

# Server configuration
PORT=8080

# Logging
LOG_LEVEL=debug

# =============================================================================
# Hypervisor Configuration (IMPORTANT FOR MACOS)
# =============================================================================
# On macOS, use "vz" (Virtualization.framework)
# - "cloud-hypervisor" and "qemu" are NOT supported on macOS
DEFAULT_HYPERVISOR=vz

# =============================================================================
# Network Configuration (DIFFERENT ON MACOS)
# =============================================================================
# On macOS with vz, network is handled automatically via NAT:
# - VMs get IP addresses from 192.168.64.0/24 via DHCP
# - No TAP devices, bridges, or iptables needed
# - The following settings are IGNORED on macOS:
# BRIDGE_NAME, SUBNET_CIDR, SUBNET_GATEWAY, UPLINK_INTERFACE

# DNS Server for VMs (used by guest for resolution)
DNS_SERVER=8.8.8.8

# =============================================================================
# Caddy / Ingress Configuration
# =============================================================================
CADDY_LISTEN_ADDRESS=0.0.0.0
CADDY_ADMIN_ADDRESS=127.0.0.1
CADDY_ADMIN_PORT=2019
# Note: 5353 is used by mDNSResponder (Bonjour) on macOS, using 5354 instead
INTERNAL_DNS_PORT=5354
CADDY_STOP_ON_SHUTDOWN=false

# =============================================================================
# Build System Configuration
# =============================================================================
# For builds on macOS with vz, the registry URL needs to be accessible from
# NAT VMs. Since vz uses 192.168.64.0/24 for NAT, the host is at 192.168.64.1.
#
# IMPORTANT: "host.docker.internal" does NOT work in vz VMs - that's a Docker
# Desktop-specific hostname. Use the NAT gateway IP instead.
#
# Registry URL (the host's hypeman API, accessible from VMs)
REGISTRY_URL=192.168.64.1:8080
# Use HTTP (not HTTPS) since hypeman's internal registry uses plaintext
REGISTRY_INSECURE=true

BUILDER_IMAGE=hypeman/builder:latest
MAX_CONCURRENT_SOURCE_BUILDS=2
BUILD_TIMEOUT=600

# =============================================================================
# Resource Limits (same as Linux)
# =============================================================================
# Per-instance limits
MAX_VCPUS_PER_INSTANCE=4
MAX_MEMORY_PER_INSTANCE=8GB

# Aggregate limits (0 or empty = unlimited)
# MAX_TOTAL_VOLUME_STORAGE=

# =============================================================================
# OpenTelemetry (optional, same as Linux)
# =============================================================================
# OTEL_ENABLED=false
# OTEL_ENDPOINT=127.0.0.1:4317
# OTEL_SERVICE_NAME=hypeman
# OTEL_INSECURE=true
# ENV=dev

# =============================================================================
# TLS / ACME Configuration (same as Linux)
# =============================================================================
# ACME_EMAIL=admin@example.com
# ACME_DNS_PROVIDER=cloudflare
# TLS_ALLOWED_DOMAINS=*.example.com
# CLOUDFLARE_API_TOKEN=

# =============================================================================
# macOS Limitations
# =============================================================================
# The following features are NOT AVAILABLE on macOS:
#
# 1. GPU Passthrough (VFIO, mdev)
# - GPU_PROFILE_CACHE_TTL is ignored
# - Device registration/binding will fail
#
# 2. Network Rate Limiting
# - UPLOAD_BURST_MULTIPLIER, DOWNLOAD_BURST_MULTIPLIER are ignored
# - No tc/HTB equivalent on macOS
#
# 3. CPU/Memory Hotplug
# - Resize operations not supported
#
# 4. Disk I/O Limiting
# - DISK_IO_LIMIT, OVERSUB_DISK_IO are ignored
#
# 5. Snapshots (requires macOS 14+ on Apple Silicon)
# - SaveMachineStateToPath/RestoreMachineStateFromURL require macOS 14+
# - Only supported on ARM64 (Apple Silicon) Macs
61 changes: 61 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,64 @@ jobs:
TLS_TEST_DOMAIN: "test.hypeman-development.com"
TLS_ALLOWED_DOMAINS: '*.hypeman-development.com'
run: make test

test-darwin:
runs-on: [self-hosted, macos, arm64]
concurrency:
group: macos-ci-test-${{ github.ref }}
cancel-in-progress: true
env:
DATA_DIR: /tmp/hypeman-ci-${{ github.run_id }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: false
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Install dependencies
run: |
brew list e2fsprogs &>/dev/null || brew install e2fsprogs
brew list erofs-utils &>/dev/null || brew install erofs-utils
go mod download
- name: Create run-scoped data directory
run: mkdir -p "$DATA_DIR"
- name: Generate OpenAPI code
run: make oapi-generate
- name: Build
run: make build
- name: Run tests
env:
DEFAULT_HYPERVISOR: vz
JWT_SECRET: ci-test-secret
run: make test
- name: Cleanup
if: always()
run: |
pkill -f "vz-shim.*$DATA_DIR" || true
rm -rf "$DATA_DIR"
make clean

e2e-install:
runs-on: [self-hosted, macos, arm64]
needs: test-darwin
concurrency:
group: macos-ci-e2e-${{ github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v6
with:
go-version: '1.25'
cache: false
- name: Install dependencies
run: brew list caddy &>/dev/null || brew install caddy
- name: Run E2E install test
run: bash scripts/e2e-install-test.sh
- name: Cleanup on failure
if: failure()
run: bash scripts/uninstall.sh || true
Loading