From e4dc5745cd1cea1f5f89f0ce9bca6ad2eb11eb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Thu, 13 Aug 2026 21:47:53 +0200 Subject: [PATCH 01/12] Pull out nginx and dehydrated roles Install nginx directly without needing using third-party role --- ansible/deploy-clickhouse-proxy.yml | 5 +- ansible/deploy-monitoring-proxy.yml | 4 +- ansible/deploy-notebook.yml | 2 + ansible/deploy-ooni-backend.yml | 1 + ansible/roles/dehydrated/meta/main.yml | 5 -- ansible/roles/nginx/defaults/main.yml | 9 +++ ansible/roles/nginx/tasks/main.yml | 75 ++++++++++++++++++- ansible/roles/notebook/tasks/jupyterhub.yml | 11 --- .../prometheus_node_exporter/tasks/main.yml | 16 ---- 9 files changed, 91 insertions(+), 37 deletions(-) delete mode 100644 ansible/roles/dehydrated/meta/main.yml diff --git a/ansible/deploy-clickhouse-proxy.yml b/ansible/deploy-clickhouse-proxy.yml index 69be5ebb..bf69e389 100644 --- a/ansible/deploy-clickhouse-proxy.yml +++ b/ansible/deploy-clickhouse-proxy.yml @@ -6,9 +6,10 @@ become: true roles: - role: bootstrap + - role: nginx - role: dehydrated - vars: - ssl_domains: + vars: + ssl_domains: - "{{ inventory_hostname }}" tls_cert_dir: /var/lib/dehydrated/certs - role: clickhouse_proxy diff --git a/ansible/deploy-monitoring-proxy.yml b/ansible/deploy-monitoring-proxy.yml index edeb3bf2..945021f9 100644 --- a/ansible/deploy-monitoring-proxy.yml +++ b/ansible/deploy-monitoring-proxy.yml @@ -6,13 +6,13 @@ become: true roles: - role: bootstrap + - role: nginx + tags: nginx - role: dehydrated vars: ssl_domains: - "{{ inventory_hostname }}" tls_cert_dir: /var/lib/dehydrated/certs - - role: nginx - tags: nginx - role: monitoring_proxy vars: monitoring_proxy_public_fqdn: "{{ inventory_hostname }}" diff --git a/ansible/deploy-notebook.yml b/ansible/deploy-notebook.yml index 318f62e4..5f4306ec 100644 --- a/ansible/deploy-notebook.yml +++ b/ansible/deploy-notebook.yml @@ -9,4 +9,6 @@ ssl_domains: - "{{ inventory_hostname }}" roles: + - nginx + - dehydrated - notebook diff --git a/ansible/deploy-ooni-backend.yml b/ansible/deploy-ooni-backend.yml index 7e056905..3306f780 100644 --- a/ansible/deploy-ooni-backend.yml +++ b/ansible/deploy-ooni-backend.yml @@ -8,6 +8,7 @@ admin_group_name: adm - role: base-backend - role: nftables + - role: nginx - role: dehydrated tags: dehydrated expand: yes diff --git a/ansible/roles/dehydrated/meta/main.yml b/ansible/roles/dehydrated/meta/main.yml deleted file mode 100644 index 0e72e865..00000000 --- a/ansible/roles/dehydrated/meta/main.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -dependencies: - - nginx -... - diff --git a/ansible/roles/nginx/defaults/main.yml b/ansible/roles/nginx/defaults/main.yml index 4c0ac11a..41a890b4 100644 --- a/ansible/roles/nginx/defaults/main.yml +++ b/ansible/roles/nginx/defaults/main.yml @@ -1 +1,10 @@ nginx_user: nginx + +# "nginxinc_role" (default, unchanged): install via the nginxinc.nginx galaxy +# role, as today. +# "official_repo": install directly from nginx.org's own apt repo, following +# https://nginx.org/en/linux_packages.html#Debian, with a pinned signing-key +# fingerprint check. Opt in per-playbook; the nginxinc_role default is left +# alone for existing callers since switching apt repos changes what nginx +# package/version they get on their next run. +nginx_install_method: nginxinc_role diff --git a/ansible/roles/nginx/tasks/main.yml b/ansible/roles/nginx/tasks/main.yml index 9af2a9b4..3b31e7a3 100644 --- a/ansible/roles/nginx/tasks/main.yml +++ b/ansible/roles/nginx/tasks/main.yml @@ -13,9 +13,82 @@ - nginx - nftables -- name: install nginx +- name: install nginx via the nginxinc.nginx galaxy role include_role: name: nginxinc.nginx + tags: + - nginx + - packages + when: nginx_install_method == 'nginxinc_role' + +# Follows https://nginx.org/en/linux_packages.html#Debian directly instead +# of a third-party role. +- name: Install nginx from nginx.org's official apt repository + when: nginx_install_method == 'official_repo' + tags: + - nginx + - packages + block: + - name: Install nginx's prerequisites + ansible.builtin.apt: + name: + - curl + - gnupg2 + - ca-certificates + state: present + update_cache: true + + - name: Download nginx's official signing key + ansible.builtin.get_url: + url: https://nginx.org/keys/nginx_signing.key + dest: /tmp/nginx_signing.key + mode: "0644" + + - name: Dearmor nginx's signing key into the apt keyring + ansible.builtin.command: gpg --dearmor --yes --output /usr/share/keyrings/nginx-archive-keyring.gpg /tmp/nginx_signing.key + args: + creates: /usr/share/keyrings/nginx-archive-keyring.gpg + + - name: Read the fingerprint of the downloaded key + ansible.builtin.command: gpg --with-colons --show-keys /usr/share/keyrings/nginx-archive-keyring.gpg + register: nginx_key_check + changed_when: false + + # Pin against nginx.org's gpg key fingerprint: + # 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62, documented at + # (https://nginx.org/en/linux_packages.html) + - name: Verify the downloaded key's fingerprint matches nginx.org's published one + ansible.builtin.assert: + that: + - nginx_key_check.stdout is + search('^fpr:::::::::573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62:$', multiline=true) + fail_msg: >- + nginx-archive-keyring.gpg's fingerprint does not match the + expected 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 -- refusing to + trust it. + success_msg: "nginx-archive-keyring.gpg's fingerprint matches the expected value." + + - name: Add the nginx.org apt repository + ansible.builtin.apt_repository: + repo: "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/debian {{ ansible_distribution_release }} nginx" + filename: nginx + state: present + + - name: Pin nginx.org packages above Debian's own nginx package + ansible.builtin.copy: + dest: /etc/apt/preferences.d/99nginx + content: | + Package: * + Pin: origin nginx.org + Pin: release o=nginx + Pin-Priority: 900 + mode: "0644" + + - name: Install nginx + ansible.builtin.apt: + name: nginx + state: present + update_cache: true # https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&guideline=5.4 # Guide https://wiki.mozilla.org/Security/Server_Side_TLS#Pre-defined_DHE_groups diff --git a/ansible/roles/notebook/tasks/jupyterhub.yml b/ansible/roles/notebook/tasks/jupyterhub.yml index ea9e0e04..de4a271b 100644 --- a/ansible/roles/notebook/tasks/jupyterhub.yml +++ b/ansible/roles/notebook/tasks/jupyterhub.yml @@ -106,14 +106,3 @@ - jupyterhub - config -- ansible.builtin.include_role: - name: nginx - tags: - - oonidata - - nginx - -- ansible.builtin.include_role: - name: dehydrated - tags: - - oonidata - - dehydrated diff --git a/ansible/roles/prometheus_node_exporter/tasks/main.yml b/ansible/roles/prometheus_node_exporter/tasks/main.yml index fb9e0e6f..e647a7cd 100644 --- a/ansible/roles/prometheus_node_exporter/tasks/main.yml +++ b/ansible/roles/prometheus_node_exporter/tasks/main.yml @@ -1,19 +1,3 @@ -- ansible.builtin.include_role: - name: nginx - tags: - - nginx - - node_exporter - when: use_nginx - -- ansible.builtin.include_role: - name: dehydrated - tags: - - oonidata - - dehydrated - vars: - ssl_domains: "{{ hostvars[inventory_hostname].ssl_domains | default([inventory_hostname]) }}" - when: use_https - - name: create ooni configuration directory ansible.builtin.file: path: "/etc/ooni/" From d32df969807c1193b5b0725eeb4310926818bdb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Thu, 13 Aug 2026 22:01:01 +0200 Subject: [PATCH 02/12] Apply tags and suggest a tagging convention --- ansible/README.md | 35 +++++++++++++++++++ ansible/roles/dehydrated/tasks/main.yml | 18 +++++----- ansible/roles/nginx/tasks/main.yml | 5 +++ .../tasks/install.yml | 30 +++++++++++++++- .../prometheus_node_exporter/tasks/main.yml | 2 ++ 5 files changed, 80 insertions(+), 10 deletions(-) diff --git a/ansible/README.md b/ansible/README.md index 8507cd29..0f49c25e 100644 --- a/ansible/README.md +++ b/ansible/README.md @@ -191,6 +191,41 @@ When deploying files or updating files already existing on the hosts it can be u This helps track down how files on the host were modified and why. ::: +#### Tagging convention + +Tasks are tagged along two independent axes, so that `--tags`/`--skip-tags` can be used to run (or skip) a +meaningful slice of a playbook without guessing what else might be silently pulled in or left out: + +* **Component tag** — matches the role name (`nginx`, `dehydrated`, `nftables`, `prometheus_node_exporter`, + `docker`, `ooniapi_gateway`, ...). Selects everything belonging to that role. +* **Phase tag** — a small, fixed vocabulary describing *what kind* of operation the task performs, independent of + which role it lives in: + + | Tag | Meaning | + |--------------|----------------------------------------------------------------------------------------------------------------------| + | `packages` | apt/package installs — slow, safe to skip when nothing package-level changed | + | `config` | template/config file rendering — fast, safe to run often | + | `certs` | dehydrated cert issuance/renewal — rate-limited by Let's Encrypt, must be independently skippable (e.g. before DNS is cut over to a new host) | + | `network` | nftables rules and docker network setup | + | `service` | service enable/start/restart/reload operations | + | `monitoring` | prometheus/node_exporter wiring and health checks | + | `secrets` | sudoers rules and deploy-credential/password setup | + + Most tasks should carry exactly one component tag and one phase tag. + + Examples: + ``` + ./play -i inventory deploy-monitoring-proxy.yml -l monitoringproxy.prod.ooni.io --tags config + ./play -i inventory deploy-ooni-backend.yml -l backend-hel.ooni.org --skip-tags certs + ./play -i inventory deploy-clickhouse-proxy.yml -l clickhouseproxy.prod.ooni.io --tags monitoring + ``` + +:::note +This taxonomy is applied incrementally as roles are touched, not retrofitted across the whole codebase in one go +— currently `nginx`, `dehydrated`, and `prometheus_node_exporter` follow it. Don't assume every task elsewhere +already does. +::: + ### Platform specific known bugs On macOS you might run into this issue: https://github.com/ansible/ansible/issues/76322 diff --git a/ansible/roles/dehydrated/tasks/main.yml b/ansible/roles/dehydrated/tasks/main.yml index ecf09a5d..860ffcc3 100644 --- a/ansible/roles/dehydrated/tasks/main.yml +++ b/ansible/roles/dehydrated/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Installs packages - tags: dehydrated + tags: [dehydrated, packages] apt: install_recommends: false cache_valid_time: 86400 @@ -23,7 +23,7 @@ # HOOK="/etc/dehydrated/hook.sh" - name: Add ACME dedicated sites-enabled file - tags: dehydrated + tags: [dehydrated, certs] ansible.builtin.template: src: templates/letsencrypt-http # the server block matches all SSL FQDNs and must be @@ -33,7 +33,7 @@ owner: root - name: Add canary file to ensure /.well-known/acme-challenge is reachable by let's encrypt - tags: dehydrated + tags: [dehydrated, certs] ansible.builtin.copy: content: | Generated by ansible using ansible/roles/dehydrated/tasks/main.yml. @@ -44,23 +44,23 @@ owner: root - name: reload nftables service - tags: dehydrated + tags: [dehydrated, network] shell: systemctl reload nftables.service - name: Configure domains {{ ssl_domains }} # https://github.com/dehydrated-io/dehydrated/blob/master/docs/domains_txt.md - tags: dehydrated + tags: [dehydrated, certs] template: src: templates/domains.txt.j2 dest: /etc/dehydrated/domains.txt - name: Register account if needed - tags: dehydrated + tags: [dehydrated, certs] ansible.builtin.shell: cmd: "test -d /var/lib/dehydrated/accounts || dehydrated --register --accept-terms" - name: Install dehydrated.service - tags: dehydrated + tags: [dehydrated, certs] template: src: templates/dehydrated.service dest: /etc/systemd/system/dehydrated.service @@ -68,7 +68,7 @@ owner: root - name: Install dehydrated.timer - tags: dehydrated + tags: [dehydrated, certs] template: src: templates/dehydrated.timer dest: /etc/systemd/system/dehydrated.timer @@ -76,7 +76,7 @@ owner: root - name: Ensure timer runs - tags: dehydrated + tags: [dehydrated, certs] systemd: name: dehydrated.timer state: started diff --git a/ansible/roles/nginx/tasks/main.yml b/ansible/roles/nginx/tasks/main.yml index 3b31e7a3..dbb2c3fc 100644 --- a/ansible/roles/nginx/tasks/main.yml +++ b/ansible/roles/nginx/tasks/main.yml @@ -12,6 +12,7 @@ tags: - nginx - nftables + - network - name: install nginx via the nginxinc.nginx galaxy role include_role: @@ -101,6 +102,7 @@ - ssl_modern.conf tags: - nginx + - config - name: remove `default` vhost file: path={{item}} state=absent @@ -111,6 +113,7 @@ - /etc/nginx/sites-enabled/default tags: - nginx + - config - name: Create nginx sites directory ansible.builtin.file: @@ -118,9 +121,11 @@ state: directory tags: - nginx + - config - name: set nginx.conf template: src=nginx.conf dest=/etc/nginx/nginx.conf mode=0444 notify: reload nginx tags: - nginx + - config diff --git a/ansible/roles/prometheus_node_exporter/tasks/install.yml b/ansible/roles/prometheus_node_exporter/tasks/install.yml index 47ed566e..1ff74425 100644 --- a/ansible/roles/prometheus_node_exporter/tasks/install.yml +++ b/ansible/roles/prometheus_node_exporter/tasks/install.yml @@ -4,6 +4,9 @@ failed_when: false changed_when: false register: node_exporter_version_check + tags: + - prometheus_node_exporter + - packages - name: Download and unarchive node_exporter into temporary location. unarchive: @@ -15,6 +18,9 @@ node_exporter_version_check.stdout is not defined or node_exporter_version not in node_exporter_version_check.stdout register: node_exporter_download_check + tags: + - prometheus_node_exporter + - packages - name: Move node_exporter binary into place. copy: @@ -26,11 +32,17 @@ when: > node_exporter_download_check is changed or node_exporter_version_check.stdout | length == 0 + tags: + - prometheus_node_exporter + - packages - name: Create node_exporter group. group: name: "{{ prometheus_group }}" state: present + tags: + - prometheus_node_exporter + - config - name: Create node_exporter user. user: @@ -38,6 +50,9 @@ shell: /sbin/nologin group: "{{ prometheus_group }}" state: present + tags: + - prometheus_node_exporter + - config - name: Add a user to a password file and ensure permissions are set community.general.htpasswd: @@ -48,9 +63,10 @@ group: "{{ 'nginx' if use_nginx else prometheus_group }}" mode: 0640 tags: + - prometheus_node_exporter - monitoring - node_exporter - - config + - secrets - name: Copy the node_exporter systemd unit file. template: @@ -58,18 +74,27 @@ dest: /etc/systemd/system/node_exporter.service mode: 0644 register: node_exporter_service + tags: + - prometheus_node_exporter + - config - name: Reload systemd daemon if unit file is changed. systemd: daemon_reload: true notify: restart node_exporter when: node_exporter_service is changed + tags: + - prometheus_node_exporter + - service - name: Ensure node_exporter is running and enabled at boot. service: name: node_exporter state: "{{ node_exporter_state }}" enabled: "{{ node_exporter_enabled }}" + tags: + - prometheus_node_exporter + - service - name: Verify node_exporter is responding to requests. uri: @@ -77,3 +102,6 @@ return_content: true register: metrics_output failed_when: "'Metrics' not in metrics_output.content" + tags: + - prometheus_node_exporter + - monitoring diff --git a/ansible/roles/prometheus_node_exporter/tasks/main.yml b/ansible/roles/prometheus_node_exporter/tasks/main.yml index e647a7cd..7512d5b9 100644 --- a/ansible/roles/prometheus_node_exporter/tasks/main.yml +++ b/ansible/roles/prometheus_node_exporter/tasks/main.yml @@ -4,6 +4,7 @@ state: directory owner: root tags: + - prometheus_node_exporter - monitoring - node_exporter - config @@ -16,6 +17,7 @@ notify: - Restart nginx tags: + - prometheus_node_exporter - monitoring - node_exporter - config From a88a72558cd34a5c0b2eba8b44b044b3d0ae4fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 13:28:46 +0200 Subject: [PATCH 03/12] Update github actions script --- .github/workflows/check_ansible.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_ansible.yml b/.github/workflows/check_ansible.yml index 396a8afc..c6c14408 100644 --- a/.github/workflows/check_ansible.yml +++ b/.github/workflows/check_ansible.yml @@ -58,7 +58,7 @@ jobs: #- name: Setup tmate session # uses: mxschmitt/action-tmate@v3 - - uses: actions/github-script@v6 + - uses: actions/github-script@v8 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | From 2da3b0c1fac18acc40c93d2738a6316afddb0dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 14:41:43 +0200 Subject: [PATCH 04/12] Bump github actions script to v9 --- .github/workflows/check_ansible.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_ansible.yml b/.github/workflows/check_ansible.yml index c6c14408..92d924d4 100644 --- a/.github/workflows/check_ansible.yml +++ b/.github/workflows/check_ansible.yml @@ -58,7 +58,7 @@ jobs: #- name: Setup tmate session # uses: mxschmitt/action-tmate@v3 - - uses: actions/github-script@v8 + - uses: actions/github-script@v9 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | From 40c0cfcdd078f926ce2189c85e048bc63bfa7bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 14:46:32 +0200 Subject: [PATCH 05/12] Comment out the ansible comment step --- .github/workflows/check_ansible.yml | 60 ++++++++++++++--------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/check_ansible.yml b/.github/workflows/check_ansible.yml index 92d924d4..1c32eb4d 100644 --- a/.github/workflows/check_ansible.yml +++ b/.github/workflows/check_ansible.yml @@ -58,41 +58,41 @@ jobs: #- name: Setup tmate session # uses: mxschmitt/action-tmate@v3 - - uses: actions/github-script@v9 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const commentTitle = "Ansible Run Output"; - const ansiblePlaybookOutput = `${{ steps.playbook.outputs.ansible_playbook}}`; - const parts = ansiblePlaybookOutput.split(/PLAY RECAP \*+/); - const ansiblePlaybookRecap = parts.length > 1 ? parts[1].trim() : ''; + #- uses: actions/github-script@v9 + # with: + # github-token: ${{ secrets.GITHUB_TOKEN }} + # script: | + # const commentTitle = "Ansible Run Output"; + # const ansiblePlaybookOutput = `${{ steps.playbook.outputs.ansible_playbook}}`; + # const parts = ansiblePlaybookOutput.split(/PLAY RECAP \*+/); + # const ansiblePlaybookRecap = parts.length > 1 ? parts[1].trim() : ''; - const commentBody = ` - #### Ansible Playbook Recap 🔍 + # const commentBody = ` + # #### Ansible Playbook Recap 🔍 - \`\`\`\n - ${ansiblePlaybookRecap} - \`\`\` + # \`\`\`\n + # ${ansiblePlaybookRecap} + # \`\`\` - #### Ansible playbook output 📖\`${{ steps.playbook.outcome }}\` + # #### Ansible playbook output 📖\`${{ steps.playbook.outcome }}\` -
Show Execution + #
Show Execution - \`\`\`\n - ${ansiblePlaybookOutput} - \`\`\` + # \`\`\`\n + # ${ansiblePlaybookOutput} + # \`\`\` -
+ #
- | | | - |-------------------|------------------------------------| - | Pusher | @${{ github.actor }} | - | Action | ${{ github.event_name }} | - | Working Directory | ${{ env.tf_actions_working_dir }} | - | Workflow | ${{ github.workflow }} | - | Last updated | ${(new Date()).toUTCString()} | - `; + # | | | + # |-------------------|------------------------------------| + # | Pusher | @${{ github.actor }} | + # | Action | ${{ github.event_name }} | + # | Working Directory | ${{ env.tf_actions_working_dir }} | + # | Workflow | ${{ github.workflow }} | + # | Last updated | ${(new Date()).toUTCString()} | + # `; - // Call the script to write the comment - const script = require('./scripts/ghactions/comment-on-pr.js'); - await script({github, context, core, commentTitle, commentBody}); + # // Call the script to write the comment + # const script = require('./scripts/ghactions/comment-on-pr.js'); + # await script({github, context, core, commentTitle, commentBody}); From 930d7057b7cefa596279111a742bf5736922b697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 17:10:55 +0200 Subject: [PATCH 06/12] Add web_connectivity test helper dev instance --- tf/environments/dev/main.tf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tf/environments/dev/main.tf b/tf/environments/dev/main.tf index 5f089f5c..2ccca183 100644 --- a/tf/environments/dev/main.tf +++ b/tf/environments/dev/main.tf @@ -409,6 +409,24 @@ module "ooni_th_droplet" { dns_zone_ooni_io = local.dns_zone_ooni_io } +resource "digitalocean_ssh_key" "oonidevops" { + name = "oonidevops" + public_key = jsondecode(data.aws_secretsmanager_secret_version.deploy_key.secret_string)["public_key"] +} + + +module "ooni_test_helpers_wc" { + source = "../../modules/ooni_th_binary_droplet" + + stage = local.environment + name = "ooniwcth" + hostname = "wc.th" + + ssh_keys = [digitalocean_ssh_key.oonidevops.fingerprint] + + dns_zone_ooni_io = local.dns_zone_ooni_io +} + ### OONI Services Clusters module "ooniapi_cluster" { From c9e58ab3b2719330057f094b4d7eee65052b7499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 17:19:07 +0200 Subject: [PATCH 07/12] Add deploy-wc-test-helper playbook --- ansible/deploy-wc-test-helper.yml | 14 ++++++++++++++ ansible/inventory | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 ansible/deploy-wc-test-helper.yml diff --git a/ansible/deploy-wc-test-helper.yml b/ansible/deploy-wc-test-helper.yml new file mode 100644 index 00000000..1b0ce980 --- /dev/null +++ b/ansible/deploy-wc-test-helper.yml @@ -0,0 +1,14 @@ +--- +- name: Deploy test helpers + hosts: + - wc.th.dev.ooni.io + become: true + vars: + ssl_domains: + - "{{ inventory_hostname }}" + nginx_install_method: official_repo + roles: + - role: bootstrap + - role: nginx + - role: dehydrated + - role: prometheus_node_exporter diff --git a/ansible/inventory b/ansible/inventory index 5008d568..bcc6e3d1 100644 --- a/ansible/inventory +++ b/ansible/inventory @@ -35,6 +35,9 @@ ams-ps.ooni.nu #mia-echoth.ooni.nu #mia-httpth.ooni.nu +[do_fra] +wc.th.dev.ooni.io + [aws-proxy] clickhouseproxy.dev.ooni.io clickhouseproxy.prod.ooni.io From 806abc04ca3fc92e7715c172ecc082b5e974ad58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 17:50:55 +0200 Subject: [PATCH 08/12] Fix resolved check command --- ansible/roles/bootstrap/handlers/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/roles/bootstrap/handlers/main.yml b/ansible/roles/bootstrap/handlers/main.yml index a9c712a4..2bdb126d 100644 --- a/ansible/roles/bootstrap/handlers/main.yml +++ b/ansible/roles/bootstrap/handlers/main.yml @@ -9,7 +9,7 @@ state: restarted - name: Test systemd-resolved - ansible.builtin.shell: resolvectl query go.dnscheck.tools --cache=no + ansible.builtin.shell: resolvectl query dnscheck.tools --cache=no - name: Restart systemd-journald ansible.builtin.systemd_service: From a557e8879ad5b6080d3d177a79039d54a968cd4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 17:51:58 +0200 Subject: [PATCH 09/12] Fix updating of locales --- ansible/roles/bootstrap/tasks/main.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ansible/roles/bootstrap/tasks/main.yml b/ansible/roles/bootstrap/tasks/main.yml index 2b65c611..5b5da161 100644 --- a/ansible/roles/bootstrap/tasks/main.yml +++ b/ansible/roles/bootstrap/tasks/main.yml @@ -26,6 +26,7 @@ - git - htop - iotop + - locales - lsof - lvm2 - man-db @@ -44,6 +45,24 @@ update_cache: yes install_recommends: no +- name: Generate en_US.UTF-8 locale + community.general.locale_gen: + name: en_US.UTF-8 + state: present + +- name: Set system locale + ansible.builtin.lineinfile: + path: /etc/default/locale + create: yes + regexp: "^{{ item.key }}=" + line: "{{ item.key }}={{ item.value }}" + owner: root + group: root + mode: "0644" + loop: + - { key: "LANG", value: "en_US.UTF-8" } + - { key: "LC_ALL", value: "en_US.UTF-8" } + - name: Set timezone community.general.timezone: name: Etc/UTC From 7ceafd72949ec1a50f7a50e1198c2d17b2a707ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 17:52:04 +0200 Subject: [PATCH 10/12] Enable post quantum sshd algorithms --- ansible/roles/ssh_users/templates/sshd_config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/roles/ssh_users/templates/sshd_config b/ansible/roles/ssh_users/templates/sshd_config index a2488721..108ab997 100644 --- a/ansible/roles/ssh_users/templates/sshd_config +++ b/ansible/roles/ssh_users/templates/sshd_config @@ -8,5 +8,5 @@ PrintMotd no AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server Ciphers chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr -KexAlgorithms curve25519-sha256 +KexAlgorithms sntrup761x25519-sha512@openssh.com,mlkem768x25519-sha256,curve25519-sha256 MACs hmac-sha2-512,hmac-sha2-256 From 2d06d40006835a96a2b37755ee5236df6aabcdbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 17:54:25 +0200 Subject: [PATCH 11/12] Exclude mlkem768x25519-sha256 since it's not in bookworm --- ansible/roles/ssh_users/tasks/main.yml | 1 + ansible/roles/ssh_users/templates/sshd_config | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ansible/roles/ssh_users/tasks/main.yml b/ansible/roles/ssh_users/tasks/main.yml index 14a5bd6e..77330df0 100644 --- a/ansible/roles/ssh_users/tasks/main.yml +++ b/ansible/roles/ssh_users/tasks/main.yml @@ -60,6 +60,7 @@ owner: root group: root mode: 0440 + validate: 'sshd -t -f %s' - name: Ensure sudoers dir exists tags: ssh_users diff --git a/ansible/roles/ssh_users/templates/sshd_config b/ansible/roles/ssh_users/templates/sshd_config index 108ab997..04a795a9 100644 --- a/ansible/roles/ssh_users/templates/sshd_config +++ b/ansible/roles/ssh_users/templates/sshd_config @@ -8,5 +8,6 @@ PrintMotd no AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server Ciphers chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr -KexAlgorithms sntrup761x25519-sha512@openssh.com,mlkem768x25519-sha256,curve25519-sha256 +# mlkem768x25519-sha256 is excluded, but we should enable it once we have all hosts on trixie +KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256 MACs hmac-sha2-512,hmac-sha2-256 From 41b5b5576766e16898e950199d76eec110c96624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 14 Aug 2026 18:13:28 +0200 Subject: [PATCH 12/12] Enable TLSv1.3 --- ansible/roles/nginx/files/ssl_modern.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/roles/nginx/files/ssl_modern.conf b/ansible/roles/nginx/files/ssl_modern.conf index 9ad7c11d..538d3097 100644 --- a/ansible/roles/nginx/files/ssl_modern.conf +++ b/ansible/roles/nginx/files/ssl_modern.conf @@ -1,4 +1,4 @@ # Oldest compatible clients: Firefox 27, Chrome 30, IE 11 on Windows 7, Edge, Opera 17, Safari 9, Android 5.0, and Java 8 -ssl_protocols TLSv1.2; +ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; # NB: technically, it does not require ssl_dhparam as it has no DHE, only ECDHE.