From 2e3b9c8d9bbbc76723ce3436b126fec70d3b00de Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 23 Aug 2023 14:01:13 +0200 Subject: [PATCH] appstore: Add gunicorn, systemd, nginx conf snippets for deployment --- store/app.py | 3 ++- store/assets/fetch_assets | 2 +- store/gunicorn.py | 13 ++++++++++ store/nginx.conf.example | 15 +++++++++++ store/requirements.txt | 1 + store/systemd.conf.example | 53 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 store/gunicorn.py create mode 100644 store/nginx.conf.example create mode 100644 store/systemd.conf.example diff --git a/store/app.py b/store/app.py index 02f21fa8..15c55249 100644 --- a/store/app.py +++ b/store/app.py @@ -16,7 +16,7 @@ from github import Github, InputGitAuthor locale = "en" app = Flask(__name__, static_url_path='/assets', static_folder="assets") -catalog = json.load(open("apps.json")) +catalog = json.load(open("../builds/default/v3/apps.json")) catalog['categories'] = {c['id']:c for c in catalog['categories']} try: @@ -32,6 +32,7 @@ mandatory_config_keys = [ "GITHUB_LOGIN", "GITHUB_TOKEN", "GITHUB_EMAIL", + "APPS_CACHE", ] for key in mandatory_config_keys: diff --git a/store/assets/fetch_assets b/store/assets/fetch_assets index f418bab8..93bf49b7 100644 --- a/store/assets/fetch_assets +++ b/store/assets/fetch_assets @@ -1,4 +1,4 @@ -curl https://cdn.tailwindcss.com?plugins=forms -O > tailwindcss.js +curl -L https://cdn.tailwindcss.com?plugins=forms > tailwindcss.js curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css > fork-awesome.min.css sed -i 's@../fonts/@@g' ./fork-awesome.min.css diff --git a/store/gunicorn.py b/store/gunicorn.py new file mode 100644 index 00000000..5346bc7d --- /dev/null +++ b/store/gunicorn.py @@ -0,0 +1,13 @@ +import os +install_dir = os.path.dirname(__file__) +command = f'{install_dir}/venv/bin/gunicorn' +pythonpath = install_dir +workers = 4 +user = 'appstore' +bind = f'unix:{install_dir}/sock' +pid = '/run/gunicorn/appstore-pid' +errorlog = '/var/log/appstore/error.log' +accesslog = '/var/log/appstore/access.log' +access_log_format = '%({X-Real-IP}i)s %({X-Forwarded-For}i)s %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' +loglevel = 'warning' +capture_output = True diff --git a/store/nginx.conf.example b/store/nginx.conf.example new file mode 100644 index 00000000..590224c3 --- /dev/null +++ b/store/nginx.conf.example @@ -0,0 +1,15 @@ +location / { + try_files $uri @appstore; +} + +location /assets { + alias __INSTALL_DIR__/assets/; +} + +location @appstore { + proxy_pass http://unix:__INSTALL_DIR__/sock; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; +} diff --git a/store/requirements.txt b/store/requirements.txt index b15084d0..fd2316cd 100644 --- a/store/requirements.txt +++ b/store/requirements.txt @@ -3,3 +3,4 @@ python-slugify PyGithub toml markdown +gunicorn diff --git a/store/systemd.conf.example b/store/systemd.conf.example new file mode 100644 index 00000000..766247fa --- /dev/null +++ b/store/systemd.conf.example @@ -0,0 +1,53 @@ +[Unit] +Description=appstore gunicorn daemon +After=network.target + +[Service] +PIDFile=/run/gunicorn/appstore-pid +User=appstore +Group=appstore +WorkingDirectory=__INSTALL_DIR__ +ExecStart=__INSTALL_DIR__/venv/bin/gunicorn -c __INSTALL_DIR__/gunicorn.py app:app +ExecReload=/bin/kill -s HUP $MAINPID +ExecStop=/bin/kill -s TERM $MAINPID +StandardOutput=append:/var/log/appstore/appstore.log +StandardError=inherit + +# Sandboxing options to harden security +# Depending on specificities of your service/app, you may need to tweak these +# .. but this should be a good baseline +# Details for these options: https://www.freedesktop.org/software/systemd/man/systemd.exec.html +NoNewPrivileges=yes +PrivateTmp=yes +PrivateDevices=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK +RestrictNamespaces=yes +RestrictRealtime=yes +DevicePolicy=closed +ProtectClock=yes +ProtectHostname=yes +ProtectProc=invisible +ProtectSystem=full +ProtectControlGroups=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +LockPersonality=yes +SystemCallArchitectures=native +SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap @cpu-emulation +# @privileged # (not sure why this need to be removed...) + +# Denying access to capabilities that should not be relevant for webapps +# Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html +CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD +CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE +CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT +CapabilityBoundingSet=~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK +CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM +CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG +CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE +CapabilityBoundingSet=~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW +CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG + + +[Install] +WantedBy=multi-user.target