Initial VPS operations handbook
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
---
|
||||
# Read-only control-plane audit. This play intentionally contains no package,
|
||||
# file, service, container, or configuration mutation tasks.
|
||||
- name: Audit managed VPS hosts without changes
|
||||
hosts: managed
|
||||
gather_facts: true
|
||||
become: false
|
||||
any_errors_fatal: false
|
||||
tasks:
|
||||
- name: Verify Docker Compose command is available
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- docker
|
||||
- compose
|
||||
- version
|
||||
changed_when: false
|
||||
|
||||
- name: Inspect configured Compose project
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- docker
|
||||
- compose
|
||||
- --project-directory
|
||||
- "{{ compose_project_dir }}"
|
||||
- ps
|
||||
- --all
|
||||
register: audit_compose_ps
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Inspect failed systemd units
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- systemctl
|
||||
- --failed
|
||||
- --no-legend
|
||||
- --no-pager
|
||||
register: audit_failed_units
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Inspect filesystem capacity
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- df
|
||||
- -P
|
||||
- -x
|
||||
- tmpfs
|
||||
- -x
|
||||
- devtmpfs
|
||||
register: audit_filesystems
|
||||
changed_when: false
|
||||
|
||||
- name: Inspect active listeners
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- ss
|
||||
- -lntup
|
||||
register: audit_listeners
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Report sanitized audit summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
host: "{{ inventory_hostname }}"
|
||||
profile: "{{ healthcheck_profile }}"
|
||||
os: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
|
||||
kernel: "{{ ansible_kernel }}"
|
||||
compose_rc: "{{ audit_compose_ps.rc }}"
|
||||
failed_units: "{{ audit_failed_units.stdout_lines | default([]) }}"
|
||||
filesystem_lines: "{{ audit_filesystems.stdout_lines | default([]) }}"
|
||||
listener_lines: "{{ audit_listeners.stdout_lines | default([]) }}"
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Baseline starts audit-only. Opt-in variables are deliberately false by default.
|
||||
- name: Apply controlled common baseline
|
||||
hosts: managed
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: baseline
|
||||
tags: [baseline, audit]
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Requires a target-local root-owned SMTP config; no credentials are passed here.
|
||||
- name: Deploy health email alert integration
|
||||
hosts: managed
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: email_alert
|
||||
tags: [healthcheck, email]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Deploy daily local health checks
|
||||
hosts: managed
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: healthcheck
|
||||
tags: [healthcheck, timers]
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Install or reconcile the single-node K3s server
|
||||
hosts: k3s_servers
|
||||
become: true
|
||||
gather_facts: true
|
||||
serial: 1
|
||||
roles:
|
||||
- role: k3s_server
|
||||
tags: [k3s, matrix, mutating]
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
# Preview only. This playbook does not install updates, restart services, or
|
||||
# change DNS/secrets. A separate, manually reviewed change is required to act.
|
||||
- name: Preview pending maintenance without changes
|
||||
hosts: managed
|
||||
become: true
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Check reboot requirement marker
|
||||
ansible.builtin.stat:
|
||||
path: /var/run/reboot-required
|
||||
register: maintenance_reboot_marker
|
||||
|
||||
- name: Preview available package updates on Debian-family hosts
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- apt-get
|
||||
- --just-print
|
||||
- upgrade
|
||||
register: maintenance_apt_preview
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: ansible_facts.os_family | default('Debian') == 'Debian'
|
||||
|
||||
- name: Report maintenance preview
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
host: "{{ inventory_hostname }}"
|
||||
reboot_required: "{{ maintenance_reboot_marker.stat.exists }}"
|
||||
package_preview: "{{ maintenance_apt_preview.stdout_lines | default([]) }}"
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Install local Matrix consistency backup jobs
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: matrix_backup
|
||||
tags: [matrix, backup, mutating]
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Reconcile Helm, cert-manager, and the Let's Encrypt issuer
|
||||
hosts: k3s_servers
|
||||
become: true
|
||||
gather_facts: false
|
||||
serial: 1
|
||||
roles:
|
||||
- role: helm_client
|
||||
tags: [helm, matrix, mutating]
|
||||
- role: cert_manager
|
||||
tags: [cert_manager, matrix, mutating]
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Run the temporary Matrix HTTP-01 certificate smoke test
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: false
|
||||
serial: 1
|
||||
roles:
|
||||
- role: matrix_certificate_smoke
|
||||
tags: [matrix, certificates, smoke_test, mutating]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Create non-secret Matrix Kubernetes foundation resources
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: matrix_cluster_base
|
||||
tags: [matrix, cluster_base, mutating]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Install Matrix K3s local health checks
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: matrix_healthcheck
|
||||
tags: [matrix, healthcheck, timers]
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Read-only gate before a K3s or Matrix change.
|
||||
- name: Validate Matrix K3s host readiness without changes
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- role: k3s_preflight
|
||||
tags: [matrix, preflight, read_only]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Validate the pre-provisioned Matrix secret contract
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: matrix_secret_contract
|
||||
tags: [matrix, secrets, validation]
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
# Deploy the official ESS OCI chart on a K3s node.
|
||||
# Pre-tasks create the non-secret values files on the target host.
|
||||
# The matrix_stack role then validates and deploys the chart.
|
||||
- name: Deploy the Matrix stack (ESS OCI chart)
|
||||
hosts: matrix
|
||||
become: true
|
||||
gather_facts: false
|
||||
serial: 1
|
||||
pre_tasks:
|
||||
- name: Ensure the ESS values directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/ess
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Write hostnames values file
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ess/hostnames.yaml
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
content: |
|
||||
serverName: {{ matrix_server_name }}
|
||||
|
||||
elementWeb:
|
||||
ingress:
|
||||
host: {{ matrix_element_host }}
|
||||
|
||||
synapse:
|
||||
ingress:
|
||||
host: {{ matrix_synapse_host }}
|
||||
|
||||
matrixAuthenticationService:
|
||||
ingress:
|
||||
host: {{ matrix_mas_host }}
|
||||
|
||||
elementAdmin:
|
||||
ingress:
|
||||
host: {{ matrix_admin_host }}
|
||||
|
||||
matrixRTC:
|
||||
ingress:
|
||||
host: {{ matrix_rtc_host }}
|
||||
|
||||
- name: Write TLS values file
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ess/tls.yaml
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
content: |
|
||||
certManager:
|
||||
clusterIssuer: letsencrypt-prod
|
||||
ingress:
|
||||
className: traefik
|
||||
tlsEnabled: true
|
||||
|
||||
- name: Write single-node tuning values file
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ess/single-node.yaml
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
content: |
|
||||
# ESS single-node resource tuning for K3s
|
||||
# Chart defaults are already single-node-friendly
|
||||
postgres:
|
||||
storage:
|
||||
size: 20Gi
|
||||
redis:
|
||||
maxMemory: 128mb
|
||||
matrixRTC:
|
||||
enabled: false
|
||||
|
||||
- name: Verify values files are in place
|
||||
ansible.builtin.stat:
|
||||
path: "/etc/ess/{{ item }}"
|
||||
loop:
|
||||
- hostnames.yaml
|
||||
- tls.yaml
|
||||
- single-node.yaml
|
||||
register: _values_check
|
||||
|
||||
- name: Assert all values files exist
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.stat.exists
|
||||
- item.stat.isreg
|
||||
- item.stat.pw_name == 'root'
|
||||
loop: "{{ _values_check.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.stat.path | default(item.item) }}"
|
||||
|
||||
roles:
|
||||
- role: matrix_stack
|
||||
tags: [matrix, stack, mutating]
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
# Intentionally targets only services with approved local dump/data sources.
|
||||
# Set restic_enabled=true only after selecting a backend and provisioning the
|
||||
# root-only repository config directly on each target.
|
||||
- name: Deploy controlled Restic timers
|
||||
hosts:
|
||||
- vaultwarden
|
||||
- powerdns
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: restic
|
||||
tags: [restic, backup]
|
||||
Reference in New Issue
Block a user