Browse Source

update certs and build system

blat 1 year ago
commit
d16d30e9aa
100 changed files with 2442 additions and 0 deletions
  1. 10 0
      .gitignore
  2. 38 0
      README.md
  3. 43 0
      README_build.md
  4. 23 0
      TODO.md
  5. 13 0
      ansible.cfg
  6. 0 0
      group_vars/builder.yml
  7. 72 0
      host_vars/belvedere-test.yml
  8. 54 0
      host_vars/belvedere-vs.yml
  9. 72 0
      host_vars/belvedere.yml
  10. 19 0
      host_vars/lime-000000000000.yml
  11. 37 0
      hosts
  12. 23 0
      inventory.yml
  13. 24 0
      main.yml
  14. 13 0
      mesh_devices_template.yml
  15. 8 0
      playbooks/ada.yml
  16. 14 0
      playbooks/belvedere.yml
  17. 32 0
      playbooks/build_all_targets.yml
  18. 30 0
      playbooks/build_single_target_dev_test.yml
  19. 17 0
      playbooks/generate-new-device.yml
  20. 13 0
      playbooks/generate-new-test-device.yml
  21. 20 0
      playbooks/infra.test.yml
  22. 14 0
      playbooks/infra.yml
  23. 14 0
      roles/stable/build/defaults/main.yml
  24. 15 0
      roles/stable/build/files/mac56-to-ip_host.sh
  25. 8 0
      roles/stable/build/files/packages/vs-fix-openwrt21/Makefile
  26. 4 0
      roles/stable/build/files/packages/vs-fix-openwrt21/root/etc/uci-defaults/90_add_bat0_to_brlan
  27. 8 0
      roles/stable/build/files/packages/vs-fix-openwrt22/Makefile
  28. 4 0
      roles/stable/build/files/packages/vs-fix-openwrt22/root/etc/uci-defaults/90_add_confdir_to_dnsmasq
  29. 27 0
      roles/stable/build/files/packages/vs-ninux-generic/Makefile
  30. 64 0
      roles/stable/build/files/packages/vs-ninux-generic/root/etc/config/lime-community
  31. 9 0
      roles/stable/build/files/packages/vs-ninux-generic/root/etc/config/lime-node
  32. 3 0
      roles/stable/build/files/packages/vs-ninux-generic/root/etc/dropbear/authorized_keys
  33. 3 0
      roles/stable/build/files/packages/vs-ninux-generic/root/etc/lime-assets/community/cron_reboot
  34. 5 0
      roles/stable/build/files/packages/vs-ninux-generic/root/etc/lime-assets/community/prometheus_enable
  35. 12 0
      roles/stable/build/files/packages/vs-ninux-generic/root/etc/lime-assets/community/wireguard_server
  36. 22 0
      roles/stable/build/files/packages/vs-ninux-tiny/Makefile
  37. 60 0
      roles/stable/build/files/packages/vs-ninux-tiny/root/etc/config/lime-community
  38. 9 0
      roles/stable/build/files/packages/vs-ninux-wg/Makefile
  39. 34 0
      roles/stable/build/files/packages/vs-ninux-wg/root/etc/init.d/wireguard
  40. 7 0
      roles/stable/build/files/packages/vs-ninux-wg/root/etc/uci-defaults/90_wg-enable
  41. 36 0
      roles/stable/build/files/packages/vs-ninux-wg/root/etc/uci-defaults/90_wg-firewall
  42. 9 0
      roles/stable/build/files/packages/vs-ninux-wg/root/etc/wireguard/wg0.conf
  43. 8 0
      roles/stable/build/files/packages/vs-test/Makefile
  44. 7 0
      roles/stable/build/files/packages/vs-test/root/etc/uci-defaults/90_vs-test
  45. 5 0
      roles/stable/build/handlers/main.yml
  46. 15 0
      roles/stable/build/tasks/conf_files_lime_mac.yml
  47. 18 0
      roles/stable/build/tasks/configure.yml
  48. 21 0
      roles/stable/build/tasks/configure_clean.yml
  49. 11 0
      roles/stable/build/tasks/configure_custom.yml
  50. 16 0
      roles/stable/build/tasks/configure_init.yml
  51. 35 0
      roles/stable/build/tasks/init_vars.yml
  52. 38 0
      roles/stable/build/tasks/init_wg_vars.yml
  53. 7 0
      roles/stable/build/tasks/install_feeds_libremesh.yml
  54. 7 0
      roles/stable/build/tasks/install_feeds_packages.yml
  55. 23 0
      roles/stable/build/tasks/install_openwrt.yml
  56. 35 0
      roles/stable/build/tasks/install_openwrt_requirements.yml
  57. 49 0
      roles/stable/build/tasks/main.yml
  58. 21 0
      roles/stable/build/tasks/preflight.yml
  59. 16 0
      roles/stable/build/tasks/vpn_wg_server.yml
  60. 10 0
      roles/stable/build/tasks/webserver.yml
  61. 15 0
      roles/stable/build/templates/default_config.j2
  62. 12 0
      roles/stable/build/templates/default_target_config.j2
  63. 22 0
      roles/stable/build/templates/lime_mac.j2
  64. 9 0
      roles/stable/build/templates/vpn_wg_peer.j2
  65. 6 0
      roles/stable/dnsmasq/handlers/main.yml
  66. 21 0
      roles/stable/dnsmasq/tasks/main.yml
  67. 57 0
      roles/stable/dnsmasq/templates/etc_dnsmasq.conf.j2
  68. 19 0
      roles/stable/dnsmasq/vars/main.yml
  69. 41 0
      roles/stable/monitoring/alertmanager/tasks/main.yml
  70. 4 0
      roles/stable/monitoring/blackbox_exporter/tasks/main.yml
  71. 47 0
      roles/stable/monitoring/blackbox_exporter/vars/main.yml
  72. 17 0
      roles/stable/monitoring/prometheus/tasks/main.yml
  73. 223 0
      roles/stable/monitoring/prometheus/vars/main.yml
  74. 6 0
      roles/stable/nginx/defaults/main.yml
  75. 23 0
      roles/stable/nginx/tasks/certbot.yml
  76. 38 0
      roles/stable/nginx/tasks/certificates.yml
  77. 78 0
      roles/stable/nginx/tasks/main.yml
  78. 25 0
      roles/stable/nginx/templates/default.j2
  79. 31 0
      roles/stable/nginx/templates/fpm_service.conf.j2
  80. 44 0
      roles/stable/nginx/templates/reverse_proxy.conf.j2
  81. 33 0
      roles/stable/nginx/templates/static_service.conf.j2
  82. 4 0
      roles/stable/openssl_certificates/defaults/main.yml
  83. BIN
      roles/stable/openssl_certificates/files/ca/images/android-12_firefox_ca-enable.jpg
  84. BIN
      roles/stable/openssl_certificates/files/ca/images/android-12_firefox_ca-enabled.jpg
  85. BIN
      roles/stable/openssl_certificates/files/ca/images/android-12_settings_ca-install.jpg
  86. BIN
      roles/stable/openssl_certificates/files/ca/images/android-12_settings_ca-installed.jpg
  87. BIN
      roles/stable/openssl_certificates/files/ca/images/green_lock.png
  88. BIN
      roles/stable/openssl_certificates/files/ca/images/linux_chromium.jpg
  89. BIN
      roles/stable/openssl_certificates/files/ca/images/linux_firefox.jpg
  90. 41 0
      roles/stable/openssl_certificates/files/ca/images/openssl_logo.svg
  91. 5 0
      roles/stable/openssl_certificates/files/ca/vendor/imagebox.min.css
  92. 5 0
      roles/stable/openssl_certificates/files/ca/vendor/imagebox.min.js
  93. 44 0
      roles/stable/openssl_certificates/tasks/authority.yml
  94. 42 0
      roles/stable/openssl_certificates/tasks/authority_webserver.yml
  95. 16 0
      roles/stable/openssl_certificates/tasks/main.yml
  96. 42 0
      roles/stable/openssl_certificates/tasks/server.yml
  97. 20 0
      roles/stable/openssl_certificates/tasks/server_webserver.yml
  98. 14 0
      roles/stable/openssl_certificates/templates/authority.conf.j2
  99. 140 0
      roles/stable/openssl_certificates/templates/authority.html.j2
  100. 14 0
      roles/stable/openssl_certificates/templates/server.conf.j2

+ 10 - 0
.gitignore

@@ -0,0 +1,10 @@
+/lime-mac/*
+doc*.md
+
+
+# public
+/lime-mac/*
+/host_vars/lime-*
+!/host_vars/lime-000000000000.yml
+group_vars/wg_server.yml
+/mesh_devices.yml

+ 38 - 0
README.md

@@ -0,0 +1,38 @@
+
+un ruolo ansible per aggiornare i belvederi e la macchina con gli strumenti
+
+alcuni ruoli per installare i componenti necessari al monitoring dei belvederi
+- prometheus
+- blackbox_exporter
+- alertmanager
+
+requirements
+    pip3 install ansible
+    pip3 install jinja2-ansible-filters
+
+Aggiungi il percorso di dove ti ha installato ansible ed aggeggi vari nel tuo .bash_profile che hai in home:
+
+```
+#ansible ed ansible-galaxy
+export PATH=$PATH:~/.local/bin
+```
+dai `source ~/.bash_profile`
+
+Installa i componenti ansible-galaxy
+
+    ansible-galaxy collection install community.general
+    ansible-galaxy install cloudalchemy.prometheus
+    ansible-galaxy install cloudalchemy.blackbox-exporter
+    ansible-galaxy install cloudalchemy.alertmanager
+    ansible-galaxy install nginxinc.nginx
+    ansible-galaxy install nginxinc.nginx_config
+
+run
+    ansible-playbook -i hosts -i inventory.yml main.yml
+
+setup dei belvederi
+    ansible-playbook -i hosts -i inventory.yml infra.yml
+
+
+#
+https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem

+ 43 - 0
README_build.md

@@ -0,0 +1,43 @@
+
+esempio di test per buildare per tutti i targets
+
+ansible-playbook                          \
+  -i hosts                                \
+  -i mesh_devices.yml                     \
+  -i inventory.yml                        \
+  --skip-tags preflight                   \
+  --skip-tags openwrt_install             \
+  --skip-tags libremesh_install           \
+  --skip-tags libremesh_packages          \
+  --skip-tags configure_profiles          \
+  --skip-tags webserver                   \
+  playbooks/build_all_targets.yml
+
+#### configura e builda
+  ansible-playbook                          \
+      -i hosts                                \
+      -i mesh_devices.yml                     \
+      -i inventory.yml                        \
+      --skip-tags preflight                   \
+      --skip-tags openwrt_install             \
+      --skip-tags libremesh_install           \
+      --skip-tags webserver                   \
+      playbooks/build_single_target_dev_test.yml
+
+
+# nuovo target
+ansible-playbook                          \
+    -i hosts                                \
+    -i mesh_devices.yml                     \
+    -i inventory.yml                        \
+    playbooks/build_single_target_dev_test.yml
+
+
+ansible-playbook                          \
+    -i hosts                                \
+    -i mesh_devices.yml                     \
+    -i inventory.yml                        \
+    --skip-tags openwrt_install             \
+    --skip-tags libremesh_install           \
+    --skip-tags webserver                   \
+    playbooks/build_all_targets.yml

+ 23 - 0
TODO.md

@@ -0,0 +1,23 @@
+
+# roles/stable/build
+[ ] create a build_all playbook
+- [ ] create target specific vars for build_all
+[ ] group firmware in human readable way
+[ ] replace mac56_to_ipCD.sh with an ansible script if possible
+[ ] move packages from roles/stable/build/files to a repo
+- [ ] finish refactor of vs-ninux-wg (should it keep this name after refactor?)
+[ ] setup a repo with an updated .gitignore for publishing purposes
+[ ] update README with build system information
+[ ] add tags or prefix in tasks of roles/stable/build/tasks/main.yml
+[ ] reduce size of lime-mac files (include only ones of the same target?)
+
+[ ] issue: building for a new target ramips_mt76x8 doesn't select the device tl-wr6400-v4 at first time. props: changing target and then make defconfig, then cat EOF the target device and redo a make defconfig
+
+[ ] add workaround to initialize device br-lan on openwrt 21.02.3
+config device
+        option name 'br-lan'
+        option type 'bridge'
+        list ports 'eth0'
+        list ports 'bat0'
+
+[ ] try to add support for lbe-m5 on openwrt 21.02.3

+ 13 - 0
ansible.cfg

@@ -0,0 +1,13 @@
+
+[passwordstore_lookup]
+lock=readwrite
+locktimeout=45000s
+
+[defaults]
+inventory = ./inventory.yml
+interpreter_python = /usr/bin/python3
+remote_user = root
+
+
+[ssh_connection]
+scp_if_ssh=True

+ 0 - 0
group_vars/builder.yml


+ 72 - 0
host_vars/belvedere-test.yml

@@ -0,0 +1,72 @@
+belvedere_targets:
+    - targets: ['10.170.169.234:9090']
+      labels:
+        host: 'ninux-59a9ea'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.213.244:9090']
+      labels:
+        host: 'scutigera'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.170.196:9090']
+      labels:
+        host: 'cetonia'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.157.135:9090']
+      labels:
+        host: 'stercoraro'
+        group: 'mesh_routers'
+        alert: 'yes'
+
+    - targets: ['10.170.247.96:9090']
+      labels:
+        host: 'neomantix'
+        group: 'mesh_stations'
+        alert: 'no'
+
+    - targets: ['10.170.135.90:9090']
+      labels:
+        host: 'cervo-volante'
+        group: 'home_routers'
+        alert: 'yes'
+
+    - targets: ['10.169.165.230:9090']
+      labels:
+        host: 'falena'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.154.103:9090']
+      labels:
+        host: 'tarlo'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.207.117.192:9090']
+      labels:
+        host: 'ninux-cabum'
+        group: 'mesh_stations'
+        alert: 'no'
+
+    - targets: ['10.170.150.95:9090']
+      labels:
+        host: 'grillo'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.135.117:9090']
+      labels:
+        host: 'ninux-598775'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.248.242:9090']
+      labels:
+        host: 'amphithrix'
+        group: 'mesh_stations'
+        alert: 'yes'

+ 54 - 0
host_vars/belvedere-vs.yml

@@ -0,0 +1,54 @@
+belvedere_targets:
+    - targets: ['10.170.161.237:9090']
+      labels:
+        host: 'ninux-dba1ed'
+        group: 'mesh_stations'
+        alert: 'no'
+
+    - targets: ['10.170.233.12:9090']
+      labels:
+        host: 'zanzara'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.173.138:9090']
+      labels:
+        host: 'scolopendra'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.147.243:9090']
+      labels:
+        host: 'ape'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.254.23.220:9090']
+      labels:
+        host: 'scarabeo'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.154.252:9090']
+      labels:
+        host: 'formica'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.130.99:9090']
+      labels:
+        host: 'mantide'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.163.2:9090']
+      labels:
+        host: 'cavolaia'
+        group: 'mesh_stations'
+        alert: 'no'
+
+    - targets: ['10.170.173.201:9090']
+      labels:
+        host: 'ninux-25adc9'
+        group: 'home_routers'
+        alert: 'no'

+ 72 - 0
host_vars/belvedere.yml

@@ -0,0 +1,72 @@
+belvedere_targets:
+    - targets: ['10.170.169.234:9090']
+      labels:
+        host: 'ninux-59a9ea'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.213.244:9090']
+      labels:
+        host: 'scutigera'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.170.196:9090']
+      labels:
+        host: 'cetonia'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.157.135:9090']
+      labels:
+        host: 'stercoraro'
+        group: 'mesh_routers'
+        alert: 'yes'
+
+    - targets: ['10.170.247.96:9090']
+      labels:
+        host: 'neomantix'
+        group: 'mesh_stations'
+        alert: 'no'
+
+    - targets: ['10.170.135.90:9090']
+      labels:
+        host: 'cervo-volante'
+        group: 'home_routers'
+        alert: 'yes'
+
+    - targets: ['10.169.165.230:9090']
+      labels:
+        host: 'falena'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.154.103:9090']
+      labels:
+        host: 'tarlo'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.207.117.192:9090']
+      labels:
+        host: 'ninux-cabum'
+        group: 'mesh_stations'
+        alert: 'no'
+
+    - targets: ['10.170.150.95:9090']
+      labels:
+        host: 'grillo'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.135.117:9090']
+      labels:
+        host: 'ninux-598775'
+        group: 'mesh_stations'
+        alert: 'yes'
+
+    - targets: ['10.170.248.242:9090']
+      labels:
+        host: 'amphithrix'
+        group: 'mesh_stations'
+        alert: 'yes'

+ 19 - 0
host_vars/lime-000000000000.yml

@@ -0,0 +1,19 @@
+# BEGIN ANSIBLE MANAGED BLOCK lime-000000000000 utils
+ip_host: 0.0
+# END ANSIBLE MANAGED BLOCK lime-000000000000 utils
+# BEGIN ANSIBLE MANAGED BLOCK lime-000000000000 common
+hostname: ninux-000000
+lime_mac: lime-000000000000
+main_ipv4_address: 10.170.0.0/16
+# END ANSIBLE MANAGED BLOCK lime-000000000000 common
+# BEGIN ANSIBLE MANAGED BLOCK lime-000000000000 config
+config_lime_system: option hostname 'ninux-000000'
+config_lime_wifi: option channel_5ghz '48'
+# END ANSIBLE MANAGED BLOCK lime-000000000000 config
+# BEGIN ANSIBLE MANAGED BLOCK lime-000000000000 vpn wireguard wg0
+vpn_wg0_privatekey: UIHZ9uTOxW07jHTQHAzUvmWAS6tkPtQWqZU9Gp6LcHY=
+vpn_wg0_publickey: HgdBD20UBNzWkDJfP4H20Nr+IyzOyWBdqXCV69XktQA=
+vpn_wg0_presharedkey: 3rod8G0DsZzkxMmR95Sf76URdH4aiZEUdlol8lOL+ww=
+vpn_wg0_listenport: 51800
+vpn_wg0_address: 192.168.0.0/16
+# END ANSIBLE MANAGED BLOCK lime-000000000000 vpn wireguard wg0

+ 37 - 0
hosts

@@ -0,0 +1,37 @@
+croara:
+  hosts:
+    belvedere:
+      ansible_host: 10.0.0.10
+      ansible_user: pi
+      ansible_become_user: root
+      ansible_become: yes
+    ada:
+      ansible_host: 10.170.42.91
+      ansible_user: antennine
+      ansible_become_pass: "{{ lookup('passwordstore', 'chiavi_antennine/ada/user_root', errors='strict') | default(omit) }}"
+      ansible_become_user: root
+      ansible_become_method: su
+      ansible_become_flags:
+    belvedere-test:
+      ansible_host: 10.170.64.34
+      ansible_user: pi
+      ansible_become_user: root
+      ansible_become: yes
+
+valsamoggia:
+  hosts:
+    belvedere-vs:
+      ansible_host: 10.0.0.11
+      ansible_user: pi
+      ansible_become_user: root
+      ansible_become: yes
+
+vps:
+  hosts:
+    jitsi:
+      ansible_host: 10.0.0.1
+      ansible_user: <redacted>
+      ansible_become_user: root
+      ansible_become_pass: "{{ lookup('passwordstore', 'chiavi_antennine/jitsi/user_root', errors='strict') | default(omit) }}"
+      ansible_become_method: su
+      ansible_become_flags:

+ 23 - 0
inventory.yml

@@ -0,0 +1,23 @@
+belvederi:
+  hosts:
+    belvedere:
+    belvedere-vs:
+
+strumenti:
+  hosts: ada
+
+ca:
+  hosts: ada
+
+builder:
+  hosts: ada
+
+wg_server:
+  hosts: jitsi
+
+# test:
+#   hosts: test.jolly
+#   vars:
+#     ansible_user: debian
+
+all:

+ 24 - 0
main.yml

@@ -0,0 +1,24 @@
+---
+- hosts: all
+  gather_facts: yes
+  become: yes
+
+  tasks:
+    - name: Perform a dist-upgrade.
+      ansible.builtin.apt:
+        upgrade: dist
+        update_cache: yes
+
+    - name: Check if a reboot is required.
+      ansible.builtin.stat:
+        path: /var/run/reboot-required
+        get_md5: no
+      register: reboot_required_file
+
+    - name: Reboot the server (if required).
+      ansible.builtin.reboot:
+      when: reboot_required_file.stat.exists == true
+
+    - name: Remove dependencies that are no longer required.
+      ansible.builtin.apt:
+        autoremove: yes

+ 13 - 0
mesh_devices_template.yml

@@ -0,0 +1,13 @@
+mesh_devices:
+  hosts:
+    # litebeam
+    lime-000000000000:
+      hostname: cocciniglia
+
+    # tplink_tl-wr940n-v6
+    lime-000000000000:
+      hostname: cervovolante
+
+    # tplink_cpe510
+    lime-000000000000:
+      hostname: oncocera-semirubella

+ 8 - 0
playbooks/ada.yml

@@ -0,0 +1,8 @@
+---
+## Ada
+- name: Ada
+  hosts: ada
+  become: yes
+  roles:
+    - '../roles/stable/openssl_certificates'
+  tags: certificates

+ 14 - 0
playbooks/belvedere.yml

@@ -0,0 +1,14 @@
+---
+## Monitoring
+- name: Monitoring
+  hosts: belvedere
+  roles:
+    - '../roles/stable/monitoring/prometheus'
+    - '../roles/stable/monitoring/blackbox_exporter'
+    - '../roles/stable/monitoring/alertmanager'
+    - '../roles/stable/dnsmasq'
+  vars_files:
+    - ../vars/monitoring.yml
+    - ../vars/smtp.yml
+    - ../vars/telegram.yml
+  tags: monitoring

+ 32 - 0
playbooks/build_all_targets.yml

@@ -0,0 +1,32 @@
+---
+# Build all targets
+
+- name: Build {{ openwrt_version }} ath79_generic
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/dev_test.yml
+    - ../vars/build/targets/ath79_generic.yml
+  tags: generate device
+
+- name: Build {{ openwrt_version }} ar71xx_generic
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/dev_test.yml
+    - ../vars/build/targets/ar71xx_generic.yml
+  tags: generate device
+
+- name: Build ath79_tiny
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/dev_test.yml
+    - ../vars/build/targets/ath79_tiny.yml
+  tags: generate device

+ 30 - 0
playbooks/build_single_target_dev_test.yml

@@ -0,0 +1,30 @@
+---
+# Build single target dev_test.
+#
+- name: Build single target dev_test.
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/openwrt.yml
+    - ../vars/build/dev_test.yml
+    - ../vars/build/_h5ai.yml
+    - ../vars/build/targets/test_stable_ramips_mt7620.yml
+    # - ../vars/build/targets/test_stable_ath79_generic.yml
+    # - ../vars/build/targets/22.03.1_ath79_generic.yml
+  tags: generate_device
+
+- name: Build single target dev_test.
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/openwrt.yml
+    - ../vars/build/dev_test.yml
+    - ../vars/build/_h5ai.yml
+    # - ../vars/build/targets/test_stable_ramips_mt7620.yml
+    - ../vars/build/targets/test_stable_ath79_generic.yml
+    # - ../vars/build/targets/22.03.1_ath79_generic.yml
+  tags: generate_device

+ 17 - 0
playbooks/generate-new-device.yml

@@ -0,0 +1,17 @@
+---
+# Generate a new device.
+#
+- name: Generate a new device.
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/main.yml
+    - ../vars/build/_h5ai.yml
+    - ../vars/build/ath79_generic.yml
+  tags: generate device
+
+- handlers:
+  - name: Add wireguard keys to server
+    import_tasks: ../roles/stable/build/tasks/server.yml

+ 13 - 0
playbooks/generate-new-test-device.yml

@@ -0,0 +1,13 @@
+---
+# Generate a new device.
+#
+- name: Generate a new device.
+  gather_facts: false
+  hosts: builder
+  roles:
+    - ../roles/stable/build
+  vars_files:
+    - ../vars/build/test.yml
+    - ../vars/build/_h5ai.yml
+    # - ../vars/build/devices.yml
+  tags: generate device

+ 20 - 0
playbooks/infra.test.yml

@@ -0,0 +1,20 @@
+---
+## Monitoring
+- name: Monitoring
+  gather_facts: false
+  hosts: belvedere-test
+  roles:
+    - '../roles/stable/monitoring/prometheus'
+    - '../roles/stable/monitoring/blackbox_exporter'
+    - '../roles/stable/monitoring/alertmanager'
+    - '../roles/stable/dnsmasq'
+    - '../roles/wireguard'
+    - '../roles/stable/nginx'
+  vars_files:
+    - ../vars/monitoring.yml
+    - ../vars/smtp.yml
+    - ../vars/telegram.yml
+    - ../vars/test.yml
+    - ../vars/wireguard.yml
+    - ../vars/belvederi.yml
+  tags: monitoring

+ 14 - 0
playbooks/infra.yml

@@ -0,0 +1,14 @@
+---
+## Monitoring
+- name: Monitoring
+  hosts: belvederi
+  roles:
+    - '../roles/stable/monitoring/prometheus'
+    - '../roles/stable/monitoring/blackbox_exporter'
+    - '../roles/stable/monitoring/alertmanager'
+    - '../roles/stable/dnsmasq'
+  vars_files:
+    - ../vars/monitoring.yml
+    - ../vars/smtp.yml
+    - ../vars/telegram.yml
+  tags: monitoring

+ 14 - 0
roles/stable/build/defaults/main.yml

@@ -0,0 +1,14 @@
+---
+skip_preflight: true
+skip_openwrt_install: false
+skip_libremesh_install: false
+skip_configure_profiles: false
+skip_configure_clean: false
+skip_configure_custom: false
+skip_configure_init: false
+skip_webserver_update: false
+
+with_wireguard: false
+
+default_channel_5ghz: 48
+default_vpn_wg0_listenport: 51800

+ 15 - 0
roles/stable/build/files/mac56-to-ip_host.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+[ $1 = "" ] && exit
+mac=$1
+mac_5=$(echo ${mac: -4:2})
+mac_6=$(echo ${mac: -2})
+ip_c=$(echo $((0x$mac_5)))
+ip_d=$(echo $((0x$mac_6)))
+
+if [[ $2 = "--start-from" ]]
+then
+  [[ $ip_c -lt $3 ]] && ((ip_c+=$3))
+fi
+
+echo ${ip_c}.${ip_d}

+ 8 - 0
roles/stable/build/files/packages/vs-fix-openwrt21/Makefile

@@ -0,0 +1,8 @@
+include $(TOPDIR)/rules.mk
+
+PROFILE_DESCRIPTION:=fix openwrt21 add bat0 to brlan
+PROFILE_DEPENDS:= +lime-system
+
+include ../../profile.mk
+
+# call BuildPackage - OpenWrt buildroot signature

+ 4 - 0
roles/stable/build/files/packages/vs-fix-openwrt21/root/etc/uci-defaults/90_add_bat0_to_brlan

@@ -0,0 +1,4 @@
+#!/bin/sh
+
+uci add_list "network.@device[0].ports=bat0"
+exit 0

+ 8 - 0
roles/stable/build/files/packages/vs-fix-openwrt22/Makefile

@@ -0,0 +1,8 @@
+include $(TOPDIR)/rules.mk
+
+PROFILE_DESCRIPTION:=fix openwrt21 add bat0 to brlan
+PROFILE_DEPENDS:= +lime-system
+
+include ../../profile.mk
+
+# call BuildPackage - OpenWrt buildroot signature

+ 4 - 0
roles/stable/build/files/packages/vs-fix-openwrt22/root/etc/uci-defaults/90_add_confdir_to_dnsmasq

@@ -0,0 +1,4 @@
+#!/bin/sh
+
+uci set "uci set dhcp.@dnsmasq[0].confdir=/etc/dnsmasq.d/"
+exit 0

+ 27 - 0
roles/stable/build/files/packages/vs-ninux-generic/Makefile

@@ -0,0 +1,27 @@
+include $(TOPDIR)/rules.mk
+
+PROFILE_DESCRIPTION:=Generic valsamoggia configuration
+PROFILE_DEPENDS:= +prometheus-node-exporter-lua \
+	+prometheus-node-exporter-lua-wifi \
+	+prometheus-node-exporter-lua-wifi_stations \
+	+prometheus-node-exporter-lua-openwrt \
+	+lime-proto-babeld \
+	+lime-proto-batadv \
+	+lime-proto-anygw \
+	+lime-proto-wan \
+	+lime-hwd-openwrt-wan \
+	+shared-state \
+	+hotplug-initd-services \
+	+shared-state-babeld_hosts \
+	+shared-state-bat_hosts \
+	+shared-state-dnsmasq_hosts \
+	+shared-state-dnsmasq_leases \
+	+shared-state-nodes_and_links \
+	+check-date-http \
+	+lime-app \
+	+lime-hwd-ground-routing \
+	+lime-debug 
+
+include ../../profile.mk
+
+# call BuildPackage - OpenWrt buildroot signature

+ 64 - 0
roles/stable/build/files/packages/vs-ninux-generic/root/etc/config/lime-community

@@ -0,0 +1,64 @@
+config lime system
+	option hostname 'ninux-%M4%M5%M6'
+	option domain 'valsamoggia.ninux.org'
+	option keep_on_upgrade 'libremesh base-files-essential /etc/sysupgrade.conf'
+	option root_password_policy 'SET_SECRET'
+	option root_password_secret '$1$5OlrdoPc$q0p0th7CmSUuCBqsS2.6W.'
+
+config lime network
+	option primary_interface 'eth0'
+	option main_ipv4_address '10.170.128.0/16/17'
+	option anygw_dhcp_start '5120'
+	option anygw_dhcp_limit '27648'
+	option main_ipv6_address 'fd%N1:%N2%N3:%N4%N5::/64'
+	list protocols ieee80211s
+	list protocols lan
+	list protocols anygw
+	list protocols batadv:%N1
+	list protocols babeld:17
+	list resolvers 4.2.2.2   # b.resolvers.Level3.net
+	list resolvers 141.1.1.1 # cns1.cw.net
+	list resolvers 2001:470:20::2 # ordns.he.net
+	option anygw_mac "aa:aa:aa:%N1:%N2:aa"
+	option use_odhcpd false
+
+config lime 'wifi'
+	option ap_ssid 'ninux'
+	option apname_ssid 'ninux/%H'
+	option ieee80211s_mesh_fwding '0'
+	option ieee80211s_mesh_id 'LiMe'
+
+config lime-wifi-band '2ghz'
+	list modes 'ap'
+	list modes 'apname'
+	list modes 'ieee80211s'
+	option channel '11'
+	option distance '1000'
+
+config lime-wifi-band '5ghz'
+	list modes 'ap'
+	list modes 'apname'
+	list modes 'ieee80211s'
+	option distance '10000'
+	option htmode 'HT40'
+	option channel '48'
+
+config generic_uci_config prometheus
+	list uci_set "prometheus-node-exporter-lua.main.listen_interface=*"
+	list uci_set "prometheus-node-exporter-lua.main.listen_ipv6=0"
+	list uci_set "prometheus-node-exporter-lua.main.listen_port=9090"
+
+config run_asset prometheus_enable
+	option asset 'community/prometheus_enable'
+	option when 'ATFIRSTBOOT'
+
+config run_asset cron_reboot
+	option asset 'community/cron_reboot'
+	option when 'ATFIRSTBOOT'
+
+config generic_uci_config dropbear
+	list uci_set "dropbear.@dropbear[0].RootPasswordAuth=off"
+
+config run_asset wireguard_server
+	option asset 'community/wireguard_server'
+	option when 'ATFIRSTBOOT'

+ 9 - 0
roles/stable/build/files/packages/vs-ninux-generic/root/etc/config/lime-node

@@ -0,0 +1,9 @@
+
+config lime 'system'
+#	option hostname 'ninux-%M4%M5%M6'
+
+config lime 'network'
+
+config lime 'wifi'
+#	option channel_5ghz '48'
+#	option distance_5ghz '8000'

+ 3 - 0
roles/stable/build/files/packages/vs-ninux-generic/root/etc/dropbear/authorized_keys

@@ -0,0 +1,3 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPQKltRbIX4D1akDOIQM+BrFQmWtRDQyojM9ZAwH87ju kiki@digitigrafo.it
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDwAsTNUxOjxe2FCeSZuoLU0ZmRvd6hOTN8885NoJTK00XdI5WZOUP9J42rGtRiWQ+rG29ZID33ALZCotS0PtLDg3LMOpJyOSluLhP1FeOsx0MzLhzFCBjfAUSUXqdTqLiFXbbNWdqYQO4XaAFbFEiMUyvsxdnVg59Uf5iLXh85dR7WUBE4AonNcfyxh7uSKOu2etUY/RpqnqFMzn068kHnDNlw6cSfJrAgLe7HAqhFiBls1/lofH/fDJqVmEjFhgaGAE59ELyg6fxhfqr5MiJD3CR6CetYxbZ6G9KKTuY9Vk8Vi3/lwFgv+0xcaMuxF4YYZ138w6fSRlhbwjPK1nnUZPFTMFbWOj95BlKXZWubIWz1bOVnJN+44CPyof2W5+2PhOq2U+TEkVwkJBCRX6LewwltPLtITWE3XZEjf7dGMtZOPF6Ue3ZCYKZls1112+pCPtIZfCS38FTQ6rJruFfh0BQFHHxlQerWwCaTd475N+KVpAU0Z6W0RmB3L5vKjRrnGTRbnUVS9hxYWQ6yDRUA76sircjKvZtKRYQJbhOEsFElLrh+4nOipL9ttLFNEux7SnKJdnXK9mgfHjd5skfs9uxjdgRhNkAsDFpKYdZ80NMLipsKSmeR/b80uL8Ng8935wvOxfFNchpLq3PgRvjiEgR4VesHdsmyeZbylsms9Q== agave@dracaena.it
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCkVKuMvdWtExnsB2U2vF9DK4EUEwqiu92u34LU6MjavcvL6vSDu1D+jcFA4r+gVN667CMDcK/Biw/zByUW9pYh9Ynx7x+DGx2MyYbJ+9AQCJzb4X/QPxH/evVap9bOh6DjiWrZZ73kZ6yvVKm3N6+KZpUx2y4hC/NEtNJQ60/9upN6DuLPhi2h31A97ylCp+J4imrVKMTNWOPVleQXTmi93xiJqR+REOz3RM8F01WF42B+PQnkFrtubnvJ+CiHEdhVXiMhOt6x8rDrvrhAaqjn1fMUQU7ZA9pSMyya/qV+EmpYQYJkBncuIYxMi39+zcPjd6OXcGA3i/eQvlM4yC309rhUVcr+dxc8DOYcCXhUVo8hTa5vBELysnhCuSOWAgU7JVjJ+cUAZqEfckD9C6GXfcLKfXoRq6Hbb68Lixxoc38UFcSMPBJgSnoZKy0D1zdJWsNC+zwtedPreUDYQxFU9Ma9CB86iGGv7xYs4TnrljXklQ9t6uPEHO2LgSfidQy3ubHzCNVPtRHfIDnHi7HiaxmTHJ+EV9JLquuAxIhAivNk37jbMuhDDyaldSMR2yMr4aLm5oiR3K8CADhXY+Vu+6zW2G+mDPAtBey3+ftmK/IU2KE2UqA3Th3gNzIf0p37W/Ija1Twf3yBcYzRvln2hTx//TOzRY3DdfLiWQ56Bw== cricco@debian

+ 3 - 0
roles/stable/build/files/packages/vs-ninux-generic/root/etc/lime-assets/community/cron_reboot

@@ -0,0 +1,3 @@
+!#/bin/sh
+echo "30 3 * * * reboot" >> /etc/crontabs/root
+

+ 5 - 0
roles/stable/build/files/packages/vs-ninux-generic/root/etc/lime-assets/community/prometheus_enable

@@ -0,0 +1,5 @@
+!#/bin/sh
+
+[ -x /etc/init.d/prometheus-node-exporter-lua ] &&
+	/etc/init.d/prometheus-node-exporter-lua enable
+exit 0

+ 12 - 0
roles/stable/build/files/packages/vs-ninux-generic/root/etc/lime-assets/community/wireguard_server

@@ -0,0 +1,12 @@
+#!/bin/sh
+
+[ -f /etc/config/wireguard ] &&
+  touch /etc/config/wireguard
+  uci set "wireguard.peer_1=wg0"
+  uci set "wireguard.peer_1.public_key=<redacted>"
+  uci set "wireguard.peer_1.endpoint_host=<redacted>"
+  uci set "wireguard.peer_1.endpoint_port=51800"
+  uci set "wireguard.peer_1.allowed_ips=192.168.0.0/16"
+  uci set "wireguard.peer_1.persistent_keepalive=25"
+  uci commit wireguard
+exit 0

+ 22 - 0
roles/stable/build/files/packages/vs-ninux-tiny/Makefile

@@ -0,0 +1,22 @@
+include $(TOPDIR)/rules.mk
+
+PROFILE_DESCRIPTION:=Tiny valsamoggia configuration
+PROFILE_DEPENDS:= +lime-proto-babeld \
+	+lime-proto-batadv \
+	+lime-proto-anygw \
+	+lime-proto-wan \
+	+lime-hwd-openwrt-wan \
+	+shared-state \
+	+hotplug-initd-services \
+	+shared-state-babeld_hosts \
+	+shared-state-bat_hosts \
+	+shared-state-dnsmasq_hosts \
+	+shared-state-dnsmasq_leases \
+	+shared-state-nodes_and_links \
+	+check-date-http \
+	+lime-app \
+	+lime-hwd-ground-routing \
+	+lime-debug
+
+include ../../profile.mk
+# call BuildPackage - OpenWrt buildroot signature

+ 60 - 0
roles/stable/build/files/packages/vs-ninux-tiny/root/etc/config/lime-community

@@ -0,0 +1,60 @@
+config lime system
+	option hostname 'ninux-%M4%M5%M6'
+	option domain 'valsamoggia.ninux.org'
+	option keep_on_upgrade 'libremesh base-files-essential /etc/sysupgrade.conf'
+	option root_password_policy 'SET_SECRET'
+	option root_password_secret '$1$5OlrdoPc$q0p0th7CmSUuCBqsS2.6W.'
+
+config lime network
+	option primary_interface 'eth0'
+	option main_ipv4_address '10.170.128.0/16/17'
+	option anygw_dhcp_start '5120'
+	option anygw_dhcp_limit '27648'
+	option main_ipv6_address 'fd%N1:%N2%N3:%N4%N5::/64'
+	list protocols ieee80211s
+	list protocols lan
+	list protocols anygw
+	list protocols batadv:%N1
+	list protocols babeld:17
+	list resolvers 4.2.2.2   # b.resolvers.Level3.net
+	list resolvers 141.1.1.1 # cns1.cw.net
+	list resolvers 2001:470:20::2 # ordns.he.net
+	option anygw_mac "aa:aa:aa:%N1:%N2:aa"
+	option use_odhcpd false
+
+config lime 'wifi'
+	option ap_ssid 'ninux'
+	option apname_ssid 'ninux/%H'
+	option ieee80211s_mesh_fwding '0'
+	option ieee80211s_mesh_id 'LiMe'
+
+config lime-wifi-band '2ghz'
+	list modes 'ap'
+	list modes 'apname'
+	list modes 'ieee80211s'
+	option channel '11'
+	option distance '1000'
+
+config lime-wifi-band '5ghz'
+	list modes 'ap'
+	list modes 'apname'
+	list modes 'ieee80211s'
+	option distance '10000'
+	option htmode 'HT40'
+	option channel '48'
+
+config generic_uci_config prometheus
+	list uci_set "prometheus-node-exporter-lua.main.listen_interface=*"
+	list uci_set "prometheus-node-exporter-lua.main.listen_ipv6=0"
+	list uci_set "prometheus-node-exporter-lua.main.listen_port=9090"
+
+config run_asset prometheus_enable
+	option asset 'community/prometheus_enable'
+	option when 'ATFIRSTBOOT'
+
+config run_asset cron_reboot
+	option asset 'community/cron_reboot'
+	option when 'ATFIRSTBOOT'
+
+config generic_uci_config dropbear
+	list uci_set "dropbear.@dropbear[0].RootPasswordAuth=off"

+ 9 - 0
roles/stable/build/files/packages/vs-ninux-wg/Makefile

@@ -0,0 +1,9 @@
+include $(TOPDIR)/rules.mk
+
+PROFILE_DESCRIPTION:=Valsamoggia wireguard
+PROFILE_DEPENDS:=+wireguard-tools \
+    +luci-app-wireguard \
+    +luci-proto-wireguard
+include ../../profile.mk
+
+# call BuildPackage - OpenWrt buildroot signature

+ 34 - 0
roles/stable/build/files/packages/vs-ninux-wg/root/etc/init.d/wireguard

@@ -0,0 +1,34 @@
+#!/bin/sh /etc/rc.common
+# This is free software, licensed under the GNU General Public License v3.
+
+START=99
+USE_PROCD=1
+
+start_service() {
+	config_load wireguard
+  config_load network
+	config_load firewall
+
+	uci set firewall.wg_allow.dest_port="$(uci get wireguard.wg0.listen_port)"
+
+  sed -i -r "s|^(PrivateKey =).*|\1 "$(uci get wireguard.wg0.private_key)"|g" /etc/wireguard/wg0.conf
+  sed -i -r "s|^(ListenPort =).*|\1 "$(uci get wireguard.wg0.listen_port)"|g" /etc/wireguard/wg0.conf
+
+  # server
+  sed -i -r "s|^(PublicKey =).*|\1 "$(uci get wireguard.@wg0[0].public_key)"|g" /etc/wireguard/wg0.conf
+  sed -i -r "s|^(Endpoint =).*|\1 "$(uci get wireguard.@wg0[0].endpoint_host):$(uci get wireguard.@wg0[0].endpoint_port)"|g" /etc/wireguard/wg0.conf
+  sed -i -r "s|^(AllowedIPs =).*|\1 "$(uci get wireguard.@wg0[0].allowed_ips)"|g" /etc/wireguard/wg0.conf
+  sed -i -r "s|^(PersistentKeepalive =).*|\1 "$(uci get wireguard.@wg0[0].persistent_keepalive)"|g" /etc/wireguard/wg0.conf
+
+  export ip=$(uci get network.lan.ipaddr)
+  export ip=${ip#*.*}
+  export ipCD=${ip#*.*}
+
+  ip l d wg0
+  ip l a wg0 type wireguard
+  ip a a 192.168.${ipCD}/16 dev wg0
+  wg syncconf wg0 /etc/wireguard/wg0.conf
+  ip l set up wg0
+
+  /etc/init.d/network reload
+}

+ 7 - 0
roles/stable/build/files/packages/vs-ninux-wg/root/etc/uci-defaults/90_wg-enable

@@ -0,0 +1,7 @@
+!#/bin/sh
+
+touch /etc/config/wireguard
+
+[ -x /etc/init.d/wireguard ] &&
+	/etc/init.d/wireguard enable
+exit 0

+ 36 - 0
roles/stable/build/files/packages/vs-ninux-wg/root/etc/uci-defaults/90_wg-firewall

@@ -0,0 +1,36 @@
+#!/bin/sh
+
+uci set firewall.wg_allow="rule"
+uci set firewall.wg_allow.src="*"
+uci set firewall.wg_allow.target="ACCEPT"
+uci set firewall.wg_allow.proto="udp"
+uci set firewall.wg_allow.dest_port="51800"
+uci set firewall.wg_allow.name="Allow-Wireguard-Inbound"
+
+# Add the firewall zone
+uci add firewall zone
+uci set firewall.@zone[-1].name='wg'
+uci set firewall.@zone[-1].input='ACCEPT'
+uci set firewall.@zone[-1].forward='ACCEPT'
+uci set firewall.@zone[-1].output='ACCEPT'
+uci set firewall.@zone[-1].masq='1'
+
+# Add the WG interface to it
+uci set firewall.@zone[-1].network='wg0'
+
+# Forward WAN and LAN traffic to/from it
+uci add firewall forwarding
+uci set firewall.@forwarding[-1].src='wg'
+uci set firewall.@forwarding[-1].dest='wan'
+uci add firewall forwarding
+uci set firewall.@forwarding[-1].src='wg'
+uci set firewall.@forwarding[-1].dest='lan'
+uci add firewall forwarding
+uci set firewall.@forwarding[-1].src='lan'
+uci set firewall.@forwarding[-1].dest='wg'
+uci add firewall forwarding
+uci set firewall.@forwarding[-1].src='wan'
+uci set firewall.@forwarding[-1].dest='wg'
+
+uci commit firewall
+/etc/init.d/firewall restart

+ 9 - 0
roles/stable/build/files/packages/vs-ninux-wg/root/etc/wireguard/wg0.conf

@@ -0,0 +1,9 @@
+[Interface]
+PrivateKey = default
+ListenPort = default
+
+[Peer]
+PublicKey = default
+Endpoint = default
+AllowedIPs = default
+PersistentKeepalive = default

+ 8 - 0
roles/stable/build/files/packages/vs-test/Makefile

@@ -0,0 +1,8 @@
+include $(TOPDIR)/rules.mk
+
+PROFILE_DESCRIPTION:=vs-test
+PROFILE_DEPENDS:= +lime-system
+
+include ../../profile.mk
+
+# call BuildPackage - OpenWrt buildroot signature

+ 7 - 0
roles/stable/build/files/packages/vs-test/root/etc/uci-defaults/90_vs-test

@@ -0,0 +1,7 @@
+#!/bin/sh
+
+uci set "lime-node.system.domain=test"
+uci set "lime-node.network.main_ipv4_address=10.%N1.128.1/16/17"
+uci set "lime-node.wifi.ieee80211s_mesh_id=Test"
+uci set "lime-node.wifi.ap_ssid=aa_test"
+exit 0

+ 5 - 0
roles/stable/build/handlers/main.yml

@@ -0,0 +1,5 @@
+---
+- name: update and install feeds
+  shell: ./scripts/feeds update -a; ./scripts/feeds install -a
+  args:
+    chdir: "{{ openwrt_build_dir }}"

+ 15 - 0
roles/stable/build/tasks/conf_files_lime_mac.yml

@@ -0,0 +1,15 @@
+---
+- name: configure - profiles - Ensure selected profile device exist
+  file:
+    path: "{{ libremesh_profile_directory }}/{{ libremesh_profile_device }}/root/etc/config"
+    state: directory
+
+- name: configure - profiles - Add lime-mac files to profile device
+  ansible.posix.synchronize:
+    src: ../lime-mac/
+    dest: "{{ libremesh_profile_directory }}/{{ libremesh_profile_device }}/root/etc/config"
+
+- name: configure - profiles - Install updated profiles
+  shell: ./scripts/feeds update profiles; ./scripts/feeds install -p profiles
+  args:
+    chdir: "{{ openwrt_build_dir }}"

+ 18 - 0
roles/stable/build/tasks/configure.yml

@@ -0,0 +1,18 @@
+---
+- name: configure - clean
+  include_tasks: configure_clean.yml
+  when: not skip_configure_clean
+  tags:
+    - configure_clean
+
+- name: configure - init
+  include_tasks: configure_init.yml
+  when: not skip_configure_init
+  tags:
+    - configure_init
+
+- name: configure - custom
+  include_tasks: configure_custom.yml
+  when: not skip_configure_custom
+  tags:
+    - configure_custom

+ 21 - 0
roles/stable/build/tasks/configure_clean.yml

@@ -0,0 +1,21 @@
+---
+- name: configure - clean - stagin_dir/toolchain*
+  shell:
+    cmd:
+      # make config-clean;
+      rm -rf build_dir/toolchain*;
+      rm -rf staging_dir/toolchain*;
+  args:
+    chdir: "{{ openwrt_build_dir }}"
+
+- name: configure - clean - Clean info files
+  shell:
+    cmd: "rm -rf {{ openwrt_build_dir }}/tmp/info/.files-packageinfo.mk;
+          rm -rf {{ openwrt_build_dir }}/tmp/info/.files-targetinfo.mk;"
+  args:
+    chdir: "{{ openwrt_build_dir }}"
+
+- name: configure - clean - Remove .config
+  file:
+    path: "{{ openwrt_build_dir }}/.config"
+    state: absent

+ 11 - 0
roles/stable/build/tasks/configure_custom.yml

@@ -0,0 +1,11 @@
+---
+- name: configure - Apply custom configs
+  blockinfile:
+    path: "{{ openwrt_build_dir }}/.config"
+    block: "{{ lookup('ansible.builtin.template', 'default_config.j2') }}"
+
+- name: configure - Expand to full config via make defconfig
+  shell: "cd {{ openwrt_build_dir }}; make defconfig"
+
+- name: configure - Diffconfig to configs/custom_config_{{openwrt_target}}_{{ openwrt_subtarget}}
+  shell: "cd {{ openwrt_build_dir }}; ./scripts/diffconfig.sh > configs/custom_config_{{openwrt_target}}_{{ openwrt_subtarget}}"

+ 16 - 0
roles/stable/build/tasks/configure_init.yml

@@ -0,0 +1,16 @@
+---
+- name: configure - Initialize .config
+  shell: "cd {{ openwrt_build_dir }}; rm .config; make defconfig"
+
+- name: configure - Append target .config
+  blockinfile:
+    path: "{{ openwrt_build_dir }}/.config"
+    block: "{{ lookup('ansible.builtin.template', 'default_target_config.j2') }}"
+
+- name: configure - Expand to full config
+  shell: "cd {{ openwrt_build_dir }}; make defconfig"
+
+- name: configure - Copy .config to configs/default_config_{{openwrt_target}}_{{ openwrt_subtarget}}
+  shell: "cd {{ openwrt_build_dir }}; \
+    mkdir configs; \
+    cp .config configs/default_config_{{openwrt_target}}_{{ openwrt_subtarget}}"

+ 35 - 0
roles/stable/build/tasks/init_vars.yml

@@ -0,0 +1,35 @@
+---
+- name: preflight - {{item}} - Define ip_host
+  shell:
+    cmd: echo "$(../roles/stable/build/files/mac56-to-ip_host.sh {{ item }} --start-from 128)"
+  register: ip_host
+  delegate_to: localhost
+
+- name: preflight - {{item}} - Save ip_host
+  blockinfile:
+    path: ../host_vars/{{ item }}.yml
+    block: "ip_host: {{ ip_host.stdout }}"
+    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item }} utils"
+    create: yes
+  delegate_to: localhost
+
+- name: preflight - {{item}} - Init host_vars common
+  blockinfile:
+    path: ../host_vars/{{ item }}.yml
+    block: |
+      hostname: {{ hostvars[item].hostname }}
+      lime_mac: {{ item }}
+      main_ipv4_address: {{ ip_network }}.{{ ip_host.stdout }}{{ ip_netmask }}
+    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item }} common"
+    create: yes
+  delegate_to: localhost
+
+- name: preflight - {{item}} - Init host_vars config
+  blockinfile:
+    path: ../host_vars/{{ item }}.yml
+    block: |
+      config_lime_system: option hostname '{{ hostvars[item].hostname }}'
+      config_lime_wifi: option channel_5ghz '{% if hostvars[item].channel_5ghz is defined %}{{ hostvars[item].channel_5ghz }}{% else %}{{ default_channel_5ghz }}{% endif %}'
+    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item }} config"
+    create: yes
+  delegate_to: localhost

+ 38 - 0
roles/stable/build/tasks/init_wg_vars.yml

@@ -0,0 +1,38 @@
+---
+- name: preflight - {{item}} - generate privatekey
+  shell:
+    cmd: echo $(wg genkey)
+  register: wg_privatekey
+  delegate_to: localhost
+  when: hostvars[item].vpn_wg0_privatekey is not defined
+
+- name: preflight - {{item}} - generate publickey
+  shell:
+    cmd: echo $(echo {{ wg_privatekey.stdout }} | wg pubkey)
+  register: wg_publickey
+  delegate_to: localhost
+  when: hostvars[item].vpn_wg0_publickey is not defined
+
+- name: preflight - {{item}} - generate presharedkey
+  shell:
+    cmd: wg genpsk
+  register: wg_presharedkey
+  delegate_to: localhost
+  when: hostvars[item].vpn_wg0_presharedkey is not defined
+
+- name: preflight - {{item}} - Init host_vars wireguard
+  blockinfile:
+    path: ../host_vars/{{ item }}.yml
+    block: |
+      vpn_wg0_privatekey: {% if hostvars[item].vpn_wg0_privatekey is defined %}{{ hostvars[item].vpn_wg0_privatekey}}{%else%}{{wg_privatekey.stdout}}{%endif%}
+
+      vpn_wg0_publickey: {% if hostvars[item].vpn_wg0_publickey is defined %}{{ hostvars[item].vpn_wg0_publickey}}{%else%}{{wg_publickey.stdout}}{%endif%}
+
+      vpn_wg0_presharedkey: {% if hostvars[item].vpn_wg0_presharedkey is defined %}{{hostvars[item].vpn_wg0_presharedkey}}{%else%}{{wg_presharedkey.stdout}}{%endif%}
+
+      vpn_wg0_listenport: {{ default_vpn_wg0_listenport }}
+      vpn_wg0_address: {{ vpn_wg0_network }}.{{ hostvars[item].ip_host }}{{ vpn_wg0_netmask }}
+
+    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item }} vpn wireguard wg0"
+  delegate_to: localhost
+  when: hostvars[item].vpn_wg0_privatekey is not defined

+ 7 - 0
roles/stable/build/tasks/install_feeds_libremesh.yml

@@ -0,0 +1,7 @@
+---
+- name: install feeds - libremesh - Add Libremesh feeds
+  blockinfile:
+    path: "{{ openwrt_build_dir }}/feeds.conf"
+    block: "{{ libremesh_feeds }}"
+  register: feeds
+  notify: "update and install feeds"

+ 7 - 0
roles/stable/build/tasks/install_feeds_packages.yml

@@ -0,0 +1,7 @@
+---
+- name: install feeds - packages - Add local packages
+  ansible.posix.synchronize:
+    src: packages/
+    dest: "{{ libremesh_profile_directory }}/"
+    delete: yes
+  notify: "update and install feeds"

+ 23 - 0
roles/stable/build/tasks/install_openwrt.yml

@@ -0,0 +1,23 @@
+---
+- name: install - openwrt - Requirements
+  include_tasks: install_openwrt_requirements.yml
+
+- name: install - openwrt - Check if openwrt_build_dir is present
+  stat:
+    path: "{{ openwrt_build_dir }}"
+  register: openwrt_build_dir_initialized
+
+- name: install - openwrt - Clone openwrt
+  git:
+    repo: https://git.openwrt.org/openwrt/openwrt.git
+    dest: "{{ openwrt_build_dir }}"
+    single_branch: yes
+    version: "{{ openwrt_version_tag }}"
+  when: not openwrt_build_dir_initialized.stat.exists
+
+- name: install - openwrt - cp feeds.conf.default feeds.conf
+  shell:
+    cmd: cp feeds.conf.default feeds.conf
+  args:
+    chdir: "{{ openwrt_build_dir }}"
+  notify: "update and install feeds"

+ 35 - 0
roles/stable/build/tasks/install_openwrt_requirements.yml

@@ -0,0 +1,35 @@
+---
+- name: install - openwrt - Install openwrt build system requirements
+  become: yes
+  ansible.builtin.apt:
+    update_cache: yes
+    state: present
+    pkg:
+      - build-essential
+      - ccache
+      - ecj
+      - fastjar
+      - file
+      - g++
+      - gawk
+      - gettext
+      - git
+      - java-propose-classpath
+      - libelf-dev
+      - libncurses5-dev
+      - libncursesw5-dev
+      - libssl-dev
+      - python
+      - python2.7-dev
+      - python3
+      - unzip
+      - wget
+      - python3-distutils-extra
+      - python3-setuptools
+      - python3-dev
+      - rsync
+      - subversion
+      - swig
+      - time
+      - xsltproc
+      - zlib1g-dev

+ 49 - 0
roles/stable/build/tasks/main.yml

@@ -0,0 +1,49 @@
+---
+- name: preflight
+  include_tasks: preflight.yml
+  when: not skip_preflight
+  tags:
+    - preflight
+
+- name: install - openwrt
+  include_tasks: install_openwrt.yml
+  when: not skip_openwrt_install
+  tags:
+    - openwrt_install
+
+- name: install - libremesh
+  include_tasks: install_feeds_libremesh.yml
+  when: not skip_libremesh_install
+  tags:
+    - libremesh_install
+
+- name: install - packages
+  include_tasks: install_feeds_packages.yml
+  tags:
+    - feeds_packages
+
+- name: Flush handlers
+  meta: flush_handlers
+
+- name: conf-files - lime mac
+  include_tasks: conf_files_lime_mac.yml
+  tags:
+    - conf_files_lime_mac
+
+- name: configure
+  include_tasks: configure.yml
+  tags:
+    - configure
+
+- name: build - Build
+  shell: make -j $(nproc) download world EXTRA_IMAGE_NAME="{{openwrt_extra_image_name}}"
+  args:
+    chdir: "{{ openwrt_build_dir }}"
+  tags:
+    - openwrt_build
+
+- name: webserver
+  include_tasks: webserver.yml
+  when: not skip_webserver_update
+  tags:
+    - webserver

+ 21 - 0
roles/stable/build/tasks/preflight.yml

@@ -0,0 +1,21 @@
+---
+- name: preflight - Init host_vars common
+  include_tasks: init_vars.yml
+  loop: "{{ groups['mesh_devices'] }}"
+  when: hostvars[item].ip_host is not defined
+
+- name: preflight - Init host_vars vpn wireguard
+  include_tasks: init_wg_vars.yml
+  loop: "{{ groups['mesh_devices'] }}"
+  when: with_wireguard and hostvars[item].vpn_wg0_privatekey is not defined
+
+- name: preflight - Generate lime-mac files
+  template:
+    src: lime_mac.j2
+    dest: "../lime-mac/{{ hostvars[item].lime_mac }}"
+  loop: "{{ groups['mesh_devices'] }}"
+  delegate_to: localhost
+
+- name: preflight - Add wireguard keys to server
+  include_tasks: vpn_wg_server.yml
+  when: with_wireguard

+ 16 - 0
roles/stable/build/tasks/vpn_wg_server.yml

@@ -0,0 +1,16 @@
+---
+- name: wg-server - Add peers to wg server
+  become: yes
+  blockinfile:
+    path: "/etc/wireguard/wg1.conf"
+    block: "{{ lookup('ansible.builtin.template', 'vpn_wg_peer.j2') }}"
+  delegate_to: "{{ hostvars[groups['wg_server'][0]].inventory_hostname }}"
+  loop: "{{ groups['mesh_devices'] }}"
+
+- name: wg-server - Make sure Wireguard Service is running
+  become: yes
+  service:
+    name: wg-quick@wg1
+    state: restarted
+    enabled: yes
+  delegate_to: "{{ hostvars[groups['wg_server'][0]].inventory_hostname }}"

+ 10 - 0
roles/stable/build/tasks/webserver.yml

@@ -0,0 +1,10 @@
+---
+- name: webserver - Rsync build directories
+  become: yes
+  shell:
+    cmd: rsync -d {{ openwrt_dir }}/* {{ webui_path }} --delete
+
+- name: webserver - Create symbolic links for all targets
+  become: yes
+  shell:
+    cmd: for path in $(ls {{ openwrt_dir }}); do ln -s -f {{ openwrt_dir }}/${path}/bin/targets/* {{ webui_path }}/${path}/; done;

+ 15 - 0
roles/stable/build/templates/default_config.j2

@@ -0,0 +1,15 @@
+# CONFIG_PACKAGE_dnsmasq is not set
+# CONFIG_PACKAGE_ppp is not set
+# CONFIG_PACKAGE_odhcpd-ipv6only is not set
+
+{{ target_configs }}
+
+{{ unstable_defaults }}
+
+{% if with_wireguard %}
+CONFIG_PACKAGE_profile-valsamoggia.ninux.org-vs-ninux-wg=y
+{% else %}
+# CONFIG_PACKAGE_profile-valsamoggia.ninux.org-vs-ninux-wg is not set
+{% endif %}
+
+# CONFIG_PACKAGE_profile-valsamoggia.ninux.org-vs-ninux-fastd is not set

+ 12 - 0
roles/stable/build/templates/default_target_config.j2

@@ -0,0 +1,12 @@
+CONFIG_USES_SQUASHFS=y
+CONFIG_TARGET_ROOTFS_SQUASHFS=y
+# CONFIG_TARGET_ROOTFS_EXT4FS is not set
+# CONFIG_TARGET_IMAGES_GZIP is not set
+
+CONFIG_TARGET_{{ openwrt_target }}=y
+CONFIG_TARGET_MULTI_PROFILE=y
+CONFIG_TARGET_{{ openwrt_target }}_{{ openwrt_subtarget }}=y
+
+{% for device in openwrt_devices %}
+CONFIG_TARGET_DEVICE_{{ openwrt_target }}_{{ openwrt_subtarget }}_DEVICE_{{ device }}=y
+{% endfor %}

+ 22 - 0
roles/stable/build/templates/lime_mac.j2

@@ -0,0 +1,22 @@
+config lime system
+{% if hostvars[item].config_lime_system is defined %}
+	{{ hostvars[item].config_lime_system }}
+{% endif %}
+
+config lime network
+{% if hostvars[item].config_lime_network is defined %}
+	{{ hostvars[item].config_lime_network }}
+{% endif %}
+
+config lime wifi
+{% if hostvars[item].config_lime_wifi is defined %}
+	{{ hostvars[item].config_lime_wifi }}
+{% endif %}
+
+{% if with_wireguard %}
+config generic_uci_config wireguard
+	list uci_set "wireguard.wg0=interface"
+	list uci_set "wireguard.wg0.address={{ hostvars[item].vpn_wg0_address }}"
+  list uci_set "wireguard.wg0.private_key={{ hostvars[item].vpn_wg0_privatekey }}"
+	list uci_set "wireguard.wg0.listen_port={{ hostvars[item].vpn_wg0_listenport }}"
+{% endif %}

+ 9 - 0
roles/stable/build/templates/vpn_wg_peer.j2

@@ -0,0 +1,9 @@
+{% for device in groups['mesh_devices'] %}
+
+[Peer]
+# {{ hostvars[device].hostname }}
+PublicKey = {{ hostvars[device].vpn_wg0_publickey }}
+Endpoint = 0.0.0.0:51800
+AllowedIPs = {{ vpn_wg0_network }}.{{ hostvars[device].ip_host }}/32
+
+{% endfor %}

+ 6 - 0
roles/stable/dnsmasq/handlers/main.yml

@@ -0,0 +1,6 @@
+---
+- name: restart dnsmasq
+  service:
+    name: dnsmasq
+    state: restarted
+  tags: dnsmasq

+ 21 - 0
roles/stable/dnsmasq/tasks/main.yml

@@ -0,0 +1,21 @@
+---
+- name: Install Dnsmasq
+  package:
+    name: dnsmasq
+    state: present
+  tags: dnsmasq
+
+- name: Set configuration file
+  template:
+    src: etc_dnsmasq.conf.j2
+    dest: /etc/dnsmasq.conf
+    validate: 'dnsmasq --test --conf-file=%s'
+  notify: restart dnsmasq
+  tags: dnsmasq
+
+- name: Make sure Dnsmasq is running
+  service:
+    name: dnsmasq
+    state: started
+    enabled: yes
+  tags: dnsmasq

+ 57 - 0
roles/stable/dnsmasq/templates/etc_dnsmasq.conf.j2

@@ -0,0 +1,57 @@
+# Dnsmasq configuration
+# {{ ansible_managed }}
+
+{% if dnsmasq_listen_address is defined %}
+listen-address={{ dnsmasq_listen_address }}
+{% endif %}
+{% if dnsmasq_interface is defined %}
+interface={{ dnsmasq_interface }}
+{% endif %}
+{% if dnsmasq_port is defined %}
+port={{ dnsmasq_port }}
+
+{% endif %}
+{% if dnsmasq_domain_needed %}
+domain-needed
+{% endif %}
+{% if dnsmasq_bogus_priv %}
+bogus-priv
+{% endif %}
+
+{% if dnsmasq_resolv_file is defined %}
+resolv-file={{ dnsmasq_resolv_file }}
+
+{% endif %}
+{% if dnsmasq_addn_hosts is defined %}
+addn-hosts={{ dnsmasq_addn_hosts }}
+
+{% endif %}
+{% if dnsmasq_expand_hosts %}
+expand-hosts
+{% endif %}
+{% if dnsmasq_domain is defined %}
+domain={{ dnsmasq_domain }}
+{% endif %}
+{% if dnsmasq_no_resolv is defined %}
+no-resolv
+{% endif %}
+
+{% if dnsmasq_upstream_servers is defined %}
+{% if dnsmasq_upstream_servers is iterable %}
+{% for host in dnsmasq_upstream_servers %}
+server={{ host }}
+{% endfor %}
+{% else %}
+server={{ dnsmasq_upstream_servers }}
+{% endif %}
+{% endif %}
+
+{% if dnsmasq_force_address is defined %}
+{% if dnsmasq_force_address is iterable %}
+{% for address in dnsmasq_force_address %}
+address={{ address }}
+{% endfor %}
+{% endif %}
+{% endif %}
+
+conf-dir=/etc/dnsmasq.d

+ 19 - 0
roles/stable/dnsmasq/vars/main.yml

@@ -0,0 +1,19 @@
+# roles/dnsmasq/defaults/main.yml
+---
+dnsmasq_listen_address: "{{ ansible_host }}"
+dnsmasq_interface: wg0
+# dnsmasq_port:
+
+dnsmasq_domain_needed: false
+dnsmasq_bogus_priv: true
+dnsmasq_expand_hosts: false
+dnsmasq_no_resolv: true
+
+dnsmasq_upstream_servers:
+  - '10.170.0.1'
+
+dnsmasq_force_address:
+  - '/ada/10.0.0.5'
+  - '/*.ada/10.0.0.5'
+  - '/belvedere/10.0.0.10'
+  - '/belvedere-vs/10.0.0.11'

+ 41 - 0
roles/stable/monitoring/alertmanager/tasks/main.yml

@@ -0,0 +1,41 @@
+---
+- name: Install alertmanager
+  ansible.builtin.import_role:
+    name: cloudalchemy.alertmanager
+  vars:
+    alertmanager_version: latest
+    alertmanager_receivers:
+      - name: email
+        email_configs:
+          - send_resolved: true
+            to: "{{ maintainer_emails }}"
+      - name: email_telegram_valli
+        email_configs:
+          - send_resolved: true
+            to: "{{ maintainer_emails }}"
+        telegram_configs:
+          - send_resolved: true
+            bot_token: "{{ telegram_bot_token }}"
+            api_url: "https://api.telegram.org"
+            chat_id: "{{ telegram_chat_id }}"
+            parse_mode: "HTML"
+    alertmanager_route:
+      group_by: ['alertname', 'cluster', 'service']
+      group_wait: 30s
+      group_interval: 5m
+      repeat_interval: 1d
+      receiver: email_telegram_valli
+      routes:
+        - match:
+            alertname: Watchdog
+          receiver: email
+          continue: false
+          repeat_interval: 1w
+    alertmanager_smtp:
+      from: "{{ smtp_from }}"
+      smarthost: "{{ smtp_smarthost }}"
+      auth_username: "{{ smtp_auth_username }}"
+      auth_password: "{{ smtp_auth_password }}"
+      auth_secret: ''
+      auth_identity: ''
+      require_tls: "True"

+ 4 - 0
roles/stable/monitoring/blackbox_exporter/tasks/main.yml

@@ -0,0 +1,4 @@
+---
+- name: Install Blackbox Exporter
+  include_role:
+    name: cloudalchemy.blackbox-exporter

+ 47 - 0
roles/stable/monitoring/blackbox_exporter/vars/main.yml

@@ -0,0 +1,47 @@
+---
+blackbox_exporter_version: 0.22.0 # 0.22.0 / 2022-08-02
+blackbox_exporter_web_listen_address: "0.0.0.0:9115"
+blackbox_exporter_cli_flags: {}
+blackbox_exporter_configuration_modules:
+  http_2xx_head:
+    http:
+      method: HEAD
+      follow_redirects: true
+      fail_if_ssl: false
+      fail_if_not_ssl: false
+      tls_config:
+        insecure_skip_verify: true
+      ip_protocol_fallback: false
+      preferred_ip_protocol: ip4
+      valid_http_versions:
+        - HTTP/1.1
+        - HTTP/2.0
+      valid_status_codes:
+        - 200
+        - 204
+    prober: http
+    timeout: 15s
+  http_2xx_get:
+    http:
+      method: GET
+      follow_redirects: true
+      fail_if_ssl: false
+      fail_if_not_ssl: false
+      tls_config:
+        insecure_skip_verify: true
+      ip_protocol_fallback: false
+      preferred_ip_protocol: ip4
+      valid_http_versions:
+        - HTTP/1.1
+        - HTTP/2.0
+      valid_status_codes:
+        - 200
+        - 204
+        - 302 # Found
+    prober: http
+    timeout: 15s
+  icmp:
+    prober: icmp
+    timeout: 5s
+    icmp:
+      preferred_ip_protocol: "ip4"

+ 17 - 0
roles/stable/monitoring/prometheus/tasks/main.yml

@@ -0,0 +1,17 @@
+---
+- name: Install Prometheus
+  ansible.builtin.import_role:
+    name: cloudalchemy.prometheus
+
+- name: Ensure Prometheus Service is running
+  service:
+    name: prometheus
+    state: restarted
+    enabled: yes
+
+- name: Ensure a job that reboot every 6 hours exists.
+  ansible.builtin.cron:
+    name: "reboot every 6 hours"
+    minute: "0"
+    hour: "*/6"
+    job: "/sbin/reboot"

+ 223 - 0
roles/stable/monitoring/prometheus/vars/main.yml

@@ -0,0 +1,223 @@
+---
+prometheus_version: 2.37.0 # LTS
+prometheus_binary_local_dir: '' # default /usr/local/bin
+prometheus_skip_install: false
+
+prometheus_config_dir: /etc/prometheus
+prometheus_db_dir: /var/lib/prometheus
+prometheus_read_only_dirs: []
+
+prometheus_web_listen_address: "0.0.0.0:9090"
+prometheus_web_external_url: ''
+# See https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md
+
+prometheus_storage_retention: "30d"
+# Available since Prometheus 2.7.0
+# [EXPERIMENTAL] Maximum number of bytes that can be stored for blocks. Units
+# supported: KB, MB, GB, TB, PB.
+prometheus_storage_retention_size: "0"
+
+# Alternative config file name, searched in ansible templates path.
+prometheus_config_file: 'prometheus.yml.j2'
+
+prometheus_targets: "{{ all_targets }}"
+
+prometheus_alertmanager_config:
+  - static_configs:
+    - targets:
+       - localhost:9093
+
+prometheus_scrape_configs:
+  - job_name: "prometheus"
+    metrics_path: "{{ prometheus_metrics_path }}"
+    static_configs:
+      - targets:
+          - "{{ ansible_fqdn | default(ansible_host) | default('localhost') }}:9090"
+  - job_name: "node"
+    file_sd_configs:
+      - files:
+          - "{{ prometheus_config_dir }}/file_sd/node.yml"
+
+  - job_name: 'blackbox-external-targets'
+    metrics_path: /probe
+    params:
+      module: [http_2xx_head]
+    static_configs:
+      - targets:
+        - https://www.google.com
+        - https://www.ripe.net
+    relabel_configs: "{{ blackbox_relabel_configs }}"
+
+  - job_name: 'blackbox-server_head'
+    metrics_path: /probe
+    params:
+      module: [http_2xx_head]
+    static_configs:
+      - targets:
+        - https://ada
+    relabel_configs: "{{ blackbox_relabel_configs }}"
+
+  - job_name: 'blackbox-server_get'
+    metrics_path: /probe
+    params:
+      module: [http_2xx_get]
+    static_configs:
+      - targets:
+         - https://torrent.ada/
+    relabel_configs: "{{ blackbox_relabel_configs }}"
+
+  - job_name: 'blackbox-ping-external'
+    metrics_path: /probe
+    params:
+      module: [icmp]
+    static_configs:
+      - targets:
+        - 1.1.1.1
+        - 8.8.8.8
+        - 4.2.2.2
+    relabel_configs: "{{ blackbox_relabel_configs }}"
+
+  - job_name: 'blackbox-ping-internal'
+    file_sd_configs:
+      - files:
+          - "{{ prometheus_config_dir }}/file_sd/blackbox_ping_internal.yml"
+    metrics_path: /probe
+    params:
+      module: [icmp]
+    relabel_configs: "{{ blackbox_relabel_configs }}"
+
+prometheus_alert_rules:
+  - alert: Watchdog
+    expr: vector(1)
+    for: 10m
+    labels:
+      severity: warning
+    annotations:
+      description: "This is an alert meant to ensure that the entire alerting pipeline is functional.\nThis alert is always firing, therefore it should always be firing in Alertmanager\nand always fire against a receiver. There are integrations with various notification\nmechanisms that send a notification when this alert is not firing. For example the\n\"DeadMansSnitch\" integration in PagerDuty."
+      summary: 'Ensure entire alerting pipeline is functional'
+  - alert: NodeDown
+    expr: "up{job=\"node\", alert=\"yes\"} == 0"
+    for: 5m
+    labels:
+      severity: critical
+    annotations:
+      description: '{% raw %}{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.{% endraw %}'
+      summary: '{% raw %}Instance {{ $labels.instance }} down{% endraw %}'
+  - alert: ToolDown
+    expr: "probe_success{job=\"blackbox-ping-internal\"} == 0"
+    for: 5m
+    labels:
+      severity: critical
+    annotations:
+      description: '{% raw %}{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.{% endraw %}'
+      summary: '{% raw %}Instance {{ $labels.instance }} down{% endraw %}'
+  - alert: RebootRequired
+    expr: 'node_reboot_required > 0'
+    labels:
+      severity: warning
+    annotations:
+      description: '{% raw %}{{ $labels.instance }} requires a reboot.{% endraw %}'
+      summary: '{% raw %}Instance {{ $labels.instance }} - reboot required{% endraw %}'
+  - alert: NodeFilesystemSpaceFillingUp
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up.{% endraw %}'
+      summary: 'Filesystem is predicted to run out of space within the next 24 hours.'
+    expr: "(\n  node_filesystem_avail_bytes{job=\"node\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node\",fstype!=\"\"} * 100 < 40\nand\n  predict_linear(node_filesystem_avail_bytes{job=\"node\",fstype!=\"\"}[6h], 24*60*60) < 0\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: warning
+  - alert: NodeFilesystemSpaceFillingUp
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up fast.{% endraw %}'
+      summary: 'Filesystem is predicted to run out of space within the next 4 hours.'
+    expr: "(\n  node_filesystem_avail_bytes{job=\"node\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node\",fstype!=\"\"} * 100 < 20\nand\n  predict_linear(node_filesystem_avail_bytes{job=\"node\",fstype!=\"\"}[6h], 4*60*60) < 0\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: critical
+  - alert: NodeFilesystemAlmostOutOfSpace
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left.{% endraw %}'
+      summary: 'Filesystem has less than 5% space left.'
+    expr: "(\n  node_filesystem_avail_bytes{job=\"node\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node\",fstype!=\"\"} * 100 < 5\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: warning
+  - alert: NodeFilesystemAlmostOutOfSpace
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left.{% endraw %}'
+      summary: 'Filesystem has less than 3% space left.'
+    expr: "(\n  node_filesystem_avail_bytes{job=\"node\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node\",fstype!=\"\"} * 100 < 3\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: critical
+  - alert: NodeFilesystemFilesFillingUp
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up.{% endraw %}'
+      summary: 'Filesystem is predicted to run out of inodes within the next 24 hours.'
+    expr: "(\n  node_filesystem_files_free{job=\"node\",fstype!=\"\"} / node_filesystem_files{job=\"node\",fstype!=\"\"} * 100 < 40\nand\n  predict_linear(node_filesystem_files_free{job=\"node\",fstype!=\"\"}[6h], 24*60*60) < 0\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: warning
+  - alert: NodeFilesystemFilesFillingUp
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up fast.{% endraw %}'
+      summary: 'Filesystem is predicted to run out of inodes within the next 4 hours.'
+    expr: "(\n  node_filesystem_files_free{job=\"node\",fstype!=\"\"} / node_filesystem_files{job=\"node\",fstype!=\"\"} * 100 < 20\nand\n  predict_linear(node_filesystem_files_free{job=\"node\",fstype!=\"\"}[6h], 4*60*60) < 0\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: critical
+  - alert: NodeFilesystemAlmostOutOfFiles
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left.{% endraw %}'
+      summary: 'Filesystem has less than 5% inodes left.'
+    expr: "(\n  node_filesystem_files_free{job=\"node\",fstype!=\"\"} / node_filesystem_files{job=\"node\",fstype!=\"\"} * 100 < 5\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: warning
+  - alert: NodeFilesystemAlmostOutOfFiles
+    annotations:
+      description: '{% raw %}Filesystem on {{ $labels.device }} at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left.{% endraw %}'
+      summary: 'Filesystem has less than 3% inodes left.'
+    expr: "(\n  node_filesystem_files_free{job=\"node\",fstype!=\"\"} / node_filesystem_files{job=\"node\",fstype!=\"\"} * 100 < 3\nand\n  node_filesystem_readonly{job=\"node\",fstype!=\"\"} == 0\n)\n"
+    for: 1h
+    labels:
+      severity: critical
+  - alert: NodeNetworkReceiveErrs
+    annotations:
+      description: '{% raw %}{{ $labels.instance }} interface {{ $labels.device }} has encountered {{ printf "%.0f" $value }} receive errors in the last two minutes.{% endraw %}'
+      summary: 'Network interface is reporting many receive errors.'
+    expr: "increase(node_network_receive_errs_total[2m]) > 10\n"
+    for: 1h
+    labels:
+      severity: warning
+  - alert: NodeNetworkTransmitErrs
+    annotations:
+      description: '{% raw %}{{ $labels.instance }} interface {{ $labels.device }} has encountered {{ printf "%.0f" $value }} transmit errors in the last two minutes.{% endraw %}'
+      summary: 'Network interface is reporting many transmit errors.'
+    expr: "increase(node_network_transmit_errs_total[2m]) > 10\n"
+    for: 1h
+    labels:
+      severity: warning
+  - alert: NodeHighNumberConntrackEntriesUsed
+    annotations:
+      description: '{% raw %}{{ $value | humanizePercentage }} of conntrack entries are used{% endraw %}'
+      summary: 'Number of conntrack are getting close to the limit'
+    expr: "(node_nf_conntrack_entries / node_nf_conntrack_entries_limit) > 0.75\n"
+    labels:
+      severity: warning
+  - alert: NodeClockSkewDetected
+    annotations:
+      message: '{% raw %}Clock on {{ $labels.instance }} is out of sync by more than 300s. Ensure NTP is configured correctly on this host.{% endraw %}'
+      summary: 'Clock skew detected.'
+    expr: "(\n  node_timex_offset_seconds > 0.05\nand\n  deriv(node_timex_offset_seconds[5m]) >= 0\n)\nor\n(\n  node_timex_offset_seconds < -0.05\nand\n  deriv(node_timex_offset_seconds[5m]) <= 0\n)\n"
+    for: 10m
+    labels:
+      severity: warning
+  - alert: NodeClockNotSynchronising
+    annotations:
+      message: '{% raw %}Clock on {{ $labels.instance }} is not synchronising. Ensure NTP is configured on this host.{% endraw %}'
+      summary: 'Clock not synchronising.'
+    expr: "min_over_time(node_timex_sync_status[5m]) == 0\n"
+    for: 10m
+    labels:
+      severity: warning

