Files
swarm-house/infra/ansible/drone-provision.yml
T
eSlider cb4664f5ee feat: add IaC layer with shared var/t1 and var/t3 data paths
Ansible provisions the k3d cluster and Flux controllers; Terraform
modules deploy the simulated fleet and ground warehouse. Compose and
k3d share var/t1 (live lake) and var/t3 (warehouse). The prototype
gains a live mode fed by the explorer read-only SQL API.
2026-07-08 20:17:32 +01:00

102 lines
3.5 KiB
YAML

# Provision a drone on the bench: identity, peer trust, WireGuard, data plane.
# Idempotent; never runs over the mission radio (bench network only).
---
- name: Provision drone data plane
hosts: drones
become: true
vars:
swarm_user: swarm
swarm_home: /opt/swarm
forced_command: "{{ swarm_home }}/bin/peer-query.sh"
tasks:
- name: Create swarm service user
ansible.builtin.user:
name: "{{ swarm_user }}"
home: "{{ swarm_home }}"
shell: /usr/sbin/nologin
system: true
# --- 1. Identity -----------------------------------------------------
- name: Generate drone ed25519 identity key
community.crypto.openssh_keypair:
path: "{{ swarm_home }}/.ssh/id_ed25519"
type: ed25519
comment: "{{ inventory_hostname }}"
owner: "{{ swarm_user }}"
mode: "0600"
register: identity
- name: Collect fleet public keys
ansible.builtin.slurp:
src: "{{ swarm_home }}/.ssh/id_ed25519.pub"
register: pubkey
# --- 2. Peer trust: forced command only ------------------------------
# Every peer may connect, but the only thing it can execute is the
# read-only SQL wrapper (docs/04). No shell, no forwarding, no pty.
- name: Authorize fleet peers with read-only forced command
ansible.posix.authorized_key:
user: "{{ swarm_user }}"
key: "{{ hostvars[item].pubkey.content | b64decode }}"
key_options: >-
command="{{ forced_command }}",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty
loop: "{{ groups['drones'] | difference([inventory_hostname]) }}"
when: hostvars[item].pubkey is defined
- name: Install peer query wrapper
ansible.builtin.copy:
dest: "{{ forced_command }}"
mode: "0755"
content: |
#!/bin/sh
# Forced command: read-only DuckDB SQL over the sealed lake.
# SSH_ORIGINAL_COMMAND carries the statement; the gate rejects
# anything that is not a single read statement.
exec {{ swarm_home }}/bin/sql-gate --read-only --data /data "$SSH_ORIGINAL_COMMAND"
# --- 3. WireGuard swarm plane ----------------------------------------
- name: Render WireGuard configuration
ansible.builtin.template:
src: templates/wg0.conf.j2
dest: /etc/wireguard/wg0.conf
mode: "0600"
notify: Restart wireguard
- name: Enable WireGuard interface
ansible.builtin.systemd:
name: wg-quick@wg0
enabled: true
state: started
# --- 4. Data plane from the fleet release manifest --------------------
- name: Read fleet release manifest
ansible.builtin.include_vars:
file: "{{ fleet_manifest }}"
name: manifest
- name: Lay down Compose bundle for release {{ manifest.release }}
ansible.builtin.unarchive:
src: "{{ playbook_dir }}/../../.tmp/{{ manifest.artifacts[0].name }}"
dest: "{{ swarm_home }}/release"
owner: "{{ swarm_user }}"
- name: Enable data plane unit
ansible.builtin.template:
src: templates/swarm-data-plane.service.j2
dest: /etc/systemd/system/swarm-data-plane.service
mode: "0644"
notify: Restart data plane
handlers:
- name: Restart wireguard
ansible.builtin.systemd:
name: wg-quick@wg0
state: restarted
- name: Restart data plane
ansible.builtin.systemd:
name: swarm-data-plane
state: restarted
daemon_reload: true