# Ansible, tailscale, proxmox automated templates

<span style="white-space: pre-wrap;">Stuff for the ansible playbook </span>

Tailscale optimizations generally, mostly for subnet routers

https://tailscale.com/kb/1320/performance-best-practices

Tailscale subnet router setup

https://tailscale.com/kb/1019/subnets

\---

\## The vault look-ups

this project helped me get a better idea on how ansible looks up variables. this diagram is how I understand this as working.

!\[\[Drawing 2024-12-11 17.47.07.excalidraw.png\]\]

<span style="white-space: pre-wrap;">basicly the way I understand this working is the vars file is used to map in variables from diffrent places including the inventory file and also the vault file. kinda brings everything together. </span>

This was the main addition that this playbook added to my knowledge of ansible. Learning to work with variables and pull information from different sources will be incredibly handy going forward. As far as I can tell this method of pulling variables works but could be turned into a oneliner and hopping over the vars file? It is possible this is wrong as Im still learning about how this all works.

\---

<span style="white-space: pre-wrap;">This is the rest of the ansible script written for this project. Beyond the use of vars files the main things I think are cool about this playbook is the use of registering facts about the packages installed using the ansible.builtin.package\_facts module to pull information about the systems targeted. I also register the outputs of certain plays to check if other plays should run. this helps when running this play against systems after they have been configured once. </span>

```YAML

\---

\- name: preliminary steps

<span style="white-space: pre-wrap;"> hosts: new\_guests</span>

<span style="white-space: pre-wrap;"> become: true</span>

<span style="white-space: pre-wrap;"> vars\_files:</span>

<span style="white-space: pre-wrap;"> - ./vars.yaml</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- ./vault.yaml

<span style="white-space: pre-wrap;"></span>

tasks:

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span>- name: Set a hostname

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.hostname:</span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span>name: "{{ inventory\_hostname }}"

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span>- name: gather facts about packages installed

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.package\_facts:</span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> manager: auto</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: install packages

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.apt:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> upgrade: full</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Check if reboot is required

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.stat:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> path: /var/run/reboot-required</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> register: reboot\_required\_file</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Reboot systems to apply kernel updates

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.reboot:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: reboot\_required\_file.stat.exists == true</span>

<span style="white-space: pre-wrap;"></span>

\- name: setup crowdsec

<span style="white-space: pre-wrap;"> hosts: new\_guests</span>

<span style="white-space: pre-wrap;"> become: true</span>

<span style="white-space: pre-wrap;"> vars\_files:</span>

<span style="white-space: pre-wrap;"> - ./vars.yaml</span>

<span style="white-space: pre-wrap;"> - ./vault.yaml</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> tasks:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Crowdsec repo's are installed via script

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: curl -s https://install.crowdsec.net | sh</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> register: my\_output # &lt;- Registers the command output.</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> changed\_when: my\_output.rc != 0 # &lt;- Uses the return code to define when the task has changed.</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'crowdsec' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Crowdsec install

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.apt:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> package:</span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> - crowdsec</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> update\_cache: true</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'crowdsec' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Crowdsec install

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.apt:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> package:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> - crowdsec-firewall-bouncer-iptables</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> update\_cache: true</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'crowdsec' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Enroll in crowdsec console

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.command: sudo cscli console enroll -n {{ inventory\_hostname }} -e context clz8lrn840007lb085o6va59z</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> register: my\_output # &lt;- Registers the command output.</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> changed\_when: my\_output.rc != 0 # &lt;- Uses the return code to define when the task has changed.</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'crowdsec' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Add linux collection

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.command: sudo cscli collections install crowdsecurity/linux</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> register: my\_output</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> changed\_when: my\_output.rc != 0</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'crowdsec' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: Restart crowdsec post enrollment to get stuff working

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.service:</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> name: crowdsec</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> state: restarted</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'crowdsec' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

\- name: install and enroll tailscale on hosts

<span style="white-space: pre-wrap;"> hosts: new\_guests</span>

<span style="white-space: pre-wrap;"> become: true</span>

<span style="white-space: pre-wrap;"> vars\_files:</span>

<span style="white-space: pre-wrap;"> - ./vars.yaml</span>

<span style="white-space: pre-wrap;"> - ./vault.yaml</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> tasks:</span>

<span style="white-space: pre-wrap;"> </span>- name: install and enroll host in tailscale

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: curl -fsSL https://tailscale.com/install.sh | sh &amp;&amp; sudo tailscale up --auth-key="{{ tailscale\_auth\_key }}"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> when: "'tailscale' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: setup subnet routers pt 1

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: echo 'net.ipv4.ip\_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> # when: "'tailscale' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: setup subnet routers pt 2

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> # when: "'tailscale' is not in ansible\_facts.packages"</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: setup subnet routers pt 3

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: sudo sysctl -p /etc/sysctl.d/99-tailscale.conf</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>\# when: "'tailscale' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: subnet router optimizations

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: printf '#!/bin/sh\\n\\nethtool -K %s rx-udp-gro-forwarding on rx-gro-list off \\n' "$(ip -o route get 1.1.1.1 | cut -f 5 -d " ")" | sudo tee /etc/networkd-dispatcher/routable.d/50-tailscale &amp;&amp; sudo chmod 755 /etc/networkd-dispatcher/routable.d/50-tailscale</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span>- name: advertise routes for systems

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> </span><span style="white-space: pre-wrap;"> ansible.builtin.shell: tailscale up --advertise-routes "{{ subnets }}"</span>

```

