From 1aeb3158b581dbb0800c3cab67c06940077bc607 Mon Sep 17 00:00:00 2001 From: ace Date: Wed, 8 Feb 2023 01:36:25 +0300 Subject: [PATCH] initial commit --- .gitignore | 1 + README.md | 86 ++++++++++++++++++++++++++++++ defaults/main.yaml | 41 +++++++++++++++ handlers/main.yaml | 7 +++ meta/main.yaml | 7 +++ tasks/cert.yaml | 40 ++++++++++++++ tasks/lua.yaml | 13 +++++ tasks/main.yaml | 111 +++++++++++++++++++++++++++++++++++++++ tasks/map.yaml | 8 +++ templates/haproxy.cfg.j2 | 67 +++++++++++++++++++++++ 10 files changed, 381 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 defaults/main.yaml create mode 100644 handlers/main.yaml create mode 100644 meta/main.yaml create mode 100644 tasks/cert.yaml create mode 100644 tasks/lua.yaml create mode 100644 tasks/main.yaml create mode 100644 tasks/map.yaml create mode 100644 templates/haproxy.cfg.j2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba6d390 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.galaxy_install_info diff --git a/README.md b/README.md new file mode 100644 index 0000000..140de59 --- /dev/null +++ b/README.md @@ -0,0 +1,86 @@ +Setup HAProxy service + +Config example: + + haproxy_ssl: yes + haproxy_self_sign_cert: yes + haproxy_config: + frontend: + well-known: + bind: ':80' + mode: http + acl: + - letsencrypt-acl path_beg /.well-known/acme-challenge/ + - has_cors res.hdr(Access-Control-Allow-Origin) -m found + http-request: + - redirect scheme https if !{ path_beg /.well-known/acme-challenge/ } !{ ssl_fc } + use_backend: + - letsencrypt-backend if letsencrypt-acl + https: + bind: ':443 ssl crt {{ haproxy_ssl_path }}' + mode: http + acl: + - letsencrypt-acl path_beg /.well-known/acme-challenge/ + use_backend: + - letsencrypt-backend if letsencrypt-acl + default_backend: localhost_5001 + backend: + letsencrypt-backend: + mode: http + server: + - letsencrypt 127.0.0.1:8080 + localhost_5001: + mode: http + server: + - localhost 127.0.0.1:5001 + listen: + rabbitmq: + bind: "10.89.10.112:5672" + mode: tcp + option: + - tcpka + server: + - t1-dev-rabbitmq-1 10.89.10.71:5672 check inter 2000 rise 2 fall 5 + - t1-dev-rabbitmq-2 10.89.10.72:5672 check inter 2000 rise 2 fall 5 + - t1-dev-rabbitmq-3 10.89.10.73:5672 check inter 2000 rise 2 fall 5 + rabbitmq_management: + bind: "10.89.10.112:15672" + mode: http + server: + - t1-dev-rabbitmq-1 10.89.10.71:15672 check inter 2000 rise 2 fall 5 + - t1-dev-rabbitmq-2 10.89.10.72:15672 check inter 2000 rise 2 fall 5 + - t1-dev-rabbitmq-3 10.89.10.73:15672 check inter 2000 rise 2 fall 5 + stats: + bind: ":9000" + mode: http + stats: + - enable + - hide-version + - realm Haproxy\ Statistics + - uri /haproxy_stats + - auth {{ haproxy_stats_user }}:{{ haproxy_stats_password }} + +Map example: + + haproxy_map: + hosts.map: | + #domainname backendname + example.com backend + *.example.com backend + +Lua example: + + haproxy_lua: + invertPath.lua: | + local function invertPath(host) + host = host:gsub('website.*','') + a, b = host:match"(.*)%.([^.]+)" + -- print(a) + -- print(b) + s = b .. ":" .. a + return s + end + + core.register_converters("invertPath", invertPath) + + diff --git a/defaults/main.yaml b/defaults/main.yaml new file mode 100644 index 0000000..409e98a --- /dev/null +++ b/defaults/main.yaml @@ -0,0 +1,41 @@ +haproxy_path: /etc/haproxy +haproxy_ssl: no +haproxy_ssl_path: "{{ haproxy_path }}/ssl" +haproxy_cert_name: haproxy.pem +haproxy_self_signed_cert: no +haproxy_self_signed_cert_gen_path: "{{ haproxy_path }}/tempssl" +haproxy_lua_path: "{{ haproxy_path }}/lua" + +haproxy_stats_user: haproxy +haproxy_stats_password: P@ssw0rd + +haproxy_default_config: + global: + daemon: + chroot: /var/lib/haproxy + maxconn: 200000 + nbproc: "{{ '2' if ansible_facts['processor_nproc'] > 1 }}" + user: haproxy + group: haproxy + pidfile: /var/run/haproxy.pid + log: + - "127.0.0.1 local0" + stats: + - "socket /var/lib/haproxy/stats mode 0660 level admin" + - "bind-process {{ '2' if ansible_facts['processor_nproc'] > 1 }}" + 'tune.ssl.default-dh-param': 2048 + defaults: + log: + - global + maxconn: 200000 + retries: 3 + option: + - redispatch + timeout: + - http-request 10s + - queue 1m + - connect 10s + - client 10m + - server 10m + - check 10s + diff --git a/handlers/main.yaml b/handlers/main.yaml new file mode 100644 index 0000000..d4ca4f3 --- /dev/null +++ b/handlers/main.yaml @@ -0,0 +1,7 @@ +--- +- name: Reload HAProxy + systemd: + name: haproxy + state: reloaded + daemon_reload: yes + when: haproxy_enable_and_start.changed diff --git a/meta/main.yaml b/meta/main.yaml new file mode 100644 index 0000000..363e443 --- /dev/null +++ b/meta/main.yaml @@ -0,0 +1,7 @@ +--- +galaxy_info: + description: HAProxy + galaxy_tags: + - haproxy + +dependencies: [] diff --git a/tasks/cert.yaml b/tasks/cert.yaml new file mode 100644 index 0000000..7d75984 --- /dev/null +++ b/tasks/cert.yaml @@ -0,0 +1,40 @@ +- name: Check if ssl dir exist + file: + name: "{{ haproxy_ssl_path }}" + state: directory + when: haproxy_ssl + +- name: Add predefined ssl cert for HAProxy + copy: + src: "{{ haproxy_cert_name }}" + dest: "{{ haproxy_ssl_path }}/{{ haproxy_cert_name }}" + notify: Reload HAProxy + when: haproxy_cert is defined + +- block: + - name: Check if temp ssl dir exist + file: + name: "{{ haproxy_self_signed_cert_gen_path }}" + state: directory + + - name: Generate an OpenSSL private key with the default values (4096 bits, RSA) + community.crypto.openssl_privatekey: + path: "{{ haproxy_self_signed_cert_gen_path }}/key.pem" + when: haproxy_cert is not defined + register: haproxy_key_gen + + - name: Generate a Self Signed OpenSSL certificate + community.crypto.x509_certificate: + path: "{{ haproxy_self_signed_cert_gen_path }}/cert.crt" + privatekey_path: "{{ haproxy_self_signed_cert_gen_path }}/key.pem" + provider: selfsigned + when: haproxy_cert is not defined + register: haproxy_cert_gen + + - name: Cat cert and key to single file for HAProxy + ansible.builtin.shell: | + cat {{ haproxy_self_signed_cert_gen_path }}/cert.crt > {{ haproxy_ssl_path }}/{{ haproxy_cert_name }} + cat {{ haproxy_self_signed_cert_gen_path }}/key.pem >> {{ haproxy_ssl_path }}/{{ haproxy_cert_name }} + when: haproxy_cert_gen.changed or haproxy_key_gen.changed + notify: Reload HAProxy + when: haproxy_self_signed_cert diff --git a/tasks/lua.yaml b/tasks/lua.yaml new file mode 100644 index 0000000..38921ae --- /dev/null +++ b/tasks/lua.yaml @@ -0,0 +1,13 @@ +--- +- name: Create lua dir for HAProxy + file: + path: "{{ haproxy_lua_path }}" + state: directory + +- name: Write lua files for HAProxy + copy: + dest: "{{ haproxy_lua_path }}/{{ item.key }}" + content: "{{ item.value }}" + loop: "{{ haproxy_lua | dict2items }}" + notify: + - Reload HAProxy diff --git a/tasks/main.yaml b/tasks/main.yaml new file mode 100644 index 0000000..120e209 --- /dev/null +++ b/tasks/main.yaml @@ -0,0 +1,111 @@ +--- +- name: Install HAProxy + package: + name: haproxy + state: present + +- name: Install python2-cryptography + package: + name: python2-cryptography + when: + - ansible_facts['os_family'] == 'RedHat' + - ansible_facts['distribution_major_version'] <= '7' + - haproxy_self_signed_cert + +- name: Install python3-cryptography + package: + name: python3-cryptography + when: + - ansible_facts['os_family'] == 'RedHat' + - ansible_facts['distribution_major_version'] == '8' or ansible_facts['distribution_major_version'] == '9' + - haproxy_self_signed_cert + +- name: Set haproxy_connect_any flag on and keep it persistent across reboots + ansible.posix.seboolean: + name: haproxy_connect_any + state: yes + persistent: yes + notify: + - Reload HAProxy + when: ansible_selinux is defined and ansible_selinux != False and ansible_selinux.status == 'enabled' + +- block: + - name: Check net.ipv4.ip_nonlocal_bind + ansible.posix.sysctl: + name: net.ipv4.ip_nonlocal_bind + value: '1' + sysctl_set: no + state: present + register: sysctl_result + + - name: Set net.ipv4.ip_nonlocal_bind = 1 + ansible.posix.sysctl: + name: net.ipv4.ip_nonlocal_bind + value: '1' + sysctl_set: yes + state: present + reload: yes + sysctl_file: /etc/sysctl.d/99-haproxy.conf + when: sysctl_result.changed + +- name: Apply default config + block: + - name: Merge config for HAProxy + set_fact: + haproxy_combined_config: "{{ haproxy_config | default({}) | combine(haproxy_default_config, recursive=true) }}" + + - name: Add HAProxy config + template: + src: "haproxy.cfg.j2" + dest: "/etc/haproxy/haproxy.cfg" + notify: + - Reload HAProxy + when: + - haproxy_config_override is not defined + - haproxy_config_base64_override is not defined + +- name: Override with config in plain text + block: + - set_fact: + haproxy_config: "{{ haproxy_config_override }}" + + - name: Override HAParoxy config in plain text + copy: + content: "{{ haproxy_config }}" + dest: "/etc/haproxy/haproxy.cfg" + notify: + - Reload HAProxy + when: haproxy_config_override is defined + +- name: Override with base64 config + block: + - set_fact: + haproxy_config: "{{ haproxy_config_base64_override | b64decode }}" + + - name: Override HAParoxy with config in base64 + copy: + content: "{{ haproxy_config }}" + dest: "/etc/haproxy/haproxy.cfg" + notify: + - Reload HAProxy + when: haproxy_config_base64_override is defined + +- name: Add maps for HAProxy + include_tasks: map.yaml + when: haproxy_map is defined + +- name: Add lua code for HAProxy + include_tasks: lua.yaml + when: haproxy_lua is defined + +- name: Add certificate for HAProxy + include_tasks: cert.yaml + when: haproxy_ssl + +- name: Enable and start HAProxy service + systemd: + name: haproxy + state: started + enabled: yes + daemon_reload: yes + register: haproxy_enable_and_start diff --git a/tasks/map.yaml b/tasks/map.yaml new file mode 100644 index 0000000..ba28564 --- /dev/null +++ b/tasks/map.yaml @@ -0,0 +1,8 @@ +--- +- name: Write maps for HAProxy + copy: + dest: "{{ haproxy_path }}/{{ item.key }}" + content: "{{ item.value }}" + loop: "{{ haproxy_map | dict2items }}" + notify: + - Reload HAProxy diff --git a/templates/haproxy.cfg.j2 b/templates/haproxy.cfg.j2 new file mode 100644 index 0000000..66014a1 --- /dev/null +++ b/templates/haproxy.cfg.j2 @@ -0,0 +1,67 @@ +{% set haproxy_config = haproxy_combined_config %} +global +{% for key, value in haproxy_config.global.items() %} +{% if value | type_debug != 'list' %} + {{ key }} {{ value }} +{% else %} +{% for list_value in value %} + {{ key }} {{ list_value }} +{% endfor %} +{% endif %} +{% endfor %} + +defaults +{% for key, value in haproxy_config.defaults.items() %} +{% if value | type_debug != 'list' %} + {{ key }} {{ value }} +{% else %} +{% for list_value in value %} + {{ key }} {{ list_value }} +{% endfor %} +{% endif %} +{% endfor %} + +{% if haproxy_config.frontend is defined %} +{% for frontend in haproxy_config.frontend %} +frontend {{ frontend }} +{% for key, value in haproxy_config.frontend[frontend].items() %} +{% if value | type_debug != 'list' %} + {{ key }} {{ value }} +{% else %} +{% for list_value in value %} + {{ key }} {{ list_value }} +{% endfor %} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} + +{% if haproxy_config.backend is defined %} +{% for backend in haproxy_config.backend %} +backend {{ backend }} +{% for key, value in haproxy_config.backend[backend].items() %} +{% if value | type_debug != 'list' %} + {{ key }} {{ value }} +{% else %} +{% for list_value in value %} + {{ key }} {{ list_value }} +{% endfor %} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} + +{% if haproxy_config.listen is defined %} +{% for listen in haproxy_config.listen %} +listen {{ listen }} +{% for key, value in haproxy_config.listen[listen].items() %} +{% if value | type_debug != 'list' %} + {{ key }} {{ value }} +{% else %} +{% for list_value in value %} + {{ key }} {{ list_value }} +{% endfor %} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %}