- Rust 100%
Implement the deferred half of Phase B for runner source fetching: - HTTP/HTTPS via reqwest, gated behind a `network` feature on sysconfig-modules (default-on, off for offline builds). - OCI registry pulls via oci-client (matches vm-manager's choice). Single-layer artifacts work directly; multi-layer artifacts require `media-type=` to disambiguate. Layer digest is always verified against the manifest, and any user-supplied `digest=` is checked too. - Archive extraction for tar, tar.gz, tar.zst, zip, and gz. `gz` is single-file (rejects `path`); the others require `path`. Path traversal (`..`, absolute paths) and in-archive `..` entries are rejected. Symlinks/hardlinks at the selected path are refused. - Both fetch backends use a local current-thread tokio runtime so the rest of the crate stays sync, matching the EC2 provider stub. Drops the `SourceSchemeUnimplemented` and `ArchiveExtractionUnimplemented` validation errors (and their tests), since validate no longer needs to gate against unimplemented backends. `NetworkSourceTooEarly` and `UnverifiedRemoteSource` stay — those are real semantic checks. Test coverage: HTTP fetch + sha256, redirect, 404, HTTP-served tar.gz archive extraction, and unit tests for each archive format including path-traversal rejection. Wiremock stands in for the OCI registry; live OCI is left to integration testing. Verified on illumos in the OmniOS r151058 VM (sysconfig-modules --no-default-features and sysconfig-providers/sysconfig-schema crates; oci-client transitively pulls deps that OOM the 2GB VM under release). |
||
|---|---|---|
| crates | ||
| docs | ||
| examples | ||
| service-configs/smf | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
sysconfig
A typed, declarative system configuration tool for illumos cloud images. A simpler, faster, type-safe replacement for cloud-init.
Why sysconfig?
cloud-init is a 60k+ line Python project that boots ~10 SMF services and takes 30+ seconds on a small VM. It has been the de facto standard for cloud provisioning, but on illumos it's a poor fit:
- Slow: serial Python startup + many SMF services
- Untyped: YAML with implicit schema, errors only at runtime
- Linux-centric: many features assume systemd, Debian, NetworkManager
- Three daemons:
cloud-init-local,cloud-init,cloud-config,cloud-final
sysconfig is a single Rust binary, one transient SMF service, KDL config:
| cloud-init | sysconfig | |
|---|---|---|
| Daemons | 4 SMF services | 1 transient |
| Config format | YAML | typed KDL |
| Lines of code | ~60,000 (Python) | ~3,500 (Rust) |
| Boot overhead | 30+ seconds | <1 second |
| Self-assembly | merge order is implicit | /etc/sysconfig.d/*.kdl lex order |
Quick start
The fastest way to try sysconfig is the prebuilt OmniOS image:
# Pull and run with vmctl (https://code.aopc.cloud/CloudNebulaProject/vm-manager)
vmctl create --name myvm \
--image-url oci://code.aopc.cloud/cloudnebulaproject/omnios-sysconfig:latest \
--vcpus 2 --memory 2048 \
--start
The VM boots, sysconfig detects the NoCloud seed ISO that vmctl created,
applies hostname/SSH keys/users from your cloud-init user-data, and
exits — no daemons left running.
Default root password (until you provide one): test123.
How it works
boot
↓
SMF starts svc:/system/sysconfig:default (transient)
↓
sysconfig provision --source auto
├── detect cloud env (NoCloud, EC2, GCP, …)
├── fetch metadata (mount CIDATA, HTTP, mdata-get, …)
├── write /etc/sysconfig.d/10-cloud.kdl
└── invoke `sysconfig apply`
├── load all /etc/sysconfig.d/*.kdl in lex order
├── merge into a typed SysConfig
├── validate
└── apply via modules: hostname → DNS → interfaces → users
↓
exit 0 (service goes online, then idle)
The merged config is the source of truth — everything else is just a way
to populate it. Drop your own 50-local.kdl next to the cloud fragment
and your overrides win.
Configuration
sysconfig {
hostname "web01"
timezone "Europe/Zurich"
nameserver "1.1.1.1"
nameserver "1.0.0.1"
search-domain "example.com"
interface "net0" {
address name="v4" kind="dhcp4"
}
interface "net1" selector="mac:52:54:00:11:22:33" {
address name="v4" kind="static" "10.0.0.5/24"
address name="v6" kind="addrconf"
}
user "admin" {
shell "/usr/bin/bash"
groups "wheel" "staff"
sudo "unrestricted"
ssh-key "ssh-ed25519 AAAA…"
}
}
See docs/configuration.md for the full schema.
Self-assembly via fragments
/etc/sysconfig.d/ is read in lexicographic order. Each fragment is a
complete sysconfig { … } block. Later fragments override earlier ones
for scalars (hostname, timezone) and append-with-dedup for lists
(nameservers, users, interfaces).
Recommended layout:
| File | Source | Purpose |
|---|---|---|
00-defaults.kdl |
image | shipped baseline (DHCP, UTC, sane DNS) |
10-cloud.kdl |
sysconfig | written by sysconfig provision |
50-local.kdl |
admin | local overrides |
90-override.kdl |
admin | last-word overrides |
This is the "drop-in" pattern, the same as systemd and cron.d.
Commands
sysconfig apply [--dry-run] [--config-dir /etc/sysconfig.d]
sysconfig provision [--source auto|nocloud|ec2|…] [--dry-run]
sysconfig diff [--config-dir /etc/sysconfig.d]
sysconfig validate [PATH...]
apply— merge fragments and configure the systemprovision— detect cloud, fetch metadata, write fragment, then applydiff— show whatapplywould do (alias forapply --dry-run)validate— check syntax and semantics of fragment files
Status
v0.1.0 — early access. Works end-to-end on OmniOS bloody. Tested with
NoCloud (vmctl/cloud-localds). EC2/GCP/Azure providers are scaffolded
but not yet wired into release builds.
| Module | illumos | Linux | FreeBSD |
|---|---|---|---|
| hostname | ✓ | ✓ | (untested) |
DNS (/etc/resolv.conf) |
✓ | ✓ | (untested) |
interfaces (ipadm) |
✓ | gated | – |
users (useradd/usermod) |
✓ | ✓ | (untested) |
| SSH keys | ✓ | ✓ | (untested) |
sudo (/etc/sudoers.d/) |
✓ | ✓ | (untested) |
| NoCloud (CIDATA mount) | ✓ | ✓ | (untested) |
cloud-init user-data parser |
✓ | ✓ | ✓ |
Building
cargo build --release
Cross-compiling to illumos from Linux requires the illumos C toolchain
(for ring/reqwest linkage). The simplest path is to build natively
inside an illumos VM. See docs/building.md.
Repo layout
crates/
sysconfig-schema/ typed config + KDL parsing + fragment merging
sysconfig-modules/ platform actions (hostname, DNS, ifaces, users)
sysconfig-providers/ cloud metadata fetchers (NoCloud today)
sysconfig/ CLI binary
service-configs/smf/ SMF manifest (single transient service)
examples/ example KDL fragments
docs/ user and developer documentation
tests/ integration tests
Documentation
- Architecture — design and rationale
- Configuration reference — KDL schema
- Provisioning — cloud data sources
- Building — native + cross-compile
- Image building — using sysconfig in OS images
- Migration from cloud-init — what maps to what
- Roadmap
License
MPL-2.0. See LICENSE.