Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b294f30
config add local rig example
Deadbytes101 Jul 5, 2026
898b606
docs define local rig config
Deadbytes101 Jul 5, 2026
3df29db
config define rig profile and flight sheet schemas
Deadbytes101 Jul 5, 2026
ef5fe47
state expose verified boot device attestation
Deadbytes101 Jul 5, 2026
5613382
firstboot integrate profile confirmation flow
Deadbytes101 Jul 5, 2026
cc056e5
test lock config import security contracts
Deadbytes101 Jul 5, 2026
64e1327
docs describe local profile and flight sheets
Deadbytes101 Jul 5, 2026
24c62ba
fix lock alpha five review blockers
Deadbytes101 Jul 5, 2026
e3ff137
fix complete alpha five compatibility flow
Deadbytes101 Jul 5, 2026
7fe474e
fix support complete Hive miner config
Deadbytes101 Jul 5, 2026
31641fc
test match complete Hive miner config shape
Deadbytes101 Jul 5, 2026
c2156ea
test lock complete Hive miner config compatibility
Deadbytes101 Jul 5, 2026
345577a
config route Hive import through strict compatibility adapter
Deadbytes101 Jul 5, 2026
67c6471
fix use canonical config types in compatibility adapter
Deadbytes101 Jul 5, 2026
e51222c
style apply rustfmt to Hive compatibility adapter
Deadbytes101 Jul 5, 2026
c772bcc
style apply rustfmt to Hive compatibility tests
Deadbytes101 Jul 5, 2026
0288897
build qualify Rust container registry
Deadbytes101 Jul 5, 2026
285d159
verify extract systemd policy units
Deadbytes101 Jul 5, 2026
f6986c6
release tty1 after firstboot
Deadbytes101 Jul 5, 2026
b135dfa
test firstboot tty1 handoff
Deadbytes101 Jul 5, 2026
9eceba2
state add Debian lsblk compatibility
Deadbytes101 Jul 5, 2026
f605958
state use isolated lsblk compatibility
Deadbytes101 Jul 5, 2026
013cd91
test lsblk compatibility wiring
Deadbytes101 Jul 5, 2026
b12c452
format lsblk compatibility test
Deadbytes101 Jul 5, 2026
8714039
state use absolute lsblk compatibility wrapper
Deadbytes101 Jul 5, 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
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ members = [
"crates/rigos-contract",
"crates/rigos-pool",
"crates/rigos-state",
"crates/rigos-config",
]
resolver = "2"

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Local-first CPU appliance delivered as a bootable USB image.

Current preview is `RIGOS 0.0.4-alpha.4`.
Current development preview is `RIGOS 0.0.4-alpha.5`.

The persistent appliance uses a raw MBR disk image for Legacy BIOS and removable-media UEFI boot.

