instance-balancer.cfg.in 9.04 KB
Newer Older
1 2 3 4
{% set part_list = [] -%}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl', {}) %}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
5
{% set shared_ca_path = slapparameter_dict['shared-certificate-authority-path'] -%}
6 7 8 9 10 11 12 13 14 15 16 17 18 19
{#
XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6
per partition. No more (undefined result), no less (IndexError).
-#}
# TODO: insert varnish between apache & haproxy.
# And think of a way to specify which urls goe through varnish, which go
# directly to haproxy. (maybe just passing literal configuration file chunk)
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set apache_ip_list = [ipv4] -%}
{% if ipv6_set -%}
{%   set ipv6 = (ipv6_set | list)[0] -%}
{%   do apache_ip_list.append('[' ~ ipv6 ~ ']') -%}
{% endif -%}

20
[jinja2-template-base]
21
recipe = slapos.recipe.template:jinja2
22 23 24 25
mode = 644

[simplefile]
< = jinja2-template-base
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
template = inline:{{ '{{ content }}' }}

{% macro simplefile(section_name, file_path, content, mode='') -%}
{%   set content_section_name = section_name ~ '-content' -%}
[{{  content_section_name }}]
content = {{ dumps(content) }}

[{{  section(section_name) }}]
< = simplefile
rendered = {{ file_path }}
context = key content {{content_section_name}}:content
mode = {{ mode }}
{%- endmacro %}

{% if use_ipv6 -%}
[zope-tunnel-base]
recipe = slapos.cookbook:ipv4toipv6
runner-path = ${directory:services}/${:base-name}
6tunnel-path = {{ parameter_dict['6tunnel'] }}/bin/6tunnel
shell-path = {{ parameter_dict['dash'] }}/bin/dash
ipv4 = {{ ipv4 }}