\---

This is the vars file included with this project. the commented out lines are from earlier iterations of this project that are helpful to understand how things are looked up using variables

```YAML

\# ansible\_password: "{{ server\_passwords.admin }}"

\# ansible\_become\_password: "{{ server\_passwords.admin }}"

tailscale\_auth\_key: "{{ individual\_sys\[server\_id\].key}}"

\# new\_borg\_password: "{{ individual\_sys\[server\_id\].borg\_pass }}"

```

\---

This is the vault file that I created and is useful for understanding how auth-keys are looked up while stored in this secure format. It is sanitized and the keys used are only useful once anyway

```YAML

individual\_sys:

<span style="white-space: pre-wrap;"> ts-node1:</span>

<span style="white-space: pre-wrap;"> key: tskey-auth-kfjkdeadfkeeCNTRL-ueoiruyaoieuryaiosudfyoaisudyfudh</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> ts-node2:</span>

<span style="white-space: pre-wrap;"> key: tskey-auth-kfjkdeadfkeeCNTRL-ueoiruyaoieuryaiosudfyoaisudyfudh</span>

<span style="white-space: pre-wrap;"> ts-node3:</span>

<span style="white-space: pre-wrap;"> key: tskey-auth-kfjkdeadfkeeCNTRL-ueoiruyaoieuryaiosudfyoaisudyfudh</span>

```

\---

This is the inventory used for this project, Useful for understanding vars and the workflow with this script

```YAML

\### uspace stuff

\## Once configured, hosts from new\_guests get moved to guests

\## you should be able to switch hosts from ip addresses to mdns names

\## Systems configured like this could also be swapped over to mainline inventorys

\##

new\_guests:

<span style="white-space: pre-wrap;"> hosts:</span>

<span style="white-space: pre-wrap;"> tailscale-node3:</span>

<span style="white-space: pre-wrap;"> # ansible\_host: tailscale-node1.local</span>

<span style="white-space: pre-wrap;"> ansible\_host: 10.0.0.13</span>

<span style="white-space: pre-wrap;"> server\_id: ts-node6</span>

<span style="white-space: pre-wrap;"> subnets: 192.168.4.0/24</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> vars:</span>

<span style="white-space: pre-wrap;"> #ansible\_user: administrator</span>

<span style="white-space: pre-wrap;"> ansible\_user: borg</span>

<span style="white-space: pre-wrap;"></span>

guests:

<span style="white-space: pre-wrap;"> hosts:</span>

<span style="white-space: pre-wrap;"> tailscale-node1:</span>

<span style="white-space: pre-wrap;"> ansible\_host: tailscale-node1.local</span>

<span style="white-space: pre-wrap;"> # ansible\_host: 10.0.0.11</span>

<span style="white-space: pre-wrap;"> server\_id: ts-node1</span>

<span style="white-space: pre-wrap;"> subnets: 192.168.0.0/24</span>

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"> tailscale-node2:</span>

<span style="white-space: pre-wrap;"> ansible\_host: tailscale-node2.local</span>

<span style="white-space: pre-wrap;"> # ansible\_host: 10.0.0.12</span>

<span style="white-space: pre-wrap;"> server\_id: ts-node2</span>

<span style="white-space: pre-wrap;"> subnets: 192.168.0.0/24</span>

<span style="white-space: pre-wrap;"> vars:</span>

<span style="white-space: pre-wrap;"> ansible\_user: borg</span>

```

