1
0
Fork 0
scripts/sysadmin/nginx-new-site.py

160 lines
4.9 KiB
Python

#!/usr/bin/python3
from pathlib import Path
from nginx.config.api import (Section, Location, EmptyBlock, Comment,
KeyValueOption, Block)
from nginx.config.helpers import duplicate_options
PROXY_OPTIONS = [
["Host", "$http_host"],
["X-Real-IP", "$remote_addr"],
["X-Forwarded-For", "$proxy_add_x_forwarded_for"],
["X-Forwarded-Host", "$host,443"],
["X-Forwarded-Server", "$host"],
["X-Forwarded-Proto", "$scheme"],
["X-Forwarded-Uri", "$request_uri"],
["X-Forwarded-Ssl", "on"],
["X-Real-IP", "$remote_addr"]
]
FPM_OPTIONS = [
["HTTPS", "on"],
["PATH_INFO", "$path_info"],
["SCRIPT_FILENAME", "$document_root$fastcgi_script_name"],
["modHeadersAvailable", "true"],
["front_controller_active", "true"]
]
PROXY_WEBSOCKETS_OPTIONS = [
["Upgrade", "$http_upgrade"],
["Connection", "Upgrade"]
]
class NginxSiteBuilder:
def __init__(self, domain, site_number=0, root="/srv/www/htdocs",
authelia=True):
self._filename = f"{site_number:02d}-{domain}.conf"
self._domain = domain
self._add_base_template(authelia)
self.add_logging()
def __str__(self):
return str(self._config)
__repr__ = __str__
def _add_base_template(self, authelia=True):
server = Section(
"server",
duplicate_options("listen", [["443 ssl http2"],
["[::]:443 ssl http2"]]),
server_name=self.domain,
server_tokens="off"
)
blocks = [["common_ssl.conf"]]
if authelia:
blocks.append(["authelia.conf"])
includes = duplicate_options("include", blocks)
server.sections.add(includes)
self._config = server
@property
def filename(self):
return self._filename
@property
def domain(self):
return self._domain
@property
def config(self):
return self._config
def write(self, path: Path):
destination = path / self.filename
with destination.open("w") as handle:
handle.write(str(self._config))
def add_upstream(self, name="server", host="127.0.0.1", port=5555):
upstream = Block(f"upstream %{name}", server=f"{host}:{port}")
upstream.sections.add(self._config)
self._config = upstream
def add_logging(self, suffix="nginx"):
if isinstance(self.domain, list):
domain = self.domain[0].replace(".", "_")
else:
domain = domain.replace(".", "_")
syslog = f"syslog:server=unix:/dev/log,tag={domain}_{suffix},"
access = syslog + "severity=info,nohostname"
error = syslog + "severity=error,nohostname"
logs = EmptyBlock(
access_log=access,
error_log=error)
self._config.sections.add(logs)
def add_proxied_location(self, location="/", address="127.0.0.1",
port=8443, websocket=True, auth=True):
location = Location(location,
proxy_pass=f"http://{address}:{port}",
gzip="off")
if auth:
location.sections.add(KeyValueOption("include", "auth.conf"))
proxy_options = duplicate_options(
"proxy_set_header",
PROXY_OPTIONS
)
if websocket:
comment = Comment(comment="Websockets")
proxy_options.sections.add(comment)
http_version = EmptyBlock(proxy_http_version="1.1")
websocket_cfg = duplicate_options(
"proxy_set_header",
PROXY_WEBSOCKETS_OPTIONS
)
http_version.sections.add(websocket_cfg)
proxy_options.sections.add(http_version)
location.sections.add(proxy_options)
self._config.sections.add(location)
def add_php_try_files(self, location="/"):
location = Location(location,
try_files=["$uri", "$uri/",
f"{location}index.php?$query_string"])
self._config.sections.add(location)
def add_php_block(self):
location = Location(r"~ ^(?<script_name>.+?\.php)(?<path_info>/.*)?$",
try_files="$script_name = 404",
include="fastcgi_params",
fastcgi_pass="unix:/run/php-fpm/php-fpm.sock",
fastcgi_hide_header="X-Powered-By")
location.sections.add(duplicate_options("fastcgi_param", FPM_OPTIONS))
self._config.sections.add(location)
def add_uwsgi_location(self, location="/", socket=None, auth=False):
location = Location(location, uwsgi_pass=socket,
include="uwsgi_params")
if auth:
location.sections.add(KeyValueOption("include", "auth.conf"))
self._config.sections.add(location)