Skip to content

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 playbooks

Note

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:

  1. 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 to pacman.conf via blockinfile (safe to re-run — the block is marker-delimited).
  2. Bootstrap BlackArch repository — runs BlackArch’s official strap.sh installer.
  3. Install packages via pacman — three separate pacman tasks for the vanilla Arch repo, the CachyOS repo, and BlackArch, each with retries/delay/until to ride out transient mirror failures.
  4. Set up yay AUR helper and install AUR packages — creates a dedicated aur_builder user in the wheel group with passwordless sudo scoped only to pacman, then builds yay and the AUR package list as that user via kewlfft.aur.aur. This avoids ever running makepkg/yay as root or needing the primary user’s password during the build.
  5. Enable snapd and install Snap applications — starts snapd.socket, waits for snap wait system seed.loaded, then installs snap packages.
  6. Install Flatpak applications — adds the Flathub remote and installs apps from it, plus one app installed directly from a .flatpakref URL.
  7. Install Xenlism GRUB theme — clones the theme repo, runs its installer, and patches GRUB_GFXMODE in /etc/default/grub before regenerating the GRUB config.
  8. System hardening — see the hardening breakdown below.
  9. Create user directory structure — ensures ~/Documents, ~/Downloads, ~/Pictures/screenshots, ~/Pictures/wallpaper, ~/Videos, and ~/git exist.
  10. Configure ZSH with Oh My ZSH and Powerlevel10k — installs a Nerd Font, points ZDOTDIR at ~/.config/zsh (keeping dotfiles out of $HOME directly), installs Oh My Zsh non-interactively, and installs the Powerlevel10k theme plus the zsh-autosuggestions and zsh-syntax-highlighting plugins.
  11. Configure git and generate SSH/GPG keys for Codeberg — loads secrets from spo-pc-ls.yml (vars_files), generates an ed25519 SSH keypair and an RSA GPG keypair non-interactively (via a temporary GPG batch-parameters file that is deleted immediately after use), sets user.name, user.email, and commit.gpgsign in the global git config, and prints both public keys so you can add them to Codeberg.
  12. Pull wallpaper collection — clones a personal wallpaper repo into ~/Pictures/wallpaper.
  13. Clone public Codeberg repositories — clones a list of repos over HTTPS into ~/git/<org>/<repo-name>, then rewrites each remote from HTTPS to SSH with git 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 (see snippets/configuration/gitConfig/gitclonePrivate.yml).

System hardening

The hardening play:

  • Ensures fail2ban.service and firewalld.service are enabled and running.
  • Copies your public key into authorized_keys on the target.
  • Configures doas to let the wheel group run commands with a persisted session.
  • Changes the SSH port and disables password authentication in sshd_config (each change triggers a handler that reloads sshd — it doesn’t restart the whole service, so existing connections aren’t dropped).
  • Writes a marker-delimited fail2ban jail configuration for sshd in aggressive mode.
  • Opens the new SSH port in firewalld as 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.yml
  • snippets/configuration/hardening.yml, sshkeys.yml, wallpaperPull.yml, zshConf.yml, folderstructure.yml, and gitConfig/ (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.ini is 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 and IdentitiesOnly=yes to avoid SSH agent key confusion.
  • requirenments.yml pins 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), and ansible.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).

Last updated on