# Mountaineer Profiles This document is the concrete manifest of what each Mountaineer build contains. `MANIFESTO.md` states the principles, `STACK.md` defends each pick. This file is the inventory. There are two builds, with a strict subset relationship per principle 13: - **Mountaineer Server** — the foundational system. Headless, service-oriented, everything an operator needs on a VPS, a homelab box, or any machine that does not need a graphical layer. - **Mountaineer Sysadmin** — Server plus the Wayland graphical layer and laptop integration. The build a sysadmin installs on the workstation they use every day. **Sysadmin = Server ∪ Graphical.** No package in Server is omitted from or replaced in Sysadmin. A Sysadmin install on a server is a Server install with idle graphical packages; a Server install on a workstation is a perfectly functional headless system. This is the constraint that keeps the two builds one mental model. Roles within a profile — `bastion`, `homelab`, `dev-workstation`, etc. — are planned for a later iteration (see the final section) and layer additional package sets and config on top of a chosen profile. They are not separate profiles. --- ## Mountaineer Server The full set of packages and configuration overlays Server adds on top of a minimal Alpine installation. ### Packages Grouped by role for readability. Versions follow Alpine's `linux-lts` release; any package not in Alpine's repositories is not in Mountaineer. **Foundation** - `alpine-base`, `alpine-conf` (Alpine baseline) - `apk-tools` (package manager — already present) - `busybox`, `busybox-suid` (already present; `/bin/sh` stays ash) - `openssh-server`, `openssh-client` - `chrony` - `unbound` **Init and supervision** - `s6`, `s6-rc`, `s6-linux-init`, `execline` - `mountaineer-s6-services` (Mountaineer-authored: the canonical s6-rc service definitions for every shipped daemon) **Interactive userland (defaults, not aliases)** - `nushell` - `helix` - `zellij` - `starship` - `ripgrep`, `fd`, `sd`, `bat`, `eza`, `dust`, `procs`, `bottom`, `zoxide`, `lnav` **Containers** - `podman`, `buildah`, `crun` - `mountaineer-podman-s6` (Mountaineer-authored: s6-rc templates for supervised containers — the quadlet analog) **Filesystem** - `zfs`, `zfs-lts`, `zfs-scripts` - `zfsbootmenu` **Networking** - `ifupdown-ng`, `ifupdown-ng-wireguard` (plugin for wireguard interfaces) - `dhcpcd` - `nftables` **Web ingress and TLS** - `caddy` **Secrets and backup** - `age` - `sops` - `restic` **Mail (send-only)** - `msmtp`, `msmtp-mta` (provides `/usr/sbin/sendmail`) **Log routing** - `vector` **Mountaineer tools** - `mountaineer-sysop` (the `sysop` CLI itself — ratatui frontends, swap-friendly backends, role-based vocabulary) - `mountaineer-base-config` (the configuration overlay — see next section) - `mountaineer-manifest` (ships `/etc/mountaineer/manifest.toml`) ### Configuration overlay Mountaineer ships defaults in these files. Each one is heavily commented; reading the file teaches what it does (principle 2). Operators edit these files directly; nothing wraps them. ``` /etc/mountaineer/ manifest.toml # role → package mapping, source of truth for `sysop info` profile # "server" or "sysadmin" /etc/ssh/sshd_config # hardened: no password auth, no root, modern KEX/cipher/MAC /etc/chrony/chrony.conf # iburst, public NTP pool, documented swap pattern /etc/unbound/unbound.conf # local recursive resolver, DoT upstream, DNSSEC /etc/caddy/Caddyfile # commented example: reverse proxy, static, podman backend /etc/nftables.d/ # default-deny, ICMP/ICMPv6 filtering, SSH rate-limited /etc/vector/vector.toml # routes container + system logs to /var/log/{containers,system} /etc/msmtprc # configured-but-failing default (operator must point at SMTP) /etc/network/interfaces.d/ # example stanzas for static, dhcp, bridge, wireguard /etc/restic/ # stub repository config; commented scheduled-job example /etc/s6/ # s6-rc compiled service database /etc/s6-rc.d/ # Mountaineer-canonical service definitions (source) /etc/nushell/ # global nushell environment + default aliases /etc/profile.d/ # interactive shell setup (PATH, zoxide init, starship init) /etc/helix/ # global helix config (themes, LSP defaults) /etc/zfs/ zpool.cache # generated at install mountaineer-arc.conf # tuned zfs_arc_max default (sized at install) ``` ### Default services (running on a fresh Server install) Supervised by s6-rc: - `sshd` - `chronyd` - `unbound` - `nftables-load` (one-shot at boot, loads ruleset) - `caddy` (off by default; enable via `sysop service enable caddy` once Caddyfile is configured) - `vector` Not running by default; available to enable: - `podman` (lazy — no daemon, but `sysop podman-s6` templates supervise individual containers as needed) - `restic-backup` (one-shot scheduled; off until `/etc/restic/` is configured) ### Explicitly not in Server - No graphical anything (no Wayland, no X, no compositor, no fonts beyond terminal essentials) - No web browser - No NetworkManager, no systemd-anything, no Docker, no OpenRC - No full MTA (msmtp is send-only) - No bash as interactive shell (`apk add bash` if you insist) --- ## Mountaineer Sysadmin Sysadmin = Server + the additions below. Everything in the Server section above applies; this section is purely the delta. ### Additional packages **Wayland and compositor** - `river` - `wlroots` (pulled in by river) - `xdg-desktop-portal`, `xdg-desktop-portal-wlr` (for application portals — screen share, file picker) **Graphical userland** - `foot` (terminal) - `yambar` (status bar) - `fuzzel` (launcher) - `cliphist` (clipboard history) - `fnott` (notifications) - `grim`, `slurp`, `swappy` (screenshots and annotation) - `swaylock`, `swayidle`, `swaybg` (lock, idle, background) - `wl-clipboard` (clipboard CLI integration) **Audio** - `pipewire`, `pipewire-pulse`, `pipewire-jack` - `wireplumber` **Wireless and laptop integration** - `iwd` - `seatd` - `brightnessctl` - `tlp`, `tlp-rdw` **Browser fallback** - `w3m` (emergency text browser only; first-boot install flow prompts for a real browser) **Fonts** - `font-jetbrains-mono-nerd` (terminal, editor) - `font-inter` (UI text) - `font-noto`, `font-noto-emoji` (broad Unicode coverage) ### Additional configuration overlay ``` /etc/mountaineer/ profile # "sysadmin" ~/.config/river/init # shipped default; tiling layout, keybinds documented inline ~/.config/foot/foot.ini # font, colors, scrollback ~/.config/yambar/config.yml # the ~30-line default status bar ~/.config/fuzzel/fuzzel.ini # launcher styling ~/.config/fnott/fnott.ini # notification styling ~/.config/swaylock/config # lock screen styling ~/.config/swayidle/config # dim, lock, suspend timeouts /etc/iwd/main.conf # iwd defaults /etc/seatd.conf /etc/tlp.conf # battery-favoring tuned defaults ``` Per-user configs ship as `/etc/skel/.config/...` and are copied into new users' home directories at account creation. ### Additional services (Sysadmin-only) Supervised by s6-rc (system) or river's session manager (user): - `seatd` - `iwd` - `pipewire`, `wireplumber` (user session) - `tlp` ### First-boot Sysadmin flow On first login to a Sysadmin install, the Mountaineer setup script: 1. Prompts for hostname, user account, SSH key import (if any). 2. Asks if the user wants to import a wifi profile (or defers to `sysop wifi` later). 3. Presents the `apk` browser packages and runs `apk add` on the user's choice (or "skip — use w3m for now"). 4. Drops the user into a river session with the default layout. Subsequent runs of any of these steps are available as `sysop` subcommands. ### Explicitly not in Sysadmin Sysadmin adds exactly the packages above and nothing else. Anything not in this delta is either in Server (and therefore in Sysadmin) or not in Mountaineer at all. In particular, Sysadmin does **not** add: - A display manager. River is launched from a TTY login via a small shell script (`/usr/local/bin/start-river`) — no greetd, no SDDM, no gdm. The login prompt is the kernel's, the way it has always been. - A file manager. The terminal is the file manager. `yazi` (or `ranger`, or any other TUI file manager) is one `apk add` away for operators who want one. - A mail client. `aerc` is the natural Mountaineer-flavored pick if we ship one in a later iteration; for now, operators install what they want. - An office suite, a media player, a chat client, a calendar, or any of the consumer-desktop expectations. Sysadmin is not a consumer desktop (manifesto: "What this isn't"). --- ## Roles (planned, v0.2+) Roles are *additive overlays* on top of a chosen profile. They are not separate profiles, do not break the subset relationship, and exist to bundle common operator setups so a fresh Mountaineer machine can become "the bastion" or "the homelab box" with one command. Each role is a small `sysop` subcommand that installs a specific package set and drops in a specific configuration overlay. The mechanism is identical to a manual `apk add ... ; cp config files` sequence — the role just curates the list. Planned roles (none of these are built yet; this list anchors the design conversation): - **`bastion`** — hardened SSH jump host. Tightens sshd, installs fail2ban-equivalent (probably `sshguard`), configures audit logging, enables port-knocking via nftables sets. Implies Server. - **`homelab`** — single-machine self-hosted services host. Adds caddy as default-on, ships an example Caddyfile for `*.home.arpa` routing, pre-seeds a podman-s6 setup for common containers (gitea, nextcloud, etc., user picks at role-init time). - **`dev-workstation`** — Sysadmin plus language toolchains for the operator's stated languages and development tooling (`git`, `gh`, `direnv`, `mise` or equivalent). The `docker → podman` shell alias is already shipped system-wide; the role does not redo it. Implies Sysadmin. - **`vps`** — Server with a focus on minimal install size, default-deny aggressively tuned for an internet-exposed machine, wireguard pre-configured for inbound from a known endpoint. Implies Server. - **`relay-mail`** — Server with msmtp replaced by OpenSMTPD configured as an outbound relay (the documented upgrade from msmtp). Implies Server. The role mechanism deliberately mirrors the profile mechanism: additive, documented, no parallel forks, swappable underlying tools per principle 14. A role that adds Caddy and one that adds OpenSMTPD compose; a role that *replaces* an init system does not exist and never will. --- ## How profiles are built (Implementation notes — separable from the inventory above.) Both profiles ship as `apkovl` overlays applied to Alpine's minimal install image, plus an ISO variant that runs the Mountaineer installer as its only first-boot action. The installer handles: 1. Disk partitioning and zpool creation (canonical dataset layout). 2. Base Alpine bootstrap via `apk add --root /mnt`. 3. Mountaineer package set install (Server set always; Sysadmin set additionally if the install was started from the Sysadmin ISO). 4. Configuration overlay deployment. 5. s6-rc service database compilation and enablement. 6. zfsbootmenu installation and the initial snapshot creation. 7. First user account creation and the first-boot flow (Sysadmin only). The package sets are maintained as plain text files in the Mountaineer repository — `profiles/server.world`, `profiles/sysadmin.world` — and the strict-subset invariant is checked in CI: every package in `server.world` must appear in `sysadmin.world`, and CI fails otherwise. The invariant is enforced mechanically, not by discipline.