{% 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) -%} {% set ca_path = slapparameter_dict['certificate-authority-path'] -%} {# 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 -%} {% set monitor = slapparameter_dict['monitor'] -%} {% if monitor -%} {% set monitor_port = slapparameter_dict['monitor-port'] %} {% endif -%} {% 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 = {} -%} {% set next_port = slapparameter_dict['tcpv4-port'] -%} {% for family_name, parameter_id_list in slapparameter_dict['zope-family-dict'].items() -%} {% 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 -%} [{{ section('zope-tunnel-' ~ next_port) }}] < = zope-tunnel-base base-name = {{ 'zeo-tunnel-' ~ next_port }} ipv4-port = {{ next_port }} ipv6-port = {{ zope_address.split(']:')[1] }} ipv6 = {{ zope_address.split(']:')[0][1:] }} {% set zope_effective_address = ipv4 ~ ":" ~ next_port -%} {% set next_port = next_port + 1 -%} {% 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] -%} {% set haproxy_port = next_port -%} {% set next_port = next_port + 1 -%} {% 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 -%} {% set backend_path = slapparameter_dict['backend-path-dict'][family_name] -%} {% set ssl_authentication = slapparameter_dict['ssl-authentication-dict'][family_name] -%} {% do apache_dict.__setitem__(family_name, (next_port, external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ backend_path, ssl_authentication)) -%} {% set next_port = next_port + 1 -%} {% 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] recipe = slapos.recipe.template:jinja2 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] backend-list = {{ dumps(apache_dict) }} 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 log-dir = ${directory:log} # 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 {% if ssl_parameter_dict.get('ca-cert') and ssl_parameter_dict.get('ca-crl') -%} ca-cert = {{ dumps(ssl_parameter_dict.get('ca-cert')) }} crl = {{ dumps(ssl_parameter_dict.get('ca-crl')) }} {% else -%} ca-cert = {{ ca_path }}/cacert.pem crl = {{ ca_path }}/crl {% endif -%} [apache-conf] recipe = slapos.recipe.template:jinja2 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 {% for family_name, (apache_port, scheme, _, _) in apache_dict.items() -%} {{ family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %} {{ family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }} {% endfor -%} {% if monitor -%} monitor-url = ${monitor-parameters:url} {% endif -%} [apache-ssl] 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} {% 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 }}] recipe = slapos.cookbook:logrotate.d logrotate-entries = ${logrotate:logrotate-entries} backup = ${logrotate:backup} name = {{ base_name }} log = ${apache-conf-parameter-dict:log-dir}/{{ base_name }}-error.log ${apache-conf-parameter-dict:log-dir}/{{ base_name }}-access.log post = {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1 {% endif -%} {% endfor -%} [logrotate-apache] recipe = slapos.cookbook:logrotate.d logrotate-entries = ${logrotate:logrotate-entries} backup = ${logrotate:backup} name = apache log = ${apache-conf-parameter-dict:error-log} ${apache-conf-parameter-dict:access-log} post = {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1 {% if monitor -%} [{{ section('monitor-current-log-access') }}] < = monitor-directory-access source = ${directory:log} [{{ section('monitor-backup-log-access') }}] < = monitor-directory-access source = ${logrotate:backup} [{{ section('monitor-apachedex-access') }}] < = monitor-directory-access source = ${monitor-directory:apachedex-result} [monitor-parameters] port = {{ slapparameter_dict['monitor-port'] }} [log-folder-cgi] log-folder = ${directory:log} [apachedex-erp5-entries] <= apachedex-entries-base script-name = apachedex-erp5 extra-context = section parameter_dict apachedex-erp5-parameters key name :script-name # XXX - Hard coded values for slapos and vifib. [apachedex-erp5-parameters] default_parameter = apache-log-list = ${logrotate:backup}/apache-access.log-%(date)s.gz base-list = +slapos.vifib.com /VirtualHostBase/https/slapos\.vifib\.com:443/erp5/web_site_module/commercial/VirtualHostRoot(/|$|\?) +www.slapos.org /VirtualHostBase/https/www\.slapos\.org:443/erp5/web_site_module/hosting/VirtualHostRoot(/|$|\?) erp5-base-list = +vifib.erp5.net /VirtualHostBase/https/vifib\.erp5\.net:443/erp5/VirtualHostRoot(/|$|\?) skip-base-list = [{{ section('cron-entry-apachedex-erp5') }}] <= cron recipe = slapos.cookbook:cron.d name = ${apachedex-erp5-entries:script-name} frequency = 0 3 * * * command = ${apachedex-erp5-entries:rendered} {% for family_name, log_name in apache_service_log_list.items() -%} [apachedex-{{ family_name }}-entries] <= apachedex-entries-base script-name = apachedex-{{ family_name }} extra-context = section parameter_dict apachedex-{{ family_name }}-parameters key name :script-name [apachedex-{{ family_name }}-parameters] default_parameter = zope-{{ family_name }} apache-log-list = ${logrotate:backup}/{{ log_name }}-access.log-%(date)s.gz base-list = erp5-base-list = skip-base-list = [{{ section('cron-entry-apachedex-' ~ family_name) }}] <= cron recipe = slapos.cookbook:cron.d name = apachedex-{{ family_name }} frequency = 0 3 * * * command = ${apachedex-{{ family_name }}-entries:rendered} {% endfor -%} {% endif -%} [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 [buildout] extends = {{ logrotate_cfg }} {% if monitor -%} # Extends template for monitor {{ parameter_dict['template-monitor'] }} {% endif -%} parts += publish logrotate-apache {% if monitor -%} # Access to zope logs certificate-authority cron-entry-monitor cron-entry-rss deploy-index deploy-logfile-cgi deploy-ressource-monitoring-cgi setup-static-files public-symlink cgi-httpd-wrapper cgi-httpd-graceful-wrapper monitor-promise monitor-instance-log-access {% endif -%} # Complete parts with sections {{ part_list | join('\n ') }}