[manage.py] Add NGINX
This commit is contained in:
parent
46ae023028
commit
52ac146067
22 changed files with 389 additions and 28 deletions
86
manage.py
86
manage.py
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import os, sys, re
|
||||
import os, sys, re, shutil
|
||||
import filecmp
|
||||
from glob import glob
|
||||
from mako.template import Template
|
||||
|
@ -115,6 +115,24 @@ def getUid(service):
|
|||
return env['podman_uid']
|
||||
|
||||
|
||||
def promptTargetProjects():
|
||||
projects = os.listdir("projects")
|
||||
print(f"\nProjects list: {projects}")
|
||||
if len(sys.argv) > 2:
|
||||
target_projects = sys.argv[2]
|
||||
else:
|
||||
target_projects = input("Target compose project(s), space separated, leave empty to target all: ")
|
||||
|
||||
if target_projects.strip() == '':
|
||||
target_projects = projects
|
||||
else:
|
||||
target_projects = re.split(' ?, ?| ', target_projects.strip())
|
||||
|
||||
print(f"Target projects: {target_projects}")
|
||||
|
||||
return target_projects
|
||||
|
||||
|
||||
def pullProj(project):
|
||||
print(f"Pulling images for project {project}.")
|
||||
|
||||
|
@ -138,16 +156,16 @@ def pullProj(project):
|
|||
return pulledImages
|
||||
|
||||
|
||||
def renderFile(templateFile):
|
||||
print(f"Rendering file {templateFile}.")
|
||||
def renderFile(templateFile, renderedFile=None):
|
||||
if renderedFile is None:
|
||||
renderedFile = re.sub('\\.mako$', '.rendered', templateFile)
|
||||
|
||||
renderedFilename = re.sub('\\.mako$', '.rendered', templateFile)
|
||||
print(f"Rendering file {templateFile} to {renderedFile}.")
|
||||
|
||||
template = Template(filename=templateFile)
|
||||
|
||||
outputFile = open(renderedFilename, "w")
|
||||
with open(renderedFile, "w") as outputFile:
|
||||
outputFile.write(template.render(env=env, secrets=secrets))
|
||||
outputFile.close()
|
||||
|
||||
|
||||
def runBorg(args, input=None):
|
||||
|
@ -192,11 +210,19 @@ def runSudo(args):
|
|||
|
||||
child = subprocess.Popen(["sudo"] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
|
||||
if re.search('^\\[sudo\\] password for .+', child.stdout.read().strip()):
|
||||
stdout = child.stdout.read().strip()
|
||||
if stdout != '':
|
||||
print(stdout)
|
||||
|
||||
if re.search('^\\[sudo\\] password for .+', stdout):
|
||||
child.communicate(input=input().encode())[0]
|
||||
|
||||
child.wait()
|
||||
|
||||
stdout = child.stdout.read().strip()
|
||||
if stdout != '':
|
||||
print(stdout)
|
||||
|
||||
stderr = child.stderr.read().strip()
|
||||
if stderr != '':
|
||||
print(stderr, file=sys.stderr)
|
||||
|
@ -259,6 +285,26 @@ def setPerms(path, mode):
|
|||
print(f"Permissions of {path} already set to {mode}.")
|
||||
|
||||
|
||||
def setupNGINX():
|
||||
if os.getuid() != 0:
|
||||
print("Current user is not root, rerunning program as root.")
|
||||
runSudo([sys.executable, sys.argv[0], "nginx"])
|
||||
return
|
||||
|
||||
for dir in ["sites-enabled", "snippets"]:
|
||||
print(f"Recreating directory /etc/nginx/{dir}")
|
||||
shutil.rmtree(f"/etc/nginx/{dir}")
|
||||
os.mkdir(f"/etc/nginx/{dir}")
|
||||
|
||||
for templateFile in glob("nginx/**/*.conf", recursive=True, include_hidden=True):
|
||||
renderFile(templateFile, "/etc/" + templateFile)
|
||||
|
||||
subprocess.run(["nginx", "-t"])
|
||||
|
||||
print("Reloading service nginx.")
|
||||
runSudo("systemctl reload nginx")
|
||||
|
||||
|
||||
def setupProj(project):
|
||||
print(f"Running setup for project {project}.")
|
||||
|
||||
|
@ -324,6 +370,7 @@ def main():
|
|||
env = yaml.safe_load(Template(filename=envFile).render())
|
||||
secrets = yaml.safe_load(secretsfile)
|
||||
|
||||
if os.getuid() != 0:
|
||||
setOwner(secretsFile, os.getuid(), os.getgid())
|
||||
setPerms(secretsFile, 600)
|
||||
|
||||
|
@ -338,28 +385,16 @@ def main():
|
|||
print("[1/S] Setup project")
|
||||
print("[2/U] Update project")
|
||||
print("[3/B] Backup project")
|
||||
print("[4/N] Setup NGINX")
|
||||
|
||||
while action == '':
|
||||
action = input("Action: ")
|
||||
|
||||
|
||||
projects = os.listdir("projects")
|
||||
print(f"\nProjects list: {projects}")
|
||||
if len(sys.argv) > 2:
|
||||
target_projects = sys.argv[2]
|
||||
else:
|
||||
target_projects = input("Target compose project(s), space separated, leave empty to target all: ")
|
||||
|
||||
if target_projects.strip() == '':
|
||||
target_projects = projects
|
||||
else:
|
||||
target_projects = re.split(' ?, ?| ', target_projects.strip())
|
||||
|
||||
print(f"Target projects: {target_projects}")
|
||||
|
||||
|
||||
match action.casefold():
|
||||
case '1' | 's' | 'setup':
|
||||
target_projects = promptTargetProjects()
|
||||
|
||||
setNftables()
|
||||
|
||||
for project in target_projects:
|
||||
|
@ -371,6 +406,8 @@ def main():
|
|||
print(f"Failed to setup project {project}.", file=sys.stderr)
|
||||
|
||||
case '2' | 'u' | 'update':
|
||||
target_projects = promptTargetProjects()
|
||||
|
||||
for project in target_projects:
|
||||
try:
|
||||
print()
|
||||
|
@ -380,6 +417,8 @@ def main():
|
|||
print(f"Failed to update project {project}.", file=sys.stderr)
|
||||
|
||||
case '3' | 'b' | 'backup':
|
||||
target_projects = promptTargetProjects()
|
||||
|
||||
print()
|
||||
if not os.path.exists(env['borg_repo']):
|
||||
print(f"Creating borg repository {env['borg_repo']}.")
|
||||
|
@ -397,6 +436,9 @@ def main():
|
|||
|
||||
runBorg(["compact", env['borg_repo']])
|
||||
|
||||
case '4' | 'n' | 'nginx':
|
||||
setupNGINX()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
38
nginx/nginx.conf
Normal file
38
nginx/nginx.conf
Normal file
|
@ -0,0 +1,38 @@
|
|||
user www-data;
|
||||
worker_processes auto;
|
||||
worker_rlimit_nofile 1024;
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 512;
|
||||
multi_accept off;
|
||||
}
|
||||
|
||||
http {
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
|
||||
gzip off;
|
||||
server_tokens off;
|
||||
keepalive_timeout 30;
|
||||
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
# Needed to support websocket connections
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' "";
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
include /etc/nginx/snippets/ssl.conf;
|
||||
include /etc/nginx/snippets/ssl-headers.conf;
|
||||
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
}
|
12
nginx/sites-enabled/clips.conf
Normal file
12
nginx/sites-enabled/clips.conf
Normal file
|
@ -0,0 +1,12 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name clips.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['fireshare']};
|
||||
|
||||
client_max_body_size 500M;
|
||||
}
|
||||
}
|
17
nginx/sites-enabled/default.conf
Normal file
17
nginx/sites-enabled/default.conf
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Redirect HTTP to HTTPS
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
return 308 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# Default HTTPS server
|
||||
server {
|
||||
listen 443 ssl default_server;
|
||||
listen [::]:443 ssl default_server;
|
||||
|
||||
http2 on;
|
||||
|
||||
return 404;
|
||||
}
|
9
nginx/sites-enabled/downloads.conf
Normal file
9
nginx/sites-enabled/downloads.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name dl.${env['domain']};
|
||||
|
||||
root /var/www/html;
|
||||
autoindex on;
|
||||
}
|
10
nginx/sites-enabled/etebase.conf
Normal file
10
nginx/sites-enabled/etebase.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name etebase.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['etebase']};
|
||||
}
|
||||
}
|
17
nginx/sites-enabled/hedgedoc.conf
Normal file
17
nginx/sites-enabled/hedgedoc.conf
Normal file
|
@ -0,0 +1,17 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name hedgedoc.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['hedgedoc']};
|
||||
}
|
||||
|
||||
location /socket.io/ {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['hedgedoc']};
|
||||
|
||||
include /etc/nginx/snippets/websocket.conf;
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
25
nginx/sites-enabled/homepage.conf
Normal file
25
nginx/sites-enabled/homepage.conf
Normal file
|
@ -0,0 +1,25 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name ${env['domain']};
|
||||
|
||||
location = /.well-known/matrix/server {
|
||||
default_type application/json;
|
||||
|
||||
return 200 '{ "m.server": "matrix.${env["domain"]}:443" }';
|
||||
}
|
||||
|
||||
location = /.well-known/matrix/client {
|
||||
default_type application/json;
|
||||
|
||||
include /etc/nginx/snippets/ssl-headers.conf;
|
||||
add_header Access-Control-Allow-Origin '*';
|
||||
|
||||
return 200 '{ "m.homeserver": { "base_url": "https://matrix.${env["domain"]}" } }';
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['homepage']};
|
||||
}
|
||||
}
|
13
nginx/sites-enabled/keycloak.conf
Normal file
13
nginx/sites-enabled/keycloak.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name kc.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass https://127.0.0.1:${env['ports']['keycloak']};
|
||||
|
||||
#include /etc/nginx/snippets/websocket.conf;
|
||||
#include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
43
nginx/sites-enabled/mail.conf
Normal file
43
nginx/sites-enabled/mail.conf
Normal file
|
@ -0,0 +1,43 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name mail.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass https://127.0.0.1:${env['ports']['mailserver_https']};
|
||||
|
||||
include /etc/nginx/snippets/websocket.conf;
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name autoconfig.${env['domain']};
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location = /mail/config-v1.1.xml {
|
||||
proxy_pass https://127.0.0.1:${env['ports']['mailserver_https']};
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name mta-sts.${env['domain']};
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location = /.well-known/mta-sts.txt {
|
||||
proxy_pass https://127.0.0.1:${env['ports']['mailserver_https']};
|
||||
}
|
||||
}
|
13
nginx/sites-enabled/searxng.conf
Normal file
13
nginx/sites-enabled/searxng.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name searx.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['searxng']};
|
||||
|
||||
include /etc/nginx/snippets/ssl-headers.conf;
|
||||
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self' https://github.com/searxng/searxng/issues/new; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self' https://overpass-api.de; img-src 'self' data: https://*.tile.openstreetmap.org; frame-src https://www.youtube-nocookie.com https://player.vimeo.com https://www.dailymotion.com https://www.deezer.com https://www.mixcloud.com https://w.soundcloud.com https://embed.spotify.com";
|
||||
}
|
||||
}
|
12
nginx/sites-enabled/sex.conf
Normal file
12
nginx/sites-enabled/sex.conf
Normal file
|
@ -0,0 +1,12 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name sex.${env['domain']};
|
||||
|
||||
root /var/www/sex;
|
||||
|
||||
location / {
|
||||
random_index on;
|
||||
}
|
||||
}
|
17
nginx/sites-enabled/stdiscosrv.conf
Normal file
17
nginx/sites-enabled/stdiscosrv.conf
Normal file
|
@ -0,0 +1,17 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name stdisco.${env['domain']};
|
||||
|
||||
ssl_verify_client optional_no_ca;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['syncthing_discosrv']};
|
||||
|
||||
proxy_set_header X-Client-Port $remote_port;
|
||||
proxy_set_header X-SSL-Cert $ssl_client_cert;
|
||||
include /etc/nginx/snippets/websocket.conf;
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
13
nginx/sites-enabled/stump.conf
Normal file
13
nginx/sites-enabled/stump.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name stump.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['stump']};
|
||||
|
||||
include /etc/nginx/snippets/websocket.conf;
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
12
nginx/sites-enabled/synapse.conf
Normal file
12
nginx/sites-enabled/synapse.conf
Normal file
|
@ -0,0 +1,12 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name matrix.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['synapse']};
|
||||
|
||||
client_max_body_size 50M;
|
||||
}
|
||||
}
|
13
nginx/sites-enabled/uptime.conf
Normal file
13
nginx/sites-enabled/uptime.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name status.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${env['ports']['uptime']};
|
||||
|
||||
include /etc/nginx/snippets/websocket.conf;
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
19
nginx/sites-enabled/vaultwarden.conf
Normal file
19
nginx/sites-enabled/vaultwarden.conf
Normal file
|
@ -0,0 +1,19 @@
|
|||
upstream vaultwarden {
|
||||
zone vaultwarden 64k;
|
||||
server 127.0.0.1:${env['ports']['vaultwarden']};
|
||||
keepalive 2;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name vw.${env['domain']};
|
||||
|
||||
location / {
|
||||
proxy_pass http://vaultwarden;
|
||||
|
||||
include /etc/nginx/snippets/websocket.conf;
|
||||
include /etc/nginx/snippets/proxy.conf;
|
||||
}
|
||||
}
|
10
nginx/snippets/proxy.conf
Normal file
10
nginx/snippets/proxy.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||
proxy_set_header X-Forwarded-URI $request_uri;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
3
nginx/snippets/ssl-headers.conf
Normal file
3
nginx/snippets/ssl-headers.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
# add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
add_header Set-Cookie "Path=/; HttpOnly; Secure";
|
18
nginx/snippets/ssl.conf
Normal file
18
nginx/snippets/ssl.conf
Normal file
|
@ -0,0 +1,18 @@
|
|||
ssl_certificate /etc/letsencrypt/live/${env['domain']}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/${env['domain']}/privkey.pem;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/${env['domain']}/chain.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
|
||||
|
||||
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
|
||||
ssl_dhparam /etc/nginx/dhparam.txt;
|
||||
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:MozSSL:10m;
|
||||
ssl_session_tickets off;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
2
nginx/snippets/websocket.conf
Normal file
2
nginx/snippets/websocket.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
9
setup.sh
9
setup.sh
|
@ -15,14 +15,14 @@ declare -a podman_units=(podman.service podman.socket podman-auto-update.service
|
|||
|
||||
|
||||
if [[ "$podman_mode" == "rootless" ]]; then
|
||||
sudo apt install -y aardvark-dns borgbackup cifs-utils dbus-user-session nftables passt podman podman-compose python3-mako slirp4netns uidmap
|
||||
sudo apt install -y aardvark-dns borgbackup cifs-utils curl dbus-user-session nftables nginx passt podman podman-compose python3-mako slirp4netns uidmap
|
||||
|
||||
sudo loginctl enable-linger "$USER"
|
||||
|
||||
sudo systemctl disable --now "${podman_units[@]}"
|
||||
systemctl --user enable --now "${podman_units[@]}"
|
||||
else
|
||||
sudo apt install -y aardvark-dns borgbackup cifs-utils nftables podman podman-compose python3-mako
|
||||
sudo apt install -y aardvark-dns borgbackup cifs-utils curl nftables nginx podman podman-compose python3-mako
|
||||
|
||||
systemctl --user disable --now "${podman_units[@]}"
|
||||
sudo systemctl enable --now "${podman_units[@]}"
|
||||
|
@ -43,4 +43,7 @@ done
|
|||
sudo sysctl -p /etc/sysctl.d/podman.conf
|
||||
|
||||
|
||||
sudo systemctl enable --now nftables
|
||||
sudo curl -o /etc/nginx/dhparam.txt https://ssl-config.mozilla.org/ffdhe2048.txt
|
||||
|
||||
|
||||
sudo systemctl enable --now nftables nginx
|
||||
|
|
Loading…
Reference in a new issue