Cloud-init metadata service built on the OpenCHAMI Fabrica framework. It serves nocloud-net metadata endpoints for HPC nodes, renders Jinja2/Pongo2 templates for group configs, and integrates with a State Management Database (SMD) or a mock client for local development. It is a drop-in replacement for the legacy cloud-init/admin service with stronger validation and generated APIs.
Key capabilities
- Auto-generated REST resources for groups, cluster defaults, and instance info
- Server-side template validation (Jinja2-compatible, YAML-safe)
- SMD-backed identity and group membership with mock mode when
SMD_URLis unset - File-based storage with persistence under
./data/ - Optional userspace WireGuard controller for compatible VPN-style bootstrapping
- Ensure Go 1.22+ is installed.
- From the repo root, start the server (mock SMD is automatic when
SMD_URLis unset):go run ./cmd/server serve --port 8888
- Hit the cloud-init endpoints using the bundled mock nodes:
curl -H "X-Forwarded-For: 10.0.0.100" http://localhost:8888/meta-data curl -H "X-Forwarded-For: 10.0.0.100" http://localhost:8888/vendor-data curl -H "X-Forwarded-For: 10.0.0.100" http://localhost:8888/compute.yaml
- Data lives under
./data/. Remove it to reset state:rm -rf ./data/*
Mock nodes available by default:
10.0.0.100(x1000c0s0b0n0): groups compute, green10.0.0.101(x1000c0s0b0n1): groups compute, blue10.0.0.102(x1000c0s1b0n0): group storage
Use the generated CLI to create or update cluster defaults, groups, and instance overrides.
# Create cluster defaults
go run ./cmd/client --server http://localhost:8888 clusterdefaults create --spec '{"name":"demo","base_url":"http://localhost:8888","cloud_provider":"OpenCHAMI","region":"dev","nid_length":4,"public_keys":["ssh-ed25519 AAA... user@example"]}'
# Create a group with a simple template
cat > /tmp/compute.json <<'EOF'
{
"name": "compute",
"description": "Compute nodes",
"template": "#cloud-config\nhostname: {{ hostname }}\nusers:\n - name: hpc\n ssh-authorized-keys: {{ metadata.public_keys }}\n",
"metadata": {
"public_keys": ["ssh-ed25519 AAA... user@example"]
}
}
EOF
go run ./cmd/client --server http://localhost:8888 group create --spec "$(cat /tmp/compute.json)"
# Optional: instance-specific overrides
go run ./cmd/client --server http://localhost:8888 instanceinfo create --spec '{"name":"x1000c0s0b0n0","hostname":"custom-host"}'The service implements nocloud-net compatible endpoints. See CLOUDINIT.md for full details and response examples.
/meta-data— YAML metadata for the requesting node (IP- or X-Forwarded-For-based identity)/vendor-data— include file list of group YAMLs/user-data— empty#cloud-configto preserve user overrides/{group}.yaml— rendered group template (requires group membership)
Set SMD_URL to point at your SMD service. Identity, group membership, and overrides will be sourced from SMD instead of the mock client.
SMD_URL=https://smd.example.com go run ./cmd/server serve --port 8888Enable with --wireguard_server to expose /wg-init and /phone-home/{id} for userspace WireGuard bootstrapping.
go run ./cmd/server serve --port 8888 --wireguard_server# Install dependencies
go mod tidy
# Regenerate Fabrica code
fabrica generate
# Run the server
go run ./cmd/server serve --port 8888
# Run tests (skips integration tests that need a legacy server)
make test- Same nocloud-net endpoints as the legacy service (
/meta-data,/user-data,/vendor-data,/{group}.yaml) - Server-side template validation (Jinja2/Pongo2 + YAML) prevents invalid configs at create time
- Mock SMD replaces legacy impersonation routes; use
X-Forwarded-Forto simulate callers - Resources created via generated client (
clusterdefaults,group,instanceinfo) instead of legacy/cloud-init/admin/*routes