Expand All @@ -22,9 +22,10 @@ The recovery ISO is stateless and does not grow the state partition.
0.0.4-alpha.2 MBR image reached GRUB ROOT_A systemd and password setup
0.0.4-alpha.3 fixed console order but kept the first boot screen hidden
0.0.4-alpha.4 keeps the first boot screen on tty and captures answers separately
0.0.4-alpha.5 adds local rig profiles and portable XMRig Flight Sheets
```

Alpha four still requires a new image build, checksum, QEMU boot matrix and physical first-boot completion.
Alpha five is isolated on its development branch. Alpha four physical state validation remains separate.

## Verification

Expand Down
2 changes: 1 addition & 1 deletion build/usb/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM rust:1.85.1-bookworm
FROM docker.io/library/rust:1.85.1-bookworm

RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
Expand Down
2 changes: 1 addition & 1 deletion build/usb/bootloaders/grub-pc/live-theme/theme.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
title-color: "#ffffff"
title-font: "Unifont Regular 16"
title-text: "RIGOS Recovery 0.0.4-alpha.4 - Stateless Diagnostics"
title-text: "RIGOS Recovery 0.0.4-alpha.5 - Stateless Diagnostics"
message-font: "Unifont Regular 16"
terminal-font: "Unifont Regular 16"

Expand Down
4 changes: 2 additions & 2 deletions build/usb/bootloaders/syslinux_common/live.cfg.in
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
label rigos-@FLAVOUR@
menu label ^RIGOS Recovery 0.0.4-alpha.4
menu label ^RIGOS Recovery 0.0.4-alpha.5
menu default
linux @LINUX@
initrd @INITRD@
append @APPEND_LIVE@

label rigos-@FLAVOUR@-failsafe
menu label RIGOS Recovery 0.0.4-alpha.4 -- ^safe mode
menu label RIGOS Recovery 0.0.4-alpha.5 -- ^safe mode
linux @LINUX@
initrd @INITRD@
append @APPEND_LIVE_FAILSAFE@
4 changes: 2 additions & 2 deletions build/usb/hooks/010-rigos.chroot
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ passwd --lock rigosadmin
install -d -o rigos -g rigos -m 0750 /var/lib/rigos /run/rigos
install -d -m 0755 /usr/lib/rigos

chmod 0755 /usr/local/sbin/rigos-firstboot /usr/lib/rigos/rigos-state-init /usr/lib/rigos/xmrig
systemctl enable NetworkManager.service rigos-state.service rigos-firstboot.service tmp.mount
chmod 0755 /usr/local/sbin/rigos-firstboot /usr/lib/rigos/rigos-state-init /usr/lib/rigos/rigos-config /usr/lib/rigos/xmrig
systemctl enable NetworkManager.service rigos-state.service rigos-profile-apply.service rigos-firstboot.service rigos-miner.service tmp.mount
systemctl disable apt-daily.timer apt-daily-upgrade.timer logrotate.timer fstrim.timer 2>/dev/null || true
systemctl disable systemd-journald-audit.socket 2>/dev/null || true

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
[Unit]
Description=RIGOS first-boot configuration
After=network-online.target rigos-state.service
After=network-online.target rigos-state.service rigos-profile-apply.service
Wants=network-online.target
Requires=rigos-state.service
Conflicts=getty@tty1.service
Before=getty@tty1.service
ConditionPathExists=!/var/lib/rigos/policy.json

Expand All @@ -17,7 +16,6 @@ TTYPath=/dev/tty1
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[Unit]
Description=RIGOS managed XMRig
After=network-online.target rigos-state.service
After=network-online.target rigos-state.service rigos-profile-apply.service
Wants=network-online.target
Requires=rigos-state.service
ConditionPathExists=/var/lib/rigos/xmrig.json
Expand All @@ -9,6 +9,7 @@ ConditionPathExists=/var/lib/rigos/xmrig.json
Type=simple
User=rigos
Group=rigos
ExecCondition=/usr/lib/rigos/rigos-config gate
ExecStart=/usr/lib/rigos/xmrig --config=/var/lib/rigos/xmrig.json
Restart=on-failure
RestartSec=5s
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Unit]
Description=Apply RIGOS persistent machine profile
After=rigos-state.service
Requires=rigos-state.service
Before=rigos-firstboot.service rigos-miner.service

[Service]
Type=oneshot
ExecStartPre=/usr/lib/rigos/rigos-config recover
ExecStart=/usr/lib/rigos/rigos-config timezone
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Before=local-fs.target rigos-firstboot.service rigos-miner.service

[Service]
Type=oneshot
RuntimeDirectory=rigos
RuntimeDirectoryMode=0755
ExecStart=/usr/lib/rigos/rigos-state-init
RemainAfterExit=yes

Expand Down
122 changes: 122 additions & 0 deletions build/usb/includes.chroot/usr/lib/rigos/lsblk-compat
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/python3

import json
import os
import re
import subprocess
import sys
from pathlib import Path

MAJOR_MINOR_RE = re.compile(r"^[0-9]+:[0-9]+$")


def runtime_paths() -> tuple[str, Path]:
test_mode = os.environ.get("RIGOS_LSBLK_COMPAT_TEST") == "1"
if test_mode:
real_lsblk = os.environ.get("RIGOS_REAL_LSBLK", "/usr/bin/lsblk")
sysfs_root = Path(os.environ.get("RIGOS_SYSFS_BLOCK_ROOT", "/sys/dev/block"))
return real_lsblk, sysfs_root
return "/usr/bin/lsblk", Path("/sys/dev/block")


def remove_partn_column(arguments: list[str]) -> tuple[list[str], bool]:
updated = list(arguments)
requested = False
index = 0
while index < len(updated):
argument = updated[index]
if argument in {"--output", "-o"}:
if index + 1 >= len(updated):
raise ValueError(f"{argument} requires a value")
columns = updated[index + 1].split(",")
if "PARTN" in columns:
requested = True
columns = [column for column in columns if column != "PARTN"]
updated[index + 1] = ",".join(columns)
index += 2
continue
if argument.startswith("--output="):
columns = argument.split("=", 1)[1].split(",")
if "PARTN" in columns:
requested = True
columns = [column for column in columns if column != "PARTN"]
updated[index] = "--output=" + ",".join(columns)
index += 1
return updated, requested


def partition_number(device: dict, sysfs_root: Path) -> int:
major_minor = device.get("maj:min")
path = device.get("path", "unknown device")
if not isinstance(major_minor, str) or not MAJOR_MINOR_RE.fullmatch(major_minor):
raise ValueError(f"invalid block identity for {path}")
source = sysfs_root / major_minor / "partition"
try:
raw = source.read_text(encoding="ascii").strip()
except OSError as error:
raise ValueError(f"partition number unavailable for {path} at {source}: {error}") from error
try:
number = int(raw, 10)
except ValueError as error:
raise ValueError(f"invalid partition number for {path} at {source}") from error
if number <= 0 or number > 0xFFFFFFFF:
raise ValueError(f"partition number out of range for {path} at {source}")
return number


def add_partition_numbers(devices: list[dict], sysfs_root: Path) -> None:
for device in devices:
if device.get("type") == "part":
device["partn"] = partition_number(device, sysfs_root)
else:
device["partn"] = None
children = device.get("children")
if children is not None:
if not isinstance(children, list):
raise ValueError("lsblk children field is not a list")
add_partition_numbers(children, sysfs_root)


def main() -> int:
real_lsblk, sysfs_root = runtime_paths()
try:
arguments, requested_partn = remove_partn_column(sys.argv[1:])
except ValueError as error:
print(f"lsblk-compat: {error}", file=sys.stderr)
return 2

if not requested_partn:
os.execv(real_lsblk, [real_lsblk, *arguments])

if "--json" not in arguments and "-J" not in arguments:
print("lsblk-compat: PARTN compatibility requires JSON output", file=sys.stderr)
return 2

result = subprocess.run(
[real_lsblk, *arguments],
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
if result.stderr:
sys.stderr.buffer.write(result.stderr)
if result.returncode != 0:
return result.returncode

try:
document = json.loads(result.stdout)
devices = document.get("blockdevices")
if not isinstance(devices, list):
raise ValueError("lsblk JSON has no blockdevices list")
add_partition_numbers(devices, sysfs_root)
except (json.JSONDecodeError, UnicodeDecodeError, ValueError) as error:
print(f"lsblk-compat: {error}", file=sys.stderr)
return 2

json.dump(document, sys.stdout, separators=(",", ":"))
sys.stdout.write("\n")
return 0


if __name__ == "__main__":
raise SystemExit(main())
Loading