Skip to content

Add the headless server edition - #11289

Open
bartex wants to merge 20 commits into
omacom:quattrofrom
bartex:omarchy-server
Open

Add the headless server edition#11289
bartex wants to merge 20 commits into
omacom:quattrofrom
bartex:omarchy-server

Conversation

@bartex

@bartex bartex commented Sep 11, 2026

Copy link
Copy Markdown

Implements the server edition described in plans/server.md: the same Omarchy, minus the desktop, plus a BBS-styled front door for the console and SSH.

What's in here

Edition mechanics. The installer records the choice in /etc/omarchy-edition; runtime code gates on the omarchy-edition-server / omarchy-edition-desktop predicates. Desktop installs are byte-for-byte unaffected — every server behavior sits behind the predicate.

The front door. A themed /etc/issue before login, a status splash at login (uptime, load, disk, services, containers, pending updates), and a door-style menu behind it: btop, lazydocker, services, update, logs (lazyjournal), network, theme, and quit to shell. ENTER at the splash opens the menu; the GOODBYE door leads back. All of it draws with the same role palette the themes already define.

Real theme colors on the console. The Linux VT's 16 palette slots are programmable (\e]P<n><rrggbb>), and the themes already ship color0color15, so the console renders the actual theme rather than the kernel defaults. The escape program is emitted only where a VT will read it — other terminals parse \e]P as a malformed OSC. The theme door previews candidates live: role swatches over SSH, a full-frame retint on the console.

Desktop-only steps gated. bluetooth, xdg-user-dirs + GTK bookmarks, chromium and default-application wiring, theme-system/browser-policy config, and the desktop service enables (cups, avahi, power-profiles, sddm) skip on server, where their packages don't exist. Encrypted server installs autologin on tty1, mirroring the SDDM rule: the LUKS prompt is the auth boundary.

Testing

  • ./test/shell passes (new coverage for the palette, console programming, and issue renderer).
  • Full install loops in QEMU (OVMF, LUKS + Btrfs) from a locally built ISO: both editions install, server boots to the themed splash, SSH reachable from first boot. Not yet tested on bare metal — extra eyes on real hardware welcome.

Companion PRs: omacom/omarchy-iso#175 (installer + ISO side), omacom/omarchy-pkgs#397 (lazyjournal).

bartex and others added 20 commits September 10, 2026 16:58
Editions are chosen at install time and read everywhere after, so the
marker needs a reader that refuses to guess and predicates cheap enough
to guard a migration with.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The server list is the base list minus the desktop, so a test enforces
that shape rather than trusting two lists to stay in step. Only the one
command that installs the default set on a live machine needs to choose
between them; fresh installs seed migration markers, so no historical
migration ever runs on a server.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The palette names roles rather than colors so a theme can move a hue
without every renderer following it, and resolves in one awk pass because
this runs on each interactive login. Depth and glyphs degrade separately:
an SGR code a terminal cannot render is ignored, a box character it cannot
draw is substituted and wrecks the alignment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The edition marker is writable, so the renderer needs an undo, not just a
no-op. Keep whatever the distribution shipped before the first overwrite,
and put it back when the marker changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The guard matters more than the splash: a byte on stdout breaks scp and
rsync, which read the stream as protocol, so every silent case is a test
before it is a line of hook. Readings are gathered on a leash and render as
a dash when they miss, because a login that waits on a wedged daemon is a
worse failure than a stale count.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
tr substitutes bytes, so it replaced the first of the rule character's three
and left sequences the terminal drew as missing glyphs. hostname -I is a
GNU flag; Arch ships inetutils, which answered with nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A launcher with a status pane: every entry hands the screen to a tool
Omarchy already ships and takes it back when that tool exits. Colour is
invisible to width arithmetic, so each line is built twice, once as plain
text to measure and once with escapes to print, and a test measures the
frame because a column of drift is not visible in a diff.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A reading longer than its column pushed the border out on that row alone,
and hostnames are longer on somebody else's machine. Redraw now composes
the whole frame and writes it once over the last one; clearing first made
the screen flash, which a held arrow key turns into a strobe.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
read -s silences only its own read; between reads the driver is the one
printing, and what a held arrow key sends it is ^[[A. Turning echo and line
editing off for the session stops that, and applying everything already
queued before redrawing stops the marker travelling on after the key is
released. Doors get the original settings back, since a prompt inside one
needs them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The menu's log door had been falling back to journalctl because the package
existed nowhere pacman could reach. It is packaged in omarchy-pkgs now, so
the offline mirror can carry it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A board with more than one phone line numbered them and told the caller
which one they were on. Concurrent sessions are the same fact.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Enabling a unit whose package was never installed fails, and the installer
runs under set -e, so cups, avahi, power-profiles-daemon and sddm would take
a server install down rather than being skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The server edition does not ship bluez, so enabling bluetooth.service
fails the hardware phase instead of doing nothing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xdg-user-dirs, the GTK bookmarks, chromium, and the default-application
wiring all belong to packages the server edition never installs, and
each aborts provisioning with command-not-found rather than skipping.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Linux VT's palette is programmable (\e]P<n><rrggbb>), and the
themes already ship color0-15, so the 16-color fallback can render the
actual theme instead of the kernel defaults. The program is emitted
only when it will reach a VT, since other terminals parse \e]P as a
malformed OSC; --console forces it for output generated off the console
but rendered on one, like /etc/issue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gum 2.0 draws its TUI on stderr, so the redirect left the services
door blank.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ENTER at a hand-run splash now opens the menu just like under the
greet, and the new GOODBYE door leads from the menu back to the splash.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The theme door now lists themes in place with role swatches drawn in
the candidate's own palette, and on the console retints the whole
frame live via the VT palette. ENTER applies, ESC keeps what was
there.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The desktop's encrypted installs autologin through SDDM because the
LUKS prompt is the auth boundary. A deferred server install gets the
same treatment with an agetty drop-in, and skips the SDDM state that
edition never installs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant