--- 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 ***** Nur für die folgende Paketinstallation sind root-Rechte erforderlich,alle weiteren Terminaleingaben erfolgen als normaler user. Die folgenden Pakete installieren: $ sudo apt install python3-pip python3-venv Dann in das Basisverzeichnis gehen (bei mir /datadisk) und die virtuelle Umgebung anlegen $ python3 -m venv ffhome In dem Verzeichnis ffhome die Umgebung aktivieren $ source bin/activate Dadurch ändert sich der prompt, je nach Einstellung $ oder 0]: (ffhome) 18:16:41[frankb@berglap /datadisk/ffhome 0] Zum Verlassen der Umgebung: $ deactivate oder Terminal Fenster schliessen Jetzt kann ansible in der ffhome Umgebung installiert werden: $ pip3 install ansible 18:11:20[frankb@berglap /datadisk/ffhome 0] Die Verzeichnistruktur der Testumgebung $ tree -L 4 /datadisk/ffhome /datadisk/ffhome ├── ansible.cfg ├── bin │   ├── activate │   ├── activate.csh │   ├── activate.fish │   ├── Activate.ps1 │   ├── ansible │   ├── ansible-community ... │   └── yamllint ├── include ├── inventory │   ├── hosts.yaml │   └── host_vars |    ├── bergdesk │      │   ├── vars │      │   ├── vars.01.bak │      │   ├── vars.02.bak │      │   └── vault │      ├── berghofen │      │   ├── vars │      │   ├── vars.01.bak │      │   ├── vars.bak │      │   └── vault │      ├── berglap │      │   ├── vars │      │   ├── vars.01.bak │      │   ├── vars.bak │      │   └── vault │      └── luna │      ├── vars │      └── vault ├── lib │   └── python3.10 ├── lib64 -> lib ... ├── playbooks │   ├── resources │   │   └── host │   │   ├── tincbergdesk.gz │   │   └── tincberghofen.gz │   ├── templates │   │   ├── tinc-up.lan.j2 │   │   └── tinc-up.wan.j2 │   ├── tincbuild.yaml │   └── update.yaml └── pyvenv.cfg Bei den ... sind Zeilen der Übersichtlichkeit halber weggelassen. 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