Rework the M-Archy splash: scale the skull to ~42% of screen height and
centre it instead of filling the screen, then draw the latest 3 boot-log
lines beneath it (fed by both the status and display-message callbacks).
Drops the imagemagick-generated dot.png throbber and its refresh loop.
Render the logo at 600px (down from 1920px) since it is no longer
full-screen, and only pull in imagemagick for the transparent-placeholder
fallback. migrate-to-lightdm purges the stale dot.png before re-running the
module so upgraded installs end up byte-clean. Update docs and module
labels ("skull logo + boot-log tail"), and simplify bg-skull.svg.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Plymouth: bg-skull.svg is a 1920x1080 transparent composition but was rendered
at 300px and treated as a small centred logo, so the skull all but vanished and
the spinner (positioned off the logo height) landed on the monitor artwork. Now
render at native 1920px, scale to fill the screen, and pin the spinner at a
fixed 0.93 of screen height. Also fix DOTFILES_DIR (was off by one level, so the
bundled SVG never resolved and it fell back to a transparent placeholder) and
the dead ../plymouth.sh paths in plymouth-custom.sh and install-modules.sh.
Greeter: HyprLua now uses LightDM + lightdm-gtk-greeter, themed with the
existing cyberqueer GTK theme and a rendered skull background, via a new
self-contained lightdm module. ly is extracted from the DE scripts into its own
module so it stays installable; niri and legacy hyprland keep their inline ly.
Both greeters are registered in modules.conf as mutually exclusive, and the
generated installer/answerfile/docs regions were rebuilt from it. install-modules.sh
guards the 'ly' token with a padded match so it can't substring-hit 'p(ly)mouth'.
Add setup/tools/migrate-to-lightdm.sh to move an existing install (ly / greetd /
GDM / SDDM / LXDM) onto the Plymouth + LightDM setup: it disables the old DM for
the next boot only (never stops the running session) and delegates install +
theming to the module scripts. Supports --dry-run / --no-plymouth / --yes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first checklist (Select Components) could silently auto-confirm its
defaults, swallowing the user's toggle: tui-install.sh runs right after the
long, mostly-unattended base install, and keystrokes buffered during that
wait were consumed by the script's very first read. Drain the tty before the
first prompt.
Also split the "shell" component into "shell" (tools/plugins/programs) and
a new "shellrc" (personal .bashrc/.zshrc/.vimrc), so the shell environment
can be installed without overwriting the user's rc files. shell-setup.sh
reads MARCHY_DEPLOY_SHELL_RC to gate the rc symlinks and now also deploys
.vimrc, which /etc/skel sync already expected but nothing ever created.
Removes the separate, easily-desynced "Shell Config for New Users" prompt
in favor of deriving /etc/skel behavior from the same shellrc choice, and
mirrors the removal in generate-answerfile.sh.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
An answerfile/PXE install runs the TUI modules with no operator present, so any
interactive prompt or confirmation hangs the deployment forever.
- tui-install.sh: run each module in the FOREGROUND with a background `tail -f`
mirroring its log, instead of backgrounding the module. Backgrounding made
interactive module reads (e.g. the EWW form-factor question) trigger SIGTTIN
and stop; the file-based log still avoids the `| tee` pipe-inherit hang that
paused installs after a module spawned a daemon. Export MARCHY_UNATTENDED=1
in answerfile mode so modules can detect it.
- hyprlua.sh: skip the EWW form-factor `read` when MARCHY_UNATTENDED=1 or stdin
is not a TTY, defaulting to the desktop/no-battery bar; add --noconfirm to the
tablet-branch yay call.
- python.sh: add --noconfirm --needed to its `pacman -Syu` so it no longer waits
on the "Proceed?" prompt during unattended installs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
When the TUI modules run inside the archiso installer chroot, the new
system's systemd is not the running init and there is no user session bus.
Operations like `systemctl start`, `enable --now`, `systemctl --user`, and
`gsettings` fail there and, under `set -e`, abort the whole module.
- logging.sh: add in_chroot/have_user_bus/enable_service/start_service
helpers. enable_service warns instead of aborting; start_service skips in
a chroot (unit starts on first boot via its enable symlink).
- core.sh, hyprland.sh, hyprlua.sh, niri.sh: route enables through
enable_service, starts through start_service, and guard gsettings behind
have_user_bus. Fixes the cronie-enable failure and the ly/DM setup abort.
- app modules (tlp, timeshift, open-webui, mysql, qemu, ollama, cockpit,
docker, ssh-server): convert `enable --now`/plain enables to
enable_service + start_service so they no longer abort during chroot install.
- tui-install.sh: run modules with output to a file plus a pid-bound tail,
waiting on the module PID, so a daemon child inheriting the pipe can no
longer hang the installer after a module (e.g. flatpak) finishes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
Flip their default field to "on" in modules.conf and regenerate the checklist
blocks in tui-install.sh and generate-answerfile.sh so they come pre-selected
in both the TUI installer and the answerfile generator.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shellcheck passes (default severity) on the base installer and the whole
answerfile chain: generate-answerfile.sh → build.sh → .automated_script.sh →
launch.sh → arch-autoinstall.sh → tui-install.sh. Verified the generator's
JSON schema (drive, kernel, keymap, hostname, username, encrypt, fido2_root,
fido2_user, run_tui, components, desktop_environment, apps, shell_rc, colors)
parses correctly through both the auto base installer (af_get/af_bool) and the
TUI installer (load_answerfile), for full and minimal/empty answerfiles.
Fixed the three legitimate findings surfaced along the way:
- generate-answerfile.sh: drop unused AVAIL_DRIVES (SC2034); the drive list is
rendered inline in the dialog prompt.
- tui-install.sh: drop unused C_RULE (SC2034); write log truncation as
': > "$LOG"' so the redirection has an explicit command (SC2188).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Flatpaks now install globally again: ensure_flatpak adds the Flathub remote at
--system and all 19 app modules use `sudo flatpak install --system`. Running
via sudo (root) performs the system op directly, avoiding the SystemHelper/
polkit D-Bus path that caused "The name is not activatable" for non-root users.
- tui-install.sh no longer prompts for or sets the hostname — the base installer
already configures it. Removed the Hostname section, the MAC-suffix helper, the
AF_HOSTNAME field and the summary line.
- archbaseos-guided-install.sh now gathers ALL input up front, including
passwords. New ask_password() prompts in clear text (by request) and requires a
confirmation entry, looping until the two match — so each password is typed
exactly twice and never again. The LUKS passphrase is captured once and fed to
luksFormat/open/luksAddKey (--key-file=-) and cryptenroll ($PASSWORD), instead
of cryptsetup prompting repeatedly. After all input, a single all-caps "type
YES" gate replaces the old per-step confirmations (answerfile mode keeps its
5-second abort window). The run-TUI choice is also asked up front.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The applications menu (~80 entries) overflowed the terminal. Render
the checklist one terminal-height page at a time, clearing and homing
the cursor each round for a stable scrollable view, with n/p paging.
Item numbering stays global so any entry can be toggled from any page.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the dialog dependency entirely so the installer runs on a bare
console with only bash + coreutils. Reimplement the needed widgets
(msgbox, yesno, input, menu, checklist, form) as ui_* helpers using
read, preserving the cyberqueer magenta/cyan palette via ANSI codes
and the stdout/stderr fd convention so existing capture sites work
unchanged. Update generate-modules.sh to emit the ui_checklist form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#2 — Word-boundary match for all module patterns
Generator now pads SELECTED_APPS with spaces and uses *" id "* in
counters, summary, and dispatch, matching the conflict fix from #1.
plymouth-custom no longer false-triggers any plymouth check.
#3 — Guided installer now runs tui-install.sh
archbaseos-guided-install.sh was calling simple-install.sh; both
paths now use the full TUI (sentinel-managed, modules.conf-driven).
#4 — EFI/boot partition size unified at 10 GiB
arch-autoinstall.sh was 15 GiB, archbaseos-guided-install.sh was
5 GiB. Both now use 10 GiB.
#5 — Interactive retry for dotfiles clone (guided installer)
Clone moved outside the chroot heredoc so read() reaches the terminal.
Loops until success or the user skips; AF_MODE warns and continues.
#6 — PAM target unified on system-local-login
archbaseos-guided-install.sh was writing to system-auth (affects
sudo). Both installers now target system-local-login only.
#7 — Redundant second clone removed from autoinstaller
arch-autoinstall.sh had a second git clone inside the chroot as a
fallback that collided with the skel copy and printed a spurious
warning. Removed; skel-only approach matches the guided installer
(last updated). Also removed the individual .zshrc/.bashrc/.vimrc
cp block; aligned to the guided installer's cleaner skel structure.
#8 — Docs: remove stale plymouth core-module section
docs/md/modules.md still described plymouth under Core Modules.
Section removed; plymouth appears in Optional Applications (system
category) via the generated sentinel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs in the module-conflicts system:
1. warn() was called by the generated conflict block but never defined —
any conflict would crash with 'warn: command not found'.
Added warn() to helpers: dialog msgbox in interactive mode, logged
printf in answerfile mode.
2. Conflict patterns used substring globs (*"id"*) which caused
plymouth-custom to match the plymouth check — selecting only
plymouth-custom would trigger the conflict block, call the missing
warn(), and then remove plymouth-custom from SELECTED_APPS, leaving
no boot splash running at all.
Fixed by padding SELECTED_APPS with spaces and using *" id "* word-
boundary patterns in both the condition and the removal substitution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both plymouth and plymouth-custom are now optional — neither is strictly
required, so removing plymouth from the core COMPONENTS checklist and
treating it identically to plymouth-custom.
- Remove plymouth from COMPONENTS checklist, counter, summary, and dispatch
- Add plymouth back to modules.conf (default=on, excludes=plymouth-custom)
- Regenerate all sentinel regions; plymouth now appears in optional apps
checklist/summary/conflicts/dispatch alongside plymouth-custom
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
plymouth is a core component (COMPONENTS checklist), not an optional app.
Moving plymouth.sh to apps/ left the core dispatch pointing at the deleted
path; also incorrectly added it to modules.conf, duplicating it in the
optional apps checklist.
- Fix core dispatch: $MODULES/optional-Modules/plymouth.sh → $APPS/plymouth.sh
- Remove plymouth from modules.conf (plymouth-custom remains as optional app)
- Regenerate all sentinel regions; conflict block now only has plymouth-custom
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
apps/ is for modules that install software during setup. freeipa-image is
support tooling for the ansipa controller, run manually before installation,
so it has no place in the TUI module picker.
- git mv optional-Modules/plymouth.sh → apps/plymouth.sh
- git mv apps/freeipa-image.sh → setup/tools/freeipa-image.sh
- modules.conf: add plymouth (default=on, excludes=plymouth-custom); remove freeipa-image
- generate-modules.sh: regenerate all sentinel regions (81 → 81 active modules,
freeipa-image dropped from checklist/summary/dispatch, plymouth added with on default,
conflict block gains plymouth ↔ plymouth-custom pair)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs io.github.suchnsuch.Tangent via Flatpak with cyberqueer theme
applied. Registered in TUI installer, answerfile generator, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs md.obsidian.Obsidian via Flatpak with cyberqueer theme applied.
Registered in TUI installer, answerfile generator, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs com.github.flxzt.rnote via Flatpak with cyberqueer theme
applied. Registered in TUI installer, answerfile generator, and docs
alongside xournal++ in the Productivity section.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs ydotool via pacman and OpenDeck via Flatpak, wires ydotoold
and OpenDeck into the Hyprland autostart. Registers the module in the
TUI installer, answerfile generator, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs a custom Plymouth theme (m-archy) with bg-skull.svg converted
to PNG (Plymouth is PNG-only via libpng — no SVG support) and a 12-dot
magenta spinner animation. Enabled by default in tui-install.sh; also
available as an optional module in install-modules.sh. Archiso image
remains Plymouth-free.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyBNiWy3wpawrWb9ryVk7p
Adds a dialog (interactive + answerfile) letting the user choose whether
to copy the dotfiles' .zshrc / .bashrc / .vimrc into /etc/skel, or leave
system defaults in place. The choice is persisted as shell_rc in the
answerfile JSON and respected by both the TUI installer and the generator.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem: every module installs its config into the running user's ~/.config, but
/etc/skel was never updated afterwards. Any additional user created with
`useradd -m` later would get an empty home directory with no configs at all —
they would have to manually copy or re-run setup.
Solution: at the end of both TUI installer scripts (after every module and the
colorway step have finished), copy the fully-configured user's home into
/etc/skel so that it becomes the template for all future users.
How it works — tui-install.sh + simple-install.sh (identical block in both):
The block runs AFTER the last run_module call and AFTER apply-theme.sh, so
the snapshot is taken when the home directory is in its final state. It copies:
~/.config/ → /etc/skel/.config/ (all app configs, DE configs, etc.)
~/.themes/ → /etc/skel/.themes/ (GTK themes, including cyberqueer)
~/.zshrc → /etc/skel/.zshrc
~/.bashrc → /etc/skel/.bashrc
~/.vimrc → /etc/skel/.vimrc
Each copy is guarded ([[ -d ]] / [[ -f ]]) so missing files are silently
skipped rather than erroring. sudo is used because /etc/skel is root-owned
but the installer runs as the normal user.
arch-autoinstall.sh + archbaseos-guided-install.sh (chroot-phase changes):
The previous version tried to cherry-pick specific subdirectories from the
Dotfiles repo clone (hypr/, niri/, waybar/, etc.) using a long list of cp
commands. This was brittle — any new module that installs to ~/.config was
not automatically captured, and the list had to be manually maintained.
Replaced with a minimal block that only copies the three shell dotfiles
(.zshrc, .bashrc, .vimrc) from the repo clone into /etc/skel. This is
sufficient for the first user created during installation (useradd -m runs
immediately after, before any modules). The full ~/.config sync above then
takes over for all subsequent users after the modules have run.
arch-autoinstall.sh additionally had the skel setup moved to before the
useradd -m call (was missing entirely before) so even the first user gets
the shell dotfiles, with a fallback direct-clone path if the skel clone fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two fully-featured module scripts already existed under optional-Modules/apps/
(mail-notmuch.sh and caldav-sync.sh) but were never surfaced in the installer
UI, so users had no way to select them during setup.
Changes across three files:
simple-install.sh
- count_steps(): added entries for mail-notmuch and caldav-sync so the
[N/total] progress counter stays accurate; also back-filled 13 other apps
(gimp, inkscape, krita, ardour, audacity, lmms, mixxx, cecilia, kdenlive,
openshot, shotcut, anti-malware, timeshift) that were already in the
checklist but missing from count_steps, causing the total to be wrong.
- Checklist: added both entries under the CLI Tools header, directly after
himalaya, with a human-readable description of the stack each installs.
- Run section: added the conditional run_module calls so the modules
actually execute when selected.
tui-install.sh (dialog-based TUI, same three locations as above)
- count_steps(): added mail-notmuch and caldav-sync.
- Checklist: added both entries with matching descriptions.
- Run section: added the conditional run_module calls.
generate-answerfile.sh
- Added both entries to the dialog checklist so the JSON answerfile
generator (used for unattended / ISO-embedded installs) can also select
them, keeping the answerfile schema in sync with the interactive TUIs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When running as root (archiso chroot context), all three TUI installers
previously died immediately. Replace the hard die with a sudo passthrough
shim ($TMP_D/bin/sudo → exec "$@") prepended to PATH, so every module's
`sudo pacman`, `sudo systemctl` etc. just executes directly as root.
The shim lives in TMP_D and is cleaned up by the existing EXIT trap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sauerbraten: open-source Cube 2 FPS (pacman)
stuntrally: rally racing game via Flatpak (io.github.stuntrally.StuntRally3)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
openarena: open-source Quake III Arena (pacman)
tetris: bastet + vitetris (pacman + AUR)
doom: Chocolate Doom + Freedoom game data (pacman)
Wired up in simple-install.sh, tui-install.sh, and install-modules.sh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nmtui is not available on the archiso live environment; direct users to
iwctl (WiFi) or ethernet instead, and pause for input before re-checking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tui-install.sh: dialog height=40 apps checklist and height=24 confirm
dialog both exceeded the standard 24-row VT console, causing dialog to
exit with code 1 and silently skip all apps. Make both heights
terminal-adaptive via tput lines/cols. Also extend the EXIT trap to
reset the terminal so Ctrl-C during a dialog doesn't leave the console
in raw/no-echo mode.
arch-autoinstall.sh, archbaseos-guided-install.sh: add a ping 1.1.1.1
check early in both scripts. In interactive mode, launches nmtui if
offline, then re-checks; prompts to abort if still down. Answerfile
mode logs a warning and continues.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs lamco-rdp-server from AUR (native Wayland RDP server, Rust,
H.264/VA-API). Enables lamco-rdp-server.service as a systemd user
service. Wired into tui-install.sh alongside the existing rdp-client
and qemu entries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
rdp-client.sh: installs Remmina with the FreeRDP and libvncserver plugins
for RDP and VNC sessions.
qemu.sh: installs the full QEMU/KVM stack (qemu-full, libvirt, virt-manager,
virt-viewer, dnsmasq, bridge-utils, edk2-ovmf, swtpm, vde2), enables and
starts libvirtd, auto-starts the default NAT network, and adds the user to
the libvirt and kvm groups.
Both modules are wired into tui-install.sh: count_steps, checklist,
confirmation summary, and run_module dispatch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Duplicates desktopenvs/hyprland/ as desktopenvs/hyprlua/ and converts all
Hyprland-specific configs (.conf) to Lua (.lua) using the 0.55+ hl.* API:
hyprland.lua, envvars.lua, monitors.lua, input.lua, autostart.lua,
windowrules.lua, binds.lua. Non-Hyprland tool configs (hyprpaper, hyprlock,
hypridle, hyprtoolkit) remain as .conf. Adds hyprlua.sh installer (user-side
.lua files install to ~/.config/hypr/ for require() resolution) and registers
HyprLua as the recommended DE option in tui-install.sh, marking the old
hyprlang-based Hyprland install as legacy.
Also consolidates hyprland (legacy) env vars into hypr-usr/envvars.conf,
removing duplicates from hyprland.conf and monitors.conf.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tui-install.sh:
- Reads /answerfile.json if present (ANSWERFILE_MODE)
- All dialog selections (components, DE, apps) sourced from file
- Hostname from answerfile gets MAC address suffix appended to
prevent conflicts when deploying one image to multiple machines
- Interactive hostname inputbox added to the normal TUI flow
- Colorway dialog added as final step; skipped if no colors differ
from defaults and no answerfile colors are set
- Answerfile mode: runs non-interactively, logs warnings on failure
generate-answerfile.sh (new):
- Dry-runs the full installer dialog flow (OS + dotfiles)
- Writes selections to ~/answerfile.json (or a given path)
- No software is installed; passwords are never written to the file
build.sh:
- New --preconf [FILE] flag embeds an answerfile into the ISO at
/answerfile.json; omitting the flag leaves the ISO clean
- Validates JSON with jq if available before embedding
- Reworked arg parsing to handle the new flag alongside OUT_DIR
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New optional modules (browsers): chromium, firefox, zen-browser,
nyxt, librewolf, min-browser.
New optional modules (editors/IDEs): vscodium, zed, geany,
codeblocks, kate.
Add lynx to default core packages.
All 11 modules wired into both install-modules.sh and tui-install.sh
(the archiso-embedded installer) with consistent count_steps,
checklist, summary, and dispatch entries. Every module path verified
to exist; all scripts pass bash -n syntax check.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the 'de' checkbox from the component checklist and always show
the desktop environment menu as a dedicated step between component and
app selection. Choosing 'none' or pressing Esc skips DE installation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each script installs the DE meta-package, an appropriate display manager,
PipeWire audio, NetworkManager, Bluetooth, and Flatpak, then enables the
relevant services (sddm/gdm/lightdm/cosmic-greeter).
COSMIC falls back to sddm if cosmic-greeter is not installed.
tui-install.sh: DE menu expanded from 3 to 8 entries (height 20×70).
install-modules.sh: DEs added to checklist, summary, and dispatch so
they can be installed standalone on an existing system.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add freeipa-client module (sssd, cyrus-sasl-gssapi, freeipa-client AUR)
with post-install enrollment hints; wired into tui-install.sh and
install-modules.sh
- Add ansipa-install-modules.sh: reads IPA host groups named
ansipa-module-<name>, applies matching module scripts via a yay wrapper
that drops to ANSIPA_USER so AUR builds work from the root service
- Add ansipa-install-modules.service + .timer (boot + 30 min)
- Add deploy-ansipa-modules.yml Ansible playbook that deploys scripts,
writes /etc/ansipa-modules.conf, and enables the timer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous proxmox-vm target (virt-customize + QCOW2) is replaced with
a proper Proxmox LXC CT template builder:
- Exports container rootfs as .tar.zst (same mechanism as the lxc target)
- Asks for CT ID, storage, bridge, memory, cores, disk size
- Generates pve-ct-<VMID>.conf with the required FreeIPA LXC options:
unprivileged: 0
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw cgroup:rw
lxc.cgroup2.devices.allow: a
- Generates proxmox-lxc-setup.txt with the full 6-step setup guide
(upload, pct create, apply LXC opts, set env vars, start, Keycloak)
- Optionally uploads template + conf to Proxmox host via SCP if a
host is provided
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
freeipa-image-builder.sh: TUI chooser that builds a FreeIPA server image
and exports it to four target formats:
docker — builds via podman/docker, optional registry push
lxc — exports container rootfs as .tar.zst Proxmox CT template,
generates pct import instructions
proxmox-vm — downloads Rocky/Fedora cloud image, customizes with
virt-customize, outputs QCOW2 + cloud-init user-data.yml
oci-archive — skopeo OCI tarball for air-gapped import
Keycloak TUI option generates the full constellation:
docker-compose.yml FreeIPA + Keycloak + PostgreSQL stack
.env pre-filled env template (passwords placeholder)
keycloak-configure.sh post-start Keycloak REST API config script
image/Dockerfile: Fedora 41 + freeipa-server-dns + ansible-core,
systemd-enabled container (CMD /sbin/init).
image/ipa-first-boot.{sh,service}: systemd oneshot that runs
ipa-server-install on first container/VM boot from env vars
(IPA_DOMAIN, IPA_ADMIN_PASSWORD, IPA_DM_PASSWORD, and optionals).
ConditionPathExists=!/etc/ipa/default.conf makes it idempotent.
image/keycloak-configure.sh: Keycloak REST API automation that:
- waits for Keycloak readiness
- creates a realm
- wires FreeIPA LDAP user federation (READ_ONLY, vendor=rhds)
- adds attribute mappers: email, firstName, lastName, uidNumber
- adds group mapper (IPA groups → Keycloak groups, cn=groups,cn=accounts)
- triggers an initial full user sync
image/docker-compose.yml: freeipa + postgres + keycloak services on
a private 172.30.0.0/24 bridge; FreeIPA has a fixed IP so Keycloak
can resolve it via extra_hosts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs open-webui from AUR and enables open-webui.service.
Serves the browser UI at http://localhost:8080; Ollama module
should be installed first for full LLM backend functionality.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ollama.sh: installs from official repos, enables ollama.service, notes
GPU sharing caveat with llama.cpp. For NVIDIA/AMD GPU variants use
ollama-cuda or ollama-rocm from AUR instead.
llama-cpp.sh: standalone inference CLI and server via yay (covers both
official repos and AUR). Both modules coexist at the package level;
docker/podman/cockpit modules confirmed conflict-free (all use --needed,
podman+cockpit base packages already in core-packages.sh).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs @anthropic-ai/claude-code via npm, sourcing nvm if npm is not
already in PATH. Wired into tui-install.sh and install-modules.sh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>