Included in this section are the artifacts and references used for building and configuring a CachyOS-based multi-purpose home server. The environment focuses on media serving (Plex), DNS ad-blocking with encrypted upstreams (AdGuard Home with DNS-over-HTTPS), and containerized services. Bulk storage and SMB file sharing are handled by a separate Ubiquiti UNAS Pro NAS; the server consumes the NAS Plex media pool over NFS. Container services and their data live on the local host drive under a configurable install location.
In some cases, the artifacts may be a subset of functionality, requiring use in a specific way or order to be helpful, where others may be a fully automated and self-contained process. Please remember that these were written for practical personal use and are not intended to be examples of best practice, nor polished and production-ready.
These resources from the base cachyos/ directory are directly compatible with the server environment and should be used as-is rather than duplicated here.
| Resource | Purpose | Notes |
|---|---|---|
cachyos/secureboot.sh |
Secure Boot setup | Only if hardware is UEFI + Limine |
cachyos/home/.config/ghostty |
Ghostty profile and Jesse theme | Installed by the server bootstrap for its Plasma session |
-
home
Based oncachyos/home, this contains the $HOME items for the user account, including zsh, git, and gpg-agent configuration adapted for the server environment withEDITOR=nanoand curses pinentry. The shared Ghostty profile remains incachyos/homeand is deployed directly by the server bootstrap rather than duplicated here. -
container-services
Docker Compose services and operational scripts for the server-hosted containers (AdGuard Home, Plex).
-
bootstrap.sh
Authored in 2026, this is an idempotent server setup script covering packages, ZSH, KDE Plasma + KRDP (KDE's built-in Remote Desktop), the shared Ghostty profile and font, Docker, firewall configuration, Python/uv, Node/NVM, and the NFS client. Pass--fullto also mount the NAS Plex media export over NFS and deploy container services end-to-end.Arguments:
If
--nas-host/--nas-media-exportare omitted, the NFS media mount is skipped (with a warning) and can be added later. Likewise, if--nas-host/--nas-backup-exportare omitted, the NAS backup mount and Kopia repo setup are skipped and can be added later.
Bulk storage lives on the UNAS Pro, configured through the UniFi Drive web UI (manual; no scripted path):
- Group 1 — 4× 8TB RAID 5 (or 5× RAID 6 if a fifth drive is added); general files + backups, shared via SMB to Windows clients and exported over NFS to this server for the Kopia backup repo.
- Group 2 — 2× 3TB RAID 1; Plex media library, exported over NFS to this server.
Both shares use the NAS's Collaborative (all-squash) mode, which maps every client to the share's owner. As a result, Plex reads media regardless of PLEX_UID/PLEX_GID, and Kopia (running as root) can write the backup repo without no_root_squash. Collaborative mode also keeps the shares reachable over SMB (Windows clients) and NFS (this server) simultaneously.
bootstrap.sh installs a single weekly maintenance job, squire-server-maintenance.timer, which runs at Saturday 00:00 by default and must finish before the 02:00 Kopia backup. It is one merged unit rather than several timers: because every step runs sequentially in one script, the steps cannot overlap or race each other, and containers are guaranteed to restart after the packages they depend on have been updated.
Steps, in order:
pacman -Syuagainst the official repositories.yay -Syufor AUR packages, run as the dedicatedaurbuildsystem account.restart-update.shto pull and restart the containers (unchanged; it is simply invoked from here now).- Cleanup: remove orphaned packages, then trim the package cache with
paccache -rk3andpaccache -ruk0. - Report unmerged
.pacnew/.pacsaveconfig files. - Reboot only if the running kernel's modules directory has disappeared, or CachyOS's own
cachyos-reboot-required.hookflagged the upgrade.
Notes on the design:
aurbuildaccount.yayrefuses to run as root and shells out tosudo pacman, so unattended AUR updates need a non-root account with a narrow grant.bootstrap.shcreates theaurbuildsystem user and installs/etc/sudoers.d/aurbuild(NOPASSWD: /usr/bin/pacman), validated withvisudo -cfbefore it is put in place. The interactive user's sudo rules are not modified. Note the practical consequence: package install still happens as root and install scriptlets run as root, so this narrows the build phase, not the blast radius.- Reboot detection is delegated, not reimplemented.
cachyos-hooksshipscachyos-reboot-required.hook, which is the distro's own authoritative answer to "does this upgrade need a reboot". It covers far more than a hand-maintained list would (microcode,mesa,cryptsetup,mkinitcpio,dracut,systemd*,wayland,xorg*,linux-firmware) and is smarter: it fires only for the running kernel, so an alternate-kernel upgrade is ignored, andbtrfs-progsonly counts when btrfs is actually mounted. Notably it does not treatlinux-headersas reboot-worthy, which a naivelinux*match would. The hook keeps no state file and its desktop notification only reaches logged-in users, so the job recordswc -lof/var/log/pacman.logbefore upgrading and afterwards inspects only the lines this run appended for the hook'sReboot is recommendedmessage. Nothing rotatespacman.logon this host today, but if alogrotatestanza is ever added, a file that has shrunk since the mark was taken is treated as proof of a mid-run rotation and the whole file is rescanned; an unnecessary reboot is a far cheaper mistake than a stale kernel running against a mismatchednvidia.ko. - Reboot safety. The job refuses to reboot if
sshdis not active. Autologin is enabled, so KRDP recovers once the Plasma session starts after a reboot; however, during early boot and on a Plasma crash, SSH is the only remote recovery path. Cleanup deliberately runs before the reboot, because a reboot terminates the script. - Missed runs are skipped, not caught up (
Persistent=false), so an update and possible reboot can never fire unexpectedly in the middle of the day. The trade-off is that a missed Saturday means a two-week gap. - Bounded runtime.
TimeoutStartSec=5400caps the run at 90 minutes, guaranteeing it cannot reach the 02:00 backup window regardless of how long an AUR build takes. - Failure reporting. There is no SMTP server available to this host, so failures are surfaced locally:
/var/lib/squire-maintenance/last-run-failedrecords the timestamp, failing step, exit status and a consecutive-failure count, and/etc/profile.d/squire-maintenance-banner.shprints a banner on every interactive login until a successful run clears it. Visibility is therefore only as timely as the next login. A run that reboots and never comes back cannot be reported by this mechanism. - Config drift reporting. Config files are never merged automatically, since a bad merge could break DNS, boot, or pacman itself. Instead the job counts
.pacnew/.pacsavefiles under/etceach run. If the count has risen since the previous run,/var/lib/squire-maintenance/pacnew-increasedis written and the same login banner reports it in yellow, listing the unmerged files. The marker clears itself on the next run where the count does not rise, so the banner reports newly appeared files rather than nagging about a standing backlog you have deliberately left alone. Review withsudo pacdiff, or dismiss without merging viasudo rm -f /var/lib/squire-maintenance/pacnew-increased. - Editors and toolchains come from the package manager.
microandnvmare installed withpacmanrather than piped fromgetmic.roandraw.githubusercontent.comintosudo bash. This matters beyond provenance: an unmanaged binary in/usr/local/binshadows the packaged one inPATH, so the weeklypacman -Syuabove would faithfully update a binary that never actually runs. Packagednvmalso drops the hard-coded version pin, so each run installs whatever is current. Because the packagednvmlives at/usr/share/nvm/init-nvm.sh,.zshrcprefers that path and falls back to~/.nvmonly if it is absent. If a legacy curl/wget install is detected,bootstrap.shprints a one-time notice telling you what to remove; it does not delete anything itself, and your installed Node versions under~/.nvm/versionsare left untouched. Subsequent runs simply use the packaged versions. - Logs.
/var/log/squire-maintenance.log, rotated by/etc/logrotate.d/squire-maintenance. - Recovery.
snap-pactakes a pre/post snapshot on every pacman transaction. Prefer fixing forward; if that is impractical,snapper -c root listthensnapper -c root rollback <N>, or pick a snapshot from the Limine boot menu if the machine will not boot.
Useful commands:
systemctl list-timers squire-server-maintenance.timer
systemctl status squire-server-maintenance.service
sudo systemctl start squire-server-maintenance.service # run now, supervised
sudo tail -f /var/log/squire-maintenance.log
pacdiff --output # list unmerged config files- Configure the UNAS Pro: create the RAID groups and enable NFS (Collaborative/all-squash) on the media (Group 2) and backups (Group 1) shares, allowed to this server's IP. No uid/gid matching is required under all-squash.
- Copy existing Plex media onto the NAS Group 2 pool before first Plex start.
- If
--nas-backup-exportwasn't provided during bootstrap, re-runbootstrap.shwith--nas-hostand--nas-backup-exportto mount the NAS backups export and complete Kopia setup. - First container start (if not using
--full):cd <install-dir>/container-services && ./start-services.sh(generates.envwith secrets). - Resolve any unmerged config files with
sudo pacdiff(pacdiff --outputlists them).pacmanwrites a.pacnewwhenever a config file it tracks was changed both locally and upstream, so it never silently discards a local edit. Keeping this list empty is what makes the maintenance job's drift report meaningful.
Minimal install (base system, no containers):
- Install CachyOS (KDE Plasma edition)
- (Optional) Run
../cachyos/secureboot.shif UEFI - Run
bootstrap.sh - Deploy containers manually via
container-services/install-services.sh <install-dir>/container-services <install-dir>/adguard - Manual steps above
Full install (end-to-end):
- Install CachyOS (KDE Plasma edition)
- (Optional) Run
../cachyos/secureboot.shif UEFI - Configure the NAS (RAID groups, SMB shares, NFS exports for media + backups) and note its IP + export paths
- Run
bootstrap.sh --full --nas-host <ip> --nas-media-export <media-path> --nas-backup-export <backups-path> - Manual steps above
