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.
102 lines
3.5 KiB
YAML
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
|