ShrekOS in two diagrams: giving an agent exactly one folder and one hostname
Leon OdorDev.to (EN Zone)
1 views
This is a companion map to my Building ShrekOS series. If you have read Part 2, you have the argument already. This post is the picture: how an untrusted workload gets to do real work while reaching almost nothing.
The whole thing runs on one idea. An agent, or any untrusted job, runs inside a Bench: a disposable box that starts with no files and no network, and is handed capabilities one at a time, narrowly, and revocably.
Four rules
Deny by default. A Bench starts with nothing. No files it can see, no network it can reach. Everything below is an exception I opened on purpose.
A grant is a pinned object, not a path. When I grant a directory, the system pins the actual inode and relocates it into the Bench mounted noexec. A swapped symlink cannot redirect it, and files cannot be directly executed from the granted host mount.
Egress is a sealed, pinned destination, never "the internet." A Bench that needs the network gets a named profile, say the Debian package host. The supervisor resolves and pins it through sealed policy; the Bench itself gets no DNS access and everything else stays dropped.
A Bench never gets both egress and a secret. A box that can read a token and reach arbitrary network destinations can mail that token to a stranger. So credentialed calls go through a broker outside the Bench, which holds the credential, makes the call, and hands back only the result.
Egress, at a glance
flowchart TB
BN["Bench (default: no net)"] --> P{"sealed profile (pinned)"}
P -->|apt| DEB["deb.debian.org"]
P -->|pip| PY["PyPI"]
P -->|model| BR["broker to provider"]
BN -.->|blocked| H["host-local"]
One Bench, start to finish
sequenceDiagram
autonumber
actor U as You / Agent
participant GK as gatekeeperd
participant BN as Bench
participant NET as Outside
U->>GK: create
U->>GK: grant [in]/[out] (pinned, noexec)
U->>GK: run
GK->>BN: start, NO network (holder PID 1)
Note over BN,NET: fail-closed: zero egress
GK->>BN: inject veth + nft allowlist
BN->>NET: deb.debian.org:443 only
U->>GK: destroy (output kept, tooling gone)
The last line is the point of the whole design. The box is thrown away, but the file it produced stays. Disposability protects the host's future; it does nothing about the present blast radius, which is why the grants above matter more than the teardown.
The deep-dives
The mechanics behind each rule get their own parts in the series: why a Bench at all (Part 2), how a single grant is made attacker-proof, and how the one egress door stays honest. This post is just the map to hang them on.
My wife and I all digitizing ALL of my family's old VHS family videos, photo prints, negatives, and slides for archival. I would like to put up a family media server so everyone in the family can log in and enjoy the content. I personally have Immich for my own photos and Jellyfin for my own movies
AWS makes it incredibly easy to provision infrastructure.
Sometimes, a little too easy.
An EC2 instance gets created for a project. A volume survives after the instance is terminated. A snapshot is kept "just in case." A development environment runs all night even though nobody is using it.
Indiv
I currently have traefik, crowdsec, authentik in my homelab, I have a dedicated ipv4 address and only 4 users. I can connect back via WireGuard for not public available tools like management tools etc. Things like immich, neko and drawio etc are behind authentik OIDC/OAuth or forward auth proxy. I w