--- format: markdown title: Ansible ff@home aufsetzen toc: yes ... # Software - Debian 12 (bookworm) oder Ubuntu 22.04 - python3 und ansible ***** Es empfiehlt sich, eine python virtuelle Umgebung zu verwenden ***** Die folgenden Pakete mit Root-Rechten installieren, sofern noch nicht geschehen: sudo apt install python3-pip python3-venv Die weiteren Befehle alle als normaler User ausführen. Im Basisverzeichnis (bei mir /datadisk) die Testumgebung herunterladen mit git clone https:/... Für ein neues Projekt, welches noch nicht von einem git geklont werden kann, ein leeres Verzeichnis anlegen mit mkdir ffhome Dann in das neue Verzeichnis ffhome wechseln und das lokale git Repository initialisieren mit git init Wenn das Verzeichnis geklont wurde, den Schritt "git init" überspringen. Nun im ffhome Verzeichnis (oder in geklonten Verzeichnis) (bei mir /datadisk/ffhome) die python virtuelle Umgebung einrichten: python3 -m venv --prompt ffhome .venv Hierdurch wird in ffhome ein Unterverzeichnis .venv angelegt. Die virtuelle Umgebung wird in /datadisk/ffhome/.venv eingerichtet und kann aktiviert werden mit source .venv/bin/activate Dadurch ändert sich der prompt: (ffhome) 18:16:41[frankb@berglap /datadisk/ffhome ] Jetzt kann ansible in der ffhome Umgebung installiert werden: pip3 install ansible Damit ist ansible nur in der virtuellen Umgebung installiert und ausführbar. Zum späteren Verlassen der Umgebung: deactivate oder Terminal Fenster schliessen 18:11:20[frankb@berglap /datadisk/ffhome 0] Die Verzeichnistruktur der Testumgebung $ tree -L 4 /datadisk/ffhome /datadisk/ffhome ├── ansible.cfg ├── inventory │   ├── hosts.yaml │   └── host_vars |    ├── bergdesk │      │   ├── vars │      │   └── vault │      ├── berghofen │      │   ├── vars │      │   └── vault │      ├── berglap │      │   ├── vars │      │   └── vault │      └── luna │      ├── vars │      └── vault ├── playbooks │   ├── resources │   │   └── host │   │   ├── tincbergdesk.gz │   │   └── tincberghofen.gz │   ├── templates │   │   ├── tinc-up.lan.j2 │   │   └── tinc-up.wan.j2 │   ├── tincbuild.yaml │   └── update.yaml Bei den ... sind Zeilen der Übersichtlichkeit halber weggelassen. Weiter sind auch die versteckten Verzeichnisse .venv und evtl .git nicht aufgeführt. Die verwendete ansible.cfg: [defaults] inventory=./inventory/ roles_path=./roles playbook_dir=./playbooks/ interpreter_python=auto_silent #vault_password_file=~/.vault-password log_path=/tmp/ansible_ffhome.log cow_selection=random nocows=True stdout_callback=yaml display_args_to_stdout=True [privilege_escalation] become=True [ssh_connection] pipelining=True Datei mit den beteiligten Hosts inventory/hosts.yaml --- all: vars: ansible_port: 24 ansible_user: frankb ansible_become: true apus: hosts: berghofen: ansible_host: 192.168.178.51 ansible_user: fb ansible_become_password: "{{ berghofen_password }}" desktops: hosts: bergdesk: ansible_host: 192.168.178.201 ansible_become_pass: '{{ bergdesk_password }}' berglap: ansible_host: 192.168.178.52 ansible_become_pass: '{{ berglap_password }}' luna: ansible_host: 192.168.178.224 ansible_become_pass: '{{ luna_password }}' altlast: hosts: hoerde: ansible_host: 193.43.220.136 ansible_become: true ansible_become_method: su supernodes: hosts: 31.172.33.20: ansible_port: 22 snng-dus01.ffdo.de: ansible_port: 22 snng-dtm01.ffdo.de: ansible_port: 22 Die Gruppen apus und desktops enthalten die testhosts, die Gruppen altlast und supernodes sind nicht komplett einbezogen. Im Verzeichnis inventory/host_vars sind Variablen für die einzelnen hosts, u.a. die passwords, in vars unverschlüsselt, in vault aes256 geschützt. Weiter sind Parameter für tinc enthalten, nur in vars, unverschlüsselt. Beispielhaft für berghofen $ cat berghofen/vars --- berghofen_password: "{{ vault_berghofen_password }}" tinc_bindto: 192.168.178.51 wan_broadcast_ip: 193.43.220.191 wan_ip: 193.43.220.162/27 lan_broadcast_ip: 192.168.34.255 lan_ip: 192.168.34.1/24 $ cat berghofen/vault $ANSIBLE_VAULT;1.2;AES256;xx 35656536383233636434636533613830303439316263636436363932333636626462616461636537 3838626266396332363236643361626134393238636133640a646333333866643161356333626564 32373735343033633666353763376230646137663639373438393537663031643562376365396337 3161646534666236350a303366373433373833373066353030363766616166666361376637393464 30613139313661643932373239333865616338653132613530393161656466326561633537383535 3631356664643139383037636565346630643036353364333866 In der vault Datei (hier Klartext) --- vault_berghofen_password: hier das echte PW eintragen dann die vault Datei verschlüsseln mit $ ansible-vault encrypt vault --vault-id xxxxx@prompt anzeigen kann man die Datei mit $ ansible-vault view vault und wieder entschlüsseln mit $ ansible-vault decrypt vault Es gibt z.Zt. zwei playbooks: update.yaml und tincbuild.yaml $ cat playbooks/update.yaml --- # name: update yaml - hosts: [desktops,apus,altlast] tasks: - name: Testausgabe debug: msg="Hallo von {{ ansible_hostname }} Ansible managed!" - name: df -h Aufruf command: df -h / changed_when: false register: df_cmd - debug: msg: '{{df_cmd.stdout_lines}} {{ansible_distribution }}' - name: ping meine hosts ansible.builtin.ping: changed_when: false # - name: Warte auf enter Taste # ansible.builtin.pause: - name: Ist flatpak installiert stat: path: /usr/bin/flatpak register: flatpak_file when: ansible_os_family == "Debian" - name: Update flatpak Pakete falls snap vh command: /usr/bin/flatpak update when: ansible_os_family == "Debian" and flatpak_file.stat.exists - name: Ist snap installiert stat: path: /usr/bin/snap register: snap_file when: ansible_os_family == "Debian" - name: Update snap Pakete falls snap vh command: /usr/bin/snap refresh when: ansible_os_family == "Debian" and snap_file.stat.exists - name: apt update mit upgrade und autoremove ansible.builtin.apt: update_cache: yes cache_valid_time: 3600 autoremove: yes upgrade: 'yes' when: ansible_os_family == "Debian" - stat: path: /var/run/needrestart register: needrestart_file - name: reboot falls erforderlich ansible.builtin.reboot: when: - ansible_os_family == "Debian" and ( needrestart_file.stat.exists or rebootreq_file.stat.exists ) - name: playbook hier beenden bei ! debian meta: end_play when: ansible_os_family != "Debian" $ cat playbooks/tincbuild.yaml --- # name: tincbuild yaml - hosts: [desktops, apus, altlast] vars: TINC_VERSION: 1.1pre18 tinc_dev: /dev/net/tun tinc_mode: switch tinc_adr_family: ipv4 tinc_max_timeout: 30 tinc_port: lan: 10001 wan: 661 tasks: # - name: Show facts available on the system # ansible.builtin.debug: # var: ansible_facts # das folgende klappt leider nicht {{tinc_port.{{ item }}}} syntaxfehler # geschachtelte variablen gehen nicht. # - name: willi # debug: msg="var {{ tinc_port.{{lan}}}}" - name: Testausgabe debug: msg="Hallo von {{ ansible_hostname }} Ansible managed!" - name: df -h Aufruf command: df -h / changed_when: false register: df_cmd - debug: msg: '{{df_cmd.stdout_lines}} {{ansible_distribution }}' # - name: ping meine hosts # ansible.builtin.ping: # changed_when: false # - name: Warte auf enter Taste # ansible.builtin.pause: - name: playbook hier beenden bei ! debian meta: end_play when: ansible_os_family != "Debian" - name: Ist tinc Konfigurationsverzeichnis vorhanden stat: path: /etc/tinc register: tinckonf - name: Gibt es Sicherung von tinc Konfiguration # ueberlebt keinen reboot stat: path: /tmp/tinc{{ ansible_hostname }}.gz register: tincgz - name: Konfiguration packen wenn noetig community.general.archive: path: /etc/tinc dest: /tmp/tinc{{ ansible_hostname }}.gz when: tinckonf.stat.exists - name: Gesicherte Konfiguration auf Controlnode kopieren ansible.builtin.fetch: src: /tmp/tinc{{ ansible_hostname }}.gz dest: resources/host/ flat: true when: tinckonf.stat.exists # - name: Gesicherte Konfiguration auf targetnode loeschen # file: # name: /tmp/tinc{{ ansible_hostname }}.gz # state: absent # when: tincgz.stat.exists - name: Abhängigkeiten fuer tinc installieren apt: pkg: "{{ item }}" state: present with_items: - build-essential - libncurses-dev - libreadline-dev - pkg-config - zlib1g-dev - liblzo2-dev - libssl-dev - texinfo - name: create directory for tinc file: name: /opt/tinc state: directory - name: Download tinc source get_url: url: "https://www.tinc-vpn.org/packages/tinc-{{TINC_VERSION}}.tar.gz" dest: /opt/tinc/tinc-{{TINC_VERSION}}.tar.gz register: gettinc - name: tinc-Quellen entpacken unarchive: src: /opt/tinc/tinc-{{TINC_VERSION}}.tar.gz dest: /usr/src remote_src: true when: - gettinc.changed - name: Pruefen tinc programm vh stat: path: /usr/sbin/tinc register: tinc_bin - name: tinc kompilieren und installieren shell: "cd /usr/src/tinc-{{TINC_VERSION}} && ./configure --prefix=/usr --sysconfdir=/etc --runstatedir=/run --localstatedir=/var --with-systemd && make && make install" when: - tinc_bin.stat.exists == False or gettinc.changed - name: Gibt es schon eine (alte) tinc Konfiguration stat: path: /etc/tinc register: tinc_etc - name: tinc Konfigurationsreste beseitigen file: path: /etc/tinc state: absent when: - tinc_etc.stat.exists - name: tinc lan/wan vorkonfigurieren in mehreren Schritten shell: "tinc --net={{ item }} init {{ansible_hostname}}" with_items: - lan - wan # when: # - tinc_bin.stat.exists == False or gettinc.changed - name: 2048er priv und pub keys löschen shell: "rm /etc/tinc/{{ item }}/*.priv && rm /etc/tinc/{{ item }}/hosts/*" with_items: - lan - wan # when: # - tinc_bin.stat.exists == False or gettinc.changed - name: 4096er keys generieren shell: "tinc --net={{ item }} -b generate-keys 4096" with_items: - lan - wan # when: # - tinc_bin.stat.exists == False or gettinc.changed - name: tinc.conf einrichten shell: "tinc --net={{ item }} set Device {{tinc_dev}} && tinc --net={{ item }} set Mode {{tinc_mode}} && tinc --net={{ item }} set AddressFamily {{tinc_adr_family}} && tinc --net={{ item }} set MaxTimeout {{tinc_max_timeout}} && tinc --net={{ item }} set BindToAddress {{tinc_bindto}}" with_items: - lan - wan # when: # - tinc_bin.stat.exists == False or gettinc.changed - name: lan/wan ports setzen # das geht leider nicht in loop, da Variablen nicht geschachtelt shell: "tinc --net=lan set Port {{ tinc_port.lan }} && tinc --net=wan set Port {{ tinc_port.wan }}" - name: tinc-up anpassen ansible.builtin.template: src: templates/tinc-up.{{ item }}.j2 dest: /etc/tinc/{{ item }}/tinc-up with_items: - lan - wan # when: # - tinc_bin.stat.exists == False or gettinc.changed - meta: end_play Für tinc-up werden folgende templates verwendet $ cat playbooks/templates/tinc-up.lan.j2 #!/bin/sh ip addr add {{ lan_ip }} brd {{ lan_broadcast_ip }} dev $INTERFACE ip link set $INTERFACE mtu 1504 up $ cat playbooks/templates/tinc-up.wan.j2 #!/bin/sh ip addr add {{ wan_ip }} brd {{ wan_broadcast_ip }} dev $INTERFACE ip link set $INTERFACE mtu 1504 up Aufruf der beiden playbooks mit $ ansible-playbook -b playbooks/update.yaml -i inventory/hosts.yaml --ask-vault-pass $ ansible-playbook -b playbooks/tincbuild.yaml -i inventory/hosts.yaml --ask-vault-pass Gekürzte Ausgabe: (ffhome) 20:55:59[frankb@berglap /datadisk/ffhome 4] ansible-playbook -b playbooks/update.yaml -i inventory/hosts.yaml --ask-vault-pass Vault password: PLAY [desktops,apus,altlast] *************************************************************** TASK [Gathering Facts] ********************************************************************* [WARNING]: Platform linux on host berglap is using the discovered Python interpreter at /usr/bin/python3.10, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.17/reference_appendices/interpreter_discovery.html for more information. ok: [berglap] [WARNING]: Platform linux on host bergdesk is using the discovered Python interpreter at /usr/bin/python3.11, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.17/reference_appendices/interpreter_discovery.html for more information. ok: [bergdesk] fatal: [luna]: UNREACHABLE! => changed=false msg: 'Failed to connect to the host via ssh: ssh: connect to host 192.168.178.224 port 24: No route to host' unreachable: true [WARNING]: Platform linux on host berghofen is using the discovered Python interpreter at /usr/bin/python3.11, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.17/reference_appendices/interpreter_discovery.html for more information. ok: [berghofen] [WARNING]: Platform freebsd on host hoerde is using the discovered Python interpreter at /usr/local/bin/python3.9, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.17/reference_appendices/interpreter_discovery.html for more information. ok: [hoerde] TASK [Testausgabe] ************************************************************************* ok: [bergdesk] => msg: Hallo von bergdesk Ansible managed! ok: [berglap] => msg: Hallo von berglap Ansible managed! ok: [berghofen] => msg: Hallo von berghofen Ansible managed! ok: [hoerde] => msg: Hallo von hoerde Ansible managed! TASK [df -h Aufruf] ************************************************************************ ok: [berglap] ok: [bergdesk] ok: [berghofen] ok: [hoerde] TASK [debug] ******************************************************************************* ok: [bergdesk] => msg: '[''Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf'', ''/dev/sdb1 439G 98G 319G 24% /''] Debian' ok: [berglap] => msg: '[''Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf'', ''/dev/mapper/system-root 444G 298G 124G 71% /''] Ubuntu' ok: [berghofen] => msg: '[''Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf'', ''/dev/sda6 18G 5,1G 12G 30% /''] Debian' ok: [hoerde] => msg: '[''Filesystem Size Used Avail Capacity Mounted on'', ''s3pool25/jail/hoerde.ffdo.net 3.9G 891M 3.0G 22% /''] FreeBSD' TASK [ping meine hosts] ******************************************************************** ok: [berglap] ok: [bergdesk] ok: [berghofen] ok: [hoerde] ... PLAY RECAP ********************************************************************************* bergdesk : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 berghofen : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 berglap : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 hoerde : ok=5 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 luna : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0