Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ansible/roles/haproxy
  • ericzillmann/haproxy
2 results
Show changes
Commits on Source (85)
Showing with 776 additions and 335 deletions
# Documentation
- https://www.haproxy.com/doc/aloha/7.0/haproxy/index.html
- https://cbonte.github.io/haproxy-dconv/index.html
- https://cbonte.github.io/haproxy-dconv/1.7/configuration.html
# Instruction to prepare a certificate file
For HaProxy to terminate SSL requests we require a single PEM file with all certificate components chained together.
The seqeuence of those compoenents is this:
- Private Key, e.g. example.com.key.pem
- Domain Certficate, e.g. example.com.crt.pem
- Intermediate Certificate, e.g. example.com.ca.crt.pem
# Watching statistics
Create an SSH tunnel to the haproxy host's port 7000 and then go to `http://127.0.0.1:7000/haproxy_stats` to get live stats.
# Talking to HaProxy Socket
HaProxy can communicate with the console through a socket and we provide a script called `hasocket` which can be used for that purpose. You either call that from the proxy's console or run it through Ansible with this command:
```
a -a "hasocket 'help'" --limit=proxyserver
```
Useful commands might be:
- "show info"
show informations like haproxy version, PID, current connections, session rates, tasks, etc..
- "show stat"
prints the stats about all frontents and backends (connection statistics etc) in a csv format
- "show errors"
indeed the following prints informations about errors if there are any
- "show sess"
show open sessions with the used backend/frontend, the source, etc..
---
default_proxy: ''
proxy_debug: no
proxy_default_backend: ''
proxy_certificates: []
proxy_timeout_connect: '5s'
proxy_timeout_client: '20s'
proxy_timeout_server: '45s'
proxy_redirect_aliase: false
proxy_timeout_connect: 5s
proxy_timeout_client: 20s
proxy_timeout_server: 45s
proxy_redirect_aliase: no
proxy_maxconn: 100
proxy_varnish_maxconn: 1000
proxy_redirect_maps:
domain: {}
domain-and-path: {}
domain-append-path: {}
path: {}
proxy_blacklist:
ip:
- '146.185.176.158'
- '162.243.9.72'
- '173.199.114.0/24'
- '173.199.115.0/24'
- '173.199.115.112/29'
- '173.199.116.0/24'
- '173.199.117.0/24'
- '173.199.118.0/24'
- '173.199.119.0/24'
- '173.199.120.0/24'
- '182.50.130.0/24'
- '188.92.74.0/24'
- '195.239.0/24'
- '198.186.190.0/23'
- '198.186.192.0/23'
- '198.186.194.0/24'
- '208.167.230.0/24'
- '209.222.12.0/24'
- '210.171.3.0/24'
- '212.100.254.105'
- '212.113.0.0/24'
- '212.113.32.0/21'
- '212.113.37.0/24'
- '213.186.0.0/24'
- '213.186.96.0/19'
- '46.137.98.159'
- '5.10.83.0/24'
- '5.10.83.0/25'
- '5.9.0.0/24'
- '5.9.104.0/24'
- '50.112.126.117'
- '54.232.100.158'
- '54.235.220.243'
- '54.249.240.15'
- '54.251.45.250'
- '54.252.97.95'
- '69.42.83.0/24'
- 146.185.176.158
- 162.243.9.72
- 173.199.114.0/24
- 173.199.115.0/24
- 173.199.115.112/29
- 173.199.116.0/24
- 173.199.117.0/24
- 173.199.118.0/24
- 173.199.119.0/24
- 173.199.120.0/24
- 182.50.130.0/24
- 188.92.74.0/24
- 195.239.0/24
- 198.186.190.0/23
- 198.186.192.0/23
- 198.186.194.0/24
- 208.167.230.0/24
- 209.222.12.0/24
- 210.171.3.0/24
- 212.100.254.105
- 212.113.0.0/24
- 212.113.32.0/21
- 212.113.37.0/24
- 213.186.0.0/24
- 213.186.96.0/19
- 46.137.98.159
- 5.10.83.0/24
- 5.10.83.0/25
- 5.9.0.0/24
- 5.9.104.0/24
- 50.112.126.117
- 54.232.100.158
- 54.235.220.243
- 54.249.240.15
- 54.251.45.250
- 54.252.97.95
- 69.42.83.0/24
referer:
- 'best-seo-solution.com'
- 'best-seo-offer.com'
- 'buttons-for-website.com'
- 'buttons-for-your-website.com'
- 'semalt.com'
- '7makemoneyonline.com'
- best-seo-solution.com
- best-seo-offer.com
- buttons-for-website.com
- buttons-for-your-website.com
- semalt.com
- 7makemoneyonline.com
agent:
- 'AhrefsBot'
- 'Ahrefs'
- 'rogerbot'
- 'MJ12bot'
- 'majestic12'
- 'MJ12'
- 'SiteBot'
- 'Semrush'
- 'CCBot'
- '80legs'
- 'Sogou'
- 'DigExt'
- 'spbot'
- 'ia_archiver'
- 'Rankivabot'
- 'DBLBot'
- 'libw'
- 'Voil'
- 'Twice'
- 'Sogou'
- 'psbot'
- 'Exabot'
- 'boitho'
- 'ajSitemap'
- 'Rankivabot'
- 'SeznamBot'
- 'DBLBot'
- 'Ezooms'
- 'Ezooms/1.0'
- 'exabot'
- 'dotbot'
- 'gigabot'
- AhrefsBot
- Ahrefs
- rogerbot
- MJ12bot
- majestic12
- MJ12
- SiteBot
- Semrush
- CCBot
- 80legs
- Sogou
- DigExt
- spbot
- ia_archiver
- Rankivabot
- DBLBot
- libw
- Voil
- Twice
- Sogou
- psbot
- Exabot
- boitho
- ajSitemap
- Rankivabot
- DBLBot
- Ezooms
- Ezooms/1.0
- exabot
- dotbot
- gigabot
- thesis-research-bot
- my-tiny-bot
other:
- 'path_beg /wp-admin'
- path_beg /wp-admin
- path_beg /wp-login
- path /autodiscover/autodiscover.xml
- path /autodiscover.xml
- path /CHANGELOG.txt
- path /COPYRIGHT.txt
- path /INSTALL.mysql.txt
- path /INSTALL.pgsql.txt
- path /INSTALL.sqlite.txt
- path /INSTALL.txt
- path /LICENSE.txt
- path /MAINTAINERS.txt
- path /README.txt
- path /UPGRADE.txt
HTTP/1.0 500 Internal Server Error
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!doctype html>
<!-- 500 Internal Server Error -->
<html>
<title>Site Maintenance | Wartung</title>
<style>
body { text-align: center; padding: 150px; }
h1 { font-size: 50px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
a { color: #dc8100; text-decoration: none; }
a:hover { color: #333; text-decoration: none; }
</style>
<body>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
</div>
</article>
<article>
<h1>Wir sind bald zur&uuml;ck!</h1>
<div>
<p>Wir f&uuml;hren derzeit einige Wartungsarbeiten durch und entschuldigen uns f&uuml;r die Unannehmlichkeiten. Wir sind bald wieder online!</p>
</div>
</article>
</body>
</html>
HTTP/1.0 502 Bad Gateway
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!doctype html>
<!-- 502 Bad Gateway -->
<html>
<title>Site Maintenance | Wartung</title>
<style>
body { text-align: center; padding: 150px; }
h1 { font-size: 50px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
a { color: #dc8100; text-decoration: none; }
a:hover { color: #333; text-decoration: none; }
</style>
<body>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
</div>
</article>
<article>
<h1>Wir sind bald zur&uuml;ck!</h1>
<div>
<p>Wir f&uuml;hren derzeit einige Wartungsarbeiten durch und entschuldigen uns f&uuml;r die Unannehmlichkeiten. Wir sind bald wieder online!</p>
</div>
</article>
</body>
</html>
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!doctype html>
<!-- 503 Service Unavailable -->
<html>
<title>Site Maintenance | Wartung</title>
<style>
body { text-align: center; padding: 150px; }
h1 { font-size: 50px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
a { color: #dc8100; text-decoration: none; }
a:hover { color: #333; text-decoration: none; }
</style>
<body>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
</div>
</article>
<article>
<h1>Wir sind bald zur&uuml;ck!</h1>
<div>
<p>Wir f&uuml;hren derzeit einige Wartungsarbeiten durch und entschuldigen uns f&uuml;r die Unannehmlichkeiten. Wir sind bald wieder online!</p>
</div>
</article>
</body>
</html>
HTTP/1.0 504 Gateway Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!doctype html>
<!-- 504 Gateway Time-out -->
<html>
<title>Site Maintenance | Wartung</title>
<style>
body { text-align: center; padding: 150px; }
h1 { font-size: 50px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
a { color: #dc8100; text-decoration: none; }
a:hover { color: #333; text-decoration: none; }
</style>
<body>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
</div>
</article>
<article>
<h1>Wir sind bald zur&uuml;ck!</h1>
<div>
<p>Wir f&uuml;hren derzeit einige Wartungsarbeiten durch und entschuldigen uns f&uuml;r die Unannehmlichkeiten. Wir sind bald wieder online!</p>
</div>
</article>
</body>
</html>
/var/log/haproxy {
daily
rotate 7
delaycompress
compress
notifempty
missingok
postrotate
service haproxy restart > /dev/null
endscript
daily
rotate 7
delaycompress
compress
notifempty
missingok
postrotate
service haproxy restart > /dev/null
endscript
}
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<!doctype html>
<!-- 503 Service Unavailable -->
<html>
<title>Site Maintenance | Wartung</title>
<style>
body { text-align: center; padding: 150px; }
h1 { font-size: 50px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
a { color: #dc8100; text-decoration: none; }
a:hover { color: #333; text-decoration: none; }
</style>
<body>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
</div>
</article>
<article>
<h1>Wir sind bald zur&uuml;ck!</h1>
<div>
<p>Wir f&uuml;hren derzeit einige Wartungsarbeiten durch und entschuldigen uns f&uuml;r die Unannehmlichkeiten. Wir sind bald wieder online!</p>
</div>
</article>
</body>
</html>
---
# file: roles/haproxy/handler/main.yml
- name: "Check HAProxy Config"
- name: Check HAProxy Config
command: haproxy -c -f /etc/haproxy/haproxy.cfg
register: haproxy_config_check
changed_when: '"Configuration file is valid" in haproxy_config_check.stdout_lines'
failed_when: '"Configuration file is valid" not in haproxy_config_check.stdout_lines'
notify: "Restart HAProxy"
notify:
- Restart HAProxy
- name: "Restart HAProxy"
service: name={{item.name}} state={{item.state}}
- name: Restart HAProxy
service:
name: '{{ item.name }}'
state: '{{ item.state }}'
with_items:
- name: haproxy
state: restarted
---
# file: roles/haproxy/tasks/blacklists.yml
- name: Update blacklists
template:
src: '{{ item }}'
dest: /etc/haproxy/{{ item }}
owner: root
group: root
mode: 0644
with_items:
- blacklist.ip
- blacklist.referer
- blacklist.agent
notify:
- Check HAProxy Config
---
# file: roles/haproxy/tasks/buildcerts.yml
- name: "Create PEM file for HaProxy"
- name: Create PEM file for HaProxy
assemble:
src='/etc/letsencrypt/live/{{ item.domain }}'
dest='/etc/haproxy/certs/{{ item.domain }}.pem'
regexp='(fullchain)|(privkey)\.pem'
src: /etc/letsencrypt/live/{{ item.domain }}
dest: /etc/haproxy/certs/{{ item.file }}
regexp: '(fullchain)|(privkey)\.pem'
with_items: '{{ proxy_certificates|default([]) }}'
when: item.letsencrypt|default(false) and item.active|default(true)
ignore_errors: yes
notify:
- "Restart HAProxy"
- Restart HAProxy
---
# file: roles/haproxy/tasks/configure.yml
- name: "Backup current settings"
- name: Backup current settings
archive:
path=/etc/haproxy
dest=/var/backups/haproxy-{{ lookup('pipe','date +%Y%m%d-%H%M%S') }}.tgz
path: /etc/haproxy
dest: /var/backups/haproxy-{{ lookup('pipe','date +%Y%m%d-%H%M%S') }}.tgz
when: no
- name: "Install SSL certificates"
- name: Install SSL certificates
copy:
src='{{inventory_dir}}/files/ssl/{{item.file}}'
dest='/etc/haproxy/certs'
src: '{{inventory_dir}}/files/ssl/{{item.file}}'
dest: /etc/haproxy/certs
with_items: '{{ proxy_certificates }}'
when: not item.letsencrypt|default(false)
notify: "Check HAProxy Config"
notify:
- Check HAProxy Config
- name: "Create host lists"
- name: Create maintenance lists
template:
src='host_list'
dest='/etc/haproxy/{{item}}.list'
owner='root'
group='root'
mode='644'
src: maintenance_list
dest: /etc/haproxy/maintenance.list
owner: root
group: root
mode: 0644
notify:
- Check HAProxy Config
- name: Create host lists
template:
src: host_list
dest: /etc/haproxy/{{item}}.list
owner: root
group: root
mode: 0644
with_items: '{{ groups.webserver|default([]) }}'
notify: "Check HAProxy Config"
notify:
- Check HAProxy Config
- name: "Create host ssl lists"
- name: Create host ssl lists
template:
src='host_ssl_list'
dest='/etc/haproxy/{{item}}.ssl.list'
owner='root'
group='root'
mode='644'
src: host_ssl_list
dest: /etc/haproxy/{{item}}.ssl.list
owner: root
group: root
mode: 0644
with_items: '{{ groups.webserver|default([]) }}'
notify: "Check HAProxy Config"
notify:
- Check HAProxy Config
- name: "Create host path lists"
- name: Create host path lists
file:
dest='/etc/haproxy/{{item}}.path.list'
owner='root'
group='root'
mode='644'
state='touch'
dest: /etc/haproxy/{{item}}.path.list
owner: root
group: root
mode: 0644
state: touch
with_items: '{{ groups.webserver|default([]) }}'
changed_when: false
changed_when: no
- name: "Create use bigpipe host lists"
- name: Create use bigpipe host lists
template:
src='use_bigpipe_list'
dest='/etc/haproxy/use_bigpipe.list'
owner='root'
group='root'
mode='644'
notify: "Check HAProxy Config"
src: use_bigpipe_list
dest: /etc/haproxy/use_bigpipe.list
owner: root
group: root
mode: 0644
notify:
- Check HAProxy Config
- name: "Create ignore varnish host lists"
- name: Create ignore varnish host lists
template:
src='ignore_varnish_list'
dest='/etc/haproxy/ignore_varnish.list'
owner='root'
group='root'
mode='644'
notify: "Check HAProxy Config"
src: ignore_varnish_list
dest: /etc/haproxy/ignore_varnish.list
owner: root
group: root
mode: 0644
notify:
- Check HAProxy Config
- name: "Create empty crm lists files"
- name: Create empty crm lists files
file:
dest='/etc/haproxy/{{item}}.crm.list'
owner='root'
group='root'
mode='644'
state='touch'
dest: /etc/haproxy/{{item}}.crm.list
owner: root
group: root
mode: 0644
state: touch
with_items: '{{ groups.webserver|default([]) }}'
changed_when: false
changed_when: no
- name: Update private ips
template:
src: privatelist.ip.jinja2
dest: /etc/haproxy/privatelist.ip
owner: root
group: root
mode: 644
when: haproxy_private is defined
notify:
- Check HAProxy Config
- name: Update private domains
template:
src: privatelist.domain.jinja2
dest: /etc/haproxy/privatelist.domain
owner: root
group: root
mode: 0644
when: haproxy_private is defined and haproxy_private.domain is defined
notify:
- Check HAProxy Config
- name: "Update blacklists"
- name: Update redirect map files
template:
src='{{ item }}'
dest='/etc/haproxy/{{ item }}'
owner='root'
group='root'
mode='644'
src: redirect.map.jinja2
dest: /etc/haproxy/redirect.{{ item }}.map
owner: root
group: root
mode: 0644
with_items:
- 'blacklist.ip'
- 'blacklist.referer'
- 'blacklist.agent'
notify: "Check HAProxy Config"
- domain
- domain-and-path
- domain-append-path
- path
notify:
- Check HAProxy Config
- name: "Create config file"
- name: Create config file
template:
src='haproxy_cfg.jinja2'
dest='/etc/haproxy/haproxy.cfg'
owner='root'
group='root'
mode='644'
notify: "Check HAProxy Config"
src: haproxy_cfg.jinja2
dest: /etc/haproxy/haproxy.cfg
owner: root
group: root
mode: 0644
notify:
- Check HAProxy Config
---
# file: roles/haproxy/tasks/install.yml
- name: "Add Apt Repositories"
- name: Add Apt Repositories
apt_repository:
repo='{{ item }}'
state=present
mode='644'
repo: '{{ item }}'
state: present
mode: 0644
with_items:
- "ppa:vbernat/haproxy-1.7"
- ppa:vbernat/haproxy-2.2
when: ansible_distribution_major_version != "16"
- name: "Install some packages"
- name: Install some packages
apt:
pkg='{{ item }}'
state=installed
with_items:
- haproxy
- hatop
- socat
pkg: '{{ packages }}'
state: latest
vars:
packages:
- haproxy
#- hatop
- socat
- name: "create directories"
- name: create directories
file:
dest='{{ item }}'
state=directory
mode='755'
dest: '{{ item }}'
state: directory
mode: 0755
with_items:
- /etc/haproxy/certs
- /etc/haproxy/update
- name: "Install hatop shortcut"
- name: Install hatop shortcut
copy:
src='usr_local_bin_hatop'
dest='/usr/local/bin/hatop'
owner='root'
group='root'
mode='755'
src: usr_local_bin_hatop
dest: /usr/local/bin/hatop
owner: root
group: root
mode: 0755
- name: "Install log rotator"
- name: Install log rotator
copy:
src='etc_logrotate_d_haproxy'
dest='/etc/logrotate.d/haproxy'
owner='root'
group='root'
mode='644'
src: etc_logrotate_d_haproxy
dest: /etc/logrotate.d/haproxy
owner: root
group: root
mode: 0644
tags:
- logrotate
- name: "Install script to read socket"
- name: Install script to read socket
template:
src='hasocket'
dest='/usr/local/bin/hasocket'
owner='root'
group='root'
mode='755'
src: hasocket
dest: /usr/local/bin/hasocket
owner: root
group: root
mode: 0755
- name: Install error response files
copy:
src: '{{ item }}.http'
dest: /etc/haproxy/errors/{{ item }}.http
owner: root
group: root
mode: 0644
with_items:
- '500'
- '502'
- '503'
- '504'
- 'maintenance'
tags:
- errorfiles
notify:
- Check HAProxy Config
---
# file: roles/haproxy/tasks/main.yml
- name: "HaProxy Role"
set_fact: role_haproxy_started=true
tags: 'always'
- name: HaProxy Role
set_fact:
role_haproxy_started: yes
tags:
- always
- block:
- include: install.yml
- include: configure.yml
tags: 'Config'
- name: Import install
import_tasks: install.yml
when: '"haproxy" not in excluded_roles'
- name: Import configure
import_tasks: configure.yml
tags:
- Config
- block:
- name: "Install Certs"
include: '../../letsencrypt/tasks/cert.yml'
with_items: '{{ proxy_certificates|default([]) }}'
loop_control:
loop_var: domain
when: domain.letsencrypt|default(false) and domain.active|default(true)
- name: "Renew Existing Cert"
include: '../../letsencrypt/tasks/renew.yml'
- name: Import blacklist
import_tasks: blacklists.yml
tags:
- Config
- Blacklists
- name: "Build HaCerts"
include: 'buildcerts.yml'
when: not excluded_roles or "haproxy" not in excluded_roles
- name: "Set directory permissions to current user"
file:
path: '/etc/letsencrypt'
owner: '{{ ansible_env.SUDO_USER }}'
recurse: yes
tags: 'Certs'
when: proxy_active
- block:
tags: 'Certs'
when: 'proxy_active and "letsencrypt" not in excluded_roles'
- name: Install Certs
include_tasks: ../../letsencrypt/tasks/cert.yml
with_items: '{{ proxy_certificates|default([]) }}'
loop_control:
loop_var: domain
when: domain.letsencrypt|default(false) and domain.active|default(true)
- block:
- name: Renew Existing Cert
import_tasks: ../../letsencrypt/tasks/renew.yml
- name: "Pull Certs from active Proxy"
include: 'pullcerts.yml'
tags: 'Certs'
- name: Build HaProxy Certs
import_tasks: buildcerts.yml
when: 'not proxy_active and "letsencrypt" not in excluded_roles'
tags:
- Certs
when: proxy_active|default(true) and (not excluded_roles or "letsencrypt" not in excluded_roles)
- name: "Set directory permissions to root"
file:
path: '/etc/letsencrypt'
owner: 'root'
recurse: yes
tags: 'Certs'
when: 'proxy_active and "letsencrypt" not in excluded_roles'
- name: Import proxypool
import_tasks: proxypool.yml
when: not excluded_roles or "letsencrypt" not in excluded_roles
tags:
- Certs
---
# file: roles/haproxy/tasks/proxypool.yml
- block:
- name: Set directory permissions to current user
file:
path: /etc/letsencrypt
owner: '{{ ansible_env.SUDO_USER|default("root") }}'
recurse: yes
follow: no
when: proxy_active|default(true)
- name: Pull Certs from active Proxy
import_tasks: pullcerts.yml
when: not proxy_active|default(true)
- name: Set directory permissions to root
file:
path: /etc/letsencrypt
owner: root
recurse: yes
follow: no
when: proxy_active|default(true)
tags:
- Certs
---
# file: roles/haproxy/tasks/pullcerts.yml
- name: "Find out active proxy"
set_fact: proxy_active_host={{ item }}
- name: Find out active proxy
set_fact:
proxy_active_host: '{{ item }}'
with_items: '{{ groups.proxyserver|default([]) }}'
when: hostvars[item].proxy_active|default(true)
- name: "Set directory permissions to current user"
- name: Set directory permissions to current user
file:
path: '{{ item }}'
owner: '{{ ansible_env.SUDO_USER }}'
owner: '{{ ansible_env.SUDO_USER|default("root") }}'
recurse: yes
follow: no
with_items:
- '/etc/letsencrypt'
- '/etc/haproxy/certs'
- /etc/letsencrypt
- /etc/haproxy/certs
- name: "Sync files"
shell: rsync -rulp '{{ proxy_active_host }}:{{ item }}/' '{{ item }}'
delegate_to: "{{ inventory_hostname }}"
- name: Sync files
shell: 'rsync -rulp "{{ proxy_active_host }}:{{ item }}/" "{{ item }}"'
delegate_to: '{{ inventory_hostname }}'
become: no
with_items:
- '/etc/letsencrypt'
- '/etc/haproxy/certs'
- /etc/letsencrypt
- /etc/haproxy/certs
ignore_errors: yes
# We ignore errors as they may happen if we run the script without the other proxy
- name: "Set directory permissions to root"
- name: Set directory permissions to root
file:
path: '{{ item }}'
owner: 'root'
owner: root
recurse: yes
follow: no
with_items:
- '/etc/letsencrypt'
- '/etc/haproxy/certs'
- /etc/letsencrypt
- /etc/haproxy/certs
{% if ansible_local is defined and ansible_local.blacklist is defined %}
{% for line in ansible_local.blacklist.agent|default([]) %}
{{line}}
{% endfor %}
{% endif %}
{% for line in proxy_blacklist.agent|default([]) %}
{{line}}
{% endfor %}
{% if ansible_local is defined and ansible_local.blacklist is defined %}
{% for line in ansible_local.blacklist.ip|default([]) %}
{{line}}
{% endfor %}
{% endif %}
{% for line in proxy_blacklist.ip|default([]) %}
{{line}}
{% endfor %}
{% if ansible_local is defined and ansible_local.blacklist is defined %}
{% for line in ansible_local.blacklist.referer|default([]) %}
{{line}}
{% endfor %}
{% endif %}
{% for line in proxy_blacklist.referer|default([]) %}
{{line}}
{% endfor %}
......@@ -8,12 +8,11 @@ global
daemon
ca-base /etc/haproxy/certs
crt-base /etc/haproxy/private
ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:!RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
pidfile /run/haproxy.pid
defaults
log global
log-format %ci:%cp\ [%T]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r
log-format %ci:%cp\ [%T]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %[ssl_fc_sni]\ %hr\ %{+Q}r
mode http
option dontlognull
timeout connect {{ proxy_timeout_connect }}
......@@ -42,16 +41,18 @@ listen stats
stats admin if TRUE
stats uri /haproxy_stats
stats realm LoadBalancerStats
{% if kibana_users is defined %}
{% if haproxy_private is defined %}
userlist kibana
{% for user in kibana_users %}
userlist notprivate
{% for user in haproxy_private.auth %}
user {{ user.username }} insecure-password '{{ user.password }}'
{% endfor %}
{% endif %}
frontend http_in
bind *:80
http-request capture req.hdr(User-Agent) len 100
log-format %ci:%cp\ [%T]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %[ssl_fc_sni]\ %hr\ %{+Q}r
http-request del-header Proxy
acl blockedip src -f /etc/haproxy/blacklist.ip
http-request deny if blockedip
......@@ -63,7 +64,39 @@ frontend http_in
http-request deny if { {{ rule }} }
{% endfor %}
http-request set-header x-routing-host undefined
{% for cert in proxy_certificates %}
{% if cert.active|default(true) %}
{% if cert.wildcard|default(false) and cert.wildcard_host is defined %}
http-request set-header x-routing-host {{ cert.wildcard_host }} if { hdr(host) -m end -i '.{{ cert.domain }}' }
use_backend backend_redirect_ssl if { hdr(host) -m end -i '.{{ cert.domain }}' }
{% endif %}
{% endif %}
{% endfor %}
acl letsencrypt_challenge path_beg /.well-known/acme-challenge/
http-request set-header x-routing-host maintenance if !letsencrypt_challenge { hdr(x-routing-host) undefined } { hdr(host) -i -n -f /etc/haproxy/maintenance.list }
http-request redirect code 301 location %[base,lower,map(/etc/haproxy/redirect.domain-and-path.map)] if !letsencrypt_challenge { base,lower,map(/etc/haproxy/redirect.domain-and-path.map) -m found }
http-request redirect code 301 location %[capture.req.uri,lower,map(/etc/haproxy/redirect.path.map)] if !letsencrypt_challenge { capture.req.uri,lower,map(/etc/haproxy/redirect.path.map) -m found }
http-request redirect code 301 location %[hdr(host),lower,map(/etc/haproxy/redirect.domain.map)] if !letsencrypt_challenge { hdr(host),lower,map(/etc/haproxy/redirect.domain.map) -m found }
http-request redirect code 301 location %[hdr(host),lower,map(/etc/haproxy/redirect.domain-append-path.map)]%[capture.req.uri] if !letsencrypt_challenge { hdr(host),lower,map(/etc/haproxy/redirect.domain-append-path.map) -m found }
{% if haproxy_private is defined %}
{% if haproxy_private.domain is defined %}
acl privatedomain hdr(host) -i -n -f /etc/haproxy/privatelist.domain
{% else %}
acl privatedomain hdr_cnt(X_Dummy) eq 0
{% endif %}
acl privateip src -f /etc/haproxy/privatelist.ip
acl private_auth http_auth(notprivate) if !privateip
http-request auth realm notprivate if !letsencrypt_challenge privatedomain !privateip !private_auth
{% endif %}
{% for redirect in proxy_redirect_search_replace|default([]) %}
{% if redirect.extra is defined %}
acl {{ redirect.extra.variable }} {{ redirect.extra.condition }}
{% endif %}
http-request redirect code 301 location %[url,regsub(\"{{ redirect.search }}\",\"{{ redirect.replace }}\",i)] if !letsencrypt_challenge {% if redirect.extra is defined %}{% if redirect.extra.negate|default(false) %}!{% endif %}{{ redirect.extra.variable }} {% endif %}{ path_reg {{ redirect.match }} }
{% endfor %}
{% for line in proxy_extra_lines|default([]) %}
{{ line }}
{% endfor %}
{% for host in groups['all']|sort %}
{% for redirect in hostvars[host].proxy_redirect|default([]) %}
{% for from in redirect.from %}
......@@ -72,7 +105,7 @@ frontend http_in
http-request deny if !letsencrypt_challenge { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }}{% if path.from is defined %} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}}{% endif %} }
{% else %}
{% if path.regex is defined and path.from is defined %}
http-request redirect code 301 location {{ path.to|default('') }}%[capture.req.uri,regsub({{path.regex}},)] if !letsencrypt_challenge { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}} }
http-request redirect code 301 location {% if path.usedomain|default(false) %}{{ redirect.protocol|default('https') }}://{{redirect.to|default(from)}}{% endif %}{{ path.to|default('') }}%[capture.req.uri,regsub({{path.regex}},)] if !letsencrypt_challenge { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}} }
{% endif %}
{% endif %}
{% endfor %}
......@@ -85,19 +118,19 @@ frontend http_in
{% for path in redirect.paths|default([]) %}
{% if not path.deny|default(false) %}
{% if path.regex is not defined or path.from is not defined %}
http-request redirect code 301 location {{ redirect.protocol|default('https') }}://{{redirect.to}}/{{path.to|default('')}}{% if path.append_path|default(false) %}%[capture.req.uri]{% endif %}{% if path.append_query is defined %}?{{ path.append_query }}{% endif %} if !letsencrypt_challenge { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }}{% if path.from is defined %} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}}{% endif %} }
http-request redirect code 301 location {{ redirect.protocol|default('https') }}://{{redirect.to|default(from)}}{% if path.to is defined %}/{{path.to}}{% endif %}{% if path.append_path|default(false) %}%[capture.req.uri]{% endif %}{% if path.append_query is defined %}?{{ path.append_query }}{% endif %} if !letsencrypt_challenge { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }}{% if path.from is defined %} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}}{% endif %}{% if path.condition is defined %} } { {{path.condition}}{% endif %} }
{% endif %}
{% endif %}
{% endfor %}
{% if (from != redirect.to or redirect.protocol|default('https') == 'https') and redirect.paths is not defined %}
redirect prefix {{ redirect.protocol|default('https') }}://{{redirect.to}} code 301 if !letsencrypt_challenge { hdr(host) -i -n {{ from }} }
{% if (from != redirect.to|default(from) or redirect.protocol|default('https') == 'https') and redirect.paths is not defined %}
redirect prefix {{ redirect.protocol|default('https') }}://{{redirect.to|default(from)}} code 301 if !letsencrypt_challenge { hdr(host) -i -n {{ from }} }
{% endif %}
{% endfor %}
{% endfor %}
{% if proxy_redirect_aliase %}
{% for drupal in hostvars[host].drupal_settings|default([]) %}
{% for domain in drupal.domains|default([]) %}
{% if not domain.multidomain|default(false) %}
{% if not domain.multidomain|default(false) and domain.aliases_redirect|default(true) %}
{% for alias in domain.aliases|default([]) %}
redirect prefix {{ domain.protocol|default('https') }}://{{domain.domain}} code 301 if !letsencrypt_challenge { hdr(host) -i -n {{alias}} }
{% endfor %}
......@@ -109,7 +142,7 @@ frontend http_in
{% if 'webserver' in groups %}
{% for host in groups['webserver']|sort %}
{% if hostvars[host].routing is defined %}
http-request set-header x-routing-host {{ host }} if !letsencrypt_challenge { hdr(x-routing-host) undefined } { hdr(host) -i -n {{ hostvars[host].routing.domain }} } { path -i -n -f /etc/haproxy/{{ host }}.path.list }
http-request set-header x-routing-host {{ host }} if !letsencrypt_challenge { hdr(x-routing-host) undefined } { hdr(host) -i -n {{ hostvars[host].routing.domain }} } { path -m reg -i -n -f /etc/haproxy/{{ host }}.path.list }
{% endif %}
{% endfor %}
{% for host in groups['webserver']|sort %}
......@@ -124,11 +157,25 @@ frontend http_in
http-request set-header x-routing-host {{ routing.default }} if !letsencrypt_challenge { hdr(x-routing-host) undefined } { hdr(host) -i -n {{ routing.domain }} }
{% endif %}
use_backend backend_letsencrypt if letsencrypt_challenge
{% if kibana_users is defined %}
use_backend backend_maintenance if { hdr(x-routing-host) maintenance }
{% if kibana_domain is defined %}
acl kibana_present hdr(host) -i -n '{{ kibana_domain|default(inventory_hostname) }}'
use_backend backend_redirect_ssl if kibana_present
{% endif %}
{% for prometheus in prometheus_settings|default([]) %}
acl prometheus_{{ prometheus.id }}_present hdr(host) -i -n '{{ prometheus.domain|default(inventory_hostname) }}'
use_backend backend_redirect_ssl if prometheus_{{ prometheus.id }}_present
{% endfor %}
{% if 'webserver' in groups %}
{% for host in groups['webserver']|sort %}
http-request set-header x-routing-host {{ host }} if !letsencrypt_challenge { hdr(x-routing-host) undefined } { hdr(host) -i -n -f /etc/haproxy/{{host}}.list }
{% endfor %}
{% for host in groups['webserver']|sort %}
{% if hostvars[host].routing_special_host is defined %}
http-request set-header x-routing-host {{ hostvars[host].routing_special_host }} if !letsencrypt_challenge !{ hdr(x-routing-special-host) -m found } { hdr(x-routing-host) {{ host }} }
http-request set-header x-routing-host {{ host }} if !letsencrypt_challenge { hdr(x-routing-special-host) -m found } { hdr(x-routing-host) {{ hostvars[host].routing_special_host }} }
{% endif %}
{% endfor %}
{% for host in groups['webserver']|sort %}
acl redirect_ssl_{{host}} hdr(host) -i -n -f /etc/haproxy/{{host}}.ssl.list
use_backend backend_redirect_ssl if redirect_ssl_{{host}}
......@@ -136,31 +183,32 @@ frontend http_in
{% endif %}
acl domain_uses_bigpipe hdr(host) -i -n -f /etc/haproxy/use_bigpipe.list
{% if varnish_host|default(false) %}
acl request_ignores_varnish hdr(x-varnish-ignore) -m found
acl is_purge method PURGE
use_backend backend_varnish if is_purge
acl is_ban method BAN
use_backend backend_varnish if is_ban
acl is_uriban method URIBAN
use_backend backend_varnish if is_uriban
acl is_urimban method URIMBAN
use_backend backend_varnish if is_urimban
acl domain_ignores_varnish hdr(host) -i -n -f /etc/haproxy/ignore_varnish.list
use_backend backend_varnish_bigpipe if domain_uses_bigpipe !domain_ignores_varnish
acl static_content path_end .jpg .jpeg .gif .png .ico .swf .css .js .htm .html
use_backend backend_varnish if static_content !domain_ignores_varnish
acl static_content path_end .jpg .jpeg .gif .png .ico .swf .css .js .htm .html .ttf .woff .woff2 .svg .eot .bmp .webp .tiff
acl static_content_private path_beg /system/
use_backend backend_varnish_bigpipe if static_content !static_content_private domain_uses_bigpipe !domain_ignores_varnish !request_ignores_varnish
use_backend backend_varnish if static_content !static_content_private !domain_ignores_varnish !request_ignores_varnish
{% endif %}
{% if 'webserver' in groups %}
{% for host in groups['webserver']|sort %}
use_backend backend_{{ host }}_bigpipe if domain_uses_bigpipe { hdr(x-routing-host) {{ host }} }
use_backend backend_{{ host }} if { hdr(x-routing-host) {{ host }} }
{% endfor %}
{% for host in groups['webserver']|sort %}
acl domain_in_{{host}} hdr(host) -i -n -f /etc/haproxy/{{host}}.list
use_backend backend_{{host}}_bigpipe if domain_uses_bigpipe domain_in_{{host}}
use_backend backend_{{host}} if domain_in_{{host}}
{% for rule in hostvars[host].proxy_special_rules|default([]) %}
acl proxy_special_rules_{{host}}_{{rule}} {{ hostvars[host].proxy_special_rules[rule] }}
use_backend backend_{{host}} if proxy_special_rules_{{host}}_{{rule}}
use_backend backend_{{host}}_special_{{ rule }} if proxy_special_rules_{{host}}_{{rule}}
{% endfor %}
{% if hostvars[host].proxy_crm_domains is defined %}
acl crm_domain_in_{{host}} hdr_dom(host) -i -n -f /etc/haproxy/{{host}}.crm.list
use_backend backend_{{host}} if crm_domain_in_{{host}}
use_backend backend_redirect_ssl if crm_domain_in_{{host}}
{% endif %}
{% endfor %}
{% endif %}
......@@ -169,7 +217,32 @@ frontend http_in
frontend https_in_{{ cert.ip }}
bind {{ cert.ip }}:443 ssl crt /etc/haproxy/certs/{{ cert.file }} no-sslv3
http-request capture req.hdr(User-Agent) len 100
log-format %ci:%cp\ [%T]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %[ssl_fc_sni]\ %hr\ %{+Q}r
http-request del-header Proxy
http-request redirect code 301 location %[base,lower,map(/etc/haproxy/redirect.domain-and-path.map)] if { base,lower,map(/etc/haproxy/redirect.domain-and-path.map) -m found }
http-request redirect code 301 location %[capture.req.uri,lower,map(/etc/haproxy/redirect.path.map)] if { capture.req.uri,lower,map(/etc/haproxy/redirect.path.map) -m found }
http-request redirect code 301 location %[hdr(host),lower,map(/etc/haproxy/redirect.domain.map)] if { hdr(host),lower,map(/etc/haproxy/redirect.domain.map) -m found }
http-request redirect code 301 location %[hdr(host),lower,map(/etc/haproxy/redirect.domain-append-path.map)]%[capture.req.uri] if { hdr(host),lower,map(/etc/haproxy/redirect.domain-append-path.map) -m found }
{% if haproxy_private is defined %}
{% if haproxy_private.domain is defined %}
acl privatedomain hdr(host) -i -n -f /etc/haproxy/privatelist.domain
{% else %}
acl privatedomain hdr_cnt(X_Dummy) eq 0
{% endif %}
acl privateip src -f /etc/haproxy/privatelist.ip
acl private_auth http_auth(notprivate) if !privateip
http-request auth realm notprivate if privatedomain !privateip !private_auth
{% endif %}
{% for redirect in proxy_redirect_search_replace|default([]) %}
{% if redirect.extra is defined %}
acl {{ redirect.extra.variable }} {{ redirect.extra.condition }}
{% endif %}
http-request redirect code 301 location %[url,regsub(\"{{ redirect.search }}\",\"{{ redirect.replace }}\",i)] if {% if redirect.extra is defined %}{% if redirect.extra.negate|default(false) %}!{% endif %}{{ redirect.extra.variable }} {% endif %}{ path_reg {{ redirect.match }} }
{% endfor %}
{% for line in proxy_extra_lines|default([]) %}
{{ line }}
{% endfor %}
acl blockedip src -f /etc/haproxy/blacklist.ip
http-request deny if blockedip
acl blockedreferer hdr_sub(referer) -i -f /etc/haproxy/blacklist.referer
......@@ -180,6 +253,10 @@ frontend https_in_{{ cert.ip }}
http-request deny if { {{ rule }} }
{% endfor %}
http-request set-header x-routing-host undefined
{% if cert.wildcard|default(false) and cert.wildcard_host is defined %}
http-request set-header x-routing-host {{ cert.wildcard_host }} if { hdr(x-routing-host) undefined } { hdr(host) -m end -i '.{{ cert.domain }}' }
{% endif %}
http-request set-header x-routing-host maintenance if { hdr(x-routing-host) undefined } { hdr(host) -i -n -f /etc/haproxy/maintenance.list }
{% for host in groups['all']|sort %}
{% for redirect in hostvars[host].proxy_redirect|default([]) %}
{% for from in redirect.from %}
......@@ -188,7 +265,7 @@ frontend https_in_{{ cert.ip }}
http-request deny if { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }}{% if path.from is defined %} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}}{% endif %} }
{% else %}
{% if path.regex is defined and path.from is defined %}
http-request redirect code 301 location {{ path.to|default('') }}%[capture.req.uri,regsub({{path.regex}},)] if { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}} }
http-request redirect code 301 location {% if path.usedomain|default(false) %}{{ redirect.protocol|default('https') }}://{{redirect.to|default(from)}}{% endif %}{{ path.to|default('') }}%[capture.req.uri,regsub({{path.regex}},)] if { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}} }
{% endif %}
{% endif %}
{% endfor %}
......@@ -201,19 +278,19 @@ frontend https_in_{{ cert.ip }}
{% for path in redirect.paths|default([]) %}
{% if not path.deny|default(false) %}
{% if path.regex is not defined or path.from is not defined %}
http-request redirect code 301 location {{ redirect.protocol|default('https') }}://{{redirect.to}}/{{path.to|default('')}}{% if path.append_path|default(false) %}%[capture.req.uri]{% endif %}{% if path.append_query is defined %}?{{ path.append_query }}{% endif %} if { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }}{% if path.from is defined %} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}}{% endif %} }
http-request redirect code 301 location {{ redirect.protocol|default('https') }}://{{redirect.to|default(from)}}{% if path.to is defined %}/{{path.to}}{% endif %}{% if path.append_path|default(false) %}%[capture.req.uri]{% endif %}{% if path.append_query is defined %}?{{ path.append_query }}{% endif %} if { {{ (from == ".") | ternary('hdr_sub', 'hdr') }}(host) -i -n {{ from }}{% if path.from is defined %} } { {{path.exact|default(false)|ternary('path /','path_reg ^/')}}{{path.from}}{% endif %}{% if path.condition is defined %} } { {{path.condition}}{% endif %} }
{% endif %}
{% endif %}
{% endfor %}
{% if (from != redirect.to or redirect.protocol|default('https') != 'https') and redirect.paths is not defined %}
redirect prefix {{ redirect.protocol|default('https') }}://{{redirect.to}} code 301 if { hdr(host) -i -n {{ from }} }
{% if (from != redirect.to|default(from) or redirect.protocol|default('https') != 'https') and redirect.paths is not defined %}
redirect prefix {{ redirect.protocol|default('https') }}://{{redirect.to|default(from)}} code 301 if { hdr(host) -i -n {{ from }} }
{% endif %}
{% endfor %}
{% endfor %}
{% if proxy_redirect_aliase %}
{% for drupal in hostvars[host].drupal_settings|default([]) %}
{% for domain in drupal.domains|default([]) %}
{% if not domain.multidomain|default(false) %}
{% if not domain.multidomain|default(false) and domain.aliases_redirect|default(true) %}
{% for alias in domain.aliases|default([]) %}
redirect prefix {{ domain.protocol|default('https') }}://{{domain.domain}} code 301 if { hdr(host) -i -n {{alias}} }
{% endfor %}
......@@ -225,7 +302,7 @@ frontend https_in_{{ cert.ip }}
{% if 'webserver' in groups %}
{% for host in groups['webserver']|sort %}
{% if hostvars[host].routing is defined %}
http-request set-header x-routing-host {{ host }} if { hdr(x-routing-host) undefined } { hdr(host) -i -n {{ hostvars[host].routing.domain }} } { path -i -n -f /etc/haproxy/{{ host }}.path.list }
http-request set-header x-routing-host {{ host }} if { hdr(x-routing-host) undefined } { hdr(host) -i -n {{ hostvars[host].routing.domain }} } { path -m reg -i -n -f /etc/haproxy/{{ host }}.path.list }
{% endif %}
{% endfor %}
{% for host in groups['webserver']|sort %}
......@@ -239,10 +316,15 @@ frontend https_in_{{ cert.ip }}
{% if routing is defined and routing.default is defined %}
http-request set-header x-routing-host {{ routing.default }} if { hdr(x-routing-host) undefined } { hdr(host) -i -n {{ routing.domain }} }
{% endif %}
{% if kibana_users is defined %}
use_backend backend_maintenance if { hdr(x-routing-host) maintenance }
{% if kibana_domain is defined %}
acl kibana_present hdr(host) -i -n '{{ kibana_domain|default(inventory_hostname) }}'
use_backend backend_kibana if kibana_present
{% endif %}
{% for prometheus in prometheus_settings|default([]) %}
acl prometheus_{{ prometheus.id }}_present hdr(host) -i -n '{{ prometheus.domain|default(inventory_hostname) }}'
use_backend backend_prometheus_{{ prometheus.id }} if prometheus_{{ prometheus.id }}_present
{% endfor %}
{% for external in cert.external|default([]) %}
acl is_{{ external.key }} {{ external.acl }}
use_backend backend_{{ external.key }} if is_{{ external.key }}
......@@ -252,13 +334,24 @@ frontend https_in_{{ cert.ip }}
acl crm_redirect_{{host}} hdr(host) -i -n -f /etc/haproxy/{{host}}.list
use_backend backend_redirect if crm_redirect_{{host}}
{% endfor %}
{% for host in groups['webserver']|sort %}
http-request set-header x-routing-host {{ host }} if { hdr(x-routing-host) undefined } { hdr(host) -i -n -f /etc/haproxy/{{host}}.ssl.list }
{% endfor %}
{% for host in groups['webserver']|sort %}
{% if hostvars[host].routing_special_host is defined %}
http-request set-header x-routing-host {{ hostvars[host].routing_special_host }} if !{ hdr(x-routing-special-host) -m found } { hdr(x-routing-host) {{ host }} }
http-request set-header x-routing-host {{ host }} if { hdr(x-routing-special-host) -m found } { hdr(x-routing-host) {{ hostvars[host].routing_special_host }} }
{% endif %}
{% endfor %}
{% endif %}
acl domain_uses_bigpipe hdr(host) -i -n -f /etc/haproxy/use_bigpipe.list
{% if varnish_host|default(false) %}
acl request_ignores_varnish hdr(x-varnish-ignore) -m found
acl domain_ignores_varnish hdr(host) -i -n -f /etc/haproxy/ignore_varnish.list
use_backend backend_varnish_bigpipe if domain_uses_bigpipe !domain_ignores_varnish
acl static_content path_end .jpg .jpeg .gif .png .ico .swf .css .js .htm .html
use_backend backend_varnish if static_content !domain_ignores_varnish
acl static_content path_end .jpg .jpeg .gif .png .ico .swf .css .js .htm .html .ttf .woff .woff2 .svg .eot .bmp .webp .tiff
acl static_content_private path_beg /system/
use_backend backend_varnish_bigpipe if static_content !static_content_private domain_uses_bigpipe !domain_ignores_varnish !request_ignores_varnish
use_backend backend_varnish if static_content !static_content_private !domain_ignores_varnish !request_ignores_varnish
{% endif %}
{% if 'webserver' in groups %}
{% for host in groups['webserver']|sort %}
......@@ -266,22 +359,24 @@ frontend https_in_{{ cert.ip }}
use_backend backend_{{ host }}_https if { hdr(x-routing-host) {{ host }} }
{% endfor %}
{% for host in groups['webserver']|sort %}
acl ssl_domain_in_{{host}} hdr(host) -i -n -f /etc/haproxy/{{host}}.ssl.list
use_backend backend_{{host}}_https_bigpipe if domain_uses_bigpipe ssl_domain_in_{{host}}
use_backend backend_{{host}}_https if ssl_domain_in_{{host}}
acl redirect_{{host}} hdr(host) -i -n -f /etc/haproxy/{{host}}.list
use_backend backend_redirect if redirect_{{host}}
{% for rule in hostvars[host].proxy_special_rules|default([]) %}
acl proxy_special_rules_{{host}}_{{rule}} {{ hostvars[host].proxy_special_rules[rule] }}
use_backend backend_{{host}}_https if proxy_special_rules_{{host}}_{{rule}}
use_backend backend_{{host}}_special_{{ rule }}_https if proxy_special_rules_{{host}}_{{rule}}
{% endfor %}
{% if hostvars[host].proxy_crm_domains is defined %}
acl crm_domain_in_{{host}} hdr_dom(host) -i -n -f /etc/haproxy/{{host}}.crm.list
use_backend backend_{{host}}_https if crm_domain_in_{{host}}
{% endif %}
{% endfor %}
{% endif %}
{% for external in cert.external|default([]) %}
backend backend_{{ external.key }}
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ external.key }}"
{% endif %}
{% for line in external.extra|default([]) %}
{{ line }}
{% endfor %}
......@@ -293,11 +388,17 @@ backend backend_{{ external.key }}
{% if proxy_default_backend not in groups['webserver'] %}
backend backend_{{ proxy_default_backend }}
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "deny"
{% endif %}
http-response deny
{% endif %}
{% for host in groups['webserver']|sort %}
backend backend_{{host}}
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ host }}"
{% endif %}
{% if host == inventory_hostname or host == 'localhost' %}
http-response deny
{% else %}
......@@ -308,6 +409,9 @@ backend backend_{{host}}
{% endif %}
backend backend_{{host}}_bigpipe
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ host }}_bigpipe"
{% endif %}
{% if host == inventory_hostname or host == 'localhost' %}
http-response deny
{% else %}
......@@ -319,6 +423,9 @@ backend backend_{{host}}_bigpipe
{% endif %}
backend backend_{{host}}_https
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ host }}_https"
{% endif %}
{% if host == inventory_hostname or host == 'localhost' %}
http-response deny
{% else %}
......@@ -330,6 +437,9 @@ backend backend_{{host}}_https
{% endif %}
backend backend_{{host}}_https_bigpipe
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ host }}_https_bigpipe"
{% endif %}
{% if host == inventory_hostname or host == 'localhost' %}
http-response deny
{% else %}
......@@ -340,47 +450,101 @@ backend backend_{{host}}_https_bigpipe
http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;"
server server_{{host}} {{hostvars[host]['static_ipv4']}}:80 check maxconn {{hostvars[host]['proxy_maxconn']|default(proxy_maxconn)}}
{% endif %}
{% for rule in hostvars[host].proxy_special_rules|default([]) %}
backend backend_{{host}}_special_{{ rule }}
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ host }}"
{% endif %}
{% if host == inventory_hostname or host == 'localhost' %}
http-response deny
{% else %}
server server_{{host}} {{hostvars[host]['static_ipv4']}}:80 check maxconn {{hostvars[host]['proxy_maxconn']|default(proxy_maxconn)}}
{% endif %}
backend backend_{{host}}_special_{{ rule }}_https
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "{{ host }}_https"
{% endif %}
{% if host == inventory_hostname or host == 'localhost' %}
http-response deny
{% else %}
http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;"
server server_{{host}} {{hostvars[host]['static_ipv4']}}:80 check maxconn {{hostvars[host]['proxy_maxconn']|default(proxy_maxconn)}}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% if varnish_host|default(false) %}
backend backend_varnish
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "varnish"
{% endif %}
option httpchk HEAD /varnishcheck
http-request set-header x-real-ip %[src]
http-check expect status 200
option forwardfor
hash-type consistent
{% if varnish_host == inventory_hostname %}
server varnish 127.0.0.1:6081 maxconn {{proxy_varnish_maxconn}}
server varnish 127.0.0.1:6081 check maxconn {{proxy_varnish_maxconn}}
{% else %}
server varnish {{ varnish_host_ip|default('') }}:6081 maxconn {{proxy_varnish_maxconn}}
server varnish {{ varnish_host_ip|default('') }}:6081 check maxconn {{proxy_varnish_maxconn}}
{% endif %}
backend backend_varnish_bigpipe
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "varnish_bigpipe"
{% endif %}
no option http-buffer-request
option httpchk HEAD /varnishcheck
http-request set-header x-real-ip %[src]
http-check expect status 200
option forwardfor
hash-type consistent
{% if varnish_host == inventory_hostname %}
server varnish 127.0.0.1:6081 maxconn {{proxy_varnish_maxconn}}
server varnish 127.0.0.1:6081 check maxconn {{proxy_varnish_maxconn}}
{% else %}
server varnish {{ varnish_host_ip|default('') }}:6081 maxconn {{proxy_varnish_maxconn}}
server varnish {{ varnish_host_ip|default('') }}:6081 check maxconn {{proxy_varnish_maxconn}}
{% endif %}
{% endif %}
backend backend_redirect_ssl
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "redirect_ssl"
{% endif %}
redirect scheme https code 301 if TRUE
backend backend_redirect
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "redirect"
{% endif %}
redirect scheme http code 301 if TRUE
backend backend_letsencrypt
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "letsencrypt"
{% endif %}
server letsencrypt 127.0.0.1:54321
{% if kibana_users is defined %}
{% if kibana_domain is defined %}
backend backend_kibana
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "kibana"
{% endif %}
server kibana 127.0.0.1:5601 check maxconn 32
acl kibana_auth http_auth(kibana) if kibana_present
http-request auth realm Kibana if !kibana_auth
{% endif %}
{% for prometheus in prometheus_settings|default([]) %}
backend backend_prometheus_{{ prometheus.id }}
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "prometheus_{{ prometheus.id }}"
{% endif %}
server prometheus_{{ prometheus.id }} 127.0.0.1:{{ prometheus.port }} check maxconn 32
{% endfor %}
backend backend_maintenance
{% if proxy_debug %}
http-response set-header X-Proxy-Backend "maintenance"
{% endif %}
errorfile 503 /etc/haproxy/errors/maintenance.http