+ 6 - 0
roles/stable/nginx/defaults/main.yml

@@ -0,0 +1,6 @@
+---
+reverse_services: []
+fpm_services: []
+with_certbot: false
+with_ssl: false
+with_distributed_certificates: false

+ 23 - 0
roles/stable/nginx/tasks/certbot.yml

@@ -0,0 +1,23 @@
+---
+- name: Install snapd
+  become: yes
+  apt:
+    pkg: ['snapd']
+  
+- name: Install snap core
+  become: yes
+  snap:
+    name: core
+
+- name: Install cerbot via snap
+  become: yes
+  snap:
+    name: certbot
+    classic: yes
+
+- name: Generate certificate if needed
+  become: yes
+  command: /snap/bin/certbot --nginx --non-interactive --agree-tos --expand
+      --domains {{ fpm_services | items2dict(key_name='server_name', value_name='server_name') | join(',') }}
+        {{ reverse_services | items2dict(key_name='server_name', value_name='server_name') | join(',') }}
+      --email {{certbot_email}}

+ 38 - 0
roles/stable/nginx/tasks/certificates.yml

@@ -0,0 +1,38 @@
+---
+- name: Create tmp certificates directory
+  file:
+    path: ./tmp/{{ hostvars['ada'].inventory_hostname }}
+    state: directory
+  delegate_to: localhost
+
+- name: Create certificates directory
+  file:
+    path: /etc/nginx/certs
+    state: directory
+
+- name: Copy crt from CA
+  ansible.builtin.fetch:
+    src: /etc/nginx/certs/{{ hostvars['ada'].inventory_hostname }}/ada.crt
+    dest: ./tmp/{{ hostvars['ada'].inventory_hostname }}/
+    flat: yes
+  delegate_to: "{{ item }}"
+  loop: "{{ groups['ca'] }}"
+
+- name: Copy key from CA
+  ansible.builtin.fetch:
+    src: /etc/nginx/certs/{{ hostvars['ada'].inventory_hostname }}/ada.key
+    dest: ./tmp/{{ hostvars['ada'].inventory_hostname }}/
+    flat: yes
+  delegate_to: "{{ item }}"
+  loop: "{{ groups['ca'] }}"
+
+- name: Copy to belvedere
+  ansible.builtin.copy:
+    src: ./tmp/{{ hostvars['ada'].inventory_hostname }}/
+    dest: /etc/nginx/certs/{{ hostvars['ada'].inventory_hostname }}/
+
+- name: Delete tmp
+  file:
+    path: ./tmp/
+    state: absent
+  delegate_to: localhost

