From 6f244e6f4f956cd8a54a2fb16189a3b6ac8c9e1a Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Thu, 15 Jan 2026 20:53:24 -0800 Subject: [PATCH] Add tailscale_serve ansible role for Layer 2 IaC - Manage tailscale serve configuration declaratively via ansible - Define services in defaults/main.yml (grafana, forge, kiwix, pypi) - Role depends on service roles to ensure correct execution order - Incremental idempotency: only apply if service missing Two-layer tailnet IaC is now complete: - Layer 1 (Pulumi): ACLs, tags, DNS - Layer 2 (Ansible): tailscale serve config Co-Authored-By: Claude Opus 4.5 --- ansible/playbooks/indri.yml | 2 ++ .../roles/tailscale_serve/defaults/main.yml | 27 +++++++++++++++++++ ansible/roles/tailscale_serve/meta/main.yml | 6 +++++ ansible/roles/tailscale_serve/tasks/main.yml | 25 +++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 ansible/roles/tailscale_serve/defaults/main.yml create mode 100644 ansible/roles/tailscale_serve/meta/main.yml create mode 100644 ansible/roles/tailscale_serve/tasks/main.yml diff --git a/ansible/playbooks/indri.yml b/ansible/playbooks/indri.yml index b6f8086..d038c89 100644 --- a/ansible/playbooks/indri.yml +++ b/ansible/playbooks/indri.yml @@ -26,3 +26,5 @@ tags: devpi_metrics - role: plex_metrics tags: plex_metrics + - role: tailscale_serve + tags: tailscale-serve diff --git a/ansible/roles/tailscale_serve/defaults/main.yml b/ansible/roles/tailscale_serve/defaults/main.yml new file mode 100644 index 0000000..8b1523d --- /dev/null +++ b/ansible/roles/tailscale_serve/defaults/main.yml @@ -0,0 +1,27 @@ +--- +# Tailscale serve configuration for this host +# Each service maps a Tailscale service name to local endpoints + +tailscale_services: + - name: svc:grafana + https: + port: 443 + upstream: http://localhost:3000 + + - name: svc:forge + https: + port: 443 + upstream: http://localhost:3001 + tcp: + port: 22 + upstream: tcp://localhost:2200 + + - name: svc:kiwix + https: + port: 443 + upstream: http://localhost:5501 + + - name: svc:pypi + https: + port: 443 + upstream: http://127.0.0.1:3141 diff --git a/ansible/roles/tailscale_serve/meta/main.yml b/ansible/roles/tailscale_serve/meta/main.yml new file mode 100644 index 0000000..904ced2 --- /dev/null +++ b/ansible/roles/tailscale_serve/meta/main.yml @@ -0,0 +1,6 @@ +--- +dependencies: + - role: grafana + - role: forgejo + - role: kiwix + - role: devpi diff --git a/ansible/roles/tailscale_serve/tasks/main.yml b/ansible/roles/tailscale_serve/tasks/main.yml new file mode 100644 index 0000000..6ed7442 --- /dev/null +++ b/ansible/roles/tailscale_serve/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: Get current tailscale serve status + ansible.builtin.command: tailscale serve status --json + register: serve_status + changed_when: false + +- name: Configure HTTPS services + ansible.builtin.command: > + tailscale serve --service="{{ item.name }}" + --https={{ item.https.port }} {{ item.https.upstream }} + loop: "{{ tailscale_services }}" + when: item.https is defined + register: https_result + changed_when: "'already serving' not in https_result.stderr | default('')" + failed_when: false + +- name: Configure TCP services + ansible.builtin.command: > + tailscale serve --service="{{ item.name }}" + --tcp={{ item.tcp.port }} {{ item.tcp.upstream }} + loop: "{{ tailscale_services }}" + when: item.tcp is defined + register: tcp_result + changed_when: "'already serving' not in tcp_result.stderr | default('')" + failed_when: false