From e7a499c6456461a5ebdcca51f086484bd050d6ec Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Tue, 18 Nov 2025 11:07:15 +0100 Subject: [PATCH 01/22] enable: wpb-17321 refactor and fixes for wiab-demo, added all changes in changelog --- ansible/inventory/demo/host.yml | 11 +- ansible/wiab-demo/clean_cluster.yml | 30 ++- ansible/wiab-demo/deploy_wiab.yml | 133 +++++++--- ansible/wiab-demo/download_artifact.yml | 27 +- ansible/wiab-demo/hairpin_networking.yml | 79 ++++++ ansible/wiab-demo/helm_install.yml | 85 ++----- ansible/wiab-demo/install_pkgs.yml | 80 +++--- ansible/wiab-demo/iptables_rules.yml | 82 ++----- ansible/wiab-demo/minikube_cluster.yml | 9 +- ansible/wiab-demo/setup_ssh.yml | 12 +- ansible/wiab-demo/verify_dns.yml | 30 ++- ansible/wiab-demo/verify_wire_ip.yml | 28 ++- ansible/wiab-demo/wire_secrets.yml | 33 ++- ansible/wiab-demo/wire_values.yml | 56 +++++ bin/wiab-demo/offline-env.sh | 47 +++- bin/wiab-demo/offline_deploy_k8s.sh | 30 +-- .../3-deploy-builds/demo-wiab-ansible-fixes | 12 + offline/demo-wiab.md | 231 ++++++++++++++---- 18 files changed, 710 insertions(+), 305 deletions(-) create mode 100644 ansible/wiab-demo/hairpin_networking.yml create mode 100644 ansible/wiab-demo/wire_values.yml create mode 100644 changelog.d/3-deploy-builds/demo-wiab-ansible-fixes diff --git a/ansible/inventory/demo/host.yml b/ansible/inventory/demo/host.yml index 19fe379e2..8c37f23bc 100644 --- a/ansible/inventory/demo/host.yml +++ b/ansible/inventory/demo/host.yml @@ -1,8 +1,9 @@ + wiab: hosts: deploy_node: ansible_host: example.com - ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' + ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o TCPKeepAlive=yes' ansible_user: 'ubuntu' ansible_ssh_private_key_file: "~/.ssh/wiab-demo.pem" @@ -17,7 +18,7 @@ wiab: wire_ip: "" # artifact_hash - artifact_hash: "89e4fa122e6ddba9df2f81612de1ee45ec2238b3" + artifact_hash: "8e5087a0d9c58a9bd34c6c02f87514abe8b3ce0e" # docker vars docker_ce_version: "5:28.1.1-1~ubuntu.24.04~noble" @@ -47,14 +48,16 @@ wiab: # list of helm charts to deploy charts_to_deploy: - fake-aws - - demo-smtp + - smtp - rabbitmq - databases-ephemeral + - postgresql - reaper + - smallstep-accomp + - kube-prometheus-stack - wire-server - webapp - account-pages - team-settings - - smallstep-accomp - ingress-nginx-controller - nginx-ingress-services diff --git a/ansible/wiab-demo/clean_cluster.yml b/ansible/wiab-demo/clean_cluster.yml index 8ff64c49c..4bd810c3c 100644 --- a/ansible/wiab-demo/clean_cluster.yml +++ b/ansible/wiab-demo/clean_cluster.yml @@ -5,6 +5,7 @@ # stopping the cluster defined in minikube_cluster playbook - name: clean minikube become_user: "{{ ansible_user }}" + tags: [never, remove_minikube] block: - name: Check if Minikube is running shell: minikube status --profile="{{ minikube_profile }}" @@ -22,11 +23,10 @@ minikube delete --profile="{{ minikube_profile }}" when: "'Running' in minikube_status.stdout" - when: "remove_minikube is defined and remove_minikube | bool" - # following packages were installed in install_pkgs playbook # these packages can only be removed post stopping the minikube cluster - name: remove packages + tags: [never, remove_packages] block: - name: Remove Minikube file: @@ -75,11 +75,10 @@ apt: update_cache: yes - when: (uninstall_pkgs | default(false) | bool) and (remove_minikube | default(false) | bool) - # remove the iptables rules defined by iptables_rules playbook # it makes sense to remove them when removing the k8s cluster or individually to clean them - name: remove iptables rules + tags: [never, remove_iptables] vars: iptables_rules_comment: "Wire Iptables Rules" iptables_save_dir: "/home/{{ ansible_user }}/wire-iptables-rules" @@ -135,28 +134,29 @@ - "{{ iptables_save_dir }}/rules_post_wire.v4" - "{{ iptables_save_dir }}" - when: (remove_iptables | default(false) | bool) or (remove_minikube | default(false) | bool) - - name: Remove ssh keys + tags: [never, remove_ssh] + become_user: "{{ ansible_user }}" block: - name: Remove SSH key if it exist shell: | - if [ -f "/home/{{ ansible_user }}/.ssh/id_rsa_wire" ]; then - rm "/home/{{ ansible_user }}/.ssh/id_rsa_wire" + if [ -f "{{ ansible_user_dir }}/.ssh/id_rsa_wire" ]; then + rm "{{ ansible_user_dir }}/.ssh/id_rsa_wire" fi - when: "remove_ssh is defined and remove_ssh | bool" - + - name: remove the downloaded artifacts + tags: [never, remove_artifacts] + become_user: "{{ ansible_user }}" file: path: "{{ item }}" state: absent loop: - - "/home/{{ ansible_user }}/wire-server-deploy" - - "/home/{{ ansible_user }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" - - "/home/{{ ansible_user }}/wire_ip" - when: "remove_artifacts is defined and remove_artifacts | bool" + - "{{ ansible_user_dir }}/wire-server-deploy" + - "{{ ansible_user_dir }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" + - "{{ ansible_user_dir }}/wire_ip" - name: clean asset_host artifacts and remove service + tags: [never, clean_assethost] block: - name: Stop and disable serve-assets systemd service systemd: @@ -178,5 +178,3 @@ file: path: /opt/assets/containers-helm state: absent - - when: "clean_assethost is defined and clean_assethost | bool" diff --git a/ansible/wiab-demo/deploy_wiab.yml b/ansible/wiab-demo/deploy_wiab.yml index 287bab91c..f7bd2a4fa 100644 --- a/ansible/wiab-demo/deploy_wiab.yml +++ b/ansible/wiab-demo/deploy_wiab.yml @@ -1,13 +1,9 @@ -- name: Verify the dns records before starting to install - import_playbook: ./verify_dns.yml - when: skip_verify_dns | default(false) == false - - name: Execute common tasks for the node hosts: deploy_node - become: yes tasks: # this is an exception to install_pkgs, as it expects netcat before other tasks take place - name: Install Netcat + become: yes apt: name: - ncat @@ -21,51 +17,107 @@ k8s_ingress_controller_node: "{{ minikube_profile }}" k8s_coturn_node: "{{ minikube_profile }}" k8s_sft_node: "{{ minikube_profile }}" + kube_config_path: "/home/{{ ansible_user }}/.kube/config" + iptables_rules_comment: "Wire Iptables Rules" + iptables_save_dir: "/home/{{ ansible_user }}/wire-iptables-rules" # shouldn't be skipped, it is neccessary to identify the network ingress # potentially we can write the information on the node to avoid running it everytime # read it from the node if not found - name: Check Wire IP access import_playbook: ./verify_wire_ip.yml + tags: always + +- name: Verify the dns records before starting to install + import_playbook: ./verify_dns.yml + tags: verify_dns - name: Install required packages import_playbook: ./install_pkgs.yml - when: skip_install_pkgs | default(false) == false + tags: install_pkgs -- name: Manage SSH keys for minikube node and ssh proxy +- name: Manage SSH keys (dependency for minikube, asset_host, seed_containers) import_playbook: ./setup_ssh.yml - when: ((skip_minikube | default(false) == false) or (skip_asset_host | default(false) == false) or (skip_setup_offline_seed | default(false) == false)) + when: > + 'minikube' not in ansible_skip_tags or + 'asset_host' not in ansible_skip_tags or + 'seed_containers' not in ansible_skip_tags - name: Configure minikube cluster import_playbook: ./minikube_cluster.yml - when: skip_minikube | default(false) == false + tags: minikube + +- name: Set k8s related ansible inventory + hosts: deploy_node + become: yes + become_user: "{{ ansible_user }}" + tasks: + - name: Get the IP address of the k8s_ingress_controller node + shell: | + kubectl --kubeconfig="{{ kube_config_path }}" get node {{ k8s_ingress_controller_node }} -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address' + register: k8s_ingress_controller_ip + changed_when: false + + - name: Get the {{ minikube_network_name }} Docker network ID + shell: | + docker network inspect {{ minikube_network_name }} | jq -r '.[0].Id' + register: docker_network_id + changed_when: false + + - name: Get all interfaces with bridge interfaces + shell: ip -o addr show | awk '{print $2}' | grep -i 'br-' + register: bridge_interfaces + changed_when: false + + - name: Find the matching bridge interface for {{ minikube_network_name }} Docker network + shell: | + for iface in {{ bridge_interfaces.stdout_lines | join(' ') }}; do + iface_id=$(echo "$iface" | cut -d '-' -f2) + if echo "{{ docker_network_id.stdout }}" | grep -q "$iface_id"; then + echo "$iface" + break + fi + done + register: matching_bridge_interface + changed_when: false + + - name: set facts for k8s ingress controller ip + set_fact: + k8s_ingress_controller_ip: "{{ k8s_ingress_controller_ip.stdout }}" + matching_bridge_interface: "{{ matching_bridge_interface.stdout }}" - name: Configure Iptables rules import_playbook: ./iptables_rules.yml - when: skip_minikube | default(false) == false + tags: minikube - name: Download wire artifact import_playbook: ./download_artifact.yml - when: skip_download | default(false) == false + tags: download - name: Add minikube nodes to ansible inventory hosts: deploy_node become: yes become_user: "{{ ansible_user }}" tasks: - - name: Extract IPs of Minikube nodes - shell: | - kubectl get nodes -o json | jq -r '.items[].status.addresses[] | select(.type=="InternalIP").address' - register: kube_ips + - name: Create a block for Minikube node tasks + block: + - name: Extract IPs of Minikube nodes + shell: | + kubectl get nodes -o json | jq -r '.items[].status.addresses[] | select(.type=="InternalIP").address' + register: kube_ips - - name: Store Minikube node IPs as variable - set_fact: - kubernetes_node_ips: "{{ kube_ips.stdout_lines }}" + - name: Store Minikube node IPs as variable + set_fact: + kubernetes_node_ips: "{{ kube_ips.stdout_lines }}" - - name: Extract IP of "{{ minikube_network_name }}" interface on host machine - shell: | - docker network inspect "{{ minikube_network_name }}" | jq -r '.[0].IPAM.Config[0].Gateway' - register: host_ip + - name: Extract IP of "{{ minikube_network_name }}" interface on host machine + shell: | + docker network inspect "{{ minikube_network_name }}" | jq -r '.[0].IPAM.Config[0].Gateway' + register: host_ip + + when: > + 'asset_host' not in ansible_skip_tags or + 'seed_containers' not in ansible_skip_tags - name: Setup ssh proxy access to k8s-cluster nodes become: no @@ -129,35 +181,46 @@ delegate_to: "{{ item }}" delegate_facts: true with_items: "{{ groups['k8s-cluster'] }}" - - when: ((skip_asset_host | default(false) == false) or (skip_setup_offline_seed | default(false) == false)) + + when: > + 'asset_host' not in ansible_skip_tags or + 'seed_containers' not in ansible_skip_tags - name: Setup Asset Host import_playbook: ../setup-offline-sources.yml vars: demo_deploy: true remote_src: yes - src_path: /home/{{ ansible_user }}/wire-server-deploy - when: skip_asset_host | default(false) == false + src_path: "/home/{{ ansible_user }}/wire-server-deploy" + tags: asset_host - name: Seed the containers in k8s-cluster nodes import_playbook: ../seed-offline-containerd.yml vars: docker_permission_fix: true skip_seed_system_containers: true - when: skip_setup_offline_seed | default(false) == false + tags: seed_containers + +- name: Prepare helm chart values + import_playbook: ./wire_values.yml + tags: wire_values - name: Create wire secrets import_playbook: ./wire_secrets.yml - when: ((skip_wire_secrets | default(false) == false) and (skip_helm_install | default(false) == false)) + tags: helm_install - name: Install Helm charts import_playbook: ./helm_install.yml - when: skip_helm_install | default(false) == false + tags: helm_install + +- name: Enable Cert Manager hairpin Networking + import_playbook: ./hairpin_networking.yml + tags: cert_manager_networking # since, the temp_dir are created in a different set of tasks, these directories need to be searched - name: Clean up temporary directories hosts: localhost + tags: cleanup tasks: - name: Find all temporary directories find: @@ -180,3 +243,15 @@ loop: "{{ temp_dirs.files }}" loop_control: label: "{{ item.path }}" + +- name: Stop and disable serve-assets systemd service post deployment + hosts: deploy_node + tags: cleanup + become: yes + tasks: + - name: Stop and disable serve-assets service + systemd: + name: serve-assets + state: stopped + enabled: no + ignore_errors: yes diff --git a/ansible/wiab-demo/download_artifact.yml b/ansible/wiab-demo/download_artifact.yml index 458d00d74..dfffbf48e 100644 --- a/ansible/wiab-demo/download_artifact.yml +++ b/ansible/wiab-demo/download_artifact.yml @@ -5,7 +5,7 @@ tasks: - name: create wire-server-deploy directory for {{ ansible_user }} user file: - path: /home/{{ ansible_user }}/wire-server-deploy + path: "{{ ansible_user_dir }}/wire-server-deploy" state: directory owner: "{{ ansible_user }}" group: "{{ ansible_user }}" @@ -13,14 +13,14 @@ - name: check if wire-server-deploy-static-demo-{{ artifact_hash }}.tgz exists stat: - path: /home/{{ ansible_user }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz + path: "{{ ansible_user_dir }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" get_checksum: False register: artifact_archive_file_check - name: download wire-server-deploy archive shell: - cmd: curl -fsSLo /home/{{ ansible_user }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz https://s3-eu-west-1.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz - creates: /home/{{ ansible_user }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz + cmd: curl -fsSLo "{{ ansible_user_dir }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" https://s3-eu-west-1.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz + creates: "{{ ansible_user_dir }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" when: not artifact_archive_file_check.stat.exists register: artifact_archive async: 1200 @@ -37,17 +37,24 @@ - name: check if wire-server-deploy folder contents exist stat: - path: /home/{{ ansible_user }}/wire-server-deploy/containers-helm.tar + path: "{{ ansible_user_dir }}/wire-server-deploy/containers-helm.tar" get_checksum: False register: artifact_folder_content_check - name: Unpack wire-server-deploy archive, will take a few mins - grab a coffee unarchive: - src: /home/{{ ansible_user }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz - dest: /home/{{ ansible_user }}/wire-server-deploy + src: "{{ ansible_user_dir }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" + dest: "{{ ansible_user_dir }}/wire-server-deploy" remote_src: yes when: not artifact_folder_content_check.stat.exists - - name: set permissions inside wire-server-deploy via shell command (fails when using ansible directive) - shell: - cmd: sudo chmod -R 0775 /home/{{ ansible_user }}/wire-server-deploy; sudo chown -R {{ ansible_user }}:{{ ansible_user }} /home/{{ ansible_user }} + - name: Ensure directory exists and set permissions + file: + path: "{{ ansible_user_dir }}/wire-server-deploy" + state: directory + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0775' + recurse: yes + follow: no + become: yes diff --git a/ansible/wiab-demo/hairpin_networking.yml b/ansible/wiab-demo/hairpin_networking.yml new file mode 100644 index 000000000..8773190be --- /dev/null +++ b/ansible/wiab-demo/hairpin_networking.yml @@ -0,0 +1,79 @@ +--- +- name: Configure networking for cert-manager HTTP access + hosts: deploy_node + become: true + tasks: + - name: Test HTTP connectivity from minikube node to its own public IP + command: > + docker exec {{ minikube_profile }} + sh -c "curl -sS -o /dev/null -w '%{http_code}' --connect-timeout 2 http://{{ wire_ip }}" + register: curl_test + failed_when: false + changed_when: false + + - name: Determine if hairpin NAT is required (treat any 1xx–5xx as success) + set_fact: + hairpin_required: >- + {{ + not ( + curl_test.stdout is match("^[1-5][0-9][0-9]$") + ) + }} + + - name: Configure hairpin NAT rules for ingress + when: hairpin_required | bool + block: + + - name: Configure DNAT hairpin rules to manage http/https traffic for the k8s ingress controller + iptables: + table: nat + chain: PREROUTING + protocol: "{{ item.protocol }}" + jump: DNAT + in_interface: "{{ matching_bridge_interface }}" + destination: "{{ default_interface_ip }}" + destination_port: "{{ item.port }}" + to_destination: "{{ k8s_ingress_controller_ip }}:{{ item.to_port }}" + state: present + action: insert + comment: "{{ iptables_rules_comment }}" + loop: "{{ http_dnat_rules }}" + loop_control: + label: "Setting DNAT rule for port {{ item.port }} -> {{ k8s_ingress_controller_ip | default('undefined') }}:{{ item.to_port }}" + + - name: MASQUERADE for intra-bridge return path to avoid ("src==dst") + iptables: + table: nat + chain: POSTROUTING + protocol: "{{ item.protocol }}" + jump: MASQUERADE + out_interface: "{{ matching_bridge_interface }}" + source: "{{ minikube_node_subnet }}" + destination: "{{ k8s_ingress_controller_ip }}/32" + destination_port: "{{ item.to_port }}" + state: present + action: insert + comment: "{{ iptables_rules_comment }}" + loop: "{{ http_dnat_rules }}" + loop_control: + label: "Setting DNAT rule for port {{ item.port }} -> {{ k8s_ingress_controller_ip | default('undefined') }}:{{ item.to_port }}" + + - name: Enable hairpin mode on all bridge ports + shell: | + changed=0 + for f in /sys/class/net/{{ matching_bridge_interface }}/brif/*/hairpin_mode; do + [ -f "$f" ] || continue + cur="$(cat "$f" 2>/dev/null || echo 0)" + if [ "$cur" != "1" ]; then + echo 1 > "$f" + changed=1 + fi + done + echo $changed + args: + executable: /bin/bash + register: hairpin_set + changed_when: hairpin_set.stdout | trim != "0" + + - name: Preserve the Iptables rules + shell: iptables-save -f "{{ iptables_save_dir }}"/rules_post_wire.v4 \ No newline at end of file diff --git a/ansible/wiab-demo/helm_install.yml b/ansible/wiab-demo/helm_install.yml index 6f9543d46..f0dfa984f 100644 --- a/ansible/wiab-demo/helm_install.yml +++ b/ansible/wiab-demo/helm_install.yml @@ -6,72 +6,29 @@ # admin container definition for WSD (wire-server-deploy) docker_cmd_base: >- docker run --network=host - -v "/home/{{ ansible_user }}/.ssh":/root/.ssh - -v "/home/{{ ansible_user }}/wire-server-deploy/":/wire-server-deploy - -v "/home/{{ ansible_user }}/.kube/config":/root/.kube/config - -v "/home/{{ ansible_user }}/.minikube":/home/ubuntu/.minikube + -v "{{ ansible_user_dir }}/.ssh":/root/.ssh + -v "{{ ansible_user_dir }}/wire-server-deploy/":/wire-server-deploy + -v "{{ ansible_user_dir }}/.kube/config":/root/.kube/config + -v "{{ ansible_user_dir }}/.minikube":{{ ansible_user_dir }}/.minikube -e KUBECONFIG=/root/.kube/config "{{ wsd_container.stdout }}" tasks: + - name: Check if WSD Docker image already exists + shell: docker images | grep "quay.io/wire/wire-server-deploy" | awk '{print $1":"$2}' | head -1 + register: existing_wsd_image + failed_when: false + changed_when: false - - name: Replace TARGET_SYSTEM example.com with target_domain in offline_deploy_k8s - lineinfile: - path: /home/{{ ansible_user }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh - regexp: '^TARGET_SYSTEM="example\.com"' - line: 'TARGET_SYSTEM="{{ target_domain }}"' - backrefs: yes - - - name: Replace CERT_MASTER_EMAIL example.com with target_domain in offline_deploy_k8s - lineinfile: - path: /home/{{ ansible_user }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh - regexp: '^CERT_MASTER_EMAIL="certmaster@example\.com"' - line: 'CERT_MASTER_EMAIL="certmaster@{{ target_domain }}"' - backrefs: yes - - - name: Add HOST_IP with wire_ip in offline_deploy_k8s - lineinfile: - path: /home/{{ ansible_user }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh - regexp: '^HOST_IP="WIRE_IP"' - line: 'HOST_IP="{{ wire_ip }}"' - backrefs: yes - - - name: Update SFT_NODE in the offline_deploy_k8s - lineinfile: - path: /home/{{ ansible_user }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh - regexp: '^SFT_NODE="K8S_SFT_NODE"' - line: 'SFT_NODE="{{ k8s_sft_node }}"' - backrefs: yes - - - name: Update NGINX_K8S_NODE in the offline_deploy_k8s - lineinfile: - path: /home/{{ ansible_user }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh - regexp: '^NGINX_K8S_NODE="NGINX_K8S_NODE"' - line: 'NGINX_K8S_NODE="{{ k8s_ingress_controller_node }}"' - backrefs: yes - - - name: Update COTURN_NODE in the offline_deploy_k8s - lineinfile: - path: /home/{{ ansible_user }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh - regexp: '^COTURN_NODE="K8S_COTURN_NODE"' - line: 'COTURN_NODE="{{ k8s_coturn_node }}"' - backrefs: yes - - - name: Load WSD Docker image - shell: | - docker load -i "/home/{{ ansible_user }}/wire-server-deploy/containers-adminhost/container-wire-server-deploy.tgz" | awk '{print $3}' - register: wsd_container - - - name: Process charts for demo environment - shell: | - {{ docker_cmd_base }} bash -c "source /wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && process_charts demo" - args: - executable: /bin/bash - - - name: Process values + - name: Load WSD Docker image (if not already present) shell: | - {{ docker_cmd_base }} bash -c "source /wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && process_values" - args: - executable: /bin/bash + docker load -i "{{ ansible_user_dir }}/wire-server-deploy/containers-adminhost/container-wire-server-deploy.tgz" | awk '{print $3}' + register: loaded_wsd_container + when: existing_wsd_image.stdout == "" + + - name: Set WSD container image name + set_fact: + wsd_container: + stdout: "{{ existing_wsd_image.stdout if existing_wsd_image.stdout != '' else loaded_wsd_container.stdout }}" - name: Deploy cert manager # disable if running in a private env shell: | @@ -91,3 +48,9 @@ {{ docker_cmd_base }} bash -c "source /wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && deploy_calling_services" args: executable: /bin/bash + + - name: Deploy wire-utility + shell: | + {{ docker_cmd_base }} bash -c "helm upgrade --install --wait wire-utility /wire-server-deploy/charts/wire-utility --values /wire-server-deploy/values/wire-server/values.yaml --values /wire-server-deploy/values/wire-server/secrets.yaml --values /wire-server-deploy/values/wire-utility/values.yaml" + args: + executable: /bin/bash diff --git a/ansible/wiab-demo/install_pkgs.yml b/ansible/wiab-demo/install_pkgs.yml index ab7a51114..c121093d6 100644 --- a/ansible/wiab-demo/install_pkgs.yml +++ b/ansible/wiab-demo/install_pkgs.yml @@ -4,51 +4,67 @@ tasks: - name: Install required packages block: - - name: apt update - apt: update_cache=yes force_apt_get=yes - - - name: apt upgrade - apt: upgrade=dist force_apt_get=yes - - name: Install dependencies apt: name: - - yq - jq state: present update_cache: yes - - name: Create /etc/apt/keyrings directory - file: - path: /etc/apt/keyrings - state: directory + - name: Install yq-go + get_url: + url: "https://github.com/mikefarah/yq/releases/download/v4.48.1/yq_linux_amd64" + dest: /usr/local/bin/yq mode: '0755' - - name: Download Docker GPG key - get_url: - url: https://download.docker.com/linux/ubuntu/gpg - dest: /etc/apt/keyrings/docker.asc - mode: '0644' + - name: Check if Docker CE is installed with correct version + shell: apt policy docker-ce | grep "Installed:" | awk '{print $2}' + register: installed_docker_version + changed_when: false - - name: Add Docker repository to apt sources - shell: | - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list - args: - executable: /bin/bash + - name: Check if containerd.io is installed with correct version + shell: apt policy containerd.io | grep "Installed:" | awk '{print $2}' + register: installed_containerd_version + changed_when: false - - name: Update apt package index - apt: - update_cache: yes + - name: Determine if Docker packages need installation + set_fact: + docker_needs_install: "{{ installed_docker_version.stdout != docker_ce_version or installed_containerd_version.stdout != containerd_version }}" - - name: Install Docker packages - apt: - name: - - docker-ce={{ docker_ce_version }} - - docker-ce-cli={{ docker_ce_version }} - - containerd.io={{ containerd_version }} - state: present + - name: Setup Docker if packages not installed or wrong version + when: docker_needs_install | bool + block: + - name: Create /etc/apt/keyrings directory + file: + path: /etc/apt/keyrings + state: directory + mode: '0755' + + - name: Download Docker GPG key + get_url: + url: https://download.docker.com/linux/ubuntu/gpg + dest: /etc/apt/keyrings/docker.asc + mode: '0644' + + - name: Add Docker repository to apt sources + shell: | + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list + args: + executable: /bin/bash + + - name: Update apt package index + apt: + update_cache: yes + + - name: Install Docker packages + apt: + name: + - docker-ce={{ docker_ce_version }} + - docker-ce-cli={{ docker_ce_version }} + - containerd.io={{ containerd_version }} + state: present - - name: Add ubuntu user to the docker group + - name: Add {{ ansible_user }} to the docker group user: name: "{{ ansible_user }}" groups: docker diff --git a/ansible/wiab-demo/iptables_rules.yml b/ansible/wiab-demo/iptables_rules.yml index 3cd52473d..54dd62754 100644 --- a/ansible/wiab-demo/iptables_rules.yml +++ b/ansible/wiab-demo/iptables_rules.yml @@ -1,9 +1,6 @@ - name: Configure Iptable rules hosts: deploy_node become: yes - vars: - iptables_rules_comment: "Wire Iptables Rules" - iptables_save_dir: "/home/{{ ansible_user }}/wire-iptables-rules" tasks: - name: Ensure iptables directory exists file: @@ -13,6 +10,14 @@ group: root mode: '0755' + - name: Enable bridge netfilter for iptables + sysctl: + name: net.bridge.bridge-nf-call-iptables + value: "1" + state: present + sysctl_set: true + reload: true + # incase, this pipeline is running again, we try to preserve initial state - name: Check if pre_wire IPv4 ruleset file exists stat: @@ -26,70 +31,29 @@ - name: Save iptables rules shell: iptables-save -f "{{ iptables_save_dir }}"/rules_pre_wire.v4 - - name: Get the default interface for the default route - shell: ip route | awk '/default/ {print $5}' | head -n 1 - register: default_interface - changed_when: false - - - name: Get the IP address of the default interface - shell: ip -4 addr show dev {{ default_interface.stdout }} | awk '/inet / {print $2}' | cut -d/ -f1 - register: default_interface_ip - changed_when: false - - - name: Get the IP address of the k8s_ingress_controller node - shell: | - kubectl --kubeconfig="/home/{{ ansible_user }}/.kube/config" get node {{ k8s_ingress_controller_node }} -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address' - register: k8s_ingress_controller_ip - become: yes - become_user: "{{ ansible_user }}" - changed_when: false - - name: Configure DNAT rules to send http/https traffic to the k8s ingress controller iptables: table: nat chain: PREROUTING protocol: "{{ item.protocol }}" jump: DNAT - in_interface: "{{ default_interface.stdout }}" - destination: "{{ default_interface_ip.stdout }}" + in_interface: "{{ default_interface }}" + destination: "{{ default_interface_ip }}" destination_port: "{{ item.port }}" - to_destination: "{{ k8s_ingress_controller_ip.stdout }}:{{ item.to_port }}" + to_destination: "{{ k8s_ingress_controller_ip }}:{{ item.to_port }}" state: present action: insert comment: "{{ iptables_rules_comment }}" loop: "{{ http_dnat_rules }}" loop_control: - label: "Setting DNAT rule for port {{ item.port }} -> {{ k8s_ingress_controller_ip.stdout | default('undefined') }}:{{ item.to_port }}" - - - name: Get the {{ minikube_network_name }} Docker network ID - shell: | - docker network inspect {{ minikube_network_name }} | jq -r '.[0].Id' - register: docker_network_id - changed_when: false - - - name: Get all interfaces with bridge interfaces - shell: ip -o addr show | awk '{print $2}' | grep -i 'br-' - register: bridge_interfaces - changed_when: false - - - name: Find the matching bridge interface for {{ minikube_network_name }} Docker network - shell: | - for iface in {{ bridge_interfaces.stdout_lines | join(' ') }}; do - iface_id=$(echo "$iface" | cut -d '-' -f2) - if echo "{{ docker_network_id.stdout }}" | grep -q "$iface_id"; then - echo "$iface" - break - fi - done - register: matching_bridge_interface - changed_when: false + label: "Setting DNAT rule for port {{ item.port }} -> {{ k8s_ingress_controller_ip | default('undefined') }}:{{ item.to_port }}" - name: Ensure FORWARD rule for traffic from main interface to ingress controller iptables: table: filter chain: FORWARD - in_interface: "{{ default_interface.stdout }}" - out_interface: "{{ matching_bridge_interface.stdout }}" + in_interface: "{{ default_interface }}" + out_interface: "{{ matching_bridge_interface }}" jump: ACCEPT state: present action: insert @@ -99,8 +63,8 @@ iptables: table: filter chain: FORWARD - in_interface: "{{ matching_bridge_interface.stdout }}" - out_interface: "{{ default_interface.stdout }}" + in_interface: "{{ matching_bridge_interface }}" + out_interface: "{{ default_interface }}" jump: ACCEPT state: present action: insert @@ -108,7 +72,7 @@ - name: Get the IP address of the coturn node shell: | - kubectl --kubeconfig="/home/{{ ansible_user }}/.kube/config" get node {{ k8s_coturn_node }} -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address' + kubectl --kubeconfig="{{ kube_config_path }}" get node {{ k8s_coturn_node }} -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address' register: k8s_coturn_node_ip changed_when: false @@ -116,15 +80,15 @@ debug: msg: "coturn node: {{ k8s_coturn_node }}, ip: {{ k8s_coturn_node_ip }}" - - name: Configure DNAT rule to send UDP traffic for coturn to coturn server on k8s node + - name: Configure DNAT rule to send UDP calling traffic for coturn/sftd pods on the k8s node iptables: table: nat chain: PREROUTING protocol: udp jump: DNAT - destination: "{{ default_interface_ip.stdout }}" - destination_ports: "49152:65535" - in_interface: "{{ default_interface.stdout }}" + destination: "{{ default_interface_ip }}" + destination_ports: "32768:65535" + in_interface: "{{ default_interface }}" to_destination: "{{ k8s_coturn_node_ip.stdout }}" state: present action: insert @@ -136,8 +100,8 @@ chain: PREROUTING protocol: "{{ item.protocol }}" jump: DNAT - in_interface: "{{ default_interface.stdout }}" - destination: "{{ default_interface_ip.stdout }}" + in_interface: "{{ default_interface }}" + destination: "{{ default_interface_ip }}" destination_port: "{{ item.port }}" to_destination: "{{ k8s_coturn_node_ip.stdout }}:{{ item.to_port }}" state: present diff --git a/ansible/wiab-demo/minikube_cluster.yml b/ansible/wiab-demo/minikube_cluster.yml index d1db40e9d..3675f1932 100644 --- a/ansible/wiab-demo/minikube_cluster.yml +++ b/ansible/wiab-demo/minikube_cluster.yml @@ -26,6 +26,7 @@ --subnet={{ minikube_node_subnet }} \ --profile="{{ minikube_profile }}" \ --wait-timeout=15m0s \ + --force \ --wait=all when: "'Running' not in minikube_status.stdout" @@ -35,7 +36,7 @@ - name: Get authorized_keys from minikube nodes shell: | - minikube cp --profile="{{ minikube_profile }}" {{ item }}:/home/docker/.ssh/authorized_keys "/home/{{ ansible_user }}/{{ item }}_authorized_keys" + minikube cp --profile="{{ minikube_profile }}" {{ item }}:/home/docker/.ssh/authorized_keys "{{ ansible_user_dir }}/{{ item }}_authorized_keys" args: executable: /bin/bash with_items: "{{ minikube_nodes_raw.stdout_lines }}" @@ -44,7 +45,7 @@ - name: Ensure our SSH key is present lineinfile: - path: "/home/{{ ansible_user }}/{{ item }}_authorized_keys" + path: "{{ ansible_user_dir }}/{{ item }}_authorized_keys" line: "{{ ssh_public_key }}" create: yes mode: '0600' @@ -52,7 +53,7 @@ register: ssh_key_result - name: Put back the authorized_keys file back to the minikube nodes - shell: minikube cp --profile="{{ minikube_profile }}" "/home/{{ ansible_user }}/{{ item }}_authorized_keys" {{ item }}:/home/docker/.ssh/authorized_keys + shell: minikube cp --profile="{{ minikube_profile }}" "{{ ansible_user_dir }}/{{ item }}_authorized_keys" {{ item }}:/home/docker/.ssh/authorized_keys args: executable: /bin/bash with_items: "{{ minikube_nodes_raw.stdout_lines }}" @@ -61,7 +62,7 @@ when: ssh_key_result is changed - name: Clean the copied authorized_keys - shell: rm "/home/{{ ansible_user }}/{{ item }}_authorized_keys" + shell: rm "{{ ansible_user_dir }}/{{ item }}_authorized_keys" args: executable: /bin/bash with_items: "{{ minikube_nodes_raw.stdout_lines }}" diff --git a/ansible/wiab-demo/setup_ssh.yml b/ansible/wiab-demo/setup_ssh.yml index ec9d31593..a256f28c2 100644 --- a/ansible/wiab-demo/setup_ssh.yml +++ b/ansible/wiab-demo/setup_ssh.yml @@ -7,7 +7,7 @@ block: - name: Ensure the .ssh directory exists file: - path: "/home/{{ ansible_user }}/.ssh" + path: "{{ ansible_user_dir }}/.ssh" state: directory mode: '0700' owner: "{{ ansible_user }}" @@ -15,20 +15,20 @@ - name: Generate SSH key if it does not exist shell: | - if [ ! -f "/home/{{ ansible_user }}/.ssh/id_rsa_wire" ]; then - ssh-keygen -t rsa -b 4096 -f "/home/{{ ansible_user }}/.ssh/id_rsa_wire" -N "" -C "ansible_generated_key_wire"; + if [ ! -f "{{ ansible_user_dir }}/.ssh/id_rsa_wire" ]; then + ssh-keygen -t rsa -b 4096 -f "{{ ansible_user_dir }}/.ssh/id_rsa_wire" -N "" -C "ansible_generated_key_wire"; fi args: - creates: "/home/{{ ansible_user }}/.ssh/id_rsa_wire" + creates: "{{ ansible_user_dir }}/.ssh/id_rsa_wire" - name: Read the private key slurp: - src: "/home/{{ ansible_user }}/.ssh/id_rsa_wire" + src: "{{ ansible_user_dir }}/.ssh/id_rsa_wire" register: ssh_key_private - name: Read the public key content slurp: - src: "/home/{{ ansible_user }}/.ssh/id_rsa_wire.pub" + src: "{{ ansible_user_dir }}/.ssh/id_rsa_wire.pub" register: ssh_key_content - name: Set the public key as a fact diff --git a/ansible/wiab-demo/verify_dns.yml b/ansible/wiab-demo/verify_dns.yml index 622c93ed5..85d9421f7 100644 --- a/ansible/wiab-demo/verify_dns.yml +++ b/ansible/wiab-demo/verify_dns.yml @@ -11,14 +11,14 @@ - account.{{ target_domain }} test_port: 3478 tasks: - - name: Check DNS A records + - name: Query DNS A records command: "dig +short {{ item }}" register: dns_result failed_when: false changed_when: false with_items: "{{ dns_records }}" - - name: Check if DNS records exist + - name: Verify if records do not exist fail: msg: "DNS record {{ item.item }} does not exist." when: item.stdout | trim == '' @@ -26,4 +26,30 @@ loop_control: label: "{% if item.stdout is defined %}{{ item.item }}{% else %}checking{% endif %}" + - name: Check SPF TXT record for the domain + command: "dig +short TXT {{ target_domain }}" + register: spf_result + failed_when: false + changed_when: false + + - name: display SPF TXT record + debug: + msg: "SPF TXT record for {{ target_domain }}: {{ spf_result.stdout | default('No TXT record found') }}" + + - name: Verify SPF TXT record exists and contains expected IP + debug: + msg: | + WARNING: SPF TXT record for {{ target_domain }} is missing or does not contain the expected IP {{ wire_ip }}. + Found: {{ spf_result.stdout | default('No TXT record found') }} + + SPF (Sender Policy Framework) records are used by email services to verify the authenticity of mail sources. + Without proper SPF configuration, emails from Wire services may be marked as spam or rejected by recipient mail servers. + + Expected SPF record: "v=spf1 ip4:{{ wire_ip }} -all" + + For more information about SPF records, see: https://docs.wire.com/latest/how-to/install/demo-wiab.html#dns-requirements + when: > + spf_result.stdout | trim == '' or + wire_ip not in spf_result.stdout + # create dns entries on the deploy_node in /etc/hosts and suggest dns records creation in case of a private ip diff --git a/ansible/wiab-demo/verify_wire_ip.yml b/ansible/wiab-demo/verify_wire_ip.yml index ea955f4e1..cf1797fc5 100644 --- a/ansible/wiab-demo/verify_wire_ip.yml +++ b/ansible/wiab-demo/verify_wire_ip.yml @@ -9,12 +9,12 @@ block: - name: Check if wire_ip file exists stat: - path: "/home/{{ ansible_user }}/wire_ip" + path: "{{ ansible_user_dir }}/wire_ip" register: wire_ip_file - name: Read Wire IP from file if it exists slurp: - src: "/home/{{ ansible_user }}/wire_ip" + src: "{{ ansible_user_dir }}/wire_ip" register: wire_ip_content when: wire_ip_file.stat.exists @@ -69,7 +69,12 @@ - name: Display connection test result ansible.builtin.debug: - msg: "{{ 'Public IP {{ temp_wire_ip }} assigned to the node is reachable' if connection_test.rc == 0 else 'Connection test failed, trying setting wire_ip to avoid testing access' }}" + msg: >- + {% if connection_test.rc == 0 %} + Public IP {{ temp_wire_ip }} assigned to the node is reachable + {% else %} + Connection test failed, trying setting wire_ip to avoid testing access + {% endif %} - name: Stop TCP service ansible.builtin.shell: | @@ -91,7 +96,7 @@ - name: Store public IP in file copy: - dest: "/home/{{ ansible_user }}/wire_ip" + dest: "{{ ansible_user_dir }}/wire_ip" content: "{{ temp_wire_ip }}" when: connection_test.rc == 0 @@ -99,3 +104,18 @@ set_fact: wire_ip: "{{ temp_wire_ip }}" when: connection_test.rc == 0 + + - name: Get the default interface for the default route + shell: ip route | awk '/default/ {print $5}' | head -n 1 + register: default_interface + changed_when: false + + - name: Get the IP address of the default interface + shell: ip -4 addr show dev {{ default_interface.stdout }} | awk '/inet / {print $2}' | cut -d/ -f1 + register: default_interface_ip + changed_when: false + + - name: set facts for default address and interface + set_fact: + default_interface: "{{ default_interface.stdout }}" + default_interface_ip: "{{ default_interface_ip.stdout }}" diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index 2b8f2879c..49f53dcb4 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -17,14 +17,27 @@ "{{ item.item.name }}": "{{ item.stdout }}" with_items: "{{ random_strings.results }}" - - name: find zauth container image name - shell: ls /home/{{ ansible_user }}/wire-server-deploy/containers-adminhost/quay.io_wire_zauth_*.tar + - name: Check if ZAUTH Docker image already exists + shell: docker images | grep "quay.io/wire/zauth" | awk '{print $1":"$2}' | head -1 + register: existing_zauth_image + failed_when: false + changed_when: false + + - name: find zauth container image file (if image not already present) + shell: find "{{ ansible_user_dir }}/wire-server-deploy/containers-adminhost/" -name "quay.io_wire_zauth_*.tar" -type f | head -1 register: zauth_docker_image + when: existing_zauth_image.stdout == "" - - name: Load ZAUTH Docker image + - name: Load ZAUTH Docker image (if not already present) shell: | docker load -i "{{ zauth_docker_image.stdout }}" | awk '{print $3}' - register: zauth_container + register: loaded_zauth_container + when: existing_zauth_image.stdout == "" + + - name: Set ZAUTH container image name + set_fact: + zauth_container: + stdout: "{{ existing_zauth_image.stdout if existing_zauth_image.stdout != '' else loaded_zauth_container.stdout }}" - name: Generate zauth keypair shell: docker run "{{ zauth_container.stdout }}" -m gen-keypair @@ -43,13 +56,13 @@ - "zauth_public: {{ zauth_public }}" - "zauth_private: {{ zauth_private }}" - - name: Update values in secrets.yaml using Python yq + - name: Update values in secrets.yaml using yq shell: | - yq -yi '.brig.secrets.turn.secret = "{{ zrest }}"' {{ secrets_yaml_path }} - yq -yi '.brig.secrets.zAuth.publicKeys = "{{ zauth_public }}"' {{ secrets_yaml_path }} - yq -yi '.brig.secrets.zAuth.privateKeys = "{{ zauth_private }}"' {{ secrets_yaml_path }} - yq -yi '.nginz.secrets.zAuth.publicKeys = "{{ zauth_public }}"' {{ secrets_yaml_path }} + yq eval -i '.brig.secrets.turn.secret = "{{ zrest }}"' {{ secrets_yaml_path }} + yq eval -i '.brig.secrets.zAuth.publicKeys = "{{ zauth_public }}"' {{ secrets_yaml_path }} + yq eval -i '.brig.secrets.zAuth.privateKeys = "{{ zauth_private }}"' {{ secrets_yaml_path }} + yq eval -i '.nginz.secrets.zAuth.publicKeys = "{{ zauth_public }}"' {{ secrets_yaml_path }} args: executable: /bin/bash vars: - secrets_yaml_path: "/home/{{ ansible_user }}/wire-server-deploy/values/wire-server/demo-secrets.example.yaml" + secrets_yaml_path: "{{ ansible_user_dir }}/wire-server-deploy/values/wire-server/secrets.yaml" diff --git a/ansible/wiab-demo/wire_values.yml b/ansible/wiab-demo/wire_values.yml new file mode 100644 index 000000000..63aa6a94e --- /dev/null +++ b/ansible/wiab-demo/wire_values.yml @@ -0,0 +1,56 @@ +- name: Prepare helm chart values + hosts: deploy_node + become: yes + become_user: "{{ ansible_user }}" + tasks: + - name: Replace TARGET_SYSTEM example.com with target_domain in offline_deploy_k8s + lineinfile: + path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" + regexp: '^TARGET_SYSTEM="example\.com"' + line: 'TARGET_SYSTEM="{{ target_domain }}"' + backrefs: yes + + - name: Replace CERT_MASTER_EMAIL example.com with target_domain in offline_deploy_k8s + lineinfile: + path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" + regexp: '^CERT_MASTER_EMAIL="certmaster@example\.com"' + line: 'CERT_MASTER_EMAIL="certmaster@{{ target_domain }}"' + backrefs: yes + + - name: Add HOST_IP with wire_ip in offline_deploy_k8s + lineinfile: + path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" + regexp: '^HOST_IP="WIRE_IP"' + line: 'HOST_IP="{{ wire_ip }}"' + backrefs: yes + + - name: Update SFT_NODE in the offline_deploy_k8s + lineinfile: + path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" + regexp: '^SFT_NODE="K8S_SFT_NODE"' + line: 'SFT_NODE="{{ k8s_sft_node }}"' + backrefs: yes + + - name: Update NGINX_K8S_NODE in the offline_deploy_k8s + lineinfile: + path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" + regexp: '^NGINX_K8S_NODE="NGINX_K8S_NODE"' + line: 'NGINX_K8S_NODE="{{ k8s_ingress_controller_node }}"' + backrefs: yes + + - name: Update COTURN_NODE in the offline_deploy_k8s + lineinfile: + path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" + regexp: '^COTURN_NODE="K8S_COTURN_NODE"' + line: 'COTURN_NODE="{{ k8s_coturn_node }}"' + backrefs: yes + + - name: Prepare values.yaml files for the demo environment + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_charts demo + args: + executable: /bin/bash + + - name: Process vars for Helm chart values + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_values + args: + executable: /bin/bash diff --git a/bin/wiab-demo/offline-env.sh b/bin/wiab-demo/offline-env.sh index d514a284a..116ff62d6 100644 --- a/bin/wiab-demo/offline-env.sh +++ b/bin/wiab-demo/offline-env.sh @@ -2,17 +2,46 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -ZAUTH_CONTAINER=$(sudo docker load -i "$SCRIPT_DIR"/../../containers-adminhost/quay.io_wire_zauth_*.tar | awk '{print $3}') +# Function to check if image exists and get its name, or load from tar +check_or_load_image() { + local tar_file="$1" + local image_pattern="$2" + + # Check if any image matching pattern exists in docker + local existing_image + existing_image=$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep "$image_pattern" | head -1) + if [ -n "$existing_image" ]; then + echo "$existing_image" + return 0 + fi + + # If no existing image, load from tar + sudo docker load -i "$tar_file" | awk '{print $3}' +} + +# Get container image names efficiently +ZAUTH_CONTAINER=$(check_or_load_image "$SCRIPT_DIR/../../containers-adminhost/quay.io_wire_zauth_"*.tar "quay.io/wire/zauth") +WSD_CONTAINER=$(check_or_load_image "$SCRIPT_DIR/../../containers-adminhost/container-wire-server-deploy.tgz" "quay.io/wire/wire-server-deploy") + export ZAUTH_CONTAINER -WSD_CONTAINER=$(sudo docker load -i "$SCRIPT_DIR"/../../containers-adminhost/container-wire-server-deploy.tgz | awk '{print $3}') +# detect if d should run interactively +d() { + local docker_flags="" + # Check if both stdin and stdout are terminals + # If either of them is not a terminal (piped/redirected), run in detached mode + if [ -t 0 ] && [ -t 1 ]; then + docker_flags="-it" + fi -alias d="sudo docker run --network=host -ti \ - -v \${SSH_AUTH_SOCK:-nonexistent}:/ssh-agent \ + # Run docker with appropriate flags + sudo docker run --network=host $docker_flags \ + -v "${SSH_AUTH_SOCK:-nonexistent}:/ssh-agent" \ -e SSH_AUTH_SOCK=/ssh-agent \ - -v \$HOME/.ssh:/root/.ssh \ - -v \$PWD:/wire-server-deploy \ - -v /home/ubuntu/.kube:/root/.kube \ - -v /home/ubuntu/.minikube:/home/ubuntu/.minikube \ + -v "$HOME/.ssh:/root/.ssh" \ + -v "$PWD:/wire-server-deploy" \ + -v "$HOME/.kube:/root/.kube" \ + -v "$HOME/.minikube:$HOME/.minikube" \ -e KUBECONFIG=/root/.kube/config \ - \$WSD_CONTAINER" + "$WSD_CONTAINER" "$@" +} diff --git a/bin/wiab-demo/offline_deploy_k8s.sh b/bin/wiab-demo/offline_deploy_k8s.sh index 5b61dd629..f7cd71ae3 100644 --- a/bin/wiab-demo/offline_deploy_k8s.sh +++ b/bin/wiab-demo/offline_deploy_k8s.sh @@ -2,7 +2,7 @@ # shellcheck disable=SC2087 set -Eeuo pipefail -BASE_DIR="/wire-server-deploy" +BASE_DIR="${BASE_DIR:-/wire-server-deploy}" TARGET_SYSTEM="example.com" CERT_MASTER_EMAIL="certmaster@example.com" @@ -28,28 +28,32 @@ process_charts() { echo "Error: This script only supports demo deployments. ENV must be 'demo', got: '$ENV'" exit 1 fi - + timestp=$(date +"%Y%m%d_%H%M%S") for chart_dir in "$BASE_DIR"/values/*/; do if [[ -d "$chart_dir" ]]; then if [[ -f "$chart_dir/${ENV}-values.example.yaml" ]]; then - # assuming if the values.yaml exist, it won't replace it again to make it idempotent if [[ ! -f "$chart_dir/values.yaml" ]]; then cp "$chart_dir/${ENV}-values.example.yaml" "$chart_dir/values.yaml" echo "Used template ${ENV}-values.example.yaml to create $chart_dir/values.yaml" + else + echo "$chart_dir/values.yaml already exists, archiving it and creating a new one." + mv "$chart_dir/values.yaml" "$chart_dir/values.yaml.bak.$timestp" + cp "$chart_dir/${ENV}-values.example.yaml" "$chart_dir/values.yaml" fi fi if [[ -f "$chart_dir/${ENV}-secrets.example.yaml" ]]; then - # assuming if the secrets.yaml exist, it won't replace it again to make it idempotent if [[ ! -f "$chart_dir/secrets.yaml" ]]; then cp "$chart_dir/${ENV}-secrets.example.yaml" "$chart_dir/secrets.yaml" echo "Used template ${ENV}-secrets.example.yaml to create $chart_dir/secrets.yaml" + else + echo "$chart_dir/secrets.yaml already exists, archiving it and creating a new one." + mv "$chart_dir/secrets.yaml" "$chart_dir/secrets.yaml.bak.$timestp" + cp "$chart_dir/${ENV}-secrets.example.yaml" "$chart_dir/secrets.yaml" fi fi - fi - done } @@ -102,9 +106,6 @@ secrets: EOF cat >"$TEMP_DIR/coturn-values.yaml"< Date: Tue, 25 Nov 2025 12:52:59 +0100 Subject: [PATCH 02/22] fix: create a new tag for wire_secrets and handle errors from zauth wpb-17321 --- ansible/wiab-demo/deploy_wiab.yml | 2 +- ansible/wiab-demo/hairpin_networking.yml | 2 +- ansible/wiab-demo/wire_secrets.yml | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ansible/wiab-demo/deploy_wiab.yml b/ansible/wiab-demo/deploy_wiab.yml index f7bd2a4fa..bf6080f1c 100644 --- a/ansible/wiab-demo/deploy_wiab.yml +++ b/ansible/wiab-demo/deploy_wiab.yml @@ -207,7 +207,7 @@ - name: Create wire secrets import_playbook: ./wire_secrets.yml - tags: helm_install + tags: wire_secrets - name: Install Helm charts import_playbook: ./helm_install.yml diff --git a/ansible/wiab-demo/hairpin_networking.yml b/ansible/wiab-demo/hairpin_networking.yml index 8773190be..201d94f94 100644 --- a/ansible/wiab-demo/hairpin_networking.yml +++ b/ansible/wiab-demo/hairpin_networking.yml @@ -76,4 +76,4 @@ changed_when: hairpin_set.stdout | trim != "0" - name: Preserve the Iptables rules - shell: iptables-save -f "{{ iptables_save_dir }}"/rules_post_wire.v4 \ No newline at end of file + shell: iptables-save -f "{{ iptables_save_dir }}"/rules_post_wire.v4 diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index 49f53dcb4..d2ed76846 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -43,19 +43,19 @@ shell: docker run "{{ zauth_container.stdout }}" -m gen-keypair register: zauth_output changed_when: false + ignore_errors: true + + - name: Fallback - Generate zauth keypair with index + shell: docker run "{{ zauth_container.stdout }}" -m gen-keypair -i 1 + register: zauth_output + changed_when: false + when: zauth_output is failed - name: Extract zauth keys set_fact: zauth_public: "{{ zauth_output.stdout_lines[0].split()[1] }}" zauth_private: "{{ zauth_output.stdout_lines[1].split()[1] }}" - - name: Created following secrets - debug: - msg: - - "zrest: {{ zrest }}" - - "zauth_public: {{ zauth_public }}" - - "zauth_private: {{ zauth_private }}" - - name: Update values in secrets.yaml using yq shell: | yq eval -i '.brig.secrets.turn.secret = "{{ zrest }}"' {{ secrets_yaml_path }} From cf86db98acaddb2c9b26e1acceecf8644baa04eb Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Wed, 26 Nov 2025 10:27:46 +0100 Subject: [PATCH 03/22] fix wpb-17321: made wire_secrets playbook idempotent --- ansible/wiab-demo/wire_secrets.yml | 188 +++++++++++++++++++---------- 1 file changed, 125 insertions(+), 63 deletions(-) diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index d2ed76846..dc479b723 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -2,67 +2,129 @@ hosts: deploy_node become_user: "{{ ansible_user }}" become: yes + vars: + secrets_file: "{{ ansible_user_dir }}/wire-server-deploy/values/wire-server/secrets.yaml" tasks: - - name: Generate random strings for zrest, minio_access_key, and minio_secret_key - shell: "tr -dc A-Za-z0-9 "{{ ansible_user_dir }}/wire_secrets" + changed_when: false + + when: not skip_secret_generation + + - name: Secrets already up-to-date message + debug: + msg: "Wire secrets already up-to-date. Skipping regeneration." + when: skip_secret_generation From e2c94c604ae7294c8c67ab74063fab712b001b23 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Wed, 26 Nov 2025 10:41:17 +0100 Subject: [PATCH 04/22] fix wpb-17321: handle wire-utility deploy issues and update documentation for demo-wiab --- ansible/wiab-demo/helm_install.yml | 6 ++ offline/demo-wiab.md | 112 ++++++++++++++++------------- 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/ansible/wiab-demo/helm_install.yml b/ansible/wiab-demo/helm_install.yml index f0dfa984f..85eb30712 100644 --- a/ansible/wiab-demo/helm_install.yml +++ b/ansible/wiab-demo/helm_install.yml @@ -54,3 +54,9 @@ {{ docker_cmd_base }} bash -c "helm upgrade --install --wait wire-utility /wire-server-deploy/charts/wire-utility --values /wire-server-deploy/values/wire-server/values.yaml --values /wire-server-deploy/values/wire-server/secrets.yaml --values /wire-server-deploy/values/wire-utility/values.yaml" args: executable: /bin/bash + failed_when: false + register: wire_utility_deploy + + - name: Note wire-utility deployment attempt + debug: + msg: "Wire-utility deployment was attempted as a best-case scenario. If it failed, Wire-in-a-Box will still function without it. Return code: {{ wire_utility_deploy.rc }}" diff --git a/offline/demo-wiab.md b/offline/demo-wiab.md index 11dc72109..1727aa8e7 100644 --- a/offline/demo-wiab.md +++ b/offline/demo-wiab.md @@ -5,7 +5,7 @@ This guide provides detailed instructions for deploying Wire-in-a-Box (WIAB) usi Note: this guide and the shipped playbooks are highly tailored to make testing straightforward on a single VM that has a public IP address. Using a public IP simplifies obtaining HTTPS certificates (for example via cert-manager HTTP challenges) and making external call configurations during tests. If you need to deploy in a private or restricted network, the playbooks can be tuned: skip or enable components via Ansible tags and adjust Helm chart values (see the `--tags` / `--skip-tags` usage below and the `values/` files generated by the playbooks). -Typically, the deployment process runs seamlessly without requiring any external flags. However, if needed, you have the option to skip certain tasks based on their tags. For instance, if you wish to bypass the [Wire Artifact Download tasks](#8-wire-artifact-download) —which can be time-consuming—you can manage the artifacts independently and skip this step in the Ansible workflow by using the tag `--skip-tags download`. +Typically, the deployment process runs seamlessly without requiring any external flags. However, if needed, you can skip certain tasks using their associated tags. For example, if you wish to skip the Enable Cert Manager hairpin Networking task—which is only required when using cert-manager with Let's Encrypt—you can use --skip-tags cert_manager_networking and configure your own certificates instead (see Bring your own certificates(./docs_ubuntu_22.04.md#bring-your-own-certificates)). For more detailed instructions on each task, please refer to the [Deployment Flow section](#deployment-flow). @@ -16,12 +16,15 @@ For more detailed instructions on each task, please refer to the [Deployment Flo - Memory > 16 GiB - Disk > 200 GiB - **Network**: No interference from UFW or other system specific firewalls, and IP forwarding enabled between network cards. Public internet access to download Wire artifacts and Ubuntu packages. -- **Packages**: Ansible and Git installed on the localhost (any machine you have access to) +- **Packages**: Ansible and unzip (or git) installed on the localhost (any machine you have access to) - Ansible version: [core 2.16.3] or compatible - **Permissions**: Sudo access required for installation on remote_node -- **Deployment requirements**: - - Clone of [wire-server-repository](https://github.com/wireapp/wire-server-deploy) - - The inventory file [../ansible/inventory/demo/host.yml](../ansible/inventory/demo/host.yml) (post cloning the previous repo) to update and verify the following default variables (required unless noted optional): +- **Ansible Playbooks**: + - The `ansible` directory from [wire-server-deploy repository](https://github.com/wireapp/wire-server-deploy) + - Obtain it using **either** method: + - **Download as ZIP:** [wire-server-deploy/archive/master.zip](https://github.com/wireapp/wire-server-deploy/archive/refs/heads/master.zip) (requires unzip) + - **Clone with Git:** `git clone https://github.com/wireapp/wire-server-deploy.git` (requires git) + - The inventory file [ansible/inventory/demo/host.yml](../ansible/inventory/demo/host.yml) to update and verify the following variables (required unless noted optional): - ansible_host: aka **deploy_node** i.e. IP address or hostname of VM where Wire will be deployed (Required) - ansible_user: username to access the deploy_node (Required) - ansible_ssh_private_key_file: SSH key file path for ansible_user@deploy_node (Required) @@ -30,33 +33,46 @@ For more detailed instructions on each task, please refer to the [Deployment Flo - artifact_hash: Check with wire support about this value (used by the download step) Note: the playbook installs a set of system tools during the `install_pkgs` tasks (for example `docker`/`containerd`, `kubectl`, `minikube` when provisioning a cluster, `yq`, `jq`, `ncat`). If you already have these tools on the deploy node you may skip the `install_pkgs` tag when running the playbook. -- **Network Access Requirements**: +- **Network Access Requirements**: -| Protocol | Direction | Start Port | End Port | Ether Type | IP Range | Reason | -|----------|-----------|------------|----------|------------|------------|---------------------------------------------| -| Any | egress | Any | Any | IPv4 | Any | Allow all outgoing IPv4 traffic | -| Any | egress | Any | Any | IPv6 | Any | Allow all outgoing IPv6 traffic | -| tcp | ingress | 22 | 22 | IPv4 | 0.0.0.0/0 | Allow SSH access | -| tcp | ingress | 443 | 443 | IPv4 | 0.0.0.0/0 | Allow HTTPS traffic | -| tcp | ingress | 80 | 80 | IPv4 | 0.0.0.0/0 | Allow HTTP traffic | -| tcp | ingress | 3478 | 3478 | IPv4 | 0.0.0.0/0 | Allow alternative STUN/TURN traffic over TCP| -| udp | ingress | 3478 | 3478 | IPv4 | Any | Allow STUN/TURN traffic for Coturn | -| udp | ingress | 32768 | 65535 | IPv4 | 0.0.0.0/0 | Allow calling traffic for Coturn and SFTD over UDP | +| Protocol | Port(s) | Purpose | +|----------|-------------|--------------------------------------------| +| TCP | 22 | SSH access (for remote management) | +| TCP | 80 | HTTP (certificate renewal) | +| TCP | 443 | HTTPS (primary Wire access) | +| TCP | 3478 | Alternative STUN/TURN traffic | +| UDP | 3478 | STUN/TURN for voice/video calls | +| UDP | 32768-65535 | Voice/video calling traffic (Coturn/SFTD) | - Note: If outbound traffic is restricted, [Note on port ranges](https://docs.wire.com/latest/understand/notes/port-ranges.html) should be followed. ## Getting Started -Start by cloning the repository and running the deployment playbook: +**Step 1: Obtain the ansible directory** +Choose one method to download the wire-server-deploy repository: + +**Option A: Download as ZIP** +```bash +wget https://github.com/wireapp/wire-server-deploy/archive/refs/heads/master.zip +unzip master.zip +cd wire-server-deploy-master +``` + +**Option B: Clone with Git** ```bash git clone https://github.com/wireapp/wire-server-deploy.git cd wire-server-deploy ``` -**Note:** Edit the file `ansible/inventory/demo/host.yml` as explained in [Requirements](#requirements) before running the next `ansible-playbook` command. -``` +**Step 2: Configure your deployment** + +Edit the file `ansible/inventory/demo/host.yml` as explained in [Requirements](#requirements) to set up your deployment variables. + +**Step 3: Run the deployment** + +```bash ansible-playbook -i ansible/inventory/demo/host.yml ansible/wiab-demo/deploy_wiab.yml ``` @@ -74,8 +90,7 @@ The playbook starts by verifying DNS records to ensure proper name resolution: ### 2. Common Setup Tasks - Installs Netcat (ncat) on the deployment node, required to find a accessible IP address. -- Sets up variables (facts required by ansible) for Kubernetes nodes based on the Minikube profile and number of nodes. -- We are defining the purpose of nodes in the Minikube cluster. +- Sets up variables (facts required by ansible) for Kubernetes node based on the Minikube profile. ### 3. Network Verification @@ -90,7 +105,7 @@ The playbook starts by verifying DNS records to ensure proper name resolution: ### 5. SSH Key Management -- Imports [setup_ssh.yml](../ansible/wiab-demo/setup_ssh.yml) to manage SSH keys for Minikube nodes and SSH proxying for the deploy_node and minikube nodes +- Imports [setup_ssh.yml](../ansible/wiab-demo/setup_ssh.yml) to manage SSH keys for Minikube node and SSH proxying for the deploy_node and minikube node - **Dependency task:** This task has no tag and runs automatically when `minikube`, `asset_host`, or `seed_containers` are selected - Cannot be run independently or skipped manually - it's controlled entirely by dependent components - **Smart dependency:** SSH setup runs when any component that needs it is selected, and is automatically skipped when none of those components are running @@ -104,7 +119,7 @@ The playbook starts by verifying DNS records to ensure proper name resolution: ### 7. IPTables Rules - Imports [iptables_rules.yml](../ansible/wiab-demo/iptables_rules.yml) to configure network rules on deploy_node -- It will configure network forwarding and postrouting rules to route traffic to k8s nodes +- It will configure network forwarding and postrouting rules to route traffic to k8s node - Runs automatically when using `--tags minikube` ### 8. Wire Artifact Download @@ -113,12 +128,12 @@ The playbook starts by verifying DNS records to ensure proper name resolution: - It is required to download all the artifacts required for further installation - Can be skipped using `--skip-tags download` -### 9. Minikube Node Inventory Setup +### 9. SSH Proxy and Inventory Setup -The playbook then configures access to the Kubernetes nodes: +The playbook then configures ssh access (via ssh proxy) for further operations: - **Dependency task:** This setup has no tag and runs automatically when `asset_host` or `seed_containers` are selected -- Retrieves the host IP (asset_host) on the Minikube network and Ip addresses for minikube k8s nodes -- Sets up SSH proxy access to cluster nodes by: +- Retrieves the host IP (asset_host) on the Minikube network and Ip addresses for minikube k8s node +- Sets up SSH proxy access to cluster node by: - Creating a temporary directory for SSH keys on the localhost - Writing the private key to a file in the temporary directory - Adding the above calculated hosts to the Ansible inventory with appropriate SSH settings @@ -132,23 +147,23 @@ The playbook then configures access to the Kubernetes nodes: ### 11. Container Seeding -- Imports [seed-offline-containerd.yml](../ansible/seed-offline-containerd.yml) to seed containers in K8s cluster nodes -- It will seed the docker images shipped for the wire related helm charts in the minikube k8s nodes +- Imports [seed-offline-containerd.yml](../ansible/seed-offline-containerd.yml) to seed containers in K8s cluster node +- It will seed the docker images shipped for the wire related helm charts in the minikube k8s node - Can be skipped using `--skip-tags seed_containers` ### 12. Wire helm charts values preparation - Imports [wire_values.yml](../ansible/wiab-demo/wire_values.yml) to prepare the Helm chart values - Runs automatically when using `--tags wire_values` - - Note: an admin can choose to skip this step if they already have their own values files and wish to avoid overwriting generated values. Provide your values in the expected `values/` paths and run the next playbook with appropriate tags. + + Note: an admin can choose to skip this step if they already have their own values files (from previous similar deployments) and wish to avoid overwriting values. Provide your values in the expected `values/` paths and run the next playbook with appropriate tags. ### 13. Wire Secrets Creation - Imports [wire_secrets.yml](../ansible/wiab-demo/wire_secrets.yml) to create required secrets for wire helm charts -- Runs automatically when using `--tags helm_install` +- Runs automatically when using `--tags helm_secrets` - Note: `wire_secrets` cannot be skipped when performing a fresh `helm_install` because unique credentials are generated for the deployment. The `helm_install` flow expects secrets to exist (the playbook will include the secrets creation when you run the `helm_install` tag). + Note: an admin can choose to skip this step if they already have pre-created secrets in helm secerts files (from previous similar deployments) and wish to avoid overwriting them. Provide your secrets in the expected `values/` paths (eg. `values/wire-server/secrets.yaml`) and run the next playbook with appropriate tags. ### 14. Helm Chart Installation @@ -170,12 +185,13 @@ If you do not use cert-manager (or you obtain certificates externally) and there - Locates all temporary SSH key directories created during deployment - Lists and removes these directories +- Stop `serve-assets` service on `deploy_node` - Can be skipped using `--skip-tags cleanup` ## SSH Proxy Configuration The deployment uses an SSH proxy mechanism to access: -1. Kubernetes nodes within the Minikube cluster +1. Kubernetes node within the Minikube cluster 2. The asset host for resource distribution SSH proxying is configured with: @@ -197,13 +213,13 @@ ansible-playbook -i ansible/inventory/demo/host.yml ansible/wiab-demo/deploy_wia ```bash ansible-playbook -i ansible/inventory/demo/host.yml ansible/wiab-demo/deploy_wiab.yml --tags helm_install ``` - This automatically includes wire secrets creation. -- All the iptables rules are not persisted after reboots, but they can be regenerated by running just the minikube setup: +- All the iptables rules are not persisted after reboots, , but they can be regenerated by running just the minikube setup (and `cert_manager_networking` if required) or restored from the `/home/ansible_user/wire-iptables-rules/rules_post_wire.v4` file. ```bash -ansible-playbook -i ansible/inventory/demo/host.yml ansible/wiab-demo/deploy_wiab.yml --tags minikube +ansible-playbook -i ansible/inventory/demo/host.yml ansible/wiab-demo/deploy_wiab.yml --tags minikube,cert_manager_networking +# or +iptables-restore < /home/ansible_user/wire-iptables-rules/rules_post_wire.v4 ``` - This automatically includes SSH setup and IPTables configuration. - The playbook is designed to be idempotent, with tags for each major section - Temporary SSH keys are created and cleaned up automatically @@ -217,7 +233,7 @@ The deployment playbook downloads an offline bundle that contains: - Docker/container image archives (used to seed Minikube/node container runtime) - Helper scripts such as `bin/wiab-demo/offline_deploy_k8s.sh` which are sourced during the playbook -If you already have a working **Kubernetes cluster** and prefer to use it instead of creating local Minikube nodes, you can skip the Minikube and seeding tasks and run only the Helm chart installation (tags `wire_secrets` and `helm_install`). However, the offline bundle is still required to obtain the charts and the image archive(s) so you can either: +If you already have a working **Kubernetes cluster** and prefer to use it instead of creating a local Minikube node, you can skip the Minikube and seeding tasks, and run only the Helm chart installation (tags `wire_values` and `helm_install`). However, the offline bundle is still required to obtain the charts and the docker image archive(s) so you can: 1. Extract charts from the bundle and point Helm to the extracted chart directories, and 2. Load container images into your cluster from the image archive. @@ -235,14 +251,14 @@ for img in /tmp/wiab-images/*.tar*; do docker load -i "$img"; done for img in /tmp/wiab-images/*.tar; do sudo ctr -n=k8s.io images import "$img"; done ``` -Note: the playbooks `10. Asset Host Setup` and `11. Container Seeding` can perform these image-extraction and loading steps for you: `setup-offline-sources.yml` will unarchive and host the images via a simple HTTP asset host, and `seed-offline-containerd.yml` will pull/load those images into Minikube nodes. Those playbooks are tuned for Minikube but can be adapted to work with your own cluster by creating an appropriate inventory and adjusting paths. +Note: Optionally the playbooks `10. Asset Host Setup` and `11. Container Seeding` can also perform these image-extraction and loading steps for you: `setup-offline-sources.yml` will unarchive and host the images via a simple HTTP asset host, and `seed-offline-containerd.yml` will pull/load those images into Minikube node. Those playbooks are tuned for Minikube but can be adapted to work with your own cluster by creating an appropriate inventory and adjusting paths. ## kubeconfig path used by Helm in this deployment Helm commands in the playbook are executed inside a helper Docker container and expect the kubeconfig to be mounted at `{{ ansible_user_dir }}/.kube/config` on the deploy node (the playbook mounts this into the container as `/root/.kube/config`). If you are using your own Kubernetes cluster instead of Minikube, ensure that the kubeconfig for your cluster is available at that path on the deploy node before running the `helm_install` step. Small note on values and secrets -- The playbook generates Helm values and secrets files under `{{ ansible_user_dir }}/wire-server-deploy/values/` (for example `values/wire-server/values.yaml` and `values/wire-server/secrets.yaml`). These files can be edited before running the `helm_install` step if you need to change chart values or secrets. +- The playbook generates Helm values and secrets files under `{{ ansible_user_dir }}/wire-server-deploy/values/` (for example `values/wire-server/values.yaml` and `values/wire-server/secrets.yaml`). These files can be edited manually before running the `helm_install` step if you need to change chart values or secrets. ## Available Tags @@ -254,22 +270,22 @@ The following tags are available for controlling playbook execution: |-----|-------------|----------------------| | `verify_dns` | DNS record verification | None | | `install_pkgs` | Package installation | None | -| `minikube` | Minikube cluster setup | SSH setup, IPTables rules | +| `minikube` | Minikube cluster setup | SSH keys setup, IPTables rules | | `download` | Wire artifact download | None | -| `asset_host` | Asset host configuration | SSH setup, Inventory setup | -| `seed_containers` | Container seeding | SSH setup, Inventory setup | +| `asset_host` | Asset host configuration | SSH Proxy and Inventory Setup | +| `seed_containers` | Container seeding | SSH Proxy and Inventory Setup| +| `wire_values` | Setup Wire Helm values | None | +| `wire_secrets` | Create Wire secrets | None | | `helm_install` | Helm chart installation | None | | `cleanup` | Temporary file cleanup | None | ### Usage Examples - **Run a complete minikube setup:** `ansible-playbook ... --tags minikube` (automatically includes SSH setup and IPTables) -- **Run only helm installation:** `ansible-playbook ... --tags helm_install` (automatically includes wire secrets) -- **Run asset host setup:** `ansible-playbook ... --tags asset_host` (automatically includes SSH and inventory setup) +- **Run only helm installation:** `ansible-playbook ... --tags helm_install` +- **Run asset host setup:** `ansible-playbook ... --tags asset_host` (automatically includes SSH Proxy and Inventory Setup) - **Skip DNS verification:** `ansible-playbook ... --skip-tags verify_dns` - **Run everything except download:** `ansible-playbook ... --skip-tags download` -- **Skip minikube but run asset/container operations:** `ansible-playbook ... --skip-tags verify_dns,install_pkgs,minikube,download` (SSH setup and inventory setup still run automatically for asset_host and seed_containers) - ## Cleaning/Uninstalling Wire-in-a-Box From d4238728f7ab9cede23f4776542ba424971ddb76 Mon Sep 17 00:00:00 2001 From: mohit rajain Date: Wed, 26 Nov 2025 12:11:13 +0100 Subject: [PATCH 05/22] Update changelog.d/3-deploy-builds/demo-wiab-ansible-fixes Co-authored-by: Sukanta --- changelog.d/3-deploy-builds/demo-wiab-ansible-fixes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes b/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes index 2c88373db..b4f8643e1 100644 --- a/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes +++ b/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes @@ -1,6 +1,6 @@ Fixed: ansible playbooks for demo-wiab for the tags Fixed: ansible playbooks for demo-wiab for the directory usage -Changed: refractor deploy_wiab to have common inventory together and stop asset service post deploy +Changed: refactor deploy_wiab to have common inventory together and stop asset service post deploy Added: hairpin_networking check and rules placement for demo_wiab deployments Changed: refactor helm_install to have separate values processing and enable wire-utility deployment Fixed: dependecy on yq-go and making docker installation idempotent From 0f8af37334a5b01212e2667ad20417c478185acb Mon Sep 17 00:00:00 2001 From: mohit rajain Date: Wed, 26 Nov 2025 12:11:22 +0100 Subject: [PATCH 06/22] Update changelog.d/3-deploy-builds/demo-wiab-ansible-fixes Co-authored-by: Sukanta --- changelog.d/3-deploy-builds/demo-wiab-ansible-fixes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes b/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes index b4f8643e1..347bfec31 100644 --- a/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes +++ b/changelog.d/3-deploy-builds/demo-wiab-ansible-fixes @@ -7,6 +7,6 @@ Fixed: dependecy on yq-go and making docker installation idempotent Changed: refactor iptables_rules, add additional checks for system and fix port ranges for calling Added: added a check for SPF TXT record in verify_dns Changed: docker load logic for zuath image, containers_adminhost and fixed expected kube_config path -Added: a sperate playbook and tag to allow bringing old values in a demo_wiab deloyment +Added: a separate playbook and tag to allow bringing old values in a demo_wiab deloyment Fixed: calling components deployment and archiving old values when processing them Changed: enable deployment of smtp, postgresql and kube-prometheus-stack, update artifact hash From f64c7bbb3f109f19268ab58a6a64b78711a87810 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Wed, 26 Nov 2025 12:19:05 +0100 Subject: [PATCH 07/22] fix wpb-17321: parameterize y-go version in install_pkgs playbook --- ansible/wiab-demo/install_pkgs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ansible/wiab-demo/install_pkgs.yml b/ansible/wiab-demo/install_pkgs.yml index c121093d6..6b0e3ee8e 100644 --- a/ansible/wiab-demo/install_pkgs.yml +++ b/ansible/wiab-demo/install_pkgs.yml @@ -1,6 +1,8 @@ - name: Package installation and configuration hosts: deploy_node become: yes + vars: + yq_version: "4.48.1" tasks: - name: Install required packages block: @@ -13,7 +15,7 @@ - name: Install yq-go get_url: - url: "https://github.com/mikefarah/yq/releases/download/v4.48.1/yq_linux_amd64" + url: "https://github.com/mikefarah/yq/releases/download/v{{ yq_version }}/yq_linux_amd64" dest: /usr/local/bin/yq mode: '0755' From f09c603ac34b3e0570290e47740f10f7b1fcca9d Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Thu, 27 Nov 2025 16:09:32 +0100 Subject: [PATCH 08/22] fix wpb-17321: change http check to netcat based check in hairpin networking --- ansible/wiab-demo/hairpin_networking.yml | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/ansible/wiab-demo/hairpin_networking.yml b/ansible/wiab-demo/hairpin_networking.yml index 201d94f94..34d65ef00 100644 --- a/ansible/wiab-demo/hairpin_networking.yml +++ b/ansible/wiab-demo/hairpin_networking.yml @@ -3,22 +3,16 @@ hosts: deploy_node become: true tasks: - - name: Test HTTP connectivity from minikube node to its own public IP - command: > - docker exec {{ minikube_profile }} - sh -c "curl -sS -o /dev/null -w '%{http_code}' --connect-timeout 2 http://{{ wire_ip }}" - register: curl_test + - name: Test port connectivity from minikube node to its own public IP + shell: | + docker exec {{ minikube_profile }} sh -c "nc -zv {{ wire_ip }} 80" + register: nc_test failed_when: false changed_when: false - - name: Determine if hairpin NAT is required (treat any 1xx–5xx as success) + - name: Determine if hairpin NAT is required (netcat connects successfully if hairpin is working) set_fact: - hairpin_required: >- - {{ - not ( - curl_test.stdout is match("^[1-5][0-9][0-9]$") - ) - }} + hairpin_required: "{{ nc_test.rc != 0 }}" - name: Configure hairpin NAT rules for ingress when: hairpin_required | bool From 318d8d178a4c234ba4e4109a80d151a396c6af87 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Thu, 27 Nov 2025 16:12:09 +0100 Subject: [PATCH 09/22] fix wpb-17321: refactor offline_deploy_k8s.sh to work with envs and update wire_values accoordingly --- ansible/wiab-demo/wire_values.yml | 54 ++++------------ bin/wiab-demo/offline_deploy_k8s.sh | 97 +++++++++++++---------------- 2 files changed, 56 insertions(+), 95 deletions(-) diff --git a/ansible/wiab-demo/wire_values.yml b/ansible/wiab-demo/wire_values.yml index 63aa6a94e..21c28af36 100644 --- a/ansible/wiab-demo/wire_values.yml +++ b/ansible/wiab-demo/wire_values.yml @@ -3,54 +3,22 @@ become: yes become_user: "{{ ansible_user }}" tasks: - - name: Replace TARGET_SYSTEM example.com with target_domain in offline_deploy_k8s - lineinfile: - path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" - regexp: '^TARGET_SYSTEM="example\.com"' - line: 'TARGET_SYSTEM="{{ target_domain }}"' - backrefs: yes - - - name: Replace CERT_MASTER_EMAIL example.com with target_domain in offline_deploy_k8s - lineinfile: - path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" - regexp: '^CERT_MASTER_EMAIL="certmaster@example\.com"' - line: 'CERT_MASTER_EMAIL="certmaster@{{ target_domain }}"' - backrefs: yes - - - name: Add HOST_IP with wire_ip in offline_deploy_k8s - lineinfile: - path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" - regexp: '^HOST_IP="WIRE_IP"' - line: 'HOST_IP="{{ wire_ip }}"' - backrefs: yes - - - name: Update SFT_NODE in the offline_deploy_k8s - lineinfile: - path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" - regexp: '^SFT_NODE="K8S_SFT_NODE"' - line: 'SFT_NODE="{{ k8s_sft_node }}"' - backrefs: yes - - - name: Update NGINX_K8S_NODE in the offline_deploy_k8s - lineinfile: - path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" - regexp: '^NGINX_K8S_NODE="NGINX_K8S_NODE"' - line: 'NGINX_K8S_NODE="{{ k8s_ingress_controller_node }}"' - backrefs: yes - - - name: Update COTURN_NODE in the offline_deploy_k8s - lineinfile: - path: "{{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh" - regexp: '^COTURN_NODE="K8S_COTURN_NODE"' - line: 'COTURN_NODE="{{ k8s_coturn_node }}"' - backrefs: yes - - name: Prepare values.yaml files for the demo environment - shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_charts demo + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_charts demo values args: executable: /bin/bash + environment: + BASE_DIR: "{{ ansible_user_dir }}/wire-server-deploy" - name: Process vars for Helm chart values shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_values args: executable: /bin/bash + environment: + BASE_DIR: "{{ ansible_user_dir }}/wire-server-deploy" + TARGET_SYSTEM: "{{ target_domain }}" + CERT_MASTER_EMAIL: "certmaster@{{ target_domain }}" + HOST_IP: "{{ wire_ip }}" + SFT_NODE: "{{ k8s_sft_node }}" + NGINX_K8S_NODE: "{{ k8s_ingress_controller_node }}" + COTURN_NODE: "{{ k8s_coturn_node }}" diff --git a/bin/wiab-demo/offline_deploy_k8s.sh b/bin/wiab-demo/offline_deploy_k8s.sh index f7cd71ae3..50118e458 100644 --- a/bin/wiab-demo/offline_deploy_k8s.sh +++ b/bin/wiab-demo/offline_deploy_k8s.sh @@ -1,21 +1,38 @@ #!/usr/bin/env bash # shellcheck disable=SC2087 -set -Eeuo pipefail +set -Eeo pipefail +# Read values from environment variables with defaults BASE_DIR="${BASE_DIR:-/wire-server-deploy}" -TARGET_SYSTEM="example.com" -CERT_MASTER_EMAIL="certmaster@example.com" +TARGET_SYSTEM="${TARGET_SYSTEM:-example.com}" +CERT_MASTER_EMAIL="${CERT_MASTER_EMAIL:-certmaster@example.com}" -# make sure these align with the iptables rules, has to be manually updated -SFT_NODE="K8S_SFT_NODE" +# this IP should match the DNS A record value for TARGET_SYSTEM +HOST_IP="${HOST_IP}" + +# make sure these align with the iptables rules +SFT_NODE="${SFT_NODE}" # picking a node for nginx -NGINX_K8S_NODE="NGINX_K8S_NODE" +NGINX_K8S_NODE="${NGINX_K8S_NODE}" # picking a node for coturn -COTURN_NODE="K8S_COTURN_NODE" +COTURN_NODE="${COTURN_NODE}" -# this IP should match the DNS A record for TARGET_SYSTEM -# keeping it empty to be replaced -HOST_IP="WIRE_IP" +# Validate that required environment variables are set +# Usage: validate_required_vars VAR_NAME1 VAR_NAME2 ... +validate_required_vars() { + local error=0 + + for var_name in "$@"; do + if [[ -z "${!var_name:-}" ]]; then + echo "$var_name environment variable is not set." + error=1 + fi + done + + if [[ $error -eq 1 ]]; then + exit 1 + fi +} # Creates values.yaml from demo-values.example.yaml and secrets.yaml from demo-secrets.example.yaml # This script is for WIAB/demo deployments only @@ -23,34 +40,24 @@ HOST_IP="WIRE_IP" process_charts() { ENV=$1 + TYPE=$2 - if [ "$ENV" != "demo" ]; then - echo "Error: This script only supports demo deployments. ENV must be 'demo', got: '$ENV'" + if [ "$ENV" != "demo" ] || [[ -z "$TYPE" ]] ; then + echo "Error: This function only supports demo deployments with TYPE as values or secrets. ENV must be 'demo', got: '$ENV' and '$TYPE'" exit 1 fi timestp=$(date +"%Y%m%d_%H%M%S") for chart_dir in "$BASE_DIR"/values/*/; do if [[ -d "$chart_dir" ]]; then - if [[ -f "$chart_dir/${ENV}-values.example.yaml" ]]; then - if [[ ! -f "$chart_dir/values.yaml" ]]; then - cp "$chart_dir/${ENV}-values.example.yaml" "$chart_dir/values.yaml" - echo "Used template ${ENV}-values.example.yaml to create $chart_dir/values.yaml" - else - echo "$chart_dir/values.yaml already exists, archiving it and creating a new one." - mv "$chart_dir/values.yaml" "$chart_dir/values.yaml.bak.$timestp" - cp "$chart_dir/${ENV}-values.example.yaml" "$chart_dir/values.yaml" - fi - fi - - if [[ -f "$chart_dir/${ENV}-secrets.example.yaml" ]]; then - if [[ ! -f "$chart_dir/secrets.yaml" ]]; then - cp "$chart_dir/${ENV}-secrets.example.yaml" "$chart_dir/secrets.yaml" - echo "Used template ${ENV}-secrets.example.yaml to create $chart_dir/secrets.yaml" + if [[ -f "$chart_dir/${ENV}-${TYPE}.example.yaml" ]]; then + if [[ ! -f "$chart_dir/${TYPE}.yaml" ]]; then + cp "$chart_dir/${ENV}-${TYPE}.example.yaml" "$chart_dir/${TYPE}.yaml" + echo "Used template ${ENV}-${TYPE}.example.yaml to create $chart_dir/${TYPE}.yaml" else - echo "$chart_dir/secrets.yaml already exists, archiving it and creating a new one." - mv "$chart_dir/secrets.yaml" "$chart_dir/secrets.yaml.bak.$timestp" - cp "$chart_dir/${ENV}-secrets.example.yaml" "$chart_dir/secrets.yaml" + echo "$chart_dir/${TYPE}.yaml already exists, archiving it and creating a new one." + mv "$chart_dir/${TYPE}.yaml" "$chart_dir/${TYPE}.yaml.bak.$timestp" + cp "$chart_dir/${ENV}-${TYPE}.example.yaml" "$chart_dir/${TYPE}.yaml" fi fi fi @@ -60,6 +67,8 @@ process_charts() { # selectively setting values of following charts which requires additional values # wire-server, webapp, team-settings, account-pages, nginx-ingress-services, ingress-nginx-controller, sftd and coturn process_values() { + validate_required_vars HOST_IP SFT_NODE NGINX_K8S_NODE COTURN_NODE + TEMP_DIR=$(mktemp -d) trap 'rm -rf $TEMP_DIR' EXIT @@ -97,19 +106,10 @@ process_values() { -e 's/name: letsencrypt-prod/name: letsencrypt-http01/' \ "$BASE_DIR/values/sftd/values.yaml" > "$TEMP_DIR/sftd-values.yaml" - # Creating coturn values and secrets - ZREST_SECRET=$(yq eval '.brig.secrets.turn.secret' "$BASE_DIR/values/wire-server/secrets.yaml" | tr -d '"') - cat >"$TEMP_DIR/coturn-secrets.yaml"<"$TEMP_DIR/coturn-values.yaml"< Date: Thu, 27 Nov 2025 16:12:53 +0100 Subject: [PATCH 10/22] fix wpb-17321: refactor wire_secrets to be idempotent and move all secret management to it --- ansible/wiab-demo/wire_secrets.yml | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index dc479b723..b2cdc91e9 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -30,7 +30,8 @@ The secrets file '{{ secrets_file }}' is required but was not found. This playbook requires the Wire values (and secrets) files to be prepared beforehand. Please ensure that wire_values.yml (tag wire_values) playbook has been executed before running this playbook. - Refer to the deployment documentation for proper sequencing of playbooks. + Refer to the deployment documentation for + proper sequencing of playbooks. when: not secrets_yaml_stat.stat.exists # a heuristic approach here to verify against one of the secrets only to check if secrets were generated or not @@ -53,6 +54,14 @@ - name: Generate wire secrets and update configuration block: + + - name: Prepare secrets.yaml files for the demo environment + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_charts demo secrets + args: + executable: /bin/bash + environment: + BASE_DIR: "{{ ansible_user_dir }}/wire-server-deploy" + - name: Generate random strings for zrest, minio_access_key, and minio_secret_key shell: "tr -dc A-Za-z0-9 Date: Thu, 27 Nov 2025 16:16:59 +0100 Subject: [PATCH 11/22] fix wpb-17321: when conditions in deploy_wiab to better manage common tasks for minikube networking --- ansible/wiab-demo/deploy_wiab.yml | 84 ++++++++++++++-------------- ansible/wiab-demo/verify_wire_ip.yml | 9 +++ 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/ansible/wiab-demo/deploy_wiab.yml b/ansible/wiab-demo/deploy_wiab.yml index bf6080f1c..9f866fc92 100644 --- a/ansible/wiab-demo/deploy_wiab.yml +++ b/ansible/wiab-demo/deploy_wiab.yml @@ -1,15 +1,7 @@ - name: Execute common tasks for the node hosts: deploy_node + tags: always tasks: - # this is an exception to install_pkgs, as it expects netcat before other tasks take place - - name: Install Netcat - become: yes - apt: - name: - - ncat - state: present - update_cache: yes - # if number of nodes increase, the logic can be adapted to change nodes for different services # currently it is pointing to the first node - name: Set facts for various Kubernetes nodes (for a single node), it will be name of profile @@ -52,39 +44,47 @@ become: yes become_user: "{{ ansible_user }}" tasks: - - name: Get the IP address of the k8s_ingress_controller node - shell: | - kubectl --kubeconfig="{{ kube_config_path }}" get node {{ k8s_ingress_controller_node }} -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address' - register: k8s_ingress_controller_ip - changed_when: false - - - name: Get the {{ minikube_network_name }} Docker network ID - shell: | - docker network inspect {{ minikube_network_name }} | jq -r '.[0].Id' - register: docker_network_id - changed_when: false - - - name: Get all interfaces with bridge interfaces - shell: ip -o addr show | awk '{print $2}' | grep -i 'br-' - register: bridge_interfaces - changed_when: false - - - name: Find the matching bridge interface for {{ minikube_network_name }} Docker network - shell: | - for iface in {{ bridge_interfaces.stdout_lines | join(' ') }}; do - iface_id=$(echo "$iface" | cut -d '-' -f2) - if echo "{{ docker_network_id.stdout }}" | grep -q "$iface_id"; then - echo "$iface" - break - fi - done - register: matching_bridge_interface - changed_when: false - - - name: set facts for k8s ingress controller ip - set_fact: - k8s_ingress_controller_ip: "{{ k8s_ingress_controller_ip.stdout }}" - matching_bridge_interface: "{{ matching_bridge_interface.stdout }}" + - name: Setting up inventory + block: + - name: Get the IP address of the k8s_ingress_controller node + shell: | + kubectl --kubeconfig="{{ kube_config_path }}" get node {{ k8s_ingress_controller_node }} -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address' + register: k8s_ingress_controller_ip + changed_when: false + + - name: Get the {{ minikube_network_name }} Docker network ID + shell: | + docker network inspect {{ minikube_network_name }} | jq -r '.[0].Id' + register: docker_network_id + changed_when: false + + - name: Get all interfaces with bridge interfaces + shell: ip -o addr show | awk '{print $2}' | grep -i 'br-' + register: bridge_interfaces + changed_when: false + + - name: Find the matching bridge interface for {{ minikube_network_name }} Docker network + shell: | + for iface in {{ bridge_interfaces.stdout_lines | join(' ') }}; do + iface_id=$(echo "$iface" | cut -d '-' -f2) + if echo "{{ docker_network_id.stdout }}" | grep -q "$iface_id"; then + echo "$iface" + break + fi + done + register: matching_bridge_interface + changed_when: false + + - name: set facts for k8s ingress controller ip + set_fact: + k8s_ingress_controller_ip: "{{ k8s_ingress_controller_ip.stdout }}" + matching_bridge_interface: "{{ matching_bridge_interface.stdout }}" + + when: > + 'minikube' not in ansible_skip_tags or + 'asset_host' not in ansible_skip_tags or + 'seed_containers' not in ansible_skip_tags or + 'cert_manager_networking' not in ansible_skip_tags - name: Configure Iptables rules import_playbook: ./iptables_rules.yml diff --git a/ansible/wiab-demo/verify_wire_ip.yml b/ansible/wiab-demo/verify_wire_ip.yml index cf1797fc5..f27d0110a 100644 --- a/ansible/wiab-demo/verify_wire_ip.yml +++ b/ansible/wiab-demo/verify_wire_ip.yml @@ -4,6 +4,15 @@ test_port: 3478 tasks: + # this is an exception to install_pkgs, as it expects netcat before other tasks take place + - name: Install Netcat + become: yes + apt: + name: + - ncat + state: present + update_cache: yes + - name: Continue finding wire_ip on the node when: wire_ip is not defined or wire_ip == '' block: From 1a026a1ec5e7f1eb34a8edcd0a5c7f7300c9e234 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Thu, 27 Nov 2025 16:17:41 +0100 Subject: [PATCH 12/22] fix wpb-17321: cert-manager deploy control with cert_manager_networking tag --- ansible/wiab-demo/helm_install.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/ansible/wiab-demo/helm_install.yml b/ansible/wiab-demo/helm_install.yml index 85eb30712..f5bbc2ddb 100644 --- a/ansible/wiab-demo/helm_install.yml +++ b/ansible/wiab-demo/helm_install.yml @@ -11,6 +11,9 @@ -v "{{ ansible_user_dir }}/.kube/config":/root/.kube/config -v "{{ ansible_user_dir }}/.minikube":{{ ansible_user_dir }}/.minikube -e KUBECONFIG=/root/.kube/config + -e HOST_IP="{{ wire_ip }}" + -e SFT_NODE="{{ k8s_sft_node }}" + -e COTURN_NODE="{{ k8s_coturn_node }}" "{{ wsd_container.stdout }}" tasks: - name: Check if WSD Docker image already exists @@ -35,7 +38,23 @@ {{ docker_cmd_base }} bash -c "source /wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && deploy_cert_manager" args: executable: /bin/bash - + tags: + - helm_install + - cert_manager_networking + when: + - "'helm_install' in ansible_run_tags" + - "'cert_manager_networking' in ansible_run_tags" + + - name: Skip message for cert manager + debug: + msg: "'Deploy cert manager' task. This task requires BOTH --tags helm_install AND --tags cert_manager_networking to run." + when: + - "not ('helm_install' in ansible_run_tags and 'cert_manager_networking' in ansible_run_tags)" + - "ansible_run_tags | length > 0" + tags: + - helm_install + - cert_manager_networking + - name: Deploy chart shell: | {{ docker_cmd_base }} bash -c "source /wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && deploy_charts {{ item }}" @@ -59,4 +78,5 @@ - name: Note wire-utility deployment attempt debug: - msg: "Wire-utility deployment was attempted as a best-case scenario. If it failed, Wire-in-a-Box will still function without it. Return code: {{ wire_utility_deploy.rc }}" + msg: "Wire-utility deployment failed. Wire-services will still function without it. Read more about it here: https://docs.wire.com/latest/how-to/administrate/wire-utility-tool.html" + when: wire_utility_deploy.rc != 0 From 84670370edc6b63852021a319ab87f064091d77e Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Thu, 27 Nov 2025 16:18:02 +0100 Subject: [PATCH 13/22] fix wpb-17321: update the documentation for demo-wiab --- ansible/inventory/demo/host.yml | 2 +- offline/demo-wiab.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ansible/inventory/demo/host.yml b/ansible/inventory/demo/host.yml index 8c37f23bc..73ee10236 100644 --- a/ansible/inventory/demo/host.yml +++ b/ansible/inventory/demo/host.yml @@ -51,7 +51,7 @@ wiab: - smtp - rabbitmq - databases-ephemeral - - postgresql + - postgresql # postgresql chart should be deployed before deploying wire-server - reaper - smallstep-accomp - kube-prometheus-stack diff --git a/offline/demo-wiab.md b/offline/demo-wiab.md index 1727aa8e7..c0a4bcb22 100644 --- a/offline/demo-wiab.md +++ b/offline/demo-wiab.md @@ -5,7 +5,7 @@ This guide provides detailed instructions for deploying Wire-in-a-Box (WIAB) usi Note: this guide and the shipped playbooks are highly tailored to make testing straightforward on a single VM that has a public IP address. Using a public IP simplifies obtaining HTTPS certificates (for example via cert-manager HTTP challenges) and making external call configurations during tests. If you need to deploy in a private or restricted network, the playbooks can be tuned: skip or enable components via Ansible tags and adjust Helm chart values (see the `--tags` / `--skip-tags` usage below and the `values/` files generated by the playbooks). -Typically, the deployment process runs seamlessly without requiring any external flags. However, if needed, you can skip certain tasks using their associated tags. For example, if you wish to skip the Enable Cert Manager hairpin Networking task—which is only required when using cert-manager with Let's Encrypt—you can use --skip-tags cert_manager_networking and configure your own certificates instead (see Bring your own certificates(./docs_ubuntu_22.04.md#bring-your-own-certificates)). +Typically, the deployment process runs seamlessly without requiring any external flags. However, if needed, you can skip certain tasks using their associated tags. For example, if you wish to use your own certificates instead of Let's Encrypt, you can use `--skip-tags cert_manager_networking` to skip cert-manager deployment and related networking configuration. For detailed instructions, see [Bring your own certificates](./docs_ubuntu_22.04.md#bring-your-own-certificates). For more detailed instructions on each task, please refer to the [Deployment Flow section](#deployment-flow). @@ -155,6 +155,7 @@ The playbook then configures ssh access (via ssh proxy) for further operations: - Imports [wire_values.yml](../ansible/wiab-demo/wire_values.yml) to prepare the Helm chart values - Runs automatically when using `--tags wire_values` +- The playbook backs up existing values files before replacing them. Note: an admin can choose to skip this step if they already have their own values files (from previous similar deployments) and wish to avoid overwriting values. Provide your values in the expected `values/` paths and run the next playbook with appropriate tags. @@ -162,6 +163,8 @@ The playbook then configures ssh access (via ssh proxy) for further operations: - Imports [wire_secrets.yml](../ansible/wiab-demo/wire_secrets.yml) to create required secrets for wire helm charts - Runs automatically when using `--tags helm_secrets` +- The playbook is idempotent: it won't regenerate secrets if they already exist from a previous run +- If existing secret files are present (e.g., `values/wire-server/secrets.yaml`), the playbook backs them up before replacing them Note: an admin can choose to skip this step if they already have pre-created secrets in helm secerts files (from previous similar deployments) and wish to avoid overwriting them. Provide your secrets in the expected `values/` paths (eg. `values/wire-server/secrets.yaml`) and run the next playbook with appropriate tags. @@ -277,6 +280,7 @@ The following tags are available for controlling playbook execution: | `wire_values` | Setup Wire Helm values | None | | `wire_secrets` | Create Wire secrets | None | | `helm_install` | Helm chart installation | None | +| `cert_manager_networking` | Enable Cert Manager hairpin Networking | None | | `cleanup` | Temporary file cleanup | None | ### Usage Examples From b7585dd047ca2e5df17c54b7fca0d307020898e9 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Fri, 28 Nov 2025 18:27:48 +0100 Subject: [PATCH 14/22] fix wpb-17321: added minio secrets in demo-values and removed extra BASE_DIR in wire_values --- ansible/wiab-demo/wire_values.yml | 4 ++-- values/fake-aws/demo-values.example.yaml | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ansible/wiab-demo/wire_values.yml b/ansible/wiab-demo/wire_values.yml index 21c28af36..98e925415 100644 --- a/ansible/wiab-demo/wire_values.yml +++ b/ansible/wiab-demo/wire_values.yml @@ -4,14 +4,14 @@ become_user: "{{ ansible_user }}" tasks: - name: Prepare values.yaml files for the demo environment - shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_charts demo values + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && process_charts demo values args: executable: /bin/bash environment: BASE_DIR: "{{ ansible_user_dir }}/wire-server-deploy" - name: Process vars for Helm chart values - shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_values + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && process_values args: executable: /bin/bash environment: diff --git a/values/fake-aws/demo-values.example.yaml b/values/fake-aws/demo-values.example.yaml index ad09d557a..2f475508e 100644 --- a/values/fake-aws/demo-values.example.yaml +++ b/values/fake-aws/demo-values.example.yaml @@ -1,3 +1,8 @@ # Disable since prod should use an externally provided minio fake-aws-s3: enabled: true + minio: + users: + - accessKey: dummykey + secretKey: dummysecret + policy: consoleAdmin From 262a2199da107b289e1657bbaabeccc90ab28ecd Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Fri, 28 Nov 2025 18:28:40 +0100 Subject: [PATCH 15/22] fix wpb-17321: move away from yq-go to ansible native yaml updates and added minio creds --- ansible/wiab-demo/wire_secrets.yml | 113 +++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index b2cdc91e9..72a3d3985 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -35,16 +35,21 @@ when: not secrets_yaml_stat.stat.exists # a heuristic approach here to verify against one of the secrets only to check if secrets were generated or not - - name: Extract and hash current .brig.secrets.turn.secret value - shell: | - yq eval '.brig.secrets.turn.secret' "{{ secrets_file }}" | sha256sum | awk '{print $1}' - register: current_secret_hash - changed_when: false + - name: Extract and hash current turn secret value + block: + - name: Read secrets file from remote + slurp: + src: "{{ secrets_file }}" + register: secrets_file_slurp + + - name: Parse and calculate hash of turn secret + set_fact: + current_secret_hash: "{{ (secrets_file_slurp.content | b64decode | from_yaml).brig.secrets.turn.secret | hash('sha256') }}" when: secrets_yaml_stat.stat.exists - name: Compare stored hash with current secret hash (only if file exists) set_fact: - skip_secret_generation: "{{ stored_secrets_hash.content | b64decode | trim == current_secret_hash.stdout }}" + skip_secret_generation: "{{ stored_secrets_hash.content | b64decode | trim == current_secret_hash }}" when: wire_secrets_file_stat.stat.exists - name: Set skip flag to false if wire_secrets file doesn't exist @@ -56,7 +61,7 @@ block: - name: Prepare secrets.yaml files for the demo environment - shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && BASE_DIR={{ ansible_user_dir }}/wire-server-deploy process_charts demo secrets + shell: source {{ ansible_user_dir }}/wire-server-deploy/bin/wiab-demo/offline_deploy_k8s.sh && process_charts demo secrets args: executable: /bin/bash environment: @@ -120,27 +125,89 @@ zauth_public: "{{ zauth_output.stdout_lines[0].split()[1] }}" zauth_private: "{{ zauth_output.stdout_lines[1].split()[1] }}" + - name: Update minio (fake-aws-s3) access key and secret + block: + - name: Read fake-aws values from remote + slurp: + src: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/values.yaml" + register: fake_aws_slurp + + - name: Update minio credentials + set_fact: + fake_aws_values: "{{ (fake_aws_slurp.content | b64decode | from_yaml) | combine(minio_update, recursive=True) }}" + vars: + minio_update: + fake-aws-s3: + minio: + users: + - accessKey: "{{ minio_access_key }}" + secretKey: "{{ minio_secret_key }}" + + - name: Write fake-aws values to file + copy: + content: "{{ fake_aws_values | to_nice_yaml }}" + dest: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/values.yaml" + - name: Update secrets for wire-server - shell: | - yq eval -i '.brig.secrets.turn.secret = "{{ zrest }}"' {{ secrets_yaml_path }} - yq eval -i '.brig.secrets.zAuth.publicKeys = "{{ zauth_public }}"' {{ secrets_yaml_path }} - yq eval -i '.brig.secrets.zAuth.privateKeys = "{{ zauth_private }}"' {{ secrets_yaml_path }} - yq eval -i '.nginz.secrets.zAuth.publicKeys = "{{ zauth_public }}"' {{ secrets_yaml_path }} - args: - executable: /bin/bash - vars: - secrets_yaml_path: "{{ secrets_file }}" + block: + - name: Read current secrets.yaml from remote + slurp: + src: "{{ secrets_file }}" + register: secrets_slurp + + - name: Update secrets in-place + set_fact: + secrets: "{{ (secrets_slurp.content | b64decode | from_yaml) | combine(update_dict, recursive=True) }}" + vars: + update_dict: + brig: + secrets: + turn: + secret: "{{ zrest }}" + zAuth: + publicKeys: "{{ zauth_public }}" + privateKeys: "{{ zauth_private }}" + nginz: + secrets: + zAuth: + publicKeys: "{{ zauth_public }}" + gundeck: + secrets: + awsKeyId: "{{ minio_access_key }}" + awsSecretKey: "{{ minio_secret_key }}" + + - name: Write updated secrets to file + copy: + content: "{{ secrets | to_nice_yaml }}" + dest: "{{ secrets_file }}" - name: Update secrets for coturn - shell: | - yq eval -i '.secrets.zrestSecrets += ["{{ zrest }}"]' "{{ ansible_user_dir }}/wire-server-deploy/values/coturn/secrets.yaml" - args: - executable: /bin/bash + block: + - name: Read current coturn secrets from remote + slurp: + src: "{{ ansible_user_dir }}/wire-server-deploy/values/coturn/secrets.yaml" + register: coturn_slurp + + - name: Update coturn zrestSecrets + set_fact: + coturn_secrets: "{{ (coturn_slurp.content | b64decode | from_yaml) | combine({'secrets': {'zrestSecrets': [zrest]}}, recursive=True) }}" + + - name: Write updated coturn secrets to file + copy: + content: "{{ coturn_secrets | to_nice_yaml }}" + dest: "{{ ansible_user_dir }}/wire-server-deploy/values/coturn/secrets.yaml" - name: Store current secret hash for future comparison - shell: | - yq eval '.brig.secrets.turn.secret' "{{ secrets_file }}" | sha256sum | awk '{print $1}' > "{{ ansible_user_dir }}/wire_secrets" - changed_when: false + block: + - name: Read secrets file from remote + slurp: + src: "{{ secrets_file }}" + register: secrets_for_hash_slurp + + - name: Calculate and store hash + copy: + content: "{{ (secrets_for_hash_slurp.content | b64decode | from_yaml).brig.secrets.turn.secret | hash('sha256') }}" + dest: "{{ ansible_user_dir }}/wire_secrets" when: not skip_secret_generation From f3f56c76d9aaead5b374cc4ac7debd6bef3b4632 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Fri, 28 Nov 2025 18:32:53 +0100 Subject: [PATCH 16/22] fix wpb-17321: fix basc script suggestions from sonarcloud --- bin/wiab-demo/offline-env.sh | 6 ++++-- bin/wiab-demo/offline_deploy_k8s.sh | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/wiab-demo/offline-env.sh b/bin/wiab-demo/offline-env.sh index 116ff62d6..81a9264a5 100644 --- a/bin/wiab-demo/offline-env.sh +++ b/bin/wiab-demo/offline-env.sh @@ -10,7 +10,7 @@ check_or_load_image() { # Check if any image matching pattern exists in docker local existing_image existing_image=$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep "$image_pattern" | head -1) - if [ -n "$existing_image" ]; then + if [[ -n "$existing_image" ]]; then echo "$existing_image" return 0 fi @@ -30,7 +30,7 @@ d() { local docker_flags="" # Check if both stdin and stdout are terminals # If either of them is not a terminal (piped/redirected), run in detached mode - if [ -t 0 ] && [ -t 1 ]; then + if [[ -t 0 ]] && [[ -t 1 ]]; then docker_flags="-it" fi @@ -44,4 +44,6 @@ d() { -v "$HOME/.minikube:$HOME/.minikube" \ -e KUBECONFIG=/root/.kube/config \ "$WSD_CONTAINER" "$@" + + return 0 } diff --git a/bin/wiab-demo/offline_deploy_k8s.sh b/bin/wiab-demo/offline_deploy_k8s.sh index 50118e458..35ab692cd 100644 --- a/bin/wiab-demo/offline_deploy_k8s.sh +++ b/bin/wiab-demo/offline_deploy_k8s.sh @@ -42,7 +42,7 @@ process_charts() { ENV=$1 TYPE=$2 - if [ "$ENV" != "demo" ] || [[ -z "$TYPE" ]] ; then + if [[ "$ENV" != "demo" ]] || [[ -z "$TYPE" ]] ; then echo "Error: This function only supports demo deployments with TYPE as values or secrets. ENV must be 'demo', got: '$ENV' and '$TYPE'" exit 1 fi From 3fcf0f096368c104fabf8878442065d84c4f6a13 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Mon, 1 Dec 2025 12:01:07 +0100 Subject: [PATCH 17/22] fix wpb-17321: fix wire_secrets for cargohold --- ansible/wiab-demo/wire_secrets.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index 72a3d3985..f9185e567 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -142,6 +142,7 @@ users: - accessKey: "{{ minio_access_key }}" secretKey: "{{ minio_secret_key }}" + policy: "consoleAdmin" - name: Write fake-aws values to file copy: @@ -171,7 +172,7 @@ secrets: zAuth: publicKeys: "{{ zauth_public }}" - gundeck: + cargohold: secrets: awsKeyId: "{{ minio_access_key }}" awsSecretKey: "{{ minio_secret_key }}" From 38fb265dbe1d79e6e08b31d355e2319daf4dcb73 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Mon, 1 Dec 2025 16:03:17 +0100 Subject: [PATCH 18/22] fix wpb-17321: fix wire_secrets for fake-aws-s3 --- ansible/wiab-demo/wire_secrets.yml | 37 +++++++++++++++++++++-- values/fake-aws/demo-secrets.example.yaml | 8 +++++ values/fake-aws/demo-values.example.yaml | 5 --- 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 values/fake-aws/demo-secrets.example.yaml diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index f9185e567..d6c0dadd4 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -127,9 +127,20 @@ - name: Update minio (fake-aws-s3) access key and secret block: + - name: Check if fake-aws secrets file exists + stat: + path: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/secrets.yaml" + register: fake_aws_secrets_stat + + - name: Create empty fake-aws secrets file if it doesn't exist + copy: + content: "fake-aws-s3: {}\n" + dest: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/secrets.yaml" + when: not fake_aws_secrets_stat.stat.exists + - name: Read fake-aws values from remote slurp: - src: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/values.yaml" + src: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/secrets.yaml" register: fake_aws_slurp - name: Update minio credentials @@ -147,10 +158,21 @@ - name: Write fake-aws values to file copy: content: "{{ fake_aws_values | to_nice_yaml }}" - dest: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/values.yaml" + dest: "{{ ansible_user_dir }}/wire-server-deploy/values/fake-aws/secrets.yaml" - name: Update secrets for wire-server block: + - name: Check if wire-server secrets file exists + stat: + path: "{{ secrets_file }}" + register: wire_server_secrets_stat + + - name: Create empty wire-server secrets file if it doesn't exist + copy: + content: "brig: {}\nninginz: {}\ncargohold: {}\n" + dest: "{{ secrets_file }}" + when: not wire_server_secrets_stat.stat.exists + - name: Read current secrets.yaml from remote slurp: src: "{{ secrets_file }}" @@ -184,6 +206,17 @@ - name: Update secrets for coturn block: + - name: Check if coturn secrets file exists + stat: + path: "{{ ansible_user_dir }}/wire-server-deploy/values/coturn/secrets.yaml" + register: coturn_secrets_stat + + - name: Create empty coturn secrets file if it doesn't exist + copy: + content: "secrets: {}\n" + dest: "{{ ansible_user_dir }}/wire-server-deploy/values/coturn/secrets.yaml" + when: not coturn_secrets_stat.stat.exists + - name: Read current coturn secrets from remote slurp: src: "{{ ansible_user_dir }}/wire-server-deploy/values/coturn/secrets.yaml" diff --git a/values/fake-aws/demo-secrets.example.yaml b/values/fake-aws/demo-secrets.example.yaml new file mode 100644 index 000000000..2f475508e --- /dev/null +++ b/values/fake-aws/demo-secrets.example.yaml @@ -0,0 +1,8 @@ +# Disable since prod should use an externally provided minio +fake-aws-s3: + enabled: true + minio: + users: + - accessKey: dummykey + secretKey: dummysecret + policy: consoleAdmin diff --git a/values/fake-aws/demo-values.example.yaml b/values/fake-aws/demo-values.example.yaml index 2f475508e..ad09d557a 100644 --- a/values/fake-aws/demo-values.example.yaml +++ b/values/fake-aws/demo-values.example.yaml @@ -1,8 +1,3 @@ # Disable since prod should use an externally provided minio fake-aws-s3: enabled: true - minio: - users: - - accessKey: dummykey - secretKey: dummysecret - policy: consoleAdmin From 85752e02466d2d396031dc36a0973968d073644c Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Tue, 2 Dec 2025 10:03:47 +0100 Subject: [PATCH 19/22] fix wpb-17321: fix clean_cluster permissions --- ansible/wiab-demo/clean_cluster.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ansible/wiab-demo/clean_cluster.yml b/ansible/wiab-demo/clean_cluster.yml index 4bd810c3c..d495bd031 100644 --- a/ansible/wiab-demo/clean_cluster.yml +++ b/ansible/wiab-demo/clean_cluster.yml @@ -1,10 +1,8 @@ - name: Clean the installation hosts: deploy_node - become: yes tasks: # stopping the cluster defined in minikube_cluster playbook - name: clean minikube - become_user: "{{ ansible_user }}" tags: [never, remove_minikube] block: - name: Check if Minikube is running @@ -27,6 +25,7 @@ # these packages can only be removed post stopping the minikube cluster - name: remove packages tags: [never, remove_packages] + become: yes block: - name: Remove Minikube file: @@ -79,6 +78,7 @@ # it makes sense to remove them when removing the k8s cluster or individually to clean them - name: remove iptables rules tags: [never, remove_iptables] + become: yes vars: iptables_rules_comment: "Wire Iptables Rules" iptables_save_dir: "/home/{{ ansible_user }}/wire-iptables-rules" @@ -146,7 +146,6 @@ - name: remove the downloaded artifacts tags: [never, remove_artifacts] - become_user: "{{ ansible_user }}" file: path: "{{ item }}" state: absent @@ -154,9 +153,11 @@ - "{{ ansible_user_dir }}/wire-server-deploy" - "{{ ansible_user_dir }}/wire-server-deploy-static-demo-{{ artifact_hash }}.tgz" - "{{ ansible_user_dir }}/wire_ip" + - "{{ ansible_user_dir }}/wire_secrets" - name: clean asset_host artifacts and remove service tags: [never, clean_assethost] + become: yes block: - name: Stop and disable serve-assets systemd service systemd: From 679360688b52d0a722038ec737093e92cdc93cbe Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Tue, 2 Dec 2025 12:56:37 +0100 Subject: [PATCH 20/22] fix: wpb-17321 add coturn empty values file, ignore the download task file permissions error --- ansible/wiab-demo/download_artifact.yml | 2 +- values/coturn/demo-values.example.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 values/coturn/demo-values.example.yaml diff --git a/ansible/wiab-demo/download_artifact.yml b/ansible/wiab-demo/download_artifact.yml index dfffbf48e..a19e91476 100644 --- a/ansible/wiab-demo/download_artifact.yml +++ b/ansible/wiab-demo/download_artifact.yml @@ -57,4 +57,4 @@ mode: '0775' recurse: yes follow: no - become: yes + ignore_errors: yes diff --git a/values/coturn/demo-values.example.yaml b/values/coturn/demo-values.example.yaml new file mode 100644 index 000000000..e38f8a3a0 --- /dev/null +++ b/values/coturn/demo-values.example.yaml @@ -0,0 +1 @@ +# using upstream values for coturn helm \ No newline at end of file From d4f37288fa983481a86046f9203d4fb7ba7a872f Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Tue, 2 Dec 2025 12:57:50 +0100 Subject: [PATCH 21/22] fix: wpb-17321 fix wire_secrets for non-prepared secrets, fixed flow using tags in deploy_wiab and update the documentation --- ansible/wiab-demo/deploy_wiab.yml | 40 +++++++++++++++++++++++------- ansible/wiab-demo/wire_secrets.yml | 23 +++++++++-------- offline/demo-wiab.md | 17 ++++++++----- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/ansible/wiab-demo/deploy_wiab.yml b/ansible/wiab-demo/deploy_wiab.yml index 9f866fc92..7062963c4 100644 --- a/ansible/wiab-demo/deploy_wiab.yml +++ b/ansible/wiab-demo/deploy_wiab.yml @@ -30,10 +30,15 @@ - name: Manage SSH keys (dependency for minikube, asset_host, seed_containers) import_playbook: ./setup_ssh.yml + tags: always when: > - 'minikube' not in ansible_skip_tags or + ('minikube' not in ansible_skip_tags or 'asset_host' not in ansible_skip_tags or - 'seed_containers' not in ansible_skip_tags + 'seed_containers' not in ansible_skip_tags) + or + ('minikube' in ansible_run_tags or + 'asset_host' in ansible_run_tags or + 'seed_containers' in ansible_run_tags) - name: Configure minikube cluster import_playbook: ./minikube_cluster.yml @@ -80,11 +85,18 @@ k8s_ingress_controller_ip: "{{ k8s_ingress_controller_ip.stdout }}" matching_bridge_interface: "{{ matching_bridge_interface.stdout }}" + tags: + - always when: > - 'minikube' not in ansible_skip_tags or - 'asset_host' not in ansible_skip_tags or - 'seed_containers' not in ansible_skip_tags or - 'cert_manager_networking' not in ansible_skip_tags + ('minikube' not in ansible_skip_tags or + 'asset_host' not in ansible_skip_tags or + 'seed_containers' not in ansible_skip_tags or + 'cert_manager_networking' not in ansible_skip_tags) + or + ('minikube' in ansible_run_tags or + 'asset_host' in ansible_run_tags or + 'seed_containers' in ansible_run_tags or + 'cert_manager_networking' in ansible_run_tags) - name: Configure Iptables rules import_playbook: ./iptables_rules.yml @@ -115,9 +127,13 @@ docker network inspect "{{ minikube_network_name }}" | jq -r '.[0].IPAM.Config[0].Gateway' register: host_ip + tags: always when: > - 'asset_host' not in ansible_skip_tags or - 'seed_containers' not in ansible_skip_tags + ('asset_host' not in ansible_skip_tags or + 'seed_containers' not in ansible_skip_tags) + or + ('asset_host' in ansible_run_tags or + 'seed_containers' in ansible_run_tags) - name: Setup ssh proxy access to k8s-cluster nodes become: no @@ -203,7 +219,13 @@ - name: Prepare helm chart values import_playbook: ./wire_values.yml - tags: wire_values + tags: + - wire_values + - helm_install + when: > + ('wire_values' in ansible_run_tags and 'helm_install' in ansible_run_tags) + or + (ansible_run_tags | length == 0) - name: Create wire secrets import_playbook: ./wire_secrets.yml diff --git a/ansible/wiab-demo/wire_secrets.yml b/ansible/wiab-demo/wire_secrets.yml index d6c0dadd4..3064d4f7f 100644 --- a/ansible/wiab-demo/wire_secrets.yml +++ b/ansible/wiab-demo/wire_secrets.yml @@ -24,14 +24,9 @@ path: "{{ secrets_file }}" register: secrets_yaml_stat - - name: Fail if secrets.yaml file doesn't exist - fail: - msg: | - The secrets file '{{ secrets_file }}' is required but was not found. - This playbook requires the Wire values (and secrets) files to be prepared beforehand. - Please ensure that wire_values.yml (tag wire_values) playbook has been executed before running this playbook. - Refer to the deployment documentation for - proper sequencing of playbooks. + - name: Set skip flag to false if secrets.yaml file doesn't exist + set_fact: + skip_secret_generation: false when: not secrets_yaml_stat.stat.exists # a heuristic approach here to verify against one of the secrets only to check if secrets were generated or not @@ -45,12 +40,20 @@ - name: Parse and calculate hash of turn secret set_fact: current_secret_hash: "{{ (secrets_file_slurp.content | b64decode | from_yaml).brig.secrets.turn.secret | hash('sha256') }}" + ignore_errors: true + + - name: Set skip flag to false if secret key is missing + set_fact: + skip_secret_generation: false + when: current_secret_hash is undefined when: secrets_yaml_stat.stat.exists - - name: Compare stored hash with current secret hash (only if file exists) + - name: Compare stored hash with current secret hash (only if file exists and secret is available) set_fact: skip_secret_generation: "{{ stored_secrets_hash.content | b64decode | trim == current_secret_hash }}" - when: wire_secrets_file_stat.stat.exists + when: + - wire_secrets_file_stat.stat.exists + - current_secret_hash is defined - name: Set skip flag to false if wire_secrets file doesn't exist set_fact: diff --git a/offline/demo-wiab.md b/offline/demo-wiab.md index c0a4bcb22..426f7d1f7 100644 --- a/offline/demo-wiab.md +++ b/offline/demo-wiab.md @@ -151,13 +151,18 @@ The playbook then configures ssh access (via ssh proxy) for further operations: - It will seed the docker images shipped for the wire related helm charts in the minikube k8s node - Can be skipped using `--skip-tags seed_containers` -### 12. Wire helm charts values preparation +### 12. Wire Helm Chart Values Preparation - Imports [wire_values.yml](../ansible/wiab-demo/wire_values.yml) to prepare the Helm chart values -- Runs automatically when using `--tags wire_values` -- The playbook backs up existing values files before replacing them. +- Runs in two scenarios: + - When running the **full playbook** (no tags specified) + - When **both** `wire_values` **and** `helm_install` tags are explicitly passed: `--tags wire_values,helm_install` +- Will be **skipped** if only `--tags wire_values` or only `--tags helm_install` is passed +- The playbook backs up existing values files before replacing them - Note: an admin can choose to skip this step if they already have their own values files (from previous similar deployments) and wish to avoid overwriting values. Provide your values in the expected `values/` paths and run the next playbook with appropriate tags. +**Note:** An admin can skip this step by: +- Running only `--tags helm_install` (if values already exist from previous deployments) +- Providing pre-created values files in the expected `values/` paths and using `--skip-tags wire_values` ### 13. Wire Secrets Creation @@ -276,8 +281,8 @@ The following tags are available for controlling playbook execution: | `minikube` | Minikube cluster setup | SSH keys setup, IPTables rules | | `download` | Wire artifact download | None | | `asset_host` | Asset host configuration | SSH Proxy and Inventory Setup | -| `seed_containers` | Container seeding | SSH Proxy and Inventory Setup| -| `wire_values` | Setup Wire Helm values | None | +| `seed_containers` | Container seeding | SSH Proxy and Inventory Setup | +| `wire_values` | Setup Wire Helm values | Requires `helm_install` tag | | `wire_secrets` | Create Wire secrets | None | | `helm_install` | Helm chart installation | None | | `cert_manager_networking` | Enable Cert Manager hairpin Networking | None | From d9a7f25c15c640cfa5eb145506e4c5b0a2b4dcc5 Mon Sep 17 00:00:00 2001 From: mohit rajain Date: Wed, 3 Dec 2025 14:12:06 +0100 Subject: [PATCH 22/22] Wpb 17321 enable demo cd (#828) * enable: wpb-17321 add terraform and bash scripts to enable cd-demo * enable: wpb-17321 added changelog and a note to old wiab-staging scripts * fix: wpb-17321 remove the debugging statements from cd-demo.sh --- .github/workflows/deploy-wiab.yml | 2 + .github/workflows/offline.yml | 17 ++++++ ansible/hetzner-single-deploy.yml | 2 + bin/autodeploy.sh | 3 + changelog.d/3-deploy-builds/cd-demo-wiab | 2 + offline/cd_demo.sh | 60 +++++++++++++++++++ terraform/examples/wiab-demo-hetzner/.envrc | 5 ++ .../examples/wiab-demo-hetzner/README.md | 4 ++ terraform/examples/wiab-demo-hetzner/main.tf | 42 +++++++++++++ .../examples/wiab-demo-hetzner/outputs.tf | 16 +++++ .../examples/wiab-demo-hetzner/versions.tf | 8 +++ 11 files changed, 161 insertions(+) create mode 100644 changelog.d/3-deploy-builds/cd-demo-wiab create mode 100755 offline/cd_demo.sh create mode 100644 terraform/examples/wiab-demo-hetzner/.envrc create mode 100644 terraform/examples/wiab-demo-hetzner/README.md create mode 100644 terraform/examples/wiab-demo-hetzner/main.tf create mode 100644 terraform/examples/wiab-demo-hetzner/outputs.tf create mode 100644 terraform/examples/wiab-demo-hetzner/versions.tf diff --git a/.github/workflows/deploy-wiab.yml b/.github/workflows/deploy-wiab.yml index a7c74e289..ad4b0a17f 100644 --- a/.github/workflows/deploy-wiab.yml +++ b/.github/workflows/deploy-wiab.yml @@ -1,3 +1,5 @@ +# This playbook is not-up-to-date, requires to be updated to match with current developments +# A new WIAB (wire in a box) dev solution has been created https://docs.wire.com/latest/how-to/install/demo-wiab.html and can be used until this (wiab-staging) gets updated name: Deploy on Hetzner WIAB setup on: workflow_run: diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index 78deb69ef..18529dfd8 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -201,6 +201,23 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" AWS_REGION: "eu-west-1" + - name: Install terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "^1.3.7" + terraform_wrapper: false + + - name: Deploy offline demo-wiab environment to hetzner + run: ./offline/cd_demo.sh + env: + HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' + + - name: Clean up hetzner wiab environment; just in case + if: always() + run: (cd terraform/examples/wiab-demo-hetzner ; terraform init && terraform destroy -auto-approve) + env: + HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' + - name: Cleanup demo build assets run: rm -rf offline/demo-build/output/ diff --git a/ansible/hetzner-single-deploy.yml b/ansible/hetzner-single-deploy.yml index 4d086fe32..f0befc5b8 100644 --- a/ansible/hetzner-single-deploy.yml +++ b/ansible/hetzner-single-deploy.yml @@ -1,3 +1,5 @@ +# This playbook is not-up-to-date, requires to be updated to match with current developments +# A new WIAB (wire in a box) dev solution has been created https://docs.wire.com/latest/how-to/install/demo-wiab.html and can be used until this (wiab-staging) gets updated - hosts: all become: true vars: diff --git a/bin/autodeploy.sh b/bin/autodeploy.sh index 4d12d032d..d7506cf3b 100755 --- a/bin/autodeploy.sh +++ b/bin/autodeploy.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# This script is not-up-to-date, requires to be updated to match with current developments +# A new WIAB (wire in a box) dev solution has been created https://docs.wire.com/latest/how-to/install/demo-wiab.html and can be used until this (wiab-staging) gets updated + # shellcheck disable=SC2087 # This script can be replaced with a simpler solution of wiab-demo installtion diff --git a/changelog.d/3-deploy-builds/cd-demo-wiab b/changelog.d/3-deploy-builds/cd-demo-wiab new file mode 100644 index 000000000..83dd6b2ac --- /dev/null +++ b/changelog.d/3-deploy-builds/cd-demo-wiab @@ -0,0 +1,2 @@ +Added: enable cd-demo.sh to verify the demo-wiab builds +Changed: add a note in old demo-staging playbooks and scripts that they aren't up-to-date and to also check demo-wiab diff --git a/offline/cd_demo.sh b/offline/cd_demo.sh new file mode 100755 index 000000000..a3fffacf1 --- /dev/null +++ b/offline/cd_demo.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TF_DIR="${CD_DIR}/../terraform/examples/wiab-demo-hetzner" +# shellcheck disable=SC2034 # May be used in future versions +BIN_DIR="${CD_DIR}/../bin" +# shellcheck disable=SC2034 # May be used in future versions +ARTIFACTS_DIR="${CD_DIR}/demo-build/output" +ANSIBLE_DIR="${CD_DIR}/../ansible" +INVENTORY_DIR="${ANSIBLE_DIR}/inventory/demo" +INVENTORY_FILE="${INVENTORY_DIR}/host.yml" +TEST_USER="demo" +COMMIT_HASH="${GITHUB_SHA}" + +function cleanup { + (cd "$TF_DIR" && terraform destroy -auto-approve) + echo "done" +} + +trap cleanup EXIT + +cd "$TF_DIR" +terraform init && terraform apply -auto-approve + +host=$(terraform output -raw host) +ssh_private_key=$(terraform output ssh_private_key) + +rm -f "${INVENTORY_DIR}/ssh_private_key" || true +echo "$ssh_private_key" > "${INVENTORY_DIR}/ssh_private_key" +chmod 400 "${INVENTORY_DIR}/ssh_private_key" + +# clean old host verification keys to avoid SSH issues +ssh-keygen -R "$host" || true + +# create demo user on the remote host +ssh -v -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 -i "${INVENTORY_DIR}/ssh_private_key" "root@$host" \ +"useradd -m -s /bin/bash ${TEST_USER} && \ +usermod -aG sudo ${TEST_USER} && \ +mkdir -p /home/${TEST_USER}/.ssh && \ +cp /root/.ssh/authorized_keys /home/${TEST_USER}/.ssh/ && \ +chown -R ${TEST_USER}:${TEST_USER} /home/${TEST_USER}/.ssh && \ +chmod 700 /home/${TEST_USER}/.ssh && \ +chmod 600 /home/${TEST_USER}/.ssh/authorized_keys && \ +echo '${TEST_USER} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/${TEST_USER}" + +# update inventory file with host details +yq eval -i ".wiab.hosts.deploy_node.ansible_host = \"$host\"" "${INVENTORY_FILE}" +yq eval -i ".wiab.hosts.deploy_node.ansible_ssh_private_key_file = \"${INVENTORY_DIR}/ssh_private_key\"" "${INVENTORY_FILE}" +yq eval -i ".wiab.vars.artifact_hash = \"$COMMIT_HASH\"" "${INVENTORY_FILE}" +yq eval -i ".wiab.hosts.deploy_node.ansible_user = \"$TEST_USER\"" "${INVENTORY_FILE}" + +echo "Running ansible playbook deploy_wiab.yml against node $host" +# deploying demo-wiab +ansible-playbook -i "${INVENTORY_FILE}" "${ANSIBLE_DIR}/wiab-demo/deploy_wiab.yml" --skip-tags verify_dns,cert_manager_networking +# cleaning demo-wiab +ansible-playbook -i "${INVENTORY_FILE}" "${ANSIBLE_DIR}/wiab-demo/clean_cluster.yml" --tags remove_minikube,remove_artifacts,remove_packages,remove_iptables,remove_ssh + +cleanup diff --git a/terraform/examples/wiab-demo-hetzner/.envrc b/terraform/examples/wiab-demo-hetzner/.envrc new file mode 100644 index 000000000..8a29ee6d6 --- /dev/null +++ b/terraform/examples/wiab-demo-hetzner/.envrc @@ -0,0 +1,5 @@ +[[ -f .envrc.local ]] && source_env .envrc.local +# You can set this in .envrc.local to keep it out of VCS +export HCLOUD_TOKEN +source_up + diff --git a/terraform/examples/wiab-demo-hetzner/README.md b/terraform/examples/wiab-demo-hetzner/README.md new file mode 100644 index 000000000..40d77a5e5 --- /dev/null +++ b/terraform/examples/wiab-demo-hetzner/README.md @@ -0,0 +1,4 @@ +# WiaB-demo-hetzner + +This environment is set up and destroyed on demand to test our demo-wiab solution. It will be used to provide an Ubuntu system for the demo. +https://docs.wire.com/latest/how-to/install/demo-wiab.html#installation-guide diff --git a/terraform/examples/wiab-demo-hetzner/main.tf b/terraform/examples/wiab-demo-hetzner/main.tf new file mode 100644 index 000000000..5b6b7e8ac --- /dev/null +++ b/terraform/examples/wiab-demo-hetzner/main.tf @@ -0,0 +1,42 @@ +locals { + # Server type preferences with fallbacks + preferred_server_types = { + size = ["cx53", "cpx62"] } +} + +# Get available server types in the specified location +data "hcloud_server_types" "available" { +} + +# Helper locals to select available server types +locals { + available_server_type_names = [for st in data.hcloud_server_types.available.server_types : st.name] + + # Select the first available server type from the preference list + server_type = [ + for preferred in local.preferred_server_types.size : + preferred if contains(local.available_server_type_names, preferred) + ][0] +} + +resource "random_pet" "host" { +} + +resource "tls_private_key" "host" { + algorithm = "ECDSA" + ecdsa_curve = "P256" +} + +resource "hcloud_ssh_key" "host" { + name = "host-${random_pet.host.id}" + public_key = tls_private_key.host.public_key_openssh +} + +resource "hcloud_server" "host" { + location = "fsn1" + name = "host-${random_pet.host.id}" + image = "ubuntu-24.04" + ssh_keys = [hcloud_ssh_key.host.name] + server_type = local.server_type + +} diff --git a/terraform/examples/wiab-demo-hetzner/outputs.tf b/terraform/examples/wiab-demo-hetzner/outputs.tf new file mode 100644 index 000000000..f2e2a63e6 --- /dev/null +++ b/terraform/examples/wiab-demo-hetzner/outputs.tf @@ -0,0 +1,16 @@ +output "ssh_private_key" { + sensitive = true + value = tls_private_key.host.private_key_pem +} + +output "selected_server_types" { + description = "Server types selected after checking availability" + value = { + server_type = local.server_type + } +} + +output "host" { + sensitive = true + value = hcloud_server.host.ipv4_address +} diff --git a/terraform/examples/wiab-demo-hetzner/versions.tf b/terraform/examples/wiab-demo-hetzner/versions.tf new file mode 100644 index 000000000..b047ba54e --- /dev/null +++ b/terraform/examples/wiab-demo-hetzner/versions.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + } + } + required_version = "~> 1.1" +}