mirror of
https://github.com/fscotto/infra.git
synced 2026-09-27 11:02:47 +00:00
Configure Aegis host DNS and NFS support
This commit is contained in:
14
AGENTS.md
14
AGENTS.md
@@ -48,6 +48,8 @@ Ansible-driven personal infrastructure repo for Fedora and Void desktops, Fedora
|
|||||||
- Rocky server after activation: `ansible-playbook ansible/site.yml --limit <host> --check --diff`
|
- Rocky server after activation: `ansible-playbook ansible/site.yml --limit <host> --check --diff`
|
||||||
- Atlas NAS: `ansible-playbook ansible/site.yml --limit atlas --check --diff`
|
- Atlas NAS: `ansible-playbook ansible/site.yml --limit atlas --check --diff`
|
||||||
- Aegis IoT: `ansible-playbook ansible/site.yml --limit aegis --check --diff`
|
- Aegis IoT: `ansible-playbook ansible/site.yml --limit aegis --check --diff`
|
||||||
|
- Aegis NFS client layer: `ansible-playbook ansible/site.yml --limit aegis --tags nfs --list-tasks`
|
||||||
|
- Aegis host DNS: `ansible-playbook ansible/site.yml --limit aegis --tags dns --check --diff`
|
||||||
- Focused checks:
|
- Focused checks:
|
||||||
- Emacs is disabled by default; temporary Emacs check: `ansible-playbook ansible/site.yml --limit <host> --tags emacs --check --diff -e emacs_enabled=true`
|
- Emacs is disabled by default; temporary Emacs check: `ansible-playbook ansible/site.yml --limit <host> --tags emacs --check --diff -e emacs_enabled=true`
|
||||||
- AI coding agents: `ansible-playbook ansible/site.yml --limit <host> --tags ai_agents --check --diff`
|
- AI coding agents: `ansible-playbook ansible/site.yml --limit <host> --tags ai_agents --check --diff`
|
||||||
@@ -221,14 +223,18 @@ The dotfile vars follow the same split: `desktop_common_dotfiles` carries mode-i
|
|||||||
- `aegis` is a remote Fedora IoT Raspberry Pi 4 node. Bootstrap it once with
|
- `aegis` is a remote Fedora IoT Raspberry Pi 4 node. Bootstrap it once with
|
||||||
`ansible/bootstrap/aegis.bu`; the remaining configuration is applied by `profile_aegis` over SSH.
|
`ansible/bootstrap/aegis.bu`; the remaining configuration is applied by `profile_aegis` over SSH.
|
||||||
- Fedora IoT is immutable. Do not add it to mutable Fedora package or shared dotfile roles.
|
- Fedora IoT is immutable. Do not add it to mutable Fedora package or shared dotfile roles.
|
||||||
- `profile_aegis` owns rootful Podman Quadlets, persistent container state under `/var/lib`, the
|
- `profile_aegis` owns the `nfs-utils` rpm-ostree layer used as the Atlas NFS client and reports the
|
||||||
Podman auto-update timer, LAN-restricted firewalld rules, and SSH hardening. Keep
|
required reboot without initiating it. It also owns rootful Podman Quadlets, persistent container
|
||||||
`aegis_lan_subnet` and `aegis_adguard_web_port` host-specific; SSH permits only the declared
|
state under `/var/lib`, the Podman auto-update timer, LAN-restricted firewalld rules, and SSH hardening. Keep
|
||||||
|
`aegis_lan_subnet`, `aegis_adguard_web_port`, and `aegis_network_connection_uuid` host-specific;
|
||||||
|
SSH permits only the declared
|
||||||
key-authenticated users, never root or password authentication. Keep Apple IDs and other
|
key-authenticated users, never root or password authentication. Keep Apple IDs and other
|
||||||
credentials in Vault and use `no_log` for their rendering.
|
credentials in Vault and use `no_log` for their rendering.
|
||||||
- `aegis_adguard_web_port` defaults to `80`. The initial AdGuard Home wizard port `3000` is intentionally unmanaged: open and close it manually only while
|
- `aegis_adguard_web_port` defaults to `80`. The initial AdGuard Home wizard port `3000` is intentionally unmanaged: open and close it manually only while
|
||||||
completing initial setup. Disable the local systemd-resolved stub through `profile_aegis` before
|
completing initial setup. Disable the local systemd-resolved stub through `profile_aegis` before
|
||||||
AdGuard binds port 53; keep
|
AdGuard binds port 53; keep
|
||||||
`/etc/resolv.conf` linked to `/run/systemd/resolve/resolv.conf` so Aegis retains router-provided DNS.
|
`/etc/resolv.conf` linked to `/run/systemd/resolve/resolv.conf`. LAN clients may use AdGuard, but
|
||||||
|
Aegis must use the independent upstream DNS declared by `aegis_host_dns_servers` so Greenboot does
|
||||||
|
not depend on the AdGuard container during startup.
|
||||||
- iCloudPD requires post-deployment interactive MFA initialization; its cookie/configuration state is
|
- iCloudPD requires post-deployment interactive MFA initialization; its cookie/configuration state is
|
||||||
persisted in `/var/lib/icloudpd/config`.
|
persisted in `/var/lib/icloudpd/config`.
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -193,12 +193,17 @@ ansible/bootstrap/generate-aegis-ign.sh --write IMAGE DEVICE
|
|||||||
The controller manages it remotely as `pi@aegis`; unlike local desktop profiles, Aegis is
|
The controller manages it remotely as `pi@aegis`; unlike local desktop profiles, Aegis is
|
||||||
intentionally an SSH inventory target. `profile_aegis` manages rootful Podman Quadlets for AdGuard
|
intentionally an SSH inventory target. `profile_aegis` manages rootful Podman Quadlets for AdGuard
|
||||||
Home and iCloudPD, persistent data under `/var/lib`, the Podman auto-update timer, LAN-restricted
|
Home and iCloudPD, persistent data under `/var/lib`, the Podman auto-update timer, LAN-restricted
|
||||||
firewalld rules, SSH key-only access for `pi`, and `wake-ikaros`. Set the host-local
|
firewalld rules, SSH key-only access for `pi`, the `nfs-utils` rpm-ostree layer required by the
|
||||||
`aegis_lan_subnet` and `aegis_adguard_web_port` values before applying it. The playbook permits
|
Atlas NFS client, and `wake-ikaros`. A new layered package deployment requires a manual reboot; the
|
||||||
|
role reports this condition but never reboots Aegis automatically. Set the host-local
|
||||||
|
`aegis_lan_subnet`, `aegis_adguard_web_port`, and `aegis_network_connection_uuid` values before
|
||||||
|
applying it. The playbook permits
|
||||||
AdGuard Home HTTP on port `80`; the initial wizard port `3000` is intentionally unmanaged and must be
|
AdGuard Home HTTP on port `80`; the initial wizard port `3000` is intentionally unmanaged and must be
|
||||||
opened and closed manually during initial setup. The profile disables the local systemd-resolved DNS
|
opened and closed manually during initial setup. The profile disables the local systemd-resolved DNS
|
||||||
stub and points `/etc/resolv.conf` to its full resolver data, freeing port 53
|
stub and points `/etc/resolv.conf` to its full resolver data, freeing port 53 for AdGuard. LAN clients
|
||||||
for AdGuard while retaining DNS learned from the router. Define
|
may use AdGuard on Aegis, while Aegis itself uses the independent upstream DNS declared by
|
||||||
|
`aegis_host_dns_servers`; this prevents Greenboot from depending on the AdGuard container during
|
||||||
|
startup. Reboot Aegis after changing its NetworkManager DNS profile. Define
|
||||||
`vault_aegis_icloudpd_apple_id` in Vault before applying it. iCloudPD still requires interactive MFA
|
`vault_aegis_icloudpd_apple_id` in Vault before applying it. iCloudPD still requires interactive MFA
|
||||||
initialization after its first deployment.
|
initialization after its first deployment.
|
||||||
|
|
||||||
@@ -213,6 +218,21 @@ ANSIBLE_LOCAL_TEMP=/tmp/ansible-local \
|
|||||||
ansible-playbook ansible/site.yml --limit aegis --check --diff --ask-become-pass
|
ansible-playbook ansible/site.yml --limit aegis --check --diff --ask-become-pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Apply only the independent host DNS configuration, then reboot Aegis manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ANSIBLE_LOCAL_TEMP=/tmp/ansible-local \
|
||||||
|
ansible-playbook ansible/site.yml --limit aegis --tags dns --ask-become-pass
|
||||||
|
```
|
||||||
|
|
||||||
|
Layer the Atlas NFS client package independently, then reboot Aegis manually when the role reports
|
||||||
|
that the new deployment is ready:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ANSIBLE_LOCAL_TEMP=/tmp/ansible-local \
|
||||||
|
ansible-playbook ansible/site.yml --limit aegis --tags nfs --ask-become-pass
|
||||||
|
```
|
||||||
|
|
||||||
## NAS
|
## NAS
|
||||||
|
|
||||||
`atlas` is a Rocky Linux 9 NAS reached through SSH. Normally its pool already exists and the profile
|
`atlas` is a Rocky Linux 9 NAS reached through SSH. Normally its pool already exists and the profile
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ ansible_ssh_use_tty: false
|
|||||||
|
|
||||||
aegis_lan_subnet: 192.168.178.0/24
|
aegis_lan_subnet: 192.168.178.0/24
|
||||||
aegis_adguard_web_port: 80
|
aegis_adguard_web_port: 80
|
||||||
|
aegis_network_connection_name: FRITZ!Box 7530 NR
|
||||||
|
aegis_network_connection_uuid: a52fda3d-3eb6-351f-bf04-753edcb76944
|
||||||
|
aegis_host_dns_servers:
|
||||||
|
- 192.168.178.1
|
||||||
|
aegis_host_dns_search_domains:
|
||||||
|
- fritz.box
|
||||||
aegis_ssh_authorized_keys:
|
aegis_ssh_authorized_keys:
|
||||||
- name: ikaros
|
- name: ikaros
|
||||||
key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrIxXjA3ffPwziKGR5gzc4gAoBehQPlnEMcXF4Wl0ZS ikaros"
|
key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrIxXjA3ffPwziKGR5gzc4gAoBehQPlnEMcXF4Wl0ZS ikaros"
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
---
|
---
|
||||||
aegis_hostname: aegis
|
aegis_hostname: aegis
|
||||||
|
aegis_layered_packages:
|
||||||
|
- nfs-utils
|
||||||
|
aegis_network_connection_name: ""
|
||||||
|
aegis_network_connection_uuid: ""
|
||||||
|
aegis_host_dns_servers: []
|
||||||
|
aegis_host_dns_search_domains: []
|
||||||
aegis_adguard_image: docker.io/adguard/adguardhome:latest
|
aegis_adguard_image: docker.io/adguard/adguardhome:latest
|
||||||
aegis_icloudpd_image: docker.io/boredazfcuk/icloudpd:latest
|
aegis_icloudpd_image: docker.io/boredazfcuk/icloudpd:latest
|
||||||
aegis_icloudpd_folder_structure: '{:%Y/%m/%d}'
|
aegis_icloudpd_folder_structure: '{:%Y/%m/%d}'
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
- name: Manage Aegis layered packages
|
||||||
|
tags: [aegis, packages, nfs]
|
||||||
|
community.general.rpm_ostree_pkg:
|
||||||
|
name: "{{ aegis_layered_packages }}"
|
||||||
|
state: present
|
||||||
|
register: aegis_layered_packages_result
|
||||||
|
when: aegis_layered_packages | length > 0
|
||||||
|
|
||||||
|
- name: Report reboot required for Aegis layered packages
|
||||||
|
tags: [aegis, packages, nfs]
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: Reboot Aegis to activate the newly layered packages, then rerun the playbook.
|
||||||
|
when: aegis_layered_packages_result.needs_reboot | default(false)
|
||||||
|
|
||||||
- name: Require Aegis iCloudPD Apple ID
|
- name: Require Aegis iCloudPD Apple ID
|
||||||
tags: [aegis, icloudpd]
|
tags: [aegis, icloudpd]
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
@@ -8,15 +22,86 @@
|
|||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
- name: Require completed Aegis network placeholders
|
- name: Require completed Aegis network placeholders
|
||||||
tags: [aegis, firewall, services]
|
tags: [aegis, dns, firewall, network, services]
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- aegis_lan_subnet != 'CHANGEME_LAN_SUBNET'
|
- aegis_lan_subnet != 'CHANGEME_LAN_SUBNET'
|
||||||
- aegis_firewalld_zone | length > 0
|
- aegis_firewalld_zone | length > 0
|
||||||
- aegis_adguard_web_port | int > 0
|
- aegis_adguard_web_port | int > 0
|
||||||
- aegis_adguard_web_port | int < 65536
|
- aegis_adguard_web_port | int < 65536
|
||||||
|
- aegis_network_connection_name | length > 0
|
||||||
|
- aegis_network_connection_uuid | length > 0
|
||||||
|
- aegis_host_dns_servers | length > 0
|
||||||
|
- ansible_facts["default_ipv4"]["address"] not in aegis_host_dns_servers
|
||||||
- aegis_ssh_allowed_users | length > 0
|
- aegis_ssh_allowed_users | length > 0
|
||||||
fail_msg: Define the Aegis LAN subnet, firewalld zone, AdGuard web port, and SSH users.
|
fail_msg: >-
|
||||||
|
Define the Aegis LAN subnet, firewalld zone, AdGuard web port, independent host DNS,
|
||||||
|
NetworkManager connection, and SSH users. Aegis must not use its own address as upstream DNS.
|
||||||
|
|
||||||
|
- name: Verify the declared Aegis NetworkManager connection exists
|
||||||
|
tags: [aegis, dns, network, services]
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- nmcli
|
||||||
|
- --get-values
|
||||||
|
- connection.id
|
||||||
|
- connection
|
||||||
|
- show
|
||||||
|
- uuid
|
||||||
|
- "{{ aegis_network_connection_uuid }}"
|
||||||
|
register: aegis_network_connection
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >-
|
||||||
|
aegis_network_connection.rc != 0
|
||||||
|
or aegis_network_connection.stdout != aegis_network_connection_name
|
||||||
|
|
||||||
|
- name: Read the current Aegis host DNS configuration
|
||||||
|
tags: [aegis, dns, network, services]
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- nmcli
|
||||||
|
- --get-values
|
||||||
|
- ipv4.ignore-auto-dns,ipv4.dns,ipv4.dns-search,ipv6.ignore-auto-dns
|
||||||
|
- connection
|
||||||
|
- show
|
||||||
|
- uuid
|
||||||
|
- "{{ aegis_network_connection_uuid }}"
|
||||||
|
register: aegis_host_dns_current
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Configure independent upstream DNS for the Aegis host
|
||||||
|
tags: [aegis, dns, network, services]
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- nmcli
|
||||||
|
- connection
|
||||||
|
- modify
|
||||||
|
- uuid
|
||||||
|
- "{{ aegis_network_connection_uuid }}"
|
||||||
|
- ipv4.ignore-auto-dns
|
||||||
|
- "yes"
|
||||||
|
- ipv4.dns
|
||||||
|
- "{{ aegis_host_dns_servers | join(',') }}"
|
||||||
|
- ipv4.dns-search
|
||||||
|
- "{{ aegis_host_dns_search_domains | join(',') }}"
|
||||||
|
- ipv6.ignore-auto-dns
|
||||||
|
- "yes"
|
||||||
|
register: aegis_host_dns_profile
|
||||||
|
when: >-
|
||||||
|
aegis_host_dns_current.stdout_lines !=
|
||||||
|
[
|
||||||
|
'yes',
|
||||||
|
aegis_host_dns_servers | join(','),
|
||||||
|
aegis_host_dns_search_domains | join(','),
|
||||||
|
'yes'
|
||||||
|
]
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Report Aegis reboot required for host DNS changes
|
||||||
|
tags: [aegis, dns, network, services]
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: Reboot Aegis to activate its independent upstream DNS before testing another OS update.
|
||||||
|
when: aegis_host_dns_profile.changed | default(false)
|
||||||
|
|
||||||
- name: Set Aegis hostname
|
- name: Set Aegis hostname
|
||||||
tags: [aegis, services]
|
tags: [aegis, services]
|
||||||
|
|||||||
Reference in New Issue
Block a user