This commit is contained in:
mwiegand 2021-07-05 22:42:42 +02:00
parent 13e4ea67c9
commit a15bdfa95f
7 changed files with 126 additions and 174 deletions

View file

@ -1,34 +0,0 @@
user www-data;
worker_processes 10;
pid /var/run/nginx.pid;
events {
worker_connections 500;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset UTF-8;
override_charset on;
sendfile on;
#tcp_nopush on;
keepalive_timeout 15;
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 1M;
large_client_header_buffers 2 1k;
include /etc/nginx/sites/*;
}

View file

@ -1,13 +0,0 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location /.well-known/acme-challenge/ {
alias /var/lib/dehydrated/acme-challenges/;
}
location / {
return 404;
}
}

View file

@ -1,6 +0,0 @@
server {
listen 127.0.0.1:22999 default_server;
server_name _;
stub_status;
}

View file

@ -18,26 +18,11 @@ directories = {
files = {
'/etc/nginx/nginx.conf': {
'content_type': 'mako',
'context': {
'username': 'www-data',
**node.metadata['nginx'],
},
'content': repo.libs.nginx.render_config(node.metadata.get('nginx/config')),
'triggers': {
'svc_systemd:nginx:restart',
},
},
'/etc/nginx/sites/stub_status': {
'triggers': {
'svc_systemd:nginx:restart',
},
},
'/etc/nginx/sites/000-port80.conf': {
'source': 'port80.conf',
'triggers': {
'svc_systemd:nginx:restart',
},
},
'/etc/nginx/fastcgi.conf': {
'triggers': {
'svc_systemd:nginx:restart',
@ -61,18 +46,15 @@ svc_systemd = {
},
}
for vhost, config in node.metadata.get('nginx/vhosts', {}).items():
files[f'/etc/nginx/sites/{vhost}'] = {
'source': 'site_template',
'content_type': 'mako',
'context': {
'create_access_log': config.get('access_log', node.metadata.get('nginx/access_log', False)),
'php_version': node.metadata.get('php/version', ''),
'vhost': vhost,
'nameservers': node.metadata.get('nameservers'),
**config,
},
'needs': set(),
for name, config in {
**node.metadata.get('nginx/default_vhosts'),
**node.metadata.get('nginx/vhosts'),
}.items():
files[f'/etc/nginx/sites/{name}'] = {
'content': repo.libs.nginx.render_config({
'server': config,
}),
'needs': [],
'needed_by': {
'svc_systemd:nginx',
'svc_systemd:nginx:restart',
@ -81,47 +63,8 @@ for vhost, config in node.metadata.get('nginx/vhosts', {}).items():
'svc_systemd:nginx:restart',
},
}
if not 'webroot' in config:
directories[f'/var/www/{vhost}'] = {}
if node.has_bundle('zfs'):
directories[f'/var/www/{vhost}']['needs'] = {
'bundle:zfs',
}
directories[f'/var/www/{vhost}'].update(config.get('webroot_config', {}))
if config.get('ssl', 'letsencrypt') == 'letsencrypt':
files[f'/etc/nginx/sites/{vhost}']['needs'].add('action:letsencrypt_ensure-some-certificate_{}'.format(config['domain']))
files[f'/etc/nginx/sites/{vhost}']['needed_by'].add('action:letsencrypt_update_certificates')
elif config.get('ssl', 'letsencrypt'):
files[f'/etc/nginx/ssl/{vhost}.crt'] = {
'content_type': 'mako',
'source': 'ssl_template',
'context': {
'domain': config['ssl'],
},
'needed_by': {
'svc_systemd:nginx',
'svc_systemd:nginx:restart',
},
'triggers': {
'svc_systemd:nginx:reload',
},
}
files[f'/etc/nginx/ssl/{vhost}.key'] = {
'content': repo.vault.decrypt_file('ssl/{}.key.pem.vault'.format(config['ssl'])),
'mode': '0600',
'needed_by': {
'svc_systemd:nginx',
'svc_systemd:nginx:restart',
},
'triggers': {
'svc_systemd:nginx:reload',
},
}
files[f'/etc/nginx/sites/{vhost}']['needs'].add(f'file:/etc/nginx/ssl/{vhost}.crt')
files[f'/etc/nginx/sites/{vhost}']['needs'].add(f'file:/etc/nginx/ssl/{vhost}.key')
if name in node.metadata.get('letsencrypt/domains'):
files[f'/etc/nginx/sites/{name}']['needs'].append(
f'action:letsencrypt_ensure-some-certificate_{name}',
)

View file

@ -7,63 +7,101 @@ defaults = {
},
},
'nginx': {
'worker_connections': 768,
'config': {
'user': 'www-data',
'worker_processes': 10,
'pid': '/var/run/nginx.pid',
'events': {
'worker_connections': 768,
},
'http': {
'include': [
'/etc/nginx/mime.types',
'/etc/nginx/sites/*',
],
'default_type': 'application/octet-stream',
'sendfile': 'on',
'tcp_nopush': 'on',
'server_names_hash_bucket_size': 128,
'access_log': '/var/log/nginx/access.log',
'error_log': '/var/log/nginx/error.log',
},
},
'default_vhosts': {
'80': {
'listen': [
'80',
'[::]:80',
],
'location /.well-known/acme-challenge/': {
'alias': '/var/lib/dehydrated/acme-challenges/',
},
'location /': {
'return': '301 https://$host$request_uri',
},
},
'stub_status': {
'listen': '127.0.0.1:22999 default_server',
'server_name': '_',
'stub_status': '',
},
},
'vhosts': {},
},
}
@metadata_reactor.provides(
'nginx/vhosts',
)
def vhosts(metadata):
vhosts = {}
for name, config in metadata.get('nginx/vhosts').items():
vhosts[name] = {
'server_name': name,
'listen': [
'443 ssl http2',
'[::]:443 ssl http2',
],
'ssl_certificate': f'/var/lib/dehydrated/certs/{name}/fullchain.pem',
'ssl_certificate_key': f'/var/lib/dehydrated/certs/{name}/privkey.pem',
'location /.well-known/acme-challenge/': {
'alias': '/var/lib/dehydrated/acme-challenges/',
},
}
return {
'nginx': {
'vhosts': vhosts,
}
}
@metadata_reactor.provides(
'dns',
)
def dns(metadata):
dns = {}
for config in metadata.get('nginx/vhosts', {}).values():
dns[config['domain']] = {
'A': [
str(ip_interface(network['ipv4']).ip)
for network in metadata.get('network').values()
if 'ipv4' in network
],
'AAAA': [
str(ip_interface(network['ipv6']).ip)
for network in metadata.get('network').values()
if 'ipv6' in network
],
}
return {
'dns': dns,
'dns': {
domain: repo.libs.dns.get_a_records(metadata)
for domain in metadata.get('nginx/vhosts')
},
}
@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',
}
return {
'letsencrypt': {
'domains': domains,
'domains': {
domain: {} for domain in metadata.get('nginx/vhosts')
},
'reload_after': {
'nginx',
},
},
'nginx': {
'vhosts': vhosts,
},
}

View file

@ -20,14 +20,6 @@ defaults = {
'php-zip': {},
},
},
'nginx': {
'vhosts': {
'roundcube': {
'webroot': '/opt/roundcube',
'php': True,
},
},
},
'roundcube': {
'database': {
'provider': 'pgsql',
@ -57,14 +49,19 @@ defaults = {
}
@metadata_reactor.provides(
'nginx/vhosts/roundcube/domain'
'nginx/vhosts'
)
def domain(metadata):
def vhost(metadata):
return {
'nginx': {
'vhosts': {
'roundcube': {
'domain': metadata.get('mailserver/hostname'),
metadata.get('mailserver/hostname'): {
'root': '/opt/roundcube',
'location ~ \.php$': {
'include': 'fastcgi.conf',
'fastcgi_split_path_info': '^(.+\.php)(/.+)$',
'fastcgi_pass': f"unix:/run/php/php{metadata.get('php/version')}-fpm.sock",
},
},
},
},

27
libs/nginx.py Normal file
View file

@ -0,0 +1,27 @@
def render_config(config):
return '\n'.join(render_lines(config))
def render_lines(config, indent=0):
lines = []
blocks = []
for key, value in sorted(config.items()):
if isinstance(value, dict):
blocks.extend([
'',
key+' {',
*render_lines(value, indent=4),
'}',
])
elif isinstance(value, list):
lines.extend([
f'{key} {_value};' for _value in value
])
else:
lines.append(
f'{key} {value};'
)
return [
f"{' '*indent}{line}" for line in lines+blocks
]