Archived
Initial infrastructure mono-repo scaffold
Consolidates nixos, docker, raspi, and debian-configuration into a single infrastructure-as-code repo. Includes: - ansible/: full inventory + proxmox-hardening, freeipa, and raspberrypi roles (converted from debian-configuration bash scripts) - terraform/: Proxmox VMs, Dynu DNS, Pi-hole (decommissioned stub), Docker container catalog — migrated from docker/infrastructure/terraform/ - stacks/docker/, stacks/raspi/, nixos/: placeholder READMEs pending git subtree population (see implementation plan) - docs/: internal MkDocs site with architecture, network topology, runbooks, and drift-detection guide; external sanitized site - scripts/: drift-detect.sh, docs-build.sh, install-hooks.sh, check-secrets.sh - CI: secret-scan (push/PR), drift-detect (daily), docs-build (on change) - Pi-hole removed throughout — DNS is FreeIPA, DHCP is router See docs/internal/implementation-plan.md for the phased rollout after pushing to Gitea. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UvNjoxTWEDkhXsd1Dq2ETP
This commit is contained in:
commit
f85c65870f
125 files changed
+8186
No files matched your search
@@ -0,0 +1,14 @@
|
||||
---
|
||||
# freeipa role defaults — all overridable in inventory host_vars or group_vars.
|
||||
# Most values come from the per-host inventory (see hosts.yml).
|
||||
|
||||
ipa_realm: "SWEET.HOME"
|
||||
ipa_domain: "sweet.home"
|
||||
|
||||
# Set these per-host in inventory/hosts.yml:
|
||||
# ipa_hostname: "domain-controller.sweet.home"
|
||||
# ipa_ip: "192.168.2.253"
|
||||
# ipa_dns_forwarder: "192.168.2.138"
|
||||
|
||||
# Swap file created if no swap exists (FreeIPA needs headroom during install)
|
||||
ipa_swap_size_mb: 2048
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
# freeipa/tasks/main.yml
|
||||
# Provisions a FreeIPA 4.x server on Rocky Linux 9.
|
||||
# The ipa-server-install step is intentionally NOT idempotent — it will
|
||||
# refuse to run if IPA is already installed, which acts as a safety guard.
|
||||
|
||||
# ── Pre-flight ────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check IPA is not already installed
|
||||
ansible.builtin.stat:
|
||||
path: /etc/ipa/default.conf
|
||||
register: ipa_installed
|
||||
tags: always
|
||||
|
||||
- name: Skip install tasks if IPA already exists
|
||||
ansible.builtin.debug:
|
||||
msg: "FreeIPA already installed — skipping install tasks. Use verify tasks to check health."
|
||||
when: ipa_installed.stat.exists
|
||||
tags: install
|
||||
|
||||
- name: Assert hostname is correct FQDN
|
||||
ansible.builtin.command:
|
||||
cmd: hostname -f
|
||||
register: fqdn_check
|
||||
changed_when: false
|
||||
failed_when: fqdn_check.stdout != ipa_hostname
|
||||
when:
|
||||
- not ipa_installed.stat.exists
|
||||
- ipa_hostname is defined
|
||||
tags: install, preflight
|
||||
|
||||
- name: Assert /etc/hosts has correct entry
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/hosts
|
||||
line: "{{ ipa_ip }} {{ ipa_hostname }} {{ ipa_hostname.split('.')[0] }}"
|
||||
state: present
|
||||
when:
|
||||
- not ipa_installed.stat.exists
|
||||
- ipa_ip is defined
|
||||
- ipa_hostname is defined
|
||||
tags: install, preflight
|
||||
|
||||
# ── Swap ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check current swap
|
||||
ansible.builtin.command:
|
||||
cmd: swapon --show
|
||||
register: swap_check
|
||||
changed_when: false
|
||||
tags: install, swap
|
||||
|
||||
- name: Create swap file if absent
|
||||
block:
|
||||
- name: Create swap file
|
||||
ansible.builtin.command:
|
||||
cmd: "dd if=/dev/zero of=/swapfile bs=1M count={{ ipa_swap_size_mb }} status=none"
|
||||
args:
|
||||
creates: /swapfile
|
||||
|
||||
- name: Set swap permissions
|
||||
ansible.builtin.file:
|
||||
path: /swapfile
|
||||
mode: "0600"
|
||||
|
||||
- name: Format swap
|
||||
ansible.builtin.command:
|
||||
cmd: mkswap /swapfile
|
||||
changed_when: true
|
||||
|
||||
- name: Enable swap
|
||||
ansible.builtin.command:
|
||||
cmd: swapon /swapfile
|
||||
changed_when: true
|
||||
|
||||
- name: Add swap to fstab
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
line: "/swapfile none swap defaults 0 0"
|
||||
state: present
|
||||
when:
|
||||
- not ipa_installed.stat.exists
|
||||
- swap_check.stdout == ""
|
||||
tags: install, swap
|
||||
|
||||
# ── Package install ───────────────────────────────────────────────────────────
|
||||
|
||||
- name: Install FreeIPA server packages
|
||||
ansible.builtin.dnf:
|
||||
name:
|
||||
- freeipa-server
|
||||
- freeipa-server-dns
|
||||
state: present
|
||||
when: not ipa_installed.stat.exists
|
||||
tags: install, packages
|
||||
|
||||
# ── IPA server install ────────────────────────────────────────────────────────
|
||||
|
||||
- name: Run ipa-server-install (interactive passwords via env vars)
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
ipa-server-install
|
||||
--realm={{ ipa_realm }}
|
||||
--domain={{ ipa_domain }}
|
||||
--hostname={{ ipa_hostname }}
|
||||
--ip-address={{ ipa_ip }}
|
||||
--forwarder={{ ipa_dns_forwarder }}
|
||||
--setup-dns
|
||||
--auto-reverse
|
||||
--no-host-dns
|
||||
--mkhomedir
|
||||
--unattended
|
||||
--ds-password="${IPA_DM_PASSWORD}"
|
||||
--admin-password="${IPA_ADMIN_PASSWORD}"
|
||||
environment:
|
||||
IPA_DM_PASSWORD: "{{ ipa_dm_password }}"
|
||||
IPA_ADMIN_PASSWORD: "{{ ipa_admin_password }}"
|
||||
no_log: true
|
||||
when: not ipa_installed.stat.exists
|
||||
tags: install
|
||||
|
||||
# ── Verification ──────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Verify IPA services are running
|
||||
ansible.builtin.command:
|
||||
cmd: ipactl status
|
||||
register: ipa_status
|
||||
changed_when: false
|
||||
tags: verify
|
||||
|
||||
- name: Print IPA service status
|
||||
ansible.builtin.debug:
|
||||
var: ipa_status.stdout_lines
|
||||
tags: verify
|
||||
Reference in new issue
Block a user