<span style="white-space: pre-wrap;">--- </span>

<span style="white-space: pre-wrap;">I did do a bit of work for a previous version of this project before i figured out custom cloud init files. below are those files. at this time I was creating a borg user, setting a borg user password, and targeting an admin account that required a password for running sudo commands. I was also passing in the whole enrollment command instead of just an auth-key which is much more cumbersome. ultimately this ended up being unnecessary. </span>

vars:

```yaml

ansible\_password: "{{ server\_passwords.admin }}"

ansible\_become\_password: "{{ server\_passwords.admin }}"

tailscale\_auth\_command: "{{ individual\_sys\[server\_id\].command}}"

new\_borg\_password: "{{ individual\_sys\[server\_id\].borg\_pass }}"

```

vault:

```YAML

server\_passwords:

admin: password123456!@#$

<span style="white-space: pre-wrap;"></span>

individual\_sys:

tsn1:

command: curl -fsSL https://tailscale.com/install.sh | sh &amp;&amp; sudo tailscale up --auth-key=tskey-auth-k8iqCx4jQV11CNTRL-xW3gNm6FuKf7ra49zQ32SfTKRJnVCGbC

borg\_pass: ez8aaBkNxRyKGeR9zhdxLRQGoJfoMEEiRuptxamr

<span style="white-space: pre-wrap;"></span>

tsn2:

command: curl -fsSL https://tailscale.com/install.sh | sh &amp;&amp; sudo tailscale up --auth-key=tskey-auth-kBxMEyjHu111CNTRL-3JzrF8UmkRacSdd4yHbuKav7udHYBkeua

borg\_pass: aoQCCYphdFvBhzxxnVQW4C6XfrtDtePKUeAhUxj9

```

<span style="white-space: pre-wrap;">here's the playbook I wrote for this its basically the same as one I ultimately used with a few slight tweaks. It also includes the steps to bootstrap a borg user. </span>

