No description
  • Jinja 78.4%
  • Shell 9.8%
  • Makefile 6.1%
  • Dockerfile 5.7%
Find a file
2026-06-15 15:41:25 -05:00
.forgejo/workflows Render yamllint output as readable text in CI 2026-06-15 14:43:39 -05:00
.github/workflows Add mirror workflow notices 2026-05-07 17:11:18 +00:00
ansible Configure host-scoped git credential helper for Forgejo 2026-06-15 15:39:47 -05:00
control-node Replace the dev wrapper with a Makefile and rename devcontainer 2026-06-10 16:40:24 -05:00
docker Add Forgejo Actions runner and systemd-managed compose stacks 2026-06-15 14:26:43 -05:00
.gitignore Drop artis3n.tailscale, manage Tailscale natively (#7) 2026-05-04 20:20:56 -05:00
.yamllint Replace hello-world CI with real validation 2026-06-10 15:53:08 -05:00
compose.yml Replace the dev wrapper with a Makefile and rename devcontainer 2026-06-10 16:40:24 -05:00
Makefile Replace the dev wrapper with a Makefile and rename devcontainer 2026-06-10 16:40:24 -05:00
README.md Add Forgejo VCS published at git.emkaytec.com 2026-06-15 12:04:59 -05:00

Foundry

Foundry is the configuration repository for a personal Ubuntu homelab server. The repo is centered on Ansible-managed host provisioning, with Docker service configuration kept alongside the playbooks that deploy it.

Note: the copy on GitHub is an intentional read-only mirror. Primary development and CI run on Codeberg.

What This Manages

  • Baseline Ansible connectivity for the foundry host
  • Apt mirror pinning for faster Ubuntu package installs
  • General-purpose system packages such as ffmpeg
  • Human user accounts, shell setup, SSH access, and developer CLIs
  • Tailscale enrollment and advertised subnet routes
  • Thunderbolt-attached storage mounted at /mnt/store
  • Tailnet-only SMB sharing from /mnt/store/share
  • Docker Engine and the Plex, Jellyfin, Forgejo, and Caddy Compose services under docker/, with Caddy reverse proxying them at *.emkaytec.com
  • Self-managed ansible-pull convergence through a systemd timer
  • Explicit system package maintenance through a dedicated update playbook

Repository Layout

.
  ansible/       Ansible inventory, playbooks, roles, and operator docs
  control-node/  Image for running Ansible locally without installing it
  docker/        Compose files deployed by the Ansible Docker role

The detailed runbook lives in ansible/README.md. Start there for manual server prerequisites, collection installation, baseline provisioning, individual playbook commands, vault usage, and maintenance tasks. Local Ansible runs expect ansible/.vault-password to exist because ansible/ansible.cfg points at it; the file is ignored by git.

Common Commands

Run commands from the Ansible directory so the repo-local ansible.cfg is used:

cd ansible
ansible-playbook foundry.yml

Running Without Installing Ansible

The repo-root compose.yml builds a disposable control-node container from control-node/ so the playbooks can run from any machine with Docker, no local Ansible install required. From the repo root:

make dev                                      # interactive shell
make dev CMD="ansible-playbook foundry.yml"   # one-off run

make dev resolves the Ansible vault password from 1Password on the host (where Touch ID works) before handing off to docker compose run --rm ansible. The raw compose command works too; vaulted playbooks then just need FOUNDRY_VAULT_PASSWORD exported first (see below).

The container mounts the repo at /workspace, starts in /workspace/ansible so the repo-local ansible.cfg applies, and mounts the host's ~/.ssh read-only so the foundry-admin SSH alias and known_hosts carry over. SSH auth flows through the ssh-agent socket the Docker VM forwards at /run/host-services/ssh-auth.sock — Colima and Docker Desktop both expose it at that path. The entrypoint strips macOS-only UseKeychain/IdentityAgent lines from the container's copy of the SSH config, so the 1Password agent works through that forwarding instead of its Mac socket path.

Two pieces of one-time Docker VM configuration are required (already applied to the local Colima profile in ~/.colima/default/colima.yaml):

  • the repo's volume must be shared into the VM — for Colima that means a mounts: entry for /Volumes/Bolt (note that listing any custom mount replaces the defaults, so ~ and /tmp/colima must be re-listed too); for Docker Desktop, add it under File Sharing
  • agent forwarding must be on — forwardAgent: true for Colima, which is what populates /run/host-services/ssh-auth.sock in the VM

The vault password is not stored on disk. ansible/.vault-password is a dual-mode helper script: when FOUNDRY_VAULT_PASSWORD is set it prints that, otherwise it reads op://Private/Foundry Ansible Vault/password through the 1Password CLI. On the Mac the op path runs directly; inside the container (which has no op) the make dev target resolves the password on the host first and passes it in through the FOUNDRY_VAULT_PASSWORD environment variable declared in compose.yml. The container entrypoint wires the helper into Ansible (ANSIBLE_VAULT_PASSWORD_FILE) only when that variable is set, so password-less sessions still run everything except vault decryption.

This compose file is purely a local development tool; the Compose files that Ansible deploys to the server live in docker/.

Run package maintenance explicitly:

cd ansible
ansible-playbook playbooks/system-updates.yml

The update playbook reports whether a reboot is required. To reboot automatically only when required:

cd ansible
ansible-playbook playbooks/system-updates.yml -e system_updates_reboot=true

Local Private Values

Committed Ansible defaults are intentionally public-safe. Host-specific human user details belong in ansible/group_vars/all/99-private.yml, which is ignored by git and loaded by Ansible when present.