{% endif -%}
{% set haproxy_dict = {} -%}
{% set apache_dict = {} -%}
51
{% set next_port = itertools.count(slapparameter_dict['tcpv4-port']).next -%}
52 53 54 55 56 57 58 59 60 61 62
{% for family_name, parameter_id_list in sorted(
  slapparameter_dict['zope-family-dict'].iteritems()) -%}
{%   set zope_family_address_list = [] -%}
{%   set has_webdav = [] -%}
{%   for parameter_id in parameter_id_list -%}
{%     set zope_address_list = slapparameter_dict[parameter_id] -%}
{%     for zope_address, maxconn, webdav in zope_address_list -%}
{%       if webdav -%}
{%         do has_webdav.append(None) %}
{%       endif -%}
{%       if use_ipv6 -%}
63 64
{%         set current_port = next_port() -%}
[{{ section('zope-tunnel-' ~ current_port) }}]
65
< = zope-tunnel-base
66 67
base-name = {{ 'zeo-tunnel-' ~ current_port }}
ipv4-port = {{ current_port }}
68 69
ipv6-port = {{ zope_address.split(']:')[1] }}
ipv6 = {{ zope_address.split(']:')[0][1:] }}
70
{%         set zope_effective_address = ipv4 ~ ":" ~ current_port -%}
71 72 73 74 75 76 77 78 79 80 81 82 83
{%       else -%}
{%         set zope_effective_address = zope_address -%}
{%       endif -%}
{%       do zope_family_address_list.append((zope_effective_address, maxconn, webdav)) -%}
{%     endfor -%}
{%   endfor -%}
{# Make rendering fail artificially if any family has no known backend.
 # This is useful as haproxy's hot-reconfiguration mechanism is
 # supervisord-incompatible.
 # As jinja2 postpones KeyError until place-holder value is actually used,
 # do a no-op getitem.
-#}
{%   do zope_family_address_list[0][0] -%}
84
{%   set haproxy_port = next_port() -%}
85 86 87 88 89 90 91 92
{%   do haproxy_dict.__setitem__(family_name, (haproxy_port, zope_family_address_list)) -%}
{%   if has_webdav -%}
{%     set internal_scheme = 'http' -%}{# mod_rewrite does not recognise webdav scheme -#}
{%     set external_scheme = 'webdavs' -%}
{%   else %}
{%     set internal_scheme = 'http' -%}
{%     set external_scheme = 'https' -%}
{%   endif -%}
93 94
{%   set backend_path = slapparameter_dict['backend-path-dict'][family_name] -%}
{%   set ssl_authentication = slapparameter_dict['ssl-authentication-dict'][family_name] -%}
95
{%   do apache_dict.__setitem__(family_name, (next_port(), external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ backend_path, ssl_authentication)) -%}
96 97 98 99 100 101 102 103 104
{% endfor -%}

[haproxy-cfg-parameter-dict]
socket-path = ${directory:run}/haproxy.sock
server-check-path = {{ dumps(slapparameter_dict['haproxy-server-check-path']) }}
backend-dict = {{ dumps(haproxy_dict) }}
ip = {{ ipv4 }}

[haproxy-cfg]
105
< = jinja2-template-base
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
template = {{ parameter_dict['template-haproxy-cfg'] }}
rendered = ${directory:etc}/haproxy.cfg
context = section parameter_dict haproxy-cfg-parameter-dict
extensions = jinja2.ext.do

[{{ section('haproxy') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/haproxy
command-line = "{{ parameter_dict['haproxy'] }}/sbin/haproxy" -f "${haproxy-cfg:rendered}"

{# TODO: build socat and wrap it as "${directory:bin}/haproxy-ctl" to connect to "${haproxy-cfg-parameter-dict:socket-path}" #}

[apache-conf-ssl]
cert = ${directory:apache-conf}/apache.crt
key = ${directory:apache-conf}/apache.pem
ca-cert =  ${directory:apache-conf}/ca.crt
crl = ${directory:apache-conf}/crl.pem

[apache-conf-parameter-dict]
125
backend-list = {{ dumps(apache_dict.values()) }}
126 127 128 129
ip-list = {{ dumps(apache_ip_list) }}
pid-file = ${directory:run}/apache.pid
error-log = ${directory:log}/apache-error.log
access-log = ${directory:log}/apache-access.log
130
log-dir = ${directory:log} 
131 132 133 134 135 136 137 138 139 140
# Apache 2.4's default value (60 seconds) can be a bit too short
timeout = 300
# Basic SSL server configuration
cert = ${apache-ssl:cert}
key = ${apache-ssl:key}
cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache
# Client x509 auth
ca-cert = ${apache-ssl-client:cert}
crl = ${apache-ssl-client:crl}
141 142 143 144 145 146

{% if shared_ca_path -%}
shared-ca-cert = {{ shared_ca_path }}/cacert.pem 
shared-crl = {{ shared_ca_path }}/crl
{%- endif %}

147

148 149

[apache-conf]
150
< = jinja2-template-base
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
template = {{ parameter_dict['template-apache-conf'] }}
rendered = ${directory:apache-conf}/apache.conf
context = section parameter_dict apache-conf-parameter-dict

[{{ section('apache') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/apache
command-line = "{{ parameter_dict['apache'] }}/bin/httpd" -f "${apache-conf:rendered}" -DFOREGROUND

[{{ section('apache-promise') }}]
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
recipe = slapos.cookbook:check_port_listening
path = ${directory:promise}/apache
hostname = {{ ipv4 }}
port = {{ apache_dict.values()[0][0] }}

[publish]
recipe = slapos.cookbook:publish.serialised
169
{% for family_name, (apache_port, scheme, _, _) in apache_dict.items() -%}
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
{{   family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
{{   family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
{% endfor -%}

[apache-ssl]
{% if ssl_parameter_dict.get('key') -%}
key = ${apache-ssl-key:rendered}
cert = ${apache-ssl-cert:rendered}
{{ simplefile('apache-ssl-key', '${apache-conf-ssl:key}', ssl_parameter_dict['key']) }}
{{ simplefile('apache-ssl-cert', '${apache-conf-ssl:cert}', ssl_parameter_dict['cert']) }}
{% else %}
recipe = plone.recipe.command
command = "{{ parameter_dict['openssl'] }}/bin/openssl" req -newkey rsa -batch -new -x509 -days 3650 -nodes -keyout "${:key}" -out "${:cert}"
key = ${apache-conf-ssl:key}
cert = ${apache-conf-ssl:cert}
{%- endif %}

[apache-ssl-client]
{% if ssl_parameter_dict.get('ca-cert') -%}
cert = ${apache-ssl-ca:rendered}
crl = ${apache-ssl-crl:rendered}
{{ simplefile('apache-ssl-ca', '${apache-conf-ssl:ca-cert}', ssl_parameter_dict['ca-cert']) }}
{{ simplefile('apache-ssl-crl', '${apache-conf-ssl:crl}', ssl_parameter_dict['crl']) }}
{% else %}
cert =
crl =
{%- endif %}

198 199 200 201 202 203 204 205

{% set apache_service_log_list = {} -%}
{% for family_name, (_, _, _, authentication) in apache_dict.items() -%}
{%   if authentication -%}
{%     set base_name = 'apache-' ~ family_name -%}
{%     do part_list.append('logrotate-' ~ base_name) -%}
{%     do apache_service_log_list.__setitem__(family_name, base_name) -%}
[logrotate-{{ base_name }}]
206
 < = logrotate-entry-base
207 208
name = {{ base_name }}
log = ${apache-conf-parameter-dict:log-dir}/{{ base_name }}-error.log ${apache-conf-parameter-dict:log-dir}/{{ base_name }}-access.log
209
post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1
210 211 212
{%   endif -%}
{% endfor -%}

213
[logrotate-apache]
214
< = logrotate-entry-base
215 216
name = apache
log = ${apache-conf-parameter-dict:error-log} ${apache-conf-parameter-dict:access-log}
217
post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

[directory]
recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc
promise = ${directory:etc}/promise
services = ${:etc}/run
var = ${buildout:directory}/var
run = ${:var}/run
log = ${:var}/log
ca-dir = ${buildout:directory}/srv/ssl
requests = ${:ca-dir}/requests
private = ${:ca-dir}/private
certs = ${:ca-dir}/certs
newcerts = ${:ca-dir}/newcerts
crl = ${:ca-dir}/crl

[monitor-instance-parameter]
monitor-httpd-ipv6 = {{ (ipv6_set | list)[0] }}
238
monitor-httpd-port = {{ next_port() }}
239 240 241 242 243 244 245 246 247 248
monitor-title = Balancer monitor

[buildout]
extends =
  {{ logrotate_cfg }}
  {{ parameter_dict['template-monitor'] }}
parts +=
  publish
  logrotate-apache
  {{ part_list | join('\n  ') }}