+ 78 - 0
roles/stable/nginx/tasks/main.yml

@@ -0,0 +1,78 @@
+---
+- name: Install NGINX
+  become: yes
+  apt:
+    name: nginx
+
+- name: Default Configuration
+  become: yes
+  template:
+    src: default.j2
+    dest: /etc/nginx/sites-available/default
+
+- name: Link Default NGINX Configuration
+  become: yes
+  file:
+    src: "/etc/nginx/sites-available/default"
+    dest: "/etc/nginx/sites-enabled/default"
+    state: link
+
+- name: Configure Reverse Proxies
+  become: yes
+  template:
+    src: reverse_proxy.conf.j2
+    dest: /etc/nginx/sites-available/{{item.server_name}}.conf
+  loop: "{{ reverse_services }}"
+
+- name: Link NGINX Reverse Proxies
+  become: yes
+  file:
+    src: "/etc/nginx/sites-available/{{item.server_name}}.conf"
+    dest: "/etc/nginx/sites-enabled/{{item.server_name}}.conf"
+    state: link
+  loop: "{{ reverse_services }}"
+
+- name: Configure FPM Services
+  become: yes
+  template:
+    src: fpm_service.conf.j2
+    dest: /etc/nginx/sites-available/{{item.server_name}}.conf
+  loop: "{{ fpm_services }}"
+
+- name: Link NGINX FPM Services
+  become: yes
+  file:
+    src: "/etc/nginx/sites-available/{{item.server_name}}.conf"
+    dest: "/etc/nginx/sites-enabled/{{item.server_name}}.conf"
+    state: link
+  loop: "{{ fpm_services }}"
+
+- name: Configure Static Services
+  become: yes
+  template:
+    src: static_service.conf.j2
+    dest: /etc/nginx/sites-available/{{item.server_name}}.conf
+  loop: "{{ static_services }}"
+
+- name: Link NGINX Static Services
+  become: yes
+  file:
+    src: "/etc/nginx/sites-available/{{item.server_name}}.conf"
+    dest: "/etc/nginx/sites-enabled/{{item.server_name}}.conf"
+    state: link
+  loop: "{{ static_services }}"
+
+- name: Make sure NGINX Service is running
+  become: yes
+  service:
+    name: nginx
+    state: restarted
+    enabled: yes
+
+- name: Run Certbot if needed
+  include: certbot.yml
+  when: with_certbot | bool
+
+- name: Sync distributed certificates
+  include: certificates.yml
+  when: with_distributed_certificates | bool

