from bundlewrap.metadata import atomic defaults = { 'apt': { 'repos': { 'nginx': { 'items': { 'deb http://nginx.org/packages/{os} {os_release} nginx', }, }, }, 'packages': { 'nginx': {}, }, }, 'backups': { 'paths': { '/var/www', }, }, 'icinga2_api': { 'nginx': { 'services': { 'NGINX PROCESS': { 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit nginx', }, 'NGINX STATUS': { 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_nginx_status', }, }, }, }, 'nginx': { 'worker_connections': 768, }, 'pacman': { 'packages': { 'nginx': {}, }, }, } if node.has_bundle('telegraf'): defaults['telegraf'] = { 'input_plugins': { 'builtin': { 'nginx': [{ 'urls': ['http://localhost:22999/server_status'], }], }, }, } @metadata_reactor.provides( 'nginx/worker_processes', ) def worker_processes(metadata): return { 'nginx': { 'worker_processes': metadata.get('vm/cpu', 2), }, } @metadata_reactor.provides( 'letsencrypt/domains', 'letsencrypt/reload_after', 'nginx/vhosts', ) def letsencrypt(metadata): if not node.has_bundle('letsencrypt'): raise DoNotRunAgain domains = {} vhosts = {} for vhost, config in metadata.get('nginx/vhosts', {}).items(): if config.get('ssl', 'letsencrypt') == 'letsencrypt': domain = config.get('domain', vhost) domains[domain] = config.get('domain_aliases', set()) vhosts[vhost] = { 'ssl': 'letsencrypt', 'force_domain': True, } return { 'letsencrypt': { 'domains': domains, 'reload_after': { 'nginx', }, }, 'nginx': { 'vhosts': vhosts, }, } @metadata_reactor.provides( 'nginx/vhosts', ) def index_files(metadata): vhosts = {} for vhost, config in metadata.get('nginx/vhosts', {}).items(): if 'index' in config: continue vhosts[vhost] = { 'index': [ 'index.html', 'index.htm', ], } if config.get('php', False): # If we're using PHP, make sure index.php is tried first vhosts[vhost]['index'].insert(0, 'index.php') return { 'nginx': { 'vhosts': vhosts, }, } @metadata_reactor.provides( 'icinga2_api/nginx/services', ) def monitoring(metadata): services = {} for vname, vconfig in metadata.get('nginx/vhosts', {}).items(): domain = vconfig.get('domain', vname) if vconfig['ssl']: scheme = 'https' else: scheme = 'http' if 'website_check_path' in vconfig and 'website_check_string' in vconfig: services['NGINX VHOST {} CONTENT'.format(vname)] = { 'check_command': 'check_http_wget', 'vars.http_wget_contains': vconfig['website_check_string'], 'vars.http_wget_url': '{}://{}{}'.format(scheme, domain, vconfig['website_check_path']), 'vars.notification.sms': True, } if vconfig.get('check_ssl', vconfig['ssl']): services['NGINX VHOST {} CERTIFICATE: {}'.format(vname, vconfig['ssl'])] = { 'check_command': 'check_https_cert_at_url', 'vars.domain': domain, 'vars.notification.mail': True, } max_connections = metadata.get('nginx/worker_connections') * metadata.get('nginx/worker_processes') connections_warn = int(max_connections * 0.8) connections_crit = int(max_connections * 0.9) services['NGINX STATUS'] = { 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_nginx_status --warn={},-1,-1 --critical={},-1,-1 -H 127.0.0.1:22999'.format(connections_warn, connections_crit), } return { 'icinga2_api': { 'nginx': { 'services': services, }, }, } @metadata_reactor.provides( 'firewall/port_rules', 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { '80/tcp': atomic(metadata.get('nginx/restrict-to', {'*'})), '443/tcp': atomic(metadata.get('nginx/restrict-to', {'*'})), }, }, } @metadata_reactor.provides( 'telegraf/input_plugins/tail', ) def telegraf_anon_timing(metadata): result = {} for vname, vconfig in metadata.get('nginx/vhosts', {}).items(): if not vconfig.get('timing_log', True): continue result[f'nginx-{vname}'] = { 'files': [f'/var/log/nginx-timing/{vname}.log'], 'from_beginning': False, 'grok_patterns': ['%{LOGPATTERN}'], 'grok_custom_patterns': 'LOGPATTERN \[%{HTTPDATE:ts:ts-httpd}\] %{NUMBER:request_time:float} (?:%{NUMBER:upstream_response_time:float}|-) "%{WORD:verb:tag} %{NOTSPACE:request} HTTP/%{NUMBER:http_version:float}" %{NUMBER:resp_code:tag}', 'data_format': 'grok', 'name_override': 'nginx_timing', } return { 'telegraf': { 'input_plugins': { 'tail': result, }, }, }