From 2646d735f778aa1a06d029763de214464647ed2d Mon Sep 17 00:00:00 2001 From: Jeroen Vermeulen Date: Mon, 9 Oct 2023 12:18:55 +0200 Subject: [PATCH] Added Cloudflare DNS, HAProxy LB --- applications.yml | 10 +++ services.yml => k8s_services.yml | 3 +- os.yml | 28 +++++++ playbook.yml | 17 ++++- requirements.txt | 6 ++ requirements.yml | 5 ++ roles/cloudflare_dns/tasks/main.yml | 11 +++ roles/common/handlers/main.yml | 4 + roles/common/handlers/restart.yml | 66 +++++++++++++++++ roles/dci_login/tasks/main.yml | 2 +- roles/dci_reinstall_talos/tasks/main.yml | 4 +- roles/debian/defaults/main.yml | 4 + roles/debian/files/security/limits.conf | 10 +++ .../systemd/journald.conf.d/persistent.conf | 4 + .../usr/local/bin/apt-get-noninteractive | 5 ++ roles/debian/meta/main.yml | 3 + roles/debian/tasks/ansible_remote.yml | 20 +++++ roles/debian/tasks/apt.yml | 19 +++++ roles/debian/tasks/bloatware.yml | 8 ++ roles/debian/tasks/environment.yml | 4 + roles/debian/tasks/firewall.yml | 32 ++++++++ roles/debian/tasks/limits.yml | 6 ++ roles/debian/tasks/local-ssh.yml | 12 +++ roles/debian/tasks/mail_postfix.yml | 18 +++++ roles/debian/tasks/mail_ssmtp.yml | 16 ++++ roles/debian/tasks/main.yml | 62 ++++++++++++++++ roles/debian/tasks/ssh.yml | 14 ++++ roles/debian/tasks/sysadmin-tools.yml | 73 +++++++++++++++++++ roles/debian/tasks/systemd.yml | 13 ++++ roles/debian/templates/postfix/main.cf.j2 | 8 ++ .../templates/profile.d/100-ansible.sh.j2 | 1 + roles/debian/templates/ssmtp/ssmtp.conf.j2 | 8 ++ roles/haproxy/files/haproxy.env | 1 + roles/haproxy/meta/main.yml | 3 + roles/haproxy/tasks/main.yml | 35 +++++++++ roles/haproxy/templates/haproxy.cfg.j2 | 36 +++++++++ roles/haproxy_control_lb/meta/main.yml | 4 + roles/haproxy_control_lb/tasks/firewall.yml | 26 +++++++ roles/haproxy_control_lb/tasks/main.yml | 14 ++++ .../templates/haproxy_control_lb.cfg.j2 | 48 ++++++++++++ roles/talos_config_apply/tasks/main.yml | 6 +- .../tasks/create_node_config.yml | 4 +- roles/talos_reboot/tasks/main.yml | 6 +- roles/talos_reset/tasks/main.yml | 6 +- roles/talos_upgrade/tasks/main.yml | 5 +- roles/talos_upgrade_k8s/tasks/main.yml | 2 +- roles/talos_wait_port/tasks/main.yml | 2 +- roles/ubuntu/handlers/main.yml | 6 ++ roles/ubuntu/tasks/apt.yml | 38 ++++++++++ roles/ubuntu/tasks/main.yml | 4 + shared/tasks/disable_service.yml | 60 +++++++++++++++ shared/tasks/talos_machine_status.yml | 8 +- shared/tasks/wait_apt.yml | 4 + talos.yml | 12 ++- 54 files changed, 799 insertions(+), 27 deletions(-) create mode 100644 applications.yml rename services.yml => k8s_services.yml (99%) create mode 100644 os.yml create mode 100755 requirements.txt create mode 100755 requirements.yml create mode 100644 roles/cloudflare_dns/tasks/main.yml create mode 100644 roles/common/handlers/restart.yml create mode 100644 roles/debian/defaults/main.yml create mode 100644 roles/debian/files/security/limits.conf create mode 100644 roles/debian/files/systemd/journald.conf.d/persistent.conf create mode 100755 roles/debian/files/usr/local/bin/apt-get-noninteractive create mode 100644 roles/debian/meta/main.yml create mode 100644 roles/debian/tasks/ansible_remote.yml create mode 100644 roles/debian/tasks/apt.yml create mode 100644 roles/debian/tasks/bloatware.yml create mode 100644 roles/debian/tasks/environment.yml create mode 100644 roles/debian/tasks/firewall.yml create mode 100644 roles/debian/tasks/limits.yml create mode 100644 roles/debian/tasks/local-ssh.yml create mode 100644 roles/debian/tasks/mail_postfix.yml create mode 100644 roles/debian/tasks/mail_ssmtp.yml create mode 100644 roles/debian/tasks/main.yml create mode 100644 roles/debian/tasks/ssh.yml create mode 100644 roles/debian/tasks/sysadmin-tools.yml create mode 100644 roles/debian/tasks/systemd.yml create mode 100644 roles/debian/templates/postfix/main.cf.j2 create mode 100644 roles/debian/templates/profile.d/100-ansible.sh.j2 create mode 100644 roles/debian/templates/ssmtp/ssmtp.conf.j2 create mode 100644 roles/haproxy/files/haproxy.env create mode 100644 roles/haproxy/meta/main.yml create mode 100644 roles/haproxy/tasks/main.yml create mode 100644 roles/haproxy/templates/haproxy.cfg.j2 create mode 100644 roles/haproxy_control_lb/meta/main.yml create mode 100644 roles/haproxy_control_lb/tasks/firewall.yml create mode 100644 roles/haproxy_control_lb/tasks/main.yml create mode 100644 roles/haproxy_control_lb/templates/haproxy_control_lb.cfg.j2 create mode 100644 roles/ubuntu/handlers/main.yml create mode 100644 roles/ubuntu/tasks/apt.yml create mode 100644 roles/ubuntu/tasks/main.yml create mode 100644 shared/tasks/disable_service.yml create mode 100644 shared/tasks/wait_apt.yml diff --git a/applications.yml b/applications.yml new file mode 100644 index 0000000..e8055cb --- /dev/null +++ b/applications.yml @@ -0,0 +1,10 @@ +# Playbook Application Install +--- +- name: Haproxy Control LB + hosts: + - control_lb_nodes + roles: + - role: haproxy_control_lb + tags: + - haproxy + - haproxy_control_lb diff --git a/services.yml b/k8s_services.yml similarity index 99% rename from services.yml rename to k8s_services.yml index 13baeb3..d5bcdec 100644 --- a/services.yml +++ b/k8s_services.yml @@ -1,6 +1,5 @@ ---- # Playbook Services Install - +--- - name: Install services on K8S become: false gather_facts: false diff --git a/os.yml b/os.yml new file mode 100644 index 0000000..21cebec --- /dev/null +++ b/os.yml @@ -0,0 +1,28 @@ +# Playbook OS Install +--- +- name: Cloudflare DNS + become: false + gather_facts: false + hosts: + - debian + roles: + - role: cloudflare_dns + tags: + - cloudflare_dns + - dns + +- name: Debian + hosts: + - debian + roles: + - role: debian + tags: + - debian + +- name: Ubuntu + hosts: + - ubuntu + roles: + - role: ubuntu + tags: + - ubuntu diff --git a/playbook.yml b/playbook.yml index 04ee8cc..95efb41 100644 --- a/playbook.yml +++ b/playbook.yml @@ -4,7 +4,20 @@ tags: - talos -- name: Include playbook services - ansible.builtin.import_playbook: services.yml +- name: Include playbook k8s_services + ansible.builtin.import_playbook: k8s_services.yml tags: + - k8s_services - services + +- name: Include playbook os + ansible.builtin.import_playbook: os.yml + tags: + - os + - loadbalancer + +- name: Include playbook applications + ansible.builtin.import_playbook: applications.yml + tags: + - applications + - loadbalancer diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..384d5a1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +#!/usr/bin/env -S python3 -m pip install --upgrade --requirement +ansible +ansible-lint +dnspython +netaddr +kubernetes diff --git a/requirements.yml b/requirements.yml new file mode 100755 index 0000000..99075ec --- /dev/null +++ b/requirements.yml @@ -0,0 +1,5 @@ +#!/usr/bin/env -S ansible-galaxy install --force --role-file +--- +collections: + - name: community.crypto + - name: community.general diff --git a/roles/cloudflare_dns/tasks/main.yml b/roles/cloudflare_dns/tasks/main.yml new file mode 100644 index 0000000..61a6239 --- /dev/null +++ b/roles/cloudflare_dns/tasks/main.yml @@ -0,0 +1,11 @@ +--- +- name: Create an A record at Cloudflare + delegate_to: localhost + when: inventory_hostname is match('.*\.k8s\.snel\.com') + community.general.cloudflare_dns: + zone: snel.com + record: "{{ inventory_hostname | regex_replace('\\.snel\\.com$', '') }}" + type: A + value: "{{ ansible_host }}" + api_token: "{{ cloudflare_token }}" + register: record diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml index 398c5b8..1766a5f 100644 --- a/roles/common/handlers/main.yml +++ b/roles/common/handlers/main.yml @@ -1,2 +1,6 @@ +--- - name: Import Talos handlers ansible.builtin.import_tasks: handlers/talos.yml + +- name: Import Restart handlers + ansible.builtin.import_tasks: handlers/restart.yml diff --git a/roles/common/handlers/restart.yml b/roles/common/handlers/restart.yml new file mode 100644 index 0000000..768f2a9 --- /dev/null +++ b/roles/common/handlers/restart.yml @@ -0,0 +1,66 @@ +--- +- name: Restart Systemd-Journald + ansible.builtin.systemd: + name: systemd-journald.service + state: restarted + daemon_reload: true + +- name: Restart Apache2 + ansible.builtin.systemd: + name: apache2.service + state: restarted + daemon_reload: true + +- name: Restart MySQL + ansible.builtin.systemd: + name: mysql.service + state: restarted + daemon_reload: true + +- name: Restart Containerd + ansible.builtin.systemd: + name: containerd.service + state: restarted + daemon_reload: true + +- name: Restart SSH + ansible.builtin.systemd: + name: ssh.service + state: restarted + daemon_reload: true + +- name: Restart Postfix + ansible.builtin.systemd: + name: postfix.service + state: restarted + daemon_reload: true + +- name: Restart haproxy + ansible.builtin.systemd: + name: haproxy.service + state: restarted + daemon_reload: true + +- name: Restart PHP-FPM + ansible.builtin.systemd: + name: php{{ php_version }}-fpm.service + state: restarted + daemon_reload: true + +- name: Restart New Relic Infra + ansible.builtin.systemd: + name: newrelic-infra.service + state: restarted + daemon_reload: true + +- name: Restart networking + ansible.builtin.systemd: + name: networking.service + state: restarted + daemon_reload: true + +- name: Restart systemd-networkd + ansible.builtin.systemd: + name: systemd-networkd.service + state: restarted + daemon_reload: true diff --git a/roles/dci_login/tasks/main.yml b/roles/dci_login/tasks/main.yml index 1bb6571..e3d3e87 100644 --- a/roles/dci_login/tasks/main.yml +++ b/roles/dci_login/tasks/main.yml @@ -66,4 +66,4 @@ - name: Set fact with server info from DCI Manager ansible.builtin.set_fact: - dci_server_info: "{{ _dci_server.content | from_json | community.general.json_query('list[?@.ip[?@.name==`' ~ ansible_remote ~ '`]]') | first }}" + dci_server_info: "{{ _dci_server.content | from_json | community.general.json_query('list[?@.ip[?@.name==`' ~ ansible_host ~ '`]]') | first }}" diff --git a/roles/dci_reinstall_talos/tasks/main.yml b/roles/dci_reinstall_talos/tasks/main.yml index 4df6ea0..b9b485a 100644 --- a/roles/dci_reinstall_talos/tasks/main.yml +++ b/roles/dci_reinstall_talos/tasks/main.yml @@ -30,7 +30,7 @@ ansible.builtin.wait_for: delay: 10 state: stopped - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 timeout: 300 @@ -39,6 +39,6 @@ become: false ansible.builtin.wait_for: delay: 10 - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 timeout: 1200 diff --git a/roles/debian/defaults/main.yml b/roles/debian/defaults/main.yml new file mode 100644 index 0000000..a25411d --- /dev/null +++ b/roles/debian/defaults/main.yml @@ -0,0 +1,4 @@ +--- +have_mail: true +have_firewall: true +timezone: Europe/Brussels diff --git a/roles/debian/files/security/limits.conf b/roles/debian/files/security/limits.conf new file mode 100644 index 0000000..3bf88c1 --- /dev/null +++ b/roles/debian/files/security/limits.conf @@ -0,0 +1,10 @@ +root soft nofile 1024000 +root hard nofile 1024000 +root soft core 0 +root hard core 0 +* soft nofile 1024000 +* hard nofile 1024000 +* soft core 0 +* hard core 0 +mysql soft memlock unlimited +mysql hard memlock unlimited diff --git a/roles/debian/files/systemd/journald.conf.d/persistent.conf b/roles/debian/files/systemd/journald.conf.d/persistent.conf new file mode 100644 index 0000000..23d01d3 --- /dev/null +++ b/roles/debian/files/systemd/journald.conf.d/persistent.conf @@ -0,0 +1,4 @@ +[Journal] +Storage=persistent +SystemMaxFiles=10000 +RuntimeMaxFiles=10000 diff --git a/roles/debian/files/usr/local/bin/apt-get-noninteractive b/roles/debian/files/usr/local/bin/apt-get-noninteractive new file mode 100755 index 0000000..7e8981a --- /dev/null +++ b/roles/debian/files/usr/local/bin/apt-get-noninteractive @@ -0,0 +1,5 @@ +#!/bin/bash +IFS=$'\n' +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +export DEBIAN_FRONTEND=noninteractive +apt-get --assume-yes -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' "$@" diff --git a/roles/debian/meta/main.yml b/roles/debian/meta/main.yml new file mode 100644 index 0000000..fdda41b --- /dev/null +++ b/roles/debian/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: common diff --git a/roles/debian/tasks/ansible_remote.yml b/roles/debian/tasks/ansible_remote.yml new file mode 100644 index 0000000..99b2a48 --- /dev/null +++ b/roles/debian/tasks/ansible_remote.yml @@ -0,0 +1,20 @@ +--- +- name: "Create Ansible remote_tmp ~/.ansible/tmp" + ansible.builtin.file: + path: ~/.ansible/tmp + state: directory + mode: u=rwx,go= + +- name: Stop & Disable unwanted services + ansible.builtin.include_tasks: shared/tasks/disable_service.yml + loop: + - motd-news + loop_control: + loop_var: __disable_service_name + +- name: Kill unattended-upgrades + ansible.builtin.command: + cmd: pkill -f unattended-upgrade + register: _pkill_unattended_upgrade + failed_when: _pkill_unattended_upgrade.rc not in [0, 1] + changed_when: false diff --git a/roles/debian/tasks/apt.yml b/roles/debian/tasks/apt.yml new file mode 100644 index 0000000..e0f603f --- /dev/null +++ b/roles/debian/tasks/apt.yml @@ -0,0 +1,19 @@ +--- +- name: Check if APT cache exists + ansible.builtin.find: + paths: /var/lib/apt/lists/ + patterns: "*_{{ ansible_distribution_release }}_InRelease" + register: _pkgcache + +- name: Update repositories cache + when: _pkgcache.matched == 0 + ansible.builtin.apt: + update_cache: true + +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install APT Transport HTTPS + ansible.builtin.apt: + name: apt-transport-https + state: present diff --git a/roles/debian/tasks/bloatware.yml b/roles/debian/tasks/bloatware.yml new file mode 100644 index 0000000..a2cc65e --- /dev/null +++ b/roles/debian/tasks/bloatware.yml @@ -0,0 +1,8 @@ +--- + +- name: Stop & Disable unwanted services + ansible.builtin.include_tasks: shared/tasks/disable_service.yml + loop: + - motd-news.service + loop_control: + loop_var: __disable_service_name diff --git a/roles/debian/tasks/environment.yml b/roles/debian/tasks/environment.yml new file mode 100644 index 0000000..e28fdf0 --- /dev/null +++ b/roles/debian/tasks/environment.yml @@ -0,0 +1,4 @@ +--- +- name: Set timezone + community.general.timezone: + name: "{{ timezone }}" diff --git a/roles/debian/tasks/firewall.yml b/roles/debian/tasks/firewall.yml new file mode 100644 index 0000000..4e59eb9 --- /dev/null +++ b/roles/debian/tasks/firewall.yml @@ -0,0 +1,32 @@ +--- +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install packages required for Firewall + ansible.builtin.apt: + name: + - ufw + install_recommends: false + +- name: Get IP of Ansible controller + ansible.builtin.set_fact: + _ssh_client_ip: "{{ ansible_env.SSH_CLIENT.split(' ')[0] }}" + +- name: Allow access to tcp port 22 + community.general.ufw: + rule: allow + name: OpenSSH + src: "{{ item }}" + loop: "{{ ip_whitelist + [_ssh_client_ip] }}" + +- name: Delete default SSH rule + community.general.ufw: + rule: allow + port: "22" + proto: tcp + delete: true + +- name: Enable UFW, deny by default + community.general.ufw: + state: enabled + default: deny diff --git a/roles/debian/tasks/limits.yml b/roles/debian/tasks/limits.yml new file mode 100644 index 0000000..a8970a3 --- /dev/null +++ b/roles/debian/tasks/limits.yml @@ -0,0 +1,6 @@ +--- +- name: Create limits.conf + ansible.builtin.copy: + src: security/limits.conf + dest: /etc/security/limits.conf + mode: u=rw,go=r diff --git a/roles/debian/tasks/local-ssh.yml b/roles/debian/tasks/local-ssh.yml new file mode 100644 index 0000000..2a46125 --- /dev/null +++ b/roles/debian/tasks/local-ssh.yml @@ -0,0 +1,12 @@ +--- +- name: Add SSH config on ansible host + delegate_to: localhost + ansible.builtin.copy: + dest: ~/.ssh/config.d/{{ inventory_hostname }}.conf + content: | + Host {{ inventory_hostname }} {{ inventory_hostname.split(".")[0] }} + Hostname {{ ansible_ssh_hostname | default(inventory_hostname) }} + Port 22 + User root + ForwardAgent yes + mode: u=rw,go=r diff --git a/roles/debian/tasks/mail_postfix.yml b/roles/debian/tasks/mail_postfix.yml new file mode 100644 index 0000000..d2db744 --- /dev/null +++ b/roles/debian/tasks/mail_postfix.yml @@ -0,0 +1,18 @@ +--- +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install packages required for Postfix + ansible.builtin.apt: + name: + - postfix + - libsasl2-modules + - mailutils + install_recommends: false + +- name: Postfix config + ansible.builtin.template: + src: postfix/main.cf.j2 + dest: /etc/postfix/main.cf + mode: u=rw,g=r,o= + notify: Restart Postfix diff --git a/roles/debian/tasks/mail_ssmtp.yml b/roles/debian/tasks/mail_ssmtp.yml new file mode 100644 index 0000000..7acde33 --- /dev/null +++ b/roles/debian/tasks/mail_ssmtp.yml @@ -0,0 +1,16 @@ +--- +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install packages required for Mail + ansible.builtin.apt: + name: + - ssmtp + - mailutils + install_recommends: false + +- name: Ssmtp config + ansible.builtin.template: + src: ssmtp/ssmtp.conf.j2 + dest: /etc/ssmtp/ssmtp.conf + mode: u=rw,g=r,o= diff --git a/roles/debian/tasks/main.yml b/roles/debian/tasks/main.yml new file mode 100644 index 0000000..d6c6c3d --- /dev/null +++ b/roles/debian/tasks/main.yml @@ -0,0 +1,62 @@ +--- +- name: Import local-ssh tasks + ansible.builtin.import_tasks: + file: local-ssh.yml + tags: + - local + - local-ssh + - ssh + +- name: Import Debian apt tasks + ansible.builtin.import_tasks: + file: apt.yml + tags: + - apt + +- name: Import Debian bloatware tasks + ansible.builtin.import_tasks: + file: bloatware.yml + tags: + - bloatware + +- name: Import ssh tasks + ansible.builtin.import_tasks: + file: ssh.yml + tags: + - ssh + +- name: Import environment tasks + ansible.builtin.import_tasks: + file: environment.yml + tags: + - environment + +- name: Import mail tasks + when: have_mail + ansible.builtin.import_tasks: + file: mail_postfix.yml + tags: + - mail + +- name: Import sysadmin-tools tasks + ansible.builtin.import_tasks: + file: sysadmin-tools.yml + +- name: Import firewall tasks + when: have_firewall + ansible.builtin.import_tasks: + file: firewall.yml + tags: + - firewall + +- name: Import limits tasks + ansible.builtin.import_tasks: + file: limits.yml + tags: + - limits + +- name: Import systemd tasks + ansible.builtin.import_tasks: + file: systemd.yml + tags: + - systemd diff --git a/roles/debian/tasks/ssh.yml b/roles/debian/tasks/ssh.yml new file mode 100644 index 0000000..40cfeed --- /dev/null +++ b/roles/debian/tasks/ssh.yml @@ -0,0 +1,14 @@ +--- +- name: Configure SSH UseDNS=no + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#?UseDNS " + line: UseDNS no + notify: Restart SSH + +- name: Configure SSH GSSAPIAuthentication=no + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#?GSSAPIAuthentication " + line: GSSAPIAuthentication no + notify: Restart SSH diff --git a/roles/debian/tasks/sysadmin-tools.yml b/roles/debian/tasks/sysadmin-tools.yml new file mode 100644 index 0000000..dced7e3 --- /dev/null +++ b/roles/debian/tasks/sysadmin-tools.yml @@ -0,0 +1,73 @@ +--- +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install system administrator tools + ansible.builtin.apt: + name: + - bash + - mlocate + - joe + - nano + - sudo + - telnet + - ncdu + - screen + - git + - curl + - python3-pip + - apt-dater-host + - net-tools + install_recommends: false + +- name: Stat mlocate + ansible.builtin.stat: + path: /var/lib/mlocate/mlocate.db + register: _mlocate + +- name: Stat plocate + ansible.builtin.stat: + path: /var/lib/plocate/plocate.db + register: _plocate + +- name: Run updatedb + when: not _mlocate.stat.exists and not _plocate.stat.exists + ansible.builtin.command: + cmd: updatedb + changed_when: true + +- name: Profile.d + ansible.builtin.template: + src: profile.d/100-ansible.sh.j2 + dest: /etc/profile.d/100-ansible.sh + mode: u=rwx,go=rx + +- name: Profile.d + ansible.builtin.template: + src: profile.d/100-ansible.sh.j2 + dest: /etc/profile.d/100-ansible.sh + mode: u=rwx,go=rx + +- name: Disable wordwrap in the Joe editor + ansible.builtin.replace: + path: /etc/joe/ftyperc + regexp: '^(-wordwrap)$' + replace: ' \1' + +- name: Directory /usr/local/bin + ansible.builtin.file: + path: /usr/local/bin + state: directory + mode: u=rwX,go=rX + +- name: Create apt-get-noninteractive script + ansible.builtin.copy: + src: usr/local/bin/apt-get-noninteractive + dest: /usr/local/bin/apt-get-noninteractive + mode: u=rwx,go= + +- name: Configure Apt-Dater to use APT wrapper + ansible.builtin.lineinfile: + path: /etc/apt-dater-host.conf + regexp: "^\\$DPKGTOOL=" + line: '$DPKGTOOL="/usr/local/bin/apt-get-noninteractive";' diff --git a/roles/debian/tasks/systemd.yml b/roles/debian/tasks/systemd.yml new file mode 100644 index 0000000..16cd1db --- /dev/null +++ b/roles/debian/tasks/systemd.yml @@ -0,0 +1,13 @@ +--- +- name: "Directory for Journald config" + ansible.builtin.file: + path: /etc/systemd/journald.conf.d + state: directory + mode: u=rw,go=r + +- name: "Config for persistent Journald logging" + ansible.builtin.copy: + dest: /etc/systemd/journald.conf.d/persistent.conf + src: systemd/journald.conf.d/persistent.conf + mode: u=rw,go=r + notify: Restart Systemd-Journald diff --git a/roles/debian/templates/postfix/main.cf.j2 b/roles/debian/templates/postfix/main.cf.j2 new file mode 100644 index 0000000..42142f8 --- /dev/null +++ b/roles/debian/templates/postfix/main.cf.j2 @@ -0,0 +1,8 @@ +inet_interfaces = loopback-only +mydestination = +myhostname = {{ inventory_hostname }} +myorigin = $mydomain +relayhost = {{ smtp_relay_host }}:{{ smtp_relay_port }} +smtp_sasl_auth_enable = yes +smtp_sasl_password_maps = static:{{ smtp_relay_user }}:{{ smtp_relay_password }} +smtp_sasl_security_options = noanonymous diff --git a/roles/debian/templates/profile.d/100-ansible.sh.j2 b/roles/debian/templates/profile.d/100-ansible.sh.j2 new file mode 100644 index 0000000..606d34d --- /dev/null +++ b/roles/debian/templates/profile.d/100-ansible.sh.j2 @@ -0,0 +1 @@ +export HISTTIMEFORMAT="%Y-%m-%d %T " diff --git a/roles/debian/templates/ssmtp/ssmtp.conf.j2 b/roles/debian/templates/ssmtp/ssmtp.conf.j2 new file mode 100644 index 0000000..dc6939a --- /dev/null +++ b/roles/debian/templates/ssmtp/ssmtp.conf.j2 @@ -0,0 +1,8 @@ +Root={{ sysadmin_email }} +Hostname={{ inventory_hostname }} +FromLineOverride=no +Mailhub={{ smtp_relay_host }}:{{ smtp_relay_port }} +UseSTARTTLS=yes +AuthUser={{ smtp_relay_user }} +AuthPass={{ smtp_relay_password }} +AuthMethod={{ smtp_relay_auth_method | default('cram-md5') }} diff --git a/roles/haproxy/files/haproxy.env b/roles/haproxy/files/haproxy.env new file mode 100644 index 0000000..4e190bc --- /dev/null +++ b/roles/haproxy/files/haproxy.env @@ -0,0 +1 @@ +CONFIG=/etc/haproxy diff --git a/roles/haproxy/meta/main.yml b/roles/haproxy/meta/main.yml new file mode 100644 index 0000000..fdda41b --- /dev/null +++ b/roles/haproxy/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: common diff --git a/roles/haproxy/tasks/main.yml b/roles/haproxy/tasks/main.yml new file mode 100644 index 0000000..476feaa --- /dev/null +++ b/roles/haproxy/tasks/main.yml @@ -0,0 +1,35 @@ +--- +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install haproxy + ansible.builtin.apt: + name: + - haproxy + install_recommends: false + +- name: Directory /etc/sysconfig + ansible.builtin.file: + path: /etc/sysconfig + state: directory + mode: u=rwX,go=rX + +- name: Haproxy service environment file + ansible.builtin.copy: + src: haproxy.env + dest: /etc/sysconfig/haproxy + mode: u=rwX,go=rX + notify: Restart haproxy + +- name: Haproxy base config + ansible.builtin.template: + src: haproxy.cfg.j2 + dest: /etc/haproxy/haproxy.cfg + mode: u=rw,g=r,o= + group: haproxy + notify: Restart haproxy + +- name: Enable haproxy service + ansible.builtin.systemd: + name: haproxy.service + enabled: true diff --git a/roles/haproxy/templates/haproxy.cfg.j2 b/roles/haproxy/templates/haproxy.cfg.j2 new file mode 100644 index 0000000..7ce3862 --- /dev/null +++ b/roles/haproxy/templates/haproxy.cfg.j2 @@ -0,0 +1,36 @@ +global + log /dev/log local0 + log /dev/log local1 debug + chroot /var/lib/haproxy + # stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners + # stats timeout 30s + user haproxy + group haproxy + daemon + # Default SSL material locations + ca-base /etc/ssl/certs + crt-base /etc/ssl/private + # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate + ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 + ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 + ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets + +defaults + log global + mode http + option httplog + option dontlognull + timeout connect 5000 + timeout client 50000 + timeout server 50000 + errorfile 400 /etc/haproxy/errors/400.http + errorfile 403 /etc/haproxy/errors/403.http + errorfile 408 /etc/haproxy/errors/408.http + errorfile 500 /etc/haproxy/errors/500.http + errorfile 502 /etc/haproxy/errors/502.http + errorfile 503 /etc/haproxy/errors/503.http + errorfile 504 /etc/haproxy/errors/504.http + +backend bk_no_match + mode http + http-request deny deny_status 403 diff --git a/roles/haproxy_control_lb/meta/main.yml b/roles/haproxy_control_lb/meta/main.yml new file mode 100644 index 0000000..08ed13c --- /dev/null +++ b/roles/haproxy_control_lb/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - role: common + - role: haproxy diff --git a/roles/haproxy_control_lb/tasks/firewall.yml b/roles/haproxy_control_lb/tasks/firewall.yml new file mode 100644 index 0000000..dcd35a6 --- /dev/null +++ b/roles/haproxy_control_lb/tasks/firewall.yml @@ -0,0 +1,26 @@ +--- + +- name: Get IP of Ansible controller + ansible.builtin.set_fact: + _ssh_client_ip: "{{ ansible_env.SSH_CLIENT.split(' ')[0] }}" + +- name: Allow access from whitelist to tcp port 50000 + community.general.ufw: + rule: allow + port: "50000" + src: "{{ item }}" + loop: "{{ ip_whitelist + [_ssh_client_ip] }}" + +- name: Allow access from nodes to tcp port 50001 + community.general.ufw: + rule: allow + port: "50001" + src: "{{ hostvars[talos_node].ansible_host }}" + loop: "{{ groups['customer_' + customer] }}" + loop_control: + loop_var: talos_node + +- name: Allow public access to tcp port 6443 + community.general.ufw: + rule: allow + port: "6443" diff --git a/roles/haproxy_control_lb/tasks/main.yml b/roles/haproxy_control_lb/tasks/main.yml new file mode 100644 index 0000000..739a2e0 --- /dev/null +++ b/roles/haproxy_control_lb/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: Import firewall tasks + ansible.builtin.import_tasks: + file: firewall.yml + tags: + - firewall + +- name: Haproxy LB config + ansible.builtin.template: + src: haproxy_control_lb.cfg.j2 + dest: /etc/haproxy/haproxy_control_lb.cfg + mode: u=rw,g=r,o= + group: haproxy + notify: Restart haproxy diff --git a/roles/haproxy_control_lb/templates/haproxy_control_lb.cfg.j2 b/roles/haproxy_control_lb/templates/haproxy_control_lb.cfg.j2 new file mode 100644 index 0000000..e363eff --- /dev/null +++ b/roles/haproxy_control_lb/templates/haproxy_control_lb.cfg.j2 @@ -0,0 +1,48 @@ +frontend tcp_talosapi + mode tcp + option tcplog + bind :50000 + default_backend bk_talosapi + +backend bk_talosapi + mode tcp + balance leastconn +{% for talos_node in groups['customer_'+customer] %} +{% if talos_node in groups['talos_control_nodes'] %} + server {{ talos_node }} {{ hostvars[talos_node].ansible_host }}:50000 check +{% endif %} +{% endfor %} + +#### + +frontend tcp_talostrustd + mode tcp + option tcplog + bind :50001 + default_backend bk_talostrustd + +backend bk_talostrustd + mode tcp + balance leastconn +{% for talos_node in groups['customer_'+customer] %} +{% if talos_node in groups['talos_control_nodes'] %} + server {{ talos_node }} {{ hostvars[talos_node].ansible_host }}:50001 check +{% endif %} +{% endfor %} + +#### + +frontend tcp_kubeapi + mode tcp + option tcplog + bind :6443 + default_backend bk_kubeapi + +backend bk_kubeapi + mode tcp + balance leastconn +{% for talos_node in groups['customer_'+customer] %} +{% if talos_node in groups['talos_control_nodes'] %} + server {{ talos_node }} {{ hostvars[talos_node].ansible_host }}:6443 check +{% endif %} +{% endfor %} diff --git a/roles/talos_config_apply/tasks/main.yml b/roles/talos_config_apply/tasks/main.yml index 0dc91a8..8642506 100644 --- a/roles/talos_config_apply/tasks/main.yml +++ b/roles/talos_config_apply/tasks/main.yml @@ -19,8 +19,8 @@ cmd: >- talosctl apply-config --file '{{ talos_node_config_file }}' - --nodes '{{ ansible_remote }}' - --endpoints '{{ ansible_remote }}' + --nodes '{{ ansible_host }}' + --endpoints '{{ ansible_host }}' --mode auto {% if talos_machine_status.spec.stage == 'maintenance' %} --insecure{% endif %} changed_when: true @@ -31,7 +31,7 @@ delegate_to: "{{ talosctl_host }}" become: false ansible.builtin.wait_for: - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 delay: 5 timeout: 600 diff --git a/roles/talos_config_create/tasks/create_node_config.yml b/roles/talos_config_create/tasks/create_node_config.yml index b55714d..58378c4 100644 --- a/roles/talos_config_create/tasks/create_node_config.yml +++ b/roles/talos_config_create/tasks/create_node_config.yml @@ -9,10 +9,10 @@ interfaces: - interface: "{{ network_interface }}" addresses: - - "{{ ansible_remote }}/{{ network_cidr_prefix }}" + - "{{ ansible_host }}/{{ network_cidr_prefix }}" routes: - network: 0.0.0.0/0 - gateway: "{{ (ansible_remote ~ '/' ~ network_cidr_prefix) | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}" + gateway: "{{ (ansible_host ~ '/' ~ network_cidr_prefix) | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}" install: disk: "{{ talos_disk }}" kubelet: diff --git a/roles/talos_reboot/tasks/main.yml b/roles/talos_reboot/tasks/main.yml index bd95d77..741e610 100644 --- a/roles/talos_reboot/tasks/main.yml +++ b/roles/talos_reboot/tasks/main.yml @@ -11,8 +11,8 @@ cmd: >- talosctl reboot --wait=true - --endpoints '{{ ansible_remote }}' - --nodes '{{ ansible_remote }}' + --endpoints '{{ ansible_host }}' + --nodes '{{ ansible_host }}' {% if talos_machine_status.spec.stage == 'maintenance' %} --insecure{% endif %} changed_when: true environment: @@ -23,5 +23,5 @@ become: false throttle: 1 ansible.builtin.wait_for: - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 diff --git a/roles/talos_reset/tasks/main.yml b/roles/talos_reset/tasks/main.yml index 2144aa6..d7ef1dd 100644 --- a/roles/talos_reset/tasks/main.yml +++ b/roles/talos_reset/tasks/main.yml @@ -14,8 +14,8 @@ --graceful=false --wait=true --reboot - --endpoints '{{ ansible_remote }}' - --nodes '{{ ansible_remote }}' + --endpoints '{{ ansible_host }}' + --nodes '{{ ansible_host }}' changed_when: true environment: TALOSCONFIG: "{{ talosconfig }}" @@ -24,5 +24,5 @@ delegate_to: "{{ talosctl_host }}" become: false ansible.builtin.wait_for: - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 diff --git a/roles/talos_upgrade/tasks/main.yml b/roles/talos_upgrade/tasks/main.yml index c63a9aa..ab06f70 100644 --- a/roles/talos_upgrade/tasks/main.yml +++ b/roles/talos_upgrade/tasks/main.yml @@ -7,7 +7,8 @@ talosctl upgrade --image="ghcr.io/siderolabs/installer:{{ talos_version }}" --endpoints='{{ talos_control_lb_hostname }}' - --nodes='{{ ansible_remote }}' + --preserve + --nodes='{{ ansible_host }}' --timeout='30m' --wait=true changed_when: true @@ -19,7 +20,7 @@ throttle: 1 become: false ansible.builtin.wait_for: - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 delay: 5 timeout: 300 diff --git a/roles/talos_upgrade_k8s/tasks/main.yml b/roles/talos_upgrade_k8s/tasks/main.yml index dfa3662..448434f 100644 --- a/roles/talos_upgrade_k8s/tasks/main.yml +++ b/roles/talos_upgrade_k8s/tasks/main.yml @@ -15,7 +15,7 @@ throttle: 1 become: false ansible.builtin.wait_for: - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 delay: 5 timeout: 300 diff --git a/roles/talos_wait_port/tasks/main.yml b/roles/talos_wait_port/tasks/main.yml index 8d13d23..0ff1ca2 100644 --- a/roles/talos_wait_port/tasks/main.yml +++ b/roles/talos_wait_port/tasks/main.yml @@ -4,5 +4,5 @@ delegate_to: "{{ talosctl_host }}" become: false ansible.builtin.wait_for: - host: "{{ ansible_remote }}" + host: "{{ ansible_host }}" port: 50000 diff --git a/roles/ubuntu/handlers/main.yml b/roles/ubuntu/handlers/main.yml new file mode 100644 index 0000000..7832e5a --- /dev/null +++ b/roles/ubuntu/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart unattended-upgrades + ansible.builtin.systemd: + name: unattended-upgrades.service + state: restarted + daemon_reload: true diff --git a/roles/ubuntu/tasks/apt.yml b/roles/ubuntu/tasks/apt.yml new file mode 100644 index 0000000..ce611e9 --- /dev/null +++ b/roles/ubuntu/tasks/apt.yml @@ -0,0 +1,38 @@ +--- +- name: Wait for APT Lock + ansible.builtin.include_tasks: shared/tasks/wait_apt.yml + +- name: Install packages required for auto update + ansible.builtin.apt: + name: + - unattended-upgrades + - update-notifier-common + install_recommends: false + +- name: Configure unattended-upgrades email + ansible.builtin.lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: "^(//)?\\s*Unattended-Upgrade::Mail " + line: Unattended-Upgrade::Mail "sysadmin@deovereo.com"; + notify: Restart unattended-upgrades + +- name: Configure unattended-upgrades email on error + ansible.builtin.lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: "^(//)?\\s*Unattended-Upgrade::MailReport " + line: Unattended-Upgrade::MailReport "only-on-error"; + notify: Restart unattended-upgrades + +- name: Configure unattended-upgrades reboot + ansible.builtin.lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: "^(//)?\\s*Unattended-Upgrade::Automatic-Reboot " + line: Unattended-Upgrade::Automatic-Reboot "true"; + notify: Restart unattended-upgrades + +- name: Configure unattended-upgrades reboot + ansible.builtin.lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: "^(//)?\\s*Unattended-Upgrade::Automatic-Reboot-WithUsers " + line: Unattended-Upgrade::Automatic-Reboot-WithUsers "false"; + notify: Restart unattended-upgrades diff --git a/roles/ubuntu/tasks/main.yml b/roles/ubuntu/tasks/main.yml new file mode 100644 index 0000000..77431cd --- /dev/null +++ b/roles/ubuntu/tasks/main.yml @@ -0,0 +1,4 @@ +--- +- name: Import Ubuntu apt + ansible.builtin.import_tasks: + file: apt.yml diff --git a/shared/tasks/disable_service.yml b/shared/tasks/disable_service.yml new file mode 100644 index 0000000..6d4d384 --- /dev/null +++ b/shared/tasks/disable_service.yml @@ -0,0 +1,60 @@ +--- +# Requires var: __disable_service_name => name with '.service' or '.timer' + +- name: disable_service | Check var __disable_service_name + ansible.builtin.assert: + that: __disable_service_name is defined and __disable_service_name != '' + quiet: true + +# - name: Update service facts +# ansible.builtin.service_facts: + +- name: disable_service | List loaded units + ansible.builtin.command: + cmd: systemctl list-units --state=loaded,masked --plain # noqa command-instead-of-module + register: _list_units + check_mode: false + changed_when: false + +- name: disable_service | When service exists + when: _list_units.stdout is regex( '\s' + (__disable_service_name | regex_escape()) + '\s') + block: + - name: Stop and disable {{ __disable_service_name }} + ansible.builtin.systemd: + name: "{{ __disable_service_name }}" + state: stopped + enabled: false + +- name: disable_service | List fa-iled services + ansible.builtin.command: + cmd: systemctl list-units --failed --plain # noqa command-instead-of-module + register: _systemctl_list_failed + changed_when: false + +- name: disable_service | Reset-fa-iled service {{ __disable_service_name }} + when: _systemctl_list_failed.stdout is regex('\s' + (__disable_service_name) + '\s') + ansible.builtin.command: + cmd: systemctl reset-failed '{{ __disable_service_name }}' # noqa command-instead-of-module + changed_when: true + +- name: disable_service | Find target paths + ansible.builtin.find: + paths: /etc/systemd/system + patterns: "*.wants" + file_type: directory + register: _target_wants_paths + +- name: disable_service | Find target unit files + ansible.builtin.find: + paths: "{{ _target_wants_paths.files | map(attribute='path') | list }}" + file_type: link + patterns: "{{ __disable_service_name }}" + register: _remove_list + +- name: disable_service | Remove target unit files + ansible.builtin.file: + path: "{{ _remove_file }}" + state: absent + loop: "{{ _remove_list.files | map(attribute='path') | list }}" + loop_control: + loop_var: _remove_file diff --git a/shared/tasks/talos_machine_status.yml b/shared/tasks/talos_machine_status.yml index 398f2dc..8f88621 100644 --- a/shared/tasks/talos_machine_status.yml +++ b/shared/tasks/talos_machine_status.yml @@ -9,8 +9,8 @@ ansible.builtin.command: cmd: >- talosctl get machinestatus - --endpoints '{{ ansible_remote }}' - --nodes '{{ ansible_remote }}' + --endpoints '{{ ansible_host }}' + --nodes '{{ ansible_host }}' --output json register: _machine_status_cmd failed_when: _machine_status_cmd.rc not in [0, 1] @@ -25,8 +25,8 @@ ansible.builtin.command: cmd: >- talosctl get machinestatus - --endpoints '{{ ansible_remote }}' - --nodes '{{ ansible_remote }}' + --endpoints '{{ ansible_host }}' + --nodes '{{ ansible_host }}' --output json --insecure register: _machine_status_cmd_insec diff --git a/shared/tasks/wait_apt.yml b/shared/tasks/wait_apt.yml new file mode 100644 index 0000000..200fdf6 --- /dev/null +++ b/shared/tasks/wait_apt.yml @@ -0,0 +1,4 @@ +--- +- name: Wait for automatic system updates + ansible.builtin.raw: systemd-run --property="After=apt-daily.service apt-daily-upgrade.service unattended-upgrades.service cloud-final.service" --wait /bin/true + changed_when: false diff --git a/talos.yml b/talos.yml index 6126d12..301a9e8 100644 --- a/talos.yml +++ b/talos.yml @@ -1,5 +1,15 @@ ---- # Playbook Talos Install +--- +- name: Cloudflare DNS + become: false + gather_facts: false + hosts: + - talos + roles: + - role: cloudflare_dns + tags: + - cloudflare_dns + - dns - name: Wait for Talos port become: false