Files
ced4568 507ac4c5d3 feat(ansible): idempotent role-based host config for both production VMs
common/firewall/docker-tls/platform/lab-host/monitoring-agent/backup roles,
orchestrated by site.yml with the ordering that matters (firewall/TLS land
before the services that depend on them). Ansible Vault for secrets, no new
tool introduced for this project's modest secret surface. Explicit
dev/staging/production environment separation, no secrets committed
(.gitignore covers vault plaintext, TLS keys, Terraform state, *.env).

Validated: ansible-playbook --syntax-check clean.
2026-08-18 17:13:01 -05:00

73 lines
2.7 KiB
YAML

---
# rn-lab-host-01: Docker Engine (TLS config comes from the docker-tls role, run before this
# one), the egress proxy + monitoring agents compose stack, kernel prerequisites for nested
# k3s in privileged Lab containers, and Docker daemon storage/limits configuration.
- name: Install Docker Engine
ansible.builtin.import_tasks: "{{ role_path }}/../common/tasks/docker-engine.yml"
- name: Kernel prerequisites for nested k3s (privileged containers)
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: true
state: present
reload: true
loop:
- { name: net.ipv4.ip_forward, value: "1" }
- { name: fs.inotify.max_user_watches, value: "524288" } # k3s/kubelet watch a lot of files
- { name: fs.inotify.max_user_instances, value: "512" }
- { name: vm.max_map_count, value: "262144" } # matches upstream k3s/etcd guidance
- name: Ensure cgroup v2 controllers needed by nested k3s are available
ansible.builtin.command: cat /sys/fs/cgroup/cgroup.controllers
register: cgroup_controllers
changed_when: false
failed_when: false
- name: Warn if cgroup v2 controllers look incomplete (informational only)
ansible.builtin.debug:
msg: >-
cgroup.controllers reports: {{ cgroup_controllers.stdout | default('unreadable') }}.
Expect at least cpu, memory, pids, io for reliable nested k3s — verify manually if any
are missing (see docs/PRODUCTION_VALIDATION_CHECKLIST.md "Lab boot" section).
when: cgroup_controllers.rc == 0
- name: Create data/config directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: docker
mode: "0750"
loop:
- /opt/rootnode/lab-host
- "{{ rootnode_data_root }}/lab-work" # disposable — see docs/BACKUP_DR.md, never backed up
- name: Render production docker-compose.yml
ansible.builtin.template:
src: "{{ role_path }}/../../../docker/lab-host/docker-compose.production.yml"
dest: /opt/rootnode/lab-host/docker-compose.yml
owner: root
group: root
mode: "0640"
notify: restart rootnode-lab-host
- name: Deploy systemd unit
ansible.builtin.template:
src: rootnode-lab-host.service.j2
dest: /etc/systemd/system/rootnode-lab-host.service
mode: "0644"
notify: restart rootnode-lab-host
- name: Enable and start rootnode-lab-host
ansible.builtin.systemd:
name: rootnode-lab-host
enabled: true
state: started
daemon_reload: true
# Storage-driver/networking daemon options live in the docker-tls role's daemon.json.j2 —
# Docker only ever reads ONE /etc/docker/daemon.json, so that's the single source of truth for
# this host's whole daemon config, not just its TLS settings (see that role's template).