+ 25 - 0
roles/stable/nginx/templates/default.j2

@@ -0,0 +1,25 @@
+# cache
+proxy_cache_path /tmp levels=1:2 keys_zone=STATIC:10m	inactive=24h  max_size=10g use_temp_path=off;
+
+{% if with_certbot -%}
+# redirect all http traffic to https
+server {
+	listen 80 default_server;
+	listen [::]:80 default_server;
+	server_name _;
+	return 301 https://$host$request_uri;
+}
+{%- endif %}
+
+server {
+  listen 80;
+  listen [::]:80;
+  server_name _server_name;
+  root /var/www/html;
+}
+
+# enable proxy websocket
+map $http_upgrade $connection_upgrade {
+	default upgrade;
+	''      close;
+}

+ 31 - 0
roles/stable/nginx/templates/fpm_service.conf.j2

@@ -0,0 +1,31 @@
+
+server {
+  listen 80;
+  listen [::]:80;
+  listen 443 ssl http2;
+  server_name {{item.server_name}};
+  root {{item.root | default('/var/www/html/')}};
+  index index.html index.html index.htm index.php;
+
+  # keepalive_timeout 200;
+  {{item.custom_config | default('') | indent(2)}}
+
+  location / {
+    try_files $uri $uri/ /index.php?$args;
+  }
+
+  location ~ \.php$ {
+    include snippets/fastcgi-php.conf;
+    fastcgi_pass {{item.proxy_pass | default('unix:/run/php/php7.4-fpm.sock')}};
+    {{item.custom_fastcgi_config | default('') | indent(2)}}
+  }
+
+  # compression
+  gzip on;
+  gzip_types      text/plain application/xml application/json;
+  gzip_proxied    no-cache no-store private expired auth;
+  gzip_min_length 1000;
+
+  # cache
+  proxy_cache STATIC;
+}

