- Shell 92.7%
- QML 5.6%
- Lua 1.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_0113ibPhtbz8W2KLngzz2g8q |
||
| child | ||
| config | ||
| docs | ||
| home/.config/hypr | ||
| lib | ||
| modules | ||
| system | ||
| tests | ||
| .gitignore | ||
| bootstrap.sh | ||
| README.org | ||
omarchy-kids-bootstrap
Turn a fresh Omarchy install into a parent-managed,
learning-first workstation for a child. Same shape as omarchy-dev-bootstrap:
a thin orchestrator, numbered idempotent modules, plain-text config lists,
--dry-run for a full preview. Run it as the parent account on the child's
machine after the normal Omarchy install.
What it does
Fourteen modules, in this order (./bootstrap.sh --help lists them):
| module | what it changes |
|---|---|
| preflight | Reports Omarchy version, accounts, LUKS/btrfs/snapper, login manager, network stack. Changes nothing. |
| login | Disables SDDM autologin; installs the omarchy-kids login theme (Omarchy's, plus a user picker); sets the hostname. |
| tpm-unlock | Binds the TPM to the LUKS disk (Clevis) so boot needs no disk passphrase; the passphrase stays as fallback. |
| child-account | Creates the child (no wheel), sets its password, chmod 700 on the parent's home, provisions the Omarchy desktop. |
| packages | Installs the learning/creative/play apps (config/packages.txt, config/aur-packages.txt) and Thonny via uv. |
| webapps | Installs Omarchy web-app launchers in the child's account (Scratch, Tinkercad, …; config/webapps.txt). |
| browser-policy | Renders a mandatory Chromium policy from config/allowed-sites.txt: everything blocked except the allowlist. |
| dns | DNS-over-TLS to a NextDNS profile via systemd-resolved; NetworkManager ignores DHCP DNS; ufw blocks other DNS. |
| screen-time | Timekpr-nExT: daily quota, allowed hours, PlayTime for games, tty counted, paused while the screen is locked. |
| desktop | Child's Hyprland: learning shortcuts instead of Omarchy's app bindings, developer launchers hidden, quieter bar. |
| lockdown | File ACLs deny the child other browsers and network tools; a pacman hook re-applies them; su limited to wheel. |
| backup | Daily restic backup of the child's work to an external disk or NAS, as a system timer. |
| ssh-admin | sshd for the parent only, from the LAN subnet; passwords turn off once a key is authorized. |
| snapshot | A labelled snapper snapshot of the system (bootable from the Limine menu). |
Two modules print instructions instead of acting until their input exists:
dns needs NEXTDNS_PROFILE_ID, backup needs RESTIC_REPO and a password
file the parent creates outside git.
Usage
On the child's machine, logged in as the parent (the account the Omarchy
installer created, which is in wheel):
git clone [email protected]:Pcsf/omarchy-kids-bootstrap.git ~/omarchy-kids-bootstrap
cd ~/omarchy-kids-bootstrap
cp config/kids.conf.example config/kids.conf
$EDITOR config/kids.conf # child's name, theme, NextDNS id, LAN subnet, limits (git-ignored)
./bootstrap.sh --dry-run # read the whole plan first
./bootstrap.sh # one sudo prompt, then the child's password prompt
./tests/acceptance.sh # as the parent
Then log out, log in as the child once (Omarchy finishes its first-login steps), and run the child-side checks from inside that session:
sudo install -m 755 tests/child-checks.sh /usr/local/bin/omarchy-kids-child-checks # as the parent, once
omarchy-kids-child-checks <parent-username> # as the child
Re-run any module alone after editing its config: ./bootstrap.sh --only
browser-policy. Every module is idempotent.
Layout
bootstrap.sh orchestrator (--only, --skip, --dry-run)
lib/common.sh helpers: run/as_root/as_kid_script, config loading, list parsing
config/
kids.conf.example the settings template; copy to kids.conf (git-ignored, machine-local)
packages.txt official-repo apps aur-packages.txt AUR apps (timekpr-next)
webapps.txt child's web-app launchers allowed-sites.txt browser allowlist
hidden-apps.txt launcher ids hidden blocked-commands.txt executables ACL-denied to the child
backup-paths.txt what restic backs up
sddm/Main.qml the omarchy-kids login screen (Omarchy's theme plus a user picker)
modules/NN-*.sh one concern each, run as the parent, sudo per privileged step
child/*.sh scripts that run AS THE CHILD (fed on stdin: the repo is in the parent's 700 home)
home/.config/hypr/ the child's hyprland.lua and bindings.lua (copied, not linked)
system/ files installed root-owned: Chromium base policy, ACL helper + pacman hook,
restic job + unit, lock-screen helper for Timekpr (bin/omarchy-kids-lockhint)
tests/
selftest.sh repo self-test, no root: syntax, config, policy rendering, planted negatives
acceptance.sh security acceptance, run as the parent after bootstrap
child-checks.sh the same restrictions seen from the child's account
docs/
deployment-plan.org the plan (v1.1) with the assessment of the v1.0 draft
operations.org parent cheat-sheet: daily operations, maintenance, restore, troubleshooting
Files for the child are copied, never symlinked: the repo lives in the parent's home, which is mode 700, so the child's session could not follow a link into it.
Design decisions
- Parent runs it, not root.
$HOMEand the clone stay the parent's; each privileged step is an explicitsudo. Child-side steps run throughsudo -u <child>with a minimal environment. - Omarchy's own per-user provisioning is reused, minus the developer extras.
Omarchy 4 provisions a user from
/etc/skelplusomarchy-provision-user, which also installs a dozen AI coding agents through mise and fetches Node.child/provision.shdoes the essential steps (theme, keyring, user dirs, default browser) and marks Omarchy's finalization and shipped migrations as done, so the child's first login does not pull in the rest. - Enforcement never lives in the child's home. Policies, DNS, firewall, Timekpr, ACLs are root-owned system state. The desktop module is cosmetic and documented as such.
- Two layers for the browser. The Chromium policy (allowlist, no DevTools, no extensions, no incognito, DoH off) plus ACLs that keep the child out of every other browser on the machine. Chromium policies are machine-wide, so they bind the parent too when browsing on this machine; administer over SSH or from another device.
- DNS has a device layer and should have a router layer. The device layer (DoT to NextDNS, plain DNS refused by ufw) protects this install. A router or NextDNS per-device policy protects the child when this layer is bypassed.
- The disk unlocks with the TPM, the accounts do not. Omarchy encrypts the
disk and asks for the passphrase at every boot; the tpm-unlock module lets
the TPM answer instead (no PCR binding: Secure Boot is off on these
machines), so power-on goes straight to the login screen. The passphrase
stays valid as the fallback.
TPM_UNLOCK=nokeeps the prompt. - Screen time is a system quota first. Timekpr's daily limit and allowed
hours are enforced by the daemon through logind, persist in
/var/lib/timekpracross reboots, and count tty sessions (off by default upstream). PlayTime is the per-game quota inside that total; it is process-name based and therefore the weaker of the two. Hyprland's lock screen does not tell logind it is locked, so a small user service sets the session's idle/locked hints while it is up and Timekpr stops counting.
Dependencies
- Omarchy 4.x (tested against 4.0.6: packaged Omarchy at
/usr/share/omarchy,/etc/skelfromomarchy-settings, SDDM, systemd-resolved, NetworkManager, ufw, snapper + limine-snapper-sync). Plain Arch works with warnings. - From Omarchy itself:
omarchy-pkg-add,omarchy-pkg-aur-add(yay),omarchy-webapp-install,omarchy-theme-set,jq,curl. - Installed by the modules:
timekpr-next0.5.11 andmkinitcpio-clevis-hook(AUR),clevisandtpm2-tools,uvandthonny(PyPI, system-wide in/opt/thonny),restic,openssh, and the apps inconfig/packages.txt(all in [extra] on 2026-10-25;minecraft-launcheris in the [omarchy] repo). - Firmware: UEFI, Secure Boot off (the Omarchy ISO does not boot with it), fTPM on for the tpm-unlock module.
- Accounts and services the parent creates: a NextDNS profile, a backup destination (external disk or NAS mount), optionally an SSH key on the parent's laptop (password logins stay on without one).
- Paid and optional: Minecraft Java needs a Microsoft account; the launcher
lines in
config/packages.txtare commented out.
Testing
tests/selftest.sh runs without root: it parses every script, renders the
policy, checks that every web app host is allowlisted, and runs a planted
negative for each absence check. Run it after any edit. tests/acceptance.sh
and tests/child-checks.sh are the security acceptance of the plan and need
the real machine.
Verified on 2026-10-25 on an Omarchy 4.0.6 development machine: self-test
passes and ./bootstrap.sh --dry-run completes for every module.
First live run on the target Beelink (AMD) on 2026-10-31. What it changed:
Thonny moved from the AUR (its build pinned an old uv_build) to uv;
Omarchy's login theme has no user picker, so the login module ships one
(SDDM's stock themes do not load with the Qt6 greeter); Omarchy 4 locks the
screen inside its quickshell shell, not hyprlock; PlayTime needs Timekpr's
global switch; the TPM unlock was added. Self-test, including shellcheck,
passes on the target machine.