[Unit] Description=__APP__ server After=network.target redis.service postgresql.service [Service] Type=simple User=__APP__ Group=__APP__ WorkingDirectory=__INSTALL_DIR__/ ExecStart=__INSTALL_DIR__/venv/bin/gunicorn --config __INSTALL_DIR__/gunicorn.conf.py wsgi StandardOutput=syslog StandardError=syslog SyslogIdentifier=__APP__-server # FIXME: Test all that # ### Depending on specificities of your service/app, you may need to tweak these # ### .. but this should be a good baseline # # Sandboxing options to harden security # # 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 # # 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