[Unit] Description=A high performance web server and a reverse proxy server (twiy) After=syslog.target network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=/run/nginx.pid Environment=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ExecStartPre=/usr/bin/install -d -o nginx -g nginx -m 0755 /run/nginx/temp /run/nginx/temp/client_body /run/nginx/temp/proxy /run/nginx/temp/fastcgi /run/nginx/temp/uwsgi /run/nginx/temp/scgi /var/log/nginx ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx -c /nginx/nginx.conf ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /run/nginx.pid)" ExecStop=/bin/sh -c "/bin/kill -s QUIT $(/bin/cat /run/nginx.pid)" TimeoutStartSec=10 LimitNOFILE=65535 # === hardening: deny-everything by default, allowlist via bind mounts === # TemporaryFileSystem=/ replaces the visible filesystem with an empty tmpfs. # Everything not bind-mounted below is invisible to nginx workers — even # read access. Compromise of a worker can no longer enumerate /etc/passwd, # /home/*, /var/lib/*, /root, /opt, etc. TemporaryFileSystem=/ # Read-only: nginx binary, dynamic linker, all linked libs, system config, # CA bundles, Let's Encrypt certs (live/ + archive/ both under /etc). BindReadOnlyPaths=/usr BindReadOnlyPaths=/lib BindReadOnlyPaths=/lib64 BindReadOnlyPaths=/bin BindReadOnlyPaths=/sbin BindReadOnlyPaths=/etc # Read-only: vhost docroots + app projects. Add a new line here when you # add a vhost whose root isn't under one of these parents. BindReadOnlyPaths=/raweb BindReadOnlyPaths=/srv BindReadOnlyPaths=/hostdata # Read-write: nginx runtime state. # /run nginx.pid, nginx.lock, /run/nginx/temp/*, PHP-FPM sock # /var/log/nginx access.log, error.log # /nginx config dir (read-mostly but reload writes some state) BindPaths=/run BindPaths=/var/log/nginx BindPaths=/nginx NoNewPrivileges=true ProtectKernelTunables=true ProtectKernelModules=true ProtectKernelLogs=true ProtectControlGroups=true ProtectClock=true ProtectHostname=true PrivateDevices=true PrivateTmp=true RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK RestrictNamespaces=true RestrictRealtime=true RestrictSUIDSGID=true LockPersonality=true SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallErrorNumber=EPERM # NOTE deliberately OFF: # MemoryDenyWriteExecute=true breaks LuaJIT (JIT writable+executable pages) # SystemCallFilter=~@resources breaks nginx workers' prlimit64() # ProtectSystem and ProtectHome are redundant under TemporaryFileSystem=/. [Install] WantedBy=multi-user.target