Issues and PRs are welcome. Each crate has a single clear responsibility and the codebase is structured so onboarding takes an afternoon, not a week.
git clone https://github.com/nechodom/hyperion
cd hyperion
cargo build --release --workspace
cargo test --workspaceThat's it. The dev path doesn't need root or a real Debian — see
docs/RUNBOOK.md for a
local-dev setup with mock filesystem layout.
crates/
├── hyperion-types/ # newtype IDs + DTOs (no I/O)
├── hyperion-validate/ # Domain + SystemUserName parsers
├── hyperion-rpc/ # trait + wire types + codec
├── hyperion-rpc-server/ # Unix-socket server
├── hyperion-rpc-client/ # Unix-socket client
├── hyperion-state/ # SQLite + migrations + audit chain
├── hyperion-adapters/ # system tool wrappers
├── hyperion-core/ # orchestration + secrets + RealAdapter
└── hyperion-auth/ # argon2id + Ed25519 sessions + CSRF
bin/
├── hyperion-agent/ # privileged daemon
├── hyperion-web/ # axum admin UI
└── hctl/ # CLI
The orchestrator lives in hyperion-core/src/service.rs — that's
where every public RPC method has its happy path + rollback. Big
file, but grep "pub async fn" gives you an index.
#![forbid(unsafe_code)]in every crate.- Typed args, never strings. Domains parse to
Domain, hosting IDs areHostingId(String), etc. — FK mix-ups become compile errors. - No shell interpolation. Every system call is
Command::new("/usr/bin/foo").arg(...)— neversh -c, never string-concatenate user input into a command line. - LIFO rollback for any mutating operation. If step 3 fails, steps 2 and 1 must un-do themselves.
- Audit log every state change. The chain is BLAKE3-hashed; missing rows produce verifiable gaps.
The canonical recipe — follow it for nginx tweaks, PHP-FPM knobs, new DB engines, etc.
- Adapter function in
hyperion-adapters— typed args, no shell interpolation. ReturnsResult<T, AdapterError>. - Method on
AdapterPortinhyperion-core— mockable for unit tests. - Orchestration in
HostingServicewith a rollback step pushed onto the LIFO stack if it mutates state. - RPC variant in
hyperion-rpc::codec+ handler inAgentApi+ dispatch inhyperion-rpc-server. - CLI subcommand in
hctl+ UI handler + template inhyperion-webif user-facing. - Tests at every layer. Pure-logic ones unconditional; the
rare integration test that wants
useraddorsystemctlgets#[ignore]and runs only on a real node.
- Per-hosting actions: read the hosting's
target_node(viafind_hosting_anywhere), pass it todispatcher::dispatch_to_node— never go straight to the local socket from a per-hosting handler. - Forms in the detail page get
target_nodeinjected as a hidden input by the JS shim at the bottom ofhostings_detail.html. The matchingFormstruct just needstarget_node: String. - Any RPC the UI calls must be implementable on workers too — no master-only assumptions inside agent code.
type(scope): short imperative summary
Optional body explaining WHY, not WHAT — the diff already shows
the what. Reference the issue or commit that triggered the work.
Mention any operator-facing behaviour change.
Co-Authored-By: …
Types: feat, fix, refactor, test, docs, chore.
Scopes are the crate or feature name: feat(jobs), fix(rpc),
docs(readme).
- Open an issue or Discussion first if the change is non-trivial — saves both of us rebuild time if the design needs tweaking.
- Branch from
main, single-purpose PRs. cargo fmt --all+cargo clippy --workspace --all-targetscargo test --workspacemust pass locally.
- Mention any operator-facing change in the PR description — "operators will see X" is the audit trail for release notes.
- Squash on merge; the title becomes the commit subject.
- New shell scripts. Anything that touches the system goes through an adapter.
- Vendoring third-party PHP. Hyperion provisions PHP; it doesn't ship it.
- "Plugins" that load arbitrary code. The trust model is "operator trusts root on the box" — anything that widens that needs a real threat-model discussion first.
- Feature flags for half-built work. Land it complete or not at all; we keep the codebase ready-to-ship.
Contributor Covenant 2.1.
Be civil, assume good faith, ping the maintainer at
hello@nechodom.dev if anything goes sideways.