Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e60c048
refactor: split platform-specific code in lib/resources and lib/devices
rgarcia Feb 2, 2026
fda09c5
refactor: split platform-specific code in lib/network and lib/vmm
rgarcia Feb 2, 2026
e827e89
refactor: split platform-specific code in lib/ingress and server startup
rgarcia Feb 2, 2026
ab8882e
feat: add VsockDialer abstraction for platform-specific vsock connect…
rgarcia Feb 2, 2026
fd399ff
feat: add vz hypervisor for macOS Virtualization.framework support
rgarcia Feb 2, 2026
c46ae7b
feat: guest system and OCI image updates for vz support
rgarcia Feb 2, 2026
2edd225
docs: add macOS build system and documentation
rgarcia Feb 2, 2026
e35bbcb
chore: add .cursor/ and api binary to gitignore
rgarcia Feb 2, 2026
7fa5ccf
feat(vz): implement vz-shim subprocess for VM persistence
rgarcia Feb 4, 2026
72d4f7e
feat(vz): add snapshot infrastructure and document vz.framework limit…
rgarcia Feb 4, 2026
87ad82d
fix(macos): add e2fsprogs PATH and don't cache failed image builds
rgarcia Feb 8, 2026
2e460b1
feat(dev): add registry push flag to gen-jwt and document builder setup
rgarcia Feb 8, 2026
3afbc1e
feat(builds): stream build logs in real-time via vsock
rgarcia Feb 8, 2026
cd892b0
fix(vz): address review feedback and fix CI
rgarcia Feb 8, 2026
1107a84
fix(vz): fix log streaming race and remove dead darwin network symbols
rgarcia Feb 8, 2026
852b488
fix(vz): remove dead duplicate path check in findShimBinary
rgarcia Feb 8, 2026
03239ae
feat(api): add vz as a valid hypervisor option in OpenAPI spec
rgarcia Feb 8, 2026
65c48cb
feat: add macOS install/uninstall scripts, CI, and builder auto-build
rgarcia Feb 8, 2026
1eefa7e
fix(ci): remove vz runner label, fix build manager test timeouts
rgarcia Feb 8, 2026
365149e
fix(ci): use separate concurrency groups per job to prevent self-dead…
rgarcia Feb 8, 2026
f1c0c9d
fix(ci): skip Linux-only tests on macOS, use go list for Darwin test …
rgarcia Feb 8, 2026
5fcfa1e
fix(ci): exclude packages with Linux-only test symbols from Darwin tests
rgarcia Feb 8, 2026
6c03616
fix(ci): add linux build tag to remaining vm_metrics test files
rgarcia Feb 8, 2026
0678c4d
fix(ci): add Docker Hub login to test-darwin to avoid rate limits
rgarcia Feb 8, 2026
056b9cf
fix(install): use sudo on macOS when INSTALL_DIR is not writable
rgarcia Feb 8, 2026
ec9d38f
fix(install): prevent set -e exit on missing CLI artifact lookup
rgarcia Feb 8, 2026
1848fdd
fix(e2e): dump service logs on health check failure for debugging
rgarcia Feb 8, 2026
0b71e93
fix(install): expand ~ to $HOME in macOS config for launchd
rgarcia Feb 8, 2026
adeefd8
fix(scripts): add sudo support to macOS uninstall for /usr/local/bin
rgarcia Feb 8, 2026
e071e3e
fix(ci): install caddy for e2e-install test on macOS
rgarcia Feb 8, 2026
222a5d0
fix(install): add Homebrew PATH to launchd plist environment
rgarcia Feb 8, 2026
8d9ff0e
fix(e2e): use /health endpoint for service readiness check
rgarcia Feb 8, 2026
67a3923
fix(test): allow pulling status in TestCreateImage_Idempotent
rgarcia Feb 8, 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 && 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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@ dist/**

# UTM VM - downloaded ISO files
scripts/utm/images/

# IDE and editor
.cursor/

# Build artifacts
api
Loading