Code Explanation
Repository layout
archPostInstall.yml the full playbook — every play, in order
spo-pc-ls.yml ansible-vault encrypted secrets (not usable by others as-is)
inventory.ini example Ansible inventory
requirenments.yml Ansible Galaxy collection dependencies
snippets/ the same plays, split into standalone, individually runnable playbooksNote
The dependencies file is named requirenments.yml (not requirements.yml) — use that exact filename
when installing collections.
archPostInstall.yml
This is the “run everything” entrypoint. It’s a sequence of independent Ansible plays, executed top to bottom:
- Bootstrap CachyOS repository — imports the CachyOS signing key, downloads the latest
keyring/mirrorlist packages directly from the CachyOS mirror, installs them with
pacman -U, and adds the[cachyos]/[cachyos-v4]blocks topacman.confviablockinfile(safe to re-run — the block is marker-delimited). - Bootstrap BlackArch repository — runs BlackArch’s official
strap.shinstaller. - Install packages via pacman — three separate
pacmantasks for the vanilla Arch repo, the CachyOS repo, and BlackArch, each withretries/delay/untilto ride out transient mirror failures. - Set up yay AUR helper and install AUR packages — creates a dedicated
aur_builderuser in thewheelgroup with passwordless sudo scoped only topacman, then buildsyayand the AUR package list as that user viakewlfft.aur.aur. This avoids ever runningmakepkg/yayas root or needing the primary user’s password during the build. - Enable snapd and install Snap applications — starts
snapd.socket, waits forsnap wait system seed.loaded, then installs snap packages. - Install Flatpak applications — adds the Flathub remote and installs apps from it, plus one app
installed directly from a
.flatpakrefURL. - Install Xenlism GRUB theme — clones the theme repo, runs its installer, and patches
GRUB_GFXMODEin/etc/default/grubbefore regenerating the GRUB config. - System hardening — see the hardening breakdown below.
- Create user directory structure — ensures
~/Documents,~/Downloads,~/Pictures/screenshots,~/Pictures/wallpaper,~/Videos, and~/gitexist. - Configure ZSH with Oh My ZSH and Powerlevel10k — installs a Nerd Font, points
ZDOTDIRat~/.config/zsh(keeping dotfiles out of$HOMEdirectly), installs Oh My Zsh non-interactively, and installs the Powerlevel10k theme plus thezsh-autosuggestionsandzsh-syntax-highlightingplugins. - Configure git and generate SSH/GPG keys for Codeberg — loads secrets from
spo-pc-ls.yml(vars_files), generates aned25519SSH keypair and an RSA GPG keypair non-interactively (via a temporary GPG batch-parameters file that is deleted immediately after use), setsuser.name,user.email, andcommit.gpgsignin the global git config, and prints both public keys so you can add them to Codeberg. - Pull wallpaper collection — clones a personal wallpaper repo into
~/Pictures/wallpaper. - Clone public Codeberg repositories — clones a list of repos over HTTPS into
~/git/<org>/<repo-name>, then rewrites each remote from HTTPS to SSH withgit remote set-url. A matching block for private repositories exists but is intentionally commented out — it depends on the SSH key generated in step 11 already being added to Codeberg, so it’s meant to be run separately afterwards (seesnippets/configuration/gitConfig/gitclonePrivate.yml).
System hardening
The hardening play:
- Ensures
fail2ban.serviceandfirewalld.serviceare enabled and running. - Copies your public key into
authorized_keyson the target. - Configures
doasto let thewheelgroup run commands with a persisted session. - Changes the SSH port and disables password authentication in
sshd_config(each change triggers a handler that reloadssshd— it doesn’t restart the whole service, so existing connections aren’t dropped). - Writes a marker-delimited
fail2banjail configuration forsshdin aggressive mode. - Opens the new SSH port in
firewalldas a permanent rich rule.
Warning
Changing the SSH port and disabling password authentication can lock you out if your inventory’s SSH key or port isn’t already correct. Keep an existing session open while you verify a new connection works.
snippets/
Every play above also exists as its own standalone playbook under snippets/, grouped by concern, so you
can run just the piece you need instead of the whole thing:
snippets/installation/—pacmanInstall.yml,AurInstaller.yml,flatpakInstall.yml,snapInstall.yml,grubTheme.yml,userCreation.yml,tailscale.yml,threemaInstall.yml,systemdStart.ymlsnippets/configuration/—hardening.yml,sshkeys.yml,wallpaperPull.yml,zshConf.yml,folderstructure.yml, andgitConfig/(gitGpgSetup.yml,gitclonePublic.yml,gitclonePrivate.yml)snippets/repos/—addCachyosRepoToArch.yml,addBlackarchRepo.yml
These aren’t auto-generated from archPostInstall.yml — they’re maintained as separate files, so if you
change a package list or a task in one, make sure to update the other if you want them to stay in sync.
inventory.ini and requirenments.yml
inventory.iniis a plain Ansible inventory. The committed version is an example — it documents both a password-based host line (commented out) and a key-based one with a custom SSH port andIdentitiesOnly=yesto avoid SSH agent key confusion.requirenments.ymlpins the external Ansible Galaxy collections the playbook needs:kewlfft.aur(AUR package management),community.general(Flatpak, git config, and more),community.crypto(SSH/GPG key generation), andansible.posix(firewalld).
spo-pc-ls.yml
An Ansible Vault-encrypted file holding
personal secrets (ssh_key_passphrase, usr_pass, gpg_passphrase, git_user_name, git_user_email,
TAILTOKEN) consumed via vars_files in the git/GPG play. It’s encrypted with a password only I have, so
it isn’t usable by anyone else — create your own equivalent file if you want to run the playbook yourself
(see Usage).