```YAML

\---

\- name: setup apt-cache proxy

hosts: new\_guests

become: true

vars\_files:

\- ./vars.yaml

\- ./vault.yaml

<span style="white-space: pre-wrap;"></span>

tasks:

<span style="white-space: pre-wrap;"></span>

\- name: remove apt-cache proxy info

ansible.builtin.file:

path: /etc/apt/apt.conf.d/00proxy

state: absent

register: proxy

<span style="white-space: pre-wrap;"></span>

\- name: reboot all hosts to apply changes

ansible.builtin.reboot:

when: proxy.changed

<span style="white-space: pre-wrap;"></span>

\- name: setup mdns and install general use packages

hosts: new\_guests

become: true

vars\_files:

\- ./vars.yaml

\- ./vault.yaml

<span style="white-space: pre-wrap;"></span>

tasks:

\- name: gather facts about packages installed

ansible.builtin.package\_facts:

manager: auto

\- name: install packages

ansible.builtin.apt:

pkg:

\- libnss-mdns

\- qemu-guest-agent

update\_cache: true

when: "'libnss-mdns' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: apply hardening

hosts: new\_guests

become: true

vars\_files:

\- ./vars.yaml

\- ./vault.yaml

<span style="white-space: pre-wrap;"></span>

tasks:

<span style="white-space: pre-wrap;"></span>

\- name: Crowdsec repo's are installed via script

ansible.builtin.shell: curl -s https://install.crowdsec.net | sh

register: my\_output # &lt;- Registers the command output.

changed\_when: my\_output.rc != 0 # &lt;- Uses the return code to define when the task has changed.

when: "'crowdsec' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: Crowdsec install

ansible.builtin.apt:

package:

\- crowdsec

update\_cache: true

when: "'crowdsec' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: Crowdsec install

ansible.builtin.apt:

package:

\- crowdsec-firewall-bouncer-iptables

update\_cache: true

when: "'crowdsec' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

<span style="white-space: pre-wrap;"></span>

\- name: Enroll in crowdsec console

ansible.builtin.command: sudo cscli console enroll -n {{ inventory\_hostname }} -e context clz8lrn840007lb085o6va59z

register: my\_output # &lt;- Registers the command output.

changed\_when: my\_output.rc != 0 # &lt;- Uses the return code to define when the task has changed.

when: "'crowdsec' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: Add linux collection

ansible.builtin.command: sudo cscli collections install crowdsecurity/linux

register: my\_output

changed\_when: my\_output.rc != 0

when: "'crowdsec' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: Restart crowdsec post enrollment to get stuff working

ansible.builtin.service:

name: crowdsec

state: restarted

when: "'crowdsec' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: Create borg user

hosts: new\_guests

become: true

vars\_files:

\- ./vars.yaml

\- ./vault.yaml

<span style="white-space: pre-wrap;"></span>

tasks:

\- name: Check if users exist

ansible.builtin.user:

name: borg

check\_mode: true

register: test\_users

<span style="white-space: pre-wrap;"></span>

\- name: Set user password from vault based on host index for new user borg

ansible.builtin.user:

name: borg

shell: /bin/bash

groups: sudo

password: "{{ new\_borg\_password }}"

append: true

create\_home: yes

no\_log: true

when: "test\_users is false"

<span style="white-space: pre-wrap;"></span>

\- name: Add borg user to sudoers with no password

ansible.builtin.copy:

src: /home/borg/tailscale-project/borgaddin

dest: /etc/sudoers.d/

owner: root

group: root

mode: "0600"

when: "test\_users is false"

<span style="white-space: pre-wrap;"></span>

\- name: Turn off cloud init

ansible.builtin.file:

path: /etc/cloud/cloud-init.disabled

mode: "0600"

state: touch

<span style="white-space: pre-wrap;"></span>

\- name: Restart cloud-init

ansible.builtin.service:

name: cloud-init

state: restarted

<span style="white-space: pre-wrap;"></span>

\- name: Upload SSH key

ansible.posix.authorized\_key:

user: borg

key: "{{ lookup('file', '/home/borg/.ssh/id\_rsa.pub') }}"

state: present

when: "test\_users is false"

<span style="white-space: pre-wrap;"></span>

\- name: install and enroll tailscale on hosts

hosts: new\_guests

become: true

vars\_files:

\- ./vars.yaml

\- ./vault.yaml

<span style="white-space: pre-wrap;"></span>

tasks:

\- name: install and enroll host in tailscale

ansible.builtin.shell: "{{ tailscale\_auth\_command }}"

when: "'tailscale' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: setup subnet routers pt 1

ansible.builtin.shell: echo 'net.ipv4.ip\_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf

\# when: "'tailscale' is not in ansible\_facts.packages"

\- name: setup subnet routers pt 2

ansible.builtin.shell: echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf

\# when: "'tailscale' is not in ansible\_facts.packages"

\- name: setup subnet routers pt 3

ansible.builtin.shell: sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

\# when: "'tailscale' is not in ansible\_facts.packages"

\- name: advertise routes for systems

ansible.builtin.shell: tailscale up --advertise-routes "{{ subnets }}"

```

I also wrote a few scripts to test things...

```YAML

\### This playbook is just a tester to see how the when flag(?)

\### it also checks out the package\_facts module

\### This playbook is useful for figuring out

<span style="white-space: pre-wrap;"></span>

\- name: check if packages exist, skip or run

hosts: new\_guests

become: true

gather\_facts: false

<span style="white-space: pre-wrap;"></span>

tasks:

\- name: gather facts about packages installed

ansible.builtin.package\_facts:

manager: auto

\- name: run arbitrary command if a specific package is installed

ansible.builtin.debug:

msg: this is a test1

when: "'libnss-mdns' is in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: run an arbitrary command if a package is not installed

ansible.builtin.debug:

msg: this is another more diffrent test

when: "'nmap' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: run arbitrary command if a specific package is installed

ansible.builtin.debug:

msg: this is a test2

when: "'libnss-mdns' is not in ansible\_facts.packages"

<span style="white-space: pre-wrap;"></span>

\- name: run an arbitrary command if a package is not installed

ansible.builtin.debug:

msg: this is another more diffrent test2

when: "'nmap' is in ansible\_facts.packages"

```

```YAML

\---

\### This script sets a hostname on systems targeted

\### matches hostnames to the inventory hostname because why not

\- name: set hostname for hosts

hosts: targeted systems

become: true

tasks:

\- name: Set a hostname

ansible.builtin.hostname:

name: "{{ inventory\_hostname }}"

```