wip
This commit is contained in:
parent
13e4ea67c9
commit
a15bdfa95f
7 changed files with 126 additions and 174 deletions
|
@ -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/*;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
server {
|
|
||||||
listen 127.0.0.1:22999 default_server;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
stub_status;
|
|
||||||
}
|
|
|
@ -18,26 +18,11 @@ directories = {
|
||||||
|
|
||||||
files = {
|
files = {
|
||||||
'/etc/nginx/nginx.conf': {
|
'/etc/nginx/nginx.conf': {
|
||||||
'content_type': 'mako',
|
'content': repo.libs.nginx.render_config(node.metadata.get('nginx/config')),
|
||||||
'context': {
|
|
||||||
'username': 'www-data',
|
|
||||||
**node.metadata['nginx'],
|
|
||||||
},
|
|
||||||
'triggers': {
|
'triggers': {
|
||||||
'svc_systemd:nginx:restart',
|
'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': {
|
'/etc/nginx/fastcgi.conf': {
|
||||||
'triggers': {
|
'triggers': {
|
||||||
'svc_systemd:nginx:restart',
|
'svc_systemd:nginx:restart',
|
||||||
|
@ -61,18 +46,15 @@ svc_systemd = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for vhost, config in node.metadata.get('nginx/vhosts', {}).items():
|
for name, config in {
|
||||||
files[f'/etc/nginx/sites/{vhost}'] = {
|
**node.metadata.get('nginx/default_vhosts'),
|
||||||
'source': 'site_template',
|
**node.metadata.get('nginx/vhosts'),
|
||||||
'content_type': 'mako',
|
}.items():
|
||||||
'context': {
|
files[f'/etc/nginx/sites/{name}'] = {
|
||||||
'create_access_log': config.get('access_log', node.metadata.get('nginx/access_log', False)),
|
'content': repo.libs.nginx.render_config({
|
||||||
'php_version': node.metadata.get('php/version', ''),
|
'server': config,
|
||||||
'vhost': vhost,
|
}),
|
||||||
'nameservers': node.metadata.get('nameservers'),
|
'needs': [],
|
||||||
**config,
|
|
||||||
},
|
|
||||||
'needs': set(),
|
|
||||||
'needed_by': {
|
'needed_by': {
|
||||||
'svc_systemd:nginx',
|
'svc_systemd:nginx',
|
||||||
'svc_systemd:nginx:restart',
|
'svc_systemd:nginx:restart',
|
||||||
|
@ -81,47 +63,8 @@ for vhost, config in node.metadata.get('nginx/vhosts', {}).items():
|
||||||
'svc_systemd:nginx:restart',
|
'svc_systemd:nginx:restart',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if not 'webroot' in config:
|
if name in node.metadata.get('letsencrypt/domains'):
|
||||||
directories[f'/var/www/{vhost}'] = {}
|
files[f'/etc/nginx/sites/{name}']['needs'].append(
|
||||||
|
f'action:letsencrypt_ensure-some-certificate_{name}',
|
||||||
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')
|
|
||||||
|
|
|
@ -7,63 +7,101 @@ defaults = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'nginx': {
|
'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(
|
@metadata_reactor.provides(
|
||||||
'dns',
|
'dns',
|
||||||
)
|
)
|
||||||
def dns(metadata):
|
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 {
|
return {
|
||||||
'dns': dns,
|
'dns': {
|
||||||
|
domain: repo.libs.dns.get_a_records(metadata)
|
||||||
|
for domain in metadata.get('nginx/vhosts')
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'letsencrypt/domains',
|
'letsencrypt/domains',
|
||||||
'letsencrypt/reload_after',
|
'letsencrypt/reload_after',
|
||||||
'nginx/vhosts',
|
|
||||||
)
|
)
|
||||||
def letsencrypt(metadata):
|
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 {
|
return {
|
||||||
'letsencrypt': {
|
'letsencrypt': {
|
||||||
'domains': domains,
|
'domains': {
|
||||||
|
domain: {} for domain in metadata.get('nginx/vhosts')
|
||||||
|
},
|
||||||
'reload_after': {
|
'reload_after': {
|
||||||
'nginx',
|
'nginx',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'nginx': {
|
|
||||||
'vhosts': vhosts,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,6 @@ defaults = {
|
||||||
'php-zip': {},
|
'php-zip': {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'nginx': {
|
|
||||||
'vhosts': {
|
|
||||||
'roundcube': {
|
|
||||||
'webroot': '/opt/roundcube',
|
|
||||||
'php': True,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'roundcube': {
|
'roundcube': {
|
||||||
'database': {
|
'database': {
|
||||||
'provider': 'pgsql',
|
'provider': 'pgsql',
|
||||||
|
@ -57,14 +49,19 @@ defaults = {
|
||||||
}
|
}
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'nginx/vhosts/roundcube/domain'
|
'nginx/vhosts'
|
||||||
)
|
)
|
||||||
def domain(metadata):
|
def vhost(metadata):
|
||||||
return {
|
return {
|
||||||
'nginx': {
|
'nginx': {
|
||||||
'vhosts': {
|
'vhosts': {
|
||||||
'roundcube': {
|
metadata.get('mailserver/hostname'): {
|
||||||
'domain': 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
27
libs/nginx.py
Normal 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
|
||||||
|
]
|
Loading…
Reference in a new issue