Gunnar

nordisk/edda

crates/appliance-pid1/Cargo.toml

[package]
name = "appliance-pid1"
# 0.2.0 (2026-09-27): the NETWORK a PID 1 owes itself, moved AS IS out of
# gunnar-server's pid1.rs (gunnar gunnar-live 18a44e3) so holger's PID 1 takes
# the same one — netlink link/address/route (feature `net`), the DHCPv4 client
# with its renewal machine and the resolver file (`dhcp`), the boot-narration
# door (`net`), and the runtime half — SIGTERM/SIGINT/SIGQUIT, the reaper on
# SIGCHLD, the lease kept alive (`runtime`, tokio). Additive: with no feature
# the crate is what 0.1.0 was, libc only.
# 0.1.5 (2026-10-21, lane G6): rickard-81's follow-ups after Gunnar moved onto 0.1.4.
# net::{LateLease, bring_up_network_with}: a late DHCP lease (D12's retry) is said
# with the boot lease's line, renewed on the product's T1 seam and its resolver
# proven; fault::{narration_from, narration_now, panic_ending}: a panic's
# crash/fault.txt holds the product's narration; net::{netlink_message, rtattr,
# align4, netlink_socket} public; `resolver` and net::prove_resolver on `net`
# alone (no DHCP client needed). Additive.
# 0.1.4 (2026-10-21, lane G4): the rest of Gunnar's pid1.rs — `stop` (StopSource,
# stop_sources, on_appliance, after_clean_stop; runtime::stop_request), `install`
# (the korp install record), `console` (the gfx console mirror), net::{Ack,
# ack_verdict, request_or_there}, fault::{PanicFault, install_panic_fault}.
# 0.1.3 (2026-10-21, lane G4): ONE PID 1 for Gunnar and Holger. `fault` (a serve
# error says its code, tells the ear and waits for its ack, then a serving box
# restarts unless it faulted within 30 min, a boot fault powers off), `stop_record`
# (the last stop kept on the ESP), `power::{restart_now, power_off_cleanly,
# quiesce_and_record}`, `durable::{write_atomic, write_new}` (staged, fsync, rename,
# fsync of the directory), `dhcp::obtain_with(quiet)` (no WARN per attempt) and
# `net::prove_with` (the resolver proof asks again for about 30 s). Additive; libc
# only for the new default modules.
# 0.1.2 (2026-09-28): `power` — the ACPI power button heard on the generic-
# netlink `acpi_event` group (a cloud's soft stop is a button press, never a
# signal) and `power_off` (sync + reboot(POWER_OFF)); `runtime::shutdown_request`
# waits on the signals AND the button. libc only; additive.
version = "0.1.8"
edition = "2021"
description = "The PID-1 duties every distroless nordisk appliance payload owes the kernel, in ONE place: reap orphaned children forever, and idle on a signal instead of a shell. A process that is PID 1 inherits every orphan on the system and is the only process that can reap them; a PID 1 that only `pause()`s accumulates zombies for the life of the appliance and can never notice a child it started has died. `reap_once` is the testable unit (it reports WHAT happened rather than looping), `idle_and_reap` is the never-returning duty a payload's `main` ends with. libc only by default; the features `net` (netlink, no ip(8)), `dhcp` (DHCPv4 + renewal + resolv.conf) and `runtime` (tokio: signals, the SIGCHLD reaper, the lease kept alive) bring the network an OS-less PID 1 must bring up itself."
license = "MIT OR Apache-2.0"
repository = "https://git.gunnar.rs/nordisk/edda"
keywords = ["pid1", "init", "reap", "zombie", "appliance"]
categories = ["os::unix-apis"]
exclude = ["/.nornir/"]

[features]
default = []
# The netlink writer (link up, address, route, the address and MAC readers),
# the net-spec parser and the boot-narration door. rustix, not libc, for the
# sockets: on x86_64-linux its backend is linux_raw, no C under the binary.
net = ["dep:rustix", "dep:anyhow", "dep:tracing"]
# The DHCPv4 client (DISCOVER→ACK, option 121 routes, option 6 resolvers),
# its renewal machine and the resolv.conf writer. `socket2` for the ONE
# setsockopt rustix cannot spell: SO_BINDTODEVICE.
dhcp = ["net", "dep:socket2"]
# The tokio half: `shutdown_signal`, the `reaper` on SIGCHLD, and (with
# `dhcp`) `dhcp_renewal` driving the renewal machine on the tokio clock.
runtime = ["dep:tokio", "dep:tracing"]

[dependencies]
# The whole dependency set of the default build. An appliance PID-1 is
# `-static` and distroless; a crate it links must not drag anything in.
libc = "0.2"
rustix = { version = "1", default-features = false, features = ["std", "process", "net", "fs"], optional = true }
anyhow = { version = "1", optional = true }
tracing = { version = "0.1", optional = true }
socket2 = { version = "0.6", default-features = false, features = ["all"], optional = true }
tokio = { version = "1", default-features = false, features = ["signal", "time", "rt", "macros"], optional = true }

[dev-dependencies]
tempfile = "3"