+ 44 - 0
roles/stable/nginx/templates/reverse_proxy.conf.j2

@@ -0,0 +1,44 @@
+
+server {
+  listen 80;
+  listen [::]:80;
+  listen 443 ssl http2;
+  server_name {{item.server_name}};
+
+  keepalive_timeout 200;
+  {{item.custom_config | default('') | indent(2)}}
+
+  {% if with_ssl %}
+
+  ssl_session_timeout 5m;
+  ssl_session_cache shared:SSL:50m;
+  ssl_session_tickets off;
+  ssl_certificate /etc/nginx/certs/ada/ada.crt;
+  ssl_certificate_key /etc/nginx/certs/ada/ada.key;
+  {% endif %}
+
+  location / {
+    proxy_pass {{item.proxy_pass}};
+
+    # set host
+    proxy_set_header Host              $host;
+    proxy_set_header X-Forwarded-For   42.42.42.42;
+    proxy_set_header X-Forwarded-Proto $scheme;
+    proxy_set_header X-Forwarded-Host  $host;
+    proxy_set_header X-Forwarded-Port  $server_port;
+
+    # websocket proxy
+    proxy_http_version 1.1;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+
+    # compression
+    gzip on;
+    gzip_types      text/plain application/xml application/json;
+    gzip_proxied    no-cache no-store private expired auth;
+    gzip_min_length 1000;
+
+    # cache
+    proxy_cache STATIC;
+  }
+}

+ 33 - 0
roles/stable/nginx/templates/static_service.conf.j2

@@ -0,0 +1,33 @@
+
+server {
+  listen 80;
+  listen [::]:80;
+  listen 443 ssl http2;
+  server_name {{item.server_name}};
+
+  keepalive_timeout 200;
+  {{item.custom_config | default('') | indent(2)}}
+
+  {% if with_ssl %}
+
+  ssl_session_timeout 5m;
+  ssl_session_cache shared:SSL:50m;
+  ssl_session_tickets off;
+  ssl_certificate /etc/nginx/certs/ada/ada.crt;
+  ssl_certificate_key /etc/nginx/certs/ada/ada.key;
+  {% endif %}
+
+  root {{ item.server_root }};
+
+  location / {
+
+    # compression
+    gzip on;
+    gzip_types      text/plain application/xml application/json;
+    gzip_proxied    no-cache no-store private expired auth;
+    gzip_min_length 1000;
+
+    # cache
+    proxy_cache STATIC;
+  }
+}

+ 4 - 0
roles/stable/openssl_certificates/defaults/main.yml

@@ -0,0 +1,4 @@
+skip_certification_authority: false
+skip_certification_authority_webserver: true
+skip_server_certificate: false
+skip_server_certificate_webserver: true

BIN
roles/stable/openssl_certificates/files/ca/images/android-12_firefox_ca-enable.jpg


BIN
roles/stable/openssl_certificates/files/ca/images/android-12_firefox_ca-enabled.jpg


BIN
roles/stable/openssl_certificates/files/ca/images/android-12_settings_ca-install.jpg


BIN
roles/stable/openssl_certificates/files/ca/images/android-12_settings_ca-installed.jpg


BIN
roles/stable/openssl_certificates/files/ca/images/green_lock.png


BIN
roles/stable/openssl_certificates/files/ca/images/linux_chromium.jpg


BIN
roles/stable/openssl_certificates/files/ca/images/linux_firefox.jpg


+ 41 - 0
roles/stable/openssl_certificates/files/ca/images/openssl_logo.svg

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   version="1.1"
+   id="svg2"
+   viewBox="0 0 973.70528 248.96588"
+   height="25.5px"
+   width="100px">
+  <defs
+     id="defs4" />
+  <g
+     transform="translate(60.758696,-843.33549)"
+     id="layer1">
+    <text
+       id="text3336"
+       y="1012.3623"
+       x="3.8487569e-06"
+       style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:180px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'"
+         y="1012.3623"
+         x="3.8487569e-06"
+         id="tspan3338"><tspan
+   id="tspan3340"
+   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:180px;font-family:sans-serif;-inkscape-font-specification:sans-serif;fill:#480e0c;fill-opacity:1">Open</tspan>SSL</tspan></text>
+    <text
+       id="text817"
+       y="1049.0681"
+       x="176.75166"
+       style="font-style:normal;font-weight:normal;font-size:17.49999619px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.93749976"
+       xml:space="preserve"><tspan
+         style="font-size:37.49998856px;stroke-width:0.93749976"
+         y="1049.0681"
+         x="176.75166"
+         id="tspan815">Cryptography and SSL/TLS Toolkit</tspan></text>
+  </g>
+</svg>

File diff suppressed because it is too large
+ 5 - 0
roles/stable/openssl_certificates/files/ca/vendor/imagebox.min.css


File diff suppressed because it is too large
+ 5 - 0
roles/stable/openssl_certificates/files/ca/vendor/imagebox.min.js


+ 44 - 0
roles/stable/openssl_certificates/tasks/authority.yml

@@ -0,0 +1,44 @@
+---
+- name: Install openssl
+  apt:
+    update_cache: yes
+    state: present
+    pkg:
+      - openssl
+
+- name: Make certificates directory
+  file:
+    path: "{{ ca_cert_dir }}"
+    state: directory
+
+- name: Certification Authority - Check if the private key is already present
+  stat:
+    path: "{{ ca_cert_dir }}/{{ ca_cert_name }}.key"
+  register: ca_cert_key
+
+- name: Certification Authority - Generate the CA private key
+  shell: openssl genrsa -des3 -passout pass:"{{ ca_cert_key_pass }}" -out {{ ca_cert_name }}.key 4096
+  args:
+    chdir: "{{ ca_cert_dir }}"
+  when: not ca_cert_key.stat.exists
+
+- name: Certification Authority - Check if the CA root certificate is already presentt
+  stat:
+    path: "{{ ca_cert_dir }}/{{ ca_cert_name }}.pem"
+  register: ca_cert_pem
+
+- name: Certification Authority - Generate the CA root configuration file
+  template:
+    src: authority.conf.j2
+    dest: "{{ ca_cert_dir }}/{{ ca_cert_name }}.conf"
+  when: not ca_cert_pem.stat.exists
+
+- name: Certification Authority - Generate the CA root certificate
+  shell: openssl req -x509 -new -nodes \
+          -key {{ ca_cert_name }}.key \
+          -passin pass:"{{ ca_cert_key_pass }}" \
+          -sha256 -days {{ ca_cert_days }} -out {{ ca_cert_name }}.pem \
+          -config {{ ca_cert_name }}.conf
+  args:
+    chdir: "{{ ca_cert_dir }}"
+  when: not ca_cert_pem.stat.exists

+ 42 - 0
roles/stable/openssl_certificates/tasks/authority_webserver.yml

@@ -0,0 +1,42 @@
+---
+- name: Certification Authority - Webserver - Create static_service root
+  file:
+    path: /home/antennine/ca/certs
+    state: directory
+
+- name: Certification Authority - Webserver - Copy certificates to webserver dir
+  copy:
+    src: /etc/certs/{{ ca_cert_name }}.pem
+    dest: /home/antennine/ca/certs/
+    remote_src: true
+
+- name: Certification Authority - Webserver - Create sha1 fingerprint
+  shell: openssl x509 -sha1 -in {{ ca_cert_dir }}/{{ ca_cert_name }}.pem -noout -fingerprint
+  register: ca_cert_sha1
+
+# - name: Certification Authority - Webserver - Convert certificate in format DER
+#   shell: openssl x509 -in {{ ca_cert_name }}.pem -inform pem -out {{ ca_cert_name }}.der -outform der
+#   register: ca_cert_der
+
+# - name: Certification Authority - Webserver - Convert certificate in format TXT
+#   shell:
+#   register: ca_cert_txt
+
+# - name: Certification Authority - Webserver - Create certificate revocation list CRL
+#   shell:
+#   register: ca_cert_crl
+
+- name: Certification Authority - Webserver - Generate index.html
+  template:
+    src: authority.html.j2
+    dest: "/home/antennine/ca/index.html"
+
+- name: Certification Authority - Webserver - Copy files
+  copy:
+    src: ./ca/
+    dest: /home/antennine/ca/
+
+- name: Certification Authority - Webserver - Webserver
+  include_role:
+    name: ../roles/stable/nginx
+    tasks_from: main

+ 16 - 0
roles/stable/openssl_certificates/tasks/main.yml

@@ -0,0 +1,16 @@
+---
+- name: Certification Authority
+  include_tasks: authority.yml
+  when: not skip_certification_authority
+
+- name: Server Certificate
+  include_tasks: server.yml
+  when: not skip_server_certificate
+
+- name: Certification Authority - Webserver
+  include_tasks: authority_webserver.yml
+  when: not skip_certification_authority_webserver
+
+- name: Server Certificate - Webserver
+  include_tasks: server_webserver.yml
+  when: not skip_server_certificate_webserver

+ 42 - 0
roles/stable/openssl_certificates/tasks/server.yml

@@ -0,0 +1,42 @@
+---
+- name: Server Certificate - Make certificates directory
+  file:
+    path: "{{ server_cert_dir }}"
+    state: directory
+
+- name: Server Certificate - Check if private key is already present
+  stat:
+    path: "{{ server_cert_dir }}/{{ server_cert_name }}.key"
+  register: server_cert_key
+
+- name: Server Certificate - Generate the private key
+  shell: openssl genrsa -out {{ server_cert_name }}.key 4096
+  args:
+    chdir: "{{ server_cert_dir }}"
+  when: not server_cert_key.stat.exists
+
+- name: Server Certificate - Generate the server configuration file
+  template:
+    src: server.conf.j2
+    dest: "{{ server_cert_dir }}/{{ server_cert_name }}.conf"
+
+- name: Server Certificate - Create the certificate signin request
+  shell: openssl req -new -key {{ server_cert_name }}.key -days {{ server_cert_days }} -out {{ server_cert_name }}.csr -config {{ server_cert_name }}.conf
+  args:
+    chdir: "{{ server_cert_dir }}"
+
+- name: Server Certificate - Create the X509 V3 extension config file to define SAN
+  template:
+    src: server.ext.j2
+    dest: "{{ server_cert_dir }}/{{ server_cert_name }}.ext"
+
+- name: Server Certificate - Sign the certificate with x509 V3 extensions
+  shell: openssl x509 -req \
+         -in {{ server_cert_name }}.csr \
+         -CA {{ ca_cert_dir }}/{{ ca_cert_name }}.pem -CAkey {{ ca_cert_dir }}/{{ ca_cert_name }}.key -CAcreateserial \
+         -passin pass:"{{ ca_cert_key_pass }}" \
+         -out {{ server_cert_name }}.crt \
+         -days {{ server_cert_days }} -sha256 \
+         -extfile {{ server_cert_name }}.ext
+  args:
+    chdir: "{{ server_cert_dir }}"

+ 20 - 0
roles/stable/openssl_certificates/tasks/server_webserver.yml

@@ -0,0 +1,20 @@
+---
+- name: Server Certificate - Webserver - Ensure webserver certs dir exists
+  file:
+    path: /etc/nginx/certs/{{ server_cert_name }}/
+    state: directory
+
+- name: Server Certificate - Webserver - Copy server key
+  copy:
+    src: /etc/certs/{{ server_cert_name }}/{{ server_cert_name }}.key
+    dest: /etc/nginx/certs/{{ server_cert_name }}/
+    remote_src: true
+
+- name: Server Certificate - Webserver - Copy server certificate
+  copy:
+    src: /etc/certs/{{ server_cert_name }}/{{ server_cert_name }}.crt
+    dest: /etc/nginx/certs/{{ server_cert_name }}/
+    remote_src: true
+
+- name: Server Certificate - Webserver - Restart Nginx
+  shell: systemctl restart nginx

+ 14 - 0
roles/stable/openssl_certificates/templates/authority.conf.j2

@@ -0,0 +1,14 @@
+[req]
+default_bits = 4096
+prompt = no
+default_md = sha256
+distinguished_name = dn
+
+[dn]
+C = {{ ca_distinguished_name['C'] }}
+ST = {{ ca_distinguished_name['ST'] }}
+L = {{ ca_distinguished_name['L'] }}
+O = {{ ca_distinguished_name['O'] }}
+OU = {{ ca_distinguished_name['OU'] }}
+emailAddress = {{ ca_distinguished_name['emailAddress'] }}
+CN = {{ ca_distinguished_name['CN'] }}

+ 140 - 0
roles/stable/openssl_certificates/templates/authority.html.j2

@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<meta http-equiv="content-type" content="text/html;charset=utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<title>Certificati di Antennine</title>
+	<link rel="shortcut icon" href="images/green_lock.png" type="image/png" />
+	<link rel="stylesheet" href="vendor/imagebox.min.css" />
+	<script src="vendor/imagebox.min.js"></script>
+</head>
+<style>
+	:root{font-size:14px;font-family:sans-serif}
+	body{padding-top:3rem;background:#efefef}
+	body > a {position:fixed;max-width:10rem;top:1rem;right:1rem}
+	h2{margin:4rem 0 1rem}
+	h3{margin:0 0 1rem}
+	img{max-width:90vw}
+	figure{margin:1rem}
+	figure img{padding:1rem 0}
+	.site-name{flex-wrap:nowrap}
+	.site-logo{width:2rem;height:2rem;padding:1rem 1rem 1rem 0}
+	code {background:#333;color:#fff;padding:0.6rem;border-radius:3px;display:block;overflow-x:scroll}
+	article,figure div{display:flex;flex-wrap:wrap}
+	article:first-of-type{align-items:center}
+	@media screen and (min-width:640px)
+	{
+		body{padding:1rem}
+		figure,figure img{max-width: 400px}
+		figure div img{max-width: calc(200px - 1rem);margin: 0 0.5rem}
+	}
+</style>
+
+<body>
+	<a href="https://openssl.org">
+		<img alt="Openssl logo" src="/images/openssl_logo.svg">
+	</a>
+	<main>
+		<article class="site-name">
+			<img class="site-logo" alt="Openssl logo" src="/images/green_lock.png">
+			<h1>Certificati di {{ ca_distinguished_name['O'] }}</h1>
+		</article>
+
+		<div>
+			<p>In questa pagina si trovano i certificati e le informazioni riguardanti la
+			Certification Authority di {{ ca_distinguished_name['O'] }}.</p>
+
+			<p>Il certificato è disponibile:
+			<ul>
+				<!-- <li>in formato <a href="certs/{{ ca_cert_name }}.der">DER</a></li> -->
+				<li>in formato <a href="certs/{{ ca_cert_name }}.pem">PEM</a></li>
+				<!-- <li>in formato <a href="certs/{{ ca_cert_name }}.txt">testo</a></li> -->
+			</ul>
+
+			<!-- <p>La Certification Revocation List è reperibile all'indirizzo
+			<a href="https://{{ static_services[0]['server_name'] }}/crl.pem">https://{{ static_services[0]['server_name'] }}/crl.pem</a>.</p> -->
+		</div>
+
+		<h2>Verifica</h2>
+		<div>
+			<p>Dopo aver scaricato il certificato, verificare la fingerprint tramite il comando di openssl:</p>
+			<code>$ openssl x509 -sha1 -in {{ ca_cert_name }}.pem -noout -fingerprint</code>
+			<p>Che deve resitituire questo risultato:</p>
+		  <code>{{ ca_cert_sha1.stdout }}</code>
+		</div>
+
+		<h2>Installazione su sistema Linux</h2>
+		<article>
+			<figure>
+				<figcaption>
+					<h3>Firefox</h3>
+					<p>Andare in <a href="about:preferences#privacy">about:preferences#privacy</a></p>
+					<p>Ed importare il certificato nella sezione <b>Authorities</b></p>
+				</figcaption>
+				<img data-imagebox alt="Screenshot installazione su Firefox" src="./images/linux_firefox.jpg">
+
+			</figure>
+
+			<figure>
+				<figcaption>
+					<h3>Chromium</h3>
+					<p>Andare in <a href="chrome://settings/certificates">chrome://settings/certificates</a></p>
+					<p>Ed importare il certificato nella sezione <b>Authorities</b></p>
+				</figcaption>
+				<img data-imagebox alt="Screenshot installazione su Chromium" src="./images/linux_chromium.jpg">
+			</figure>
+
+			<figure>
+				<h3>Linux system-wide (Debian, Ubuntu)</h3>
+				<p>Per installare la CA system-wide su Linux usare i seguenti passi:</p>
+
+		    <p>Mettere una copia del certificato in formato PEM in <b>/usr/share/ca-certificates/</b></p>
+				<code># cp ~/Downloads/antennineCA.pem /usr/share/ca-certificates/</code>
+		    <p>Aggiungere il nome del file del certificato (senza directory) alla fine di <b>/etc/ca-certificates.conf</b></p>
+				<code># echo {{ ca_cert_name }}.pem >> /etc/ca-certificates.conf</code>
+				<p>Installare il certificato</p>
+		    <code># update-ca-certificates --verbose</code>
+			</figure>
+		</article>
+
+		<h2>Installazione su sistema Android</h2>
+		<p>Nota: su Android è necessario installare la CA su tutto il sistema (system-wide).</p>
+		<p>Firefox inoltre richiede di abilitare l'utilizzo dei certificati installati dall'utente.</p>
+
+		<article>
+			<figure>
+				<figcaption>
+					<h3>Android system-wide</h3>
+					<p>Andare in <b>Settings</b> e ricercare la sezione dei certificati</p>
+					<p>Installare il certificato che verrà inserito nella sezione <b>User</b> e non <b>System</b></p>
+					<p>Ora sui browsers Chrome, Brave, ecc. sarà possibile navigare col protocollo sicuro <b>https://</b></p>
+				</figcaption>
+				<div>
+					<img data-imagebox alt="Screenshot installazione su Android" src="./images/android-12_settings_ca-install.jpg">
+					<img data-imagebox alt="Screenshot installazione su Android" src="./images/android-12_settings_ca-installed.jpg">
+				</div>
+			</figure>
+
+			<figure>
+				<figcaption>
+					<h3>Firefox</h3>
+					<p>Andare in <b>Settings</b> e poi in <b>About Firefox</b></p>
+					<p>Toccare 7 volte il logo di Firefox per abilitare i <b>Secret Settings</b></p>
+					<p>Andare in <b>Settings</b> e poi in <b>Secret Settings</b>, e abilitare <b>Use third party CA certificates</b></p>
+				</figcaption>
+				<div>
+					<img data-imagebox alt="Screenshot installazione su Firefox Android" src="./images/android-12_firefox_ca-enable.jpg">
+					<img data-imagebox alt="Screenshot installazione su Firefox Android" src="./images/android-12_firefox_ca-enabled.jpg">
+				</div>
+			</figure>
+
+			<figure>
+				<h3>Firefox Beta, Firefox Nightly, IceCatMobile</h3>
+				<p>In altre versioni derivate da Firefox ricercare about:config</p>
+				<p>Andare in <a href="about:config">about:config</a> e impostare:</p>
+				<p><b>security.enterprise_roots.enabled = true</b></p>
+			</figure>
+		</article>
+	</main>
+</body>
+</html>

+ 14 - 0
roles/stable/openssl_certificates/templates/server.conf.j2

@@ -0,0 +1,14 @@
+[req]
+default_bits = 4096
+prompt = no
+default_md = sha256
+distinguished_name = dn
+
+[dn]
+C = {{ server_distinguished_name['C'] }}
+ST = {{ server_distinguished_name['ST'] }}
+L = {{ server_distinguished_name['L'] }}
+O = {{ server_distinguished_name['O'] }}
+OU = {{ server_distinguished_name['OU'] }}
+emailAddress = {{ server_distinguished_name['emailAddress'] }}
+CN = {{ server_distinguished_name['CN'] }}

Some files were not shown because too many files changed in this diff