Created
April 22, 2026 21:00
-
-
Save jurelou/fdc7e6666780bf6d840bc73da9f0c424 to your computer and use it in GitHub Desktop.
Otel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Otel |
Author
Author
# /etc/systemd/system/nginx.service
[Unit]
Description=nginx - hardened
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# --- Tourne entièrement sous www-data, y compris le master ---
User=www-data
Group=www-data
# Permet de binder 443 (<1024) sans être root
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
# Empêche l'acquisition de nouveaux privilèges
NoNewPrivileges=true
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
Restart=on-failure
RestartSec=2
# --- Durcissement du bac à sable ---
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
ProtectClock=true
ProtectHostname=true
ProtectProc=invisible
ProcSubset=pid
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
RemoveIPC=true
# Familles d'adresses autorisées
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
# Filtrage des appels système
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources @obsolete
# --- Chemins accessibles en écriture (ProtectSystem=strict rend tout / en lecture seule) ---
ReadWritePaths=/var/log/nginx /var/lib/nginx /var/cache/nginx /run
# Facultatif : masquer les binaires/dossiers sensibles
InaccessiblePaths=/boot /srv
[Install]
WantedBy=multi-user.target
# Répertoires runtime accessibles à www-data
sudo mkdir -p /var/lib/nginx /var/cache/nginx /var/log/nginx
sudo chown -R www-data:www-data /var/lib/nginx /var/cache/nginx /var/log/nginx
# Le PID dans /run : systemd gère /run via ReadWritePaths,
# mais assure-toi que nginx.conf pointe bien vers /run/nginx.pid
# Clé TLS lisible par www-data uniquement
sudo chown root:www-data /etc/nginx/ssl/server.key
sudo chmod 640 /etc/nginx/ssl/server.key
sudo systemctl daemon-reload
sudo systemctl restart nginx
sudo systemctl status nginx
Points clés :
Comme le master tourne sous www-data (pas root), retire la directive user nginx-worker; de nginx.conf — elle serait ignorée avec un warning, et seul root peut changer d'utilisateur de toute façon.
AmbientCapabilities=CAP_NET_BIND_SERVICE est ce qui remplace root pour binder 443. CapabilityBoundingSet limité à cette seule capacité + NoNewPrivileges verrouille le reste.
MemoryDenyWriteExecute=true peut casser certains modules dynamiques compilés en JIT (rare avec nginx standard) ; retire-le si tu as des erreurs de chargement de module.
Vérifie le durcissement effectif avec systemd-analyze security nginx — tu devrais tomber sous un score de 2.0 (« OK/exposed » faible).
Author
avec biunder
# /etc/systemd/system/nginx.socket
[Unit]
Description=nginx HTTPS socket (443)
[Socket]
ListenStream=443
BindIPv6Only=both
Backlog=4096
# Le master nginx s'attend à hériter le fd sur un nom précis.
# On force l'ordre pour que ce soit le fd 3 (SD_LISTEN_FDS_START).
[Install]
WantedBy=sockets.target
# /etc/systemd/system/nginx.service
[Unit]
Description=nginx - hardened, socket-activated
After=network-online.target nss-lookup.target nginx.socket
Wants=network-online.target
Requires=nginx.socket
[Service]
Type=forking
PIDFile=/run/nginx.pid
User=www-data
Group=www-data
# --- Aucune capability : le socket est fourni par systemd ---
CapabilityBoundingSet=
AmbientCapabilities=
NoNewPrivileges=true
# nginx lit le fd hérité via la variable NGINX (format "fd_count;fd_num")
Environment=NGINX=3;
# 3 = SD_LISTEN_FDS_START (premier fd passé par systemd)
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
KillMode=mixed
Restart=on-failure
RestartSec=2
# --- Filesystem : whitelist stricte ---
TemporaryFileSystem=/:ro
BindReadOnlyPaths=/usr/sbin/nginx /sbin/start-stop-daemon
BindReadOnlyPaths=/lib /lib64 /usr/lib /usr/lib64
BindReadOnlyPaths=/etc/nginx /etc/ssl/certs /etc/localtime
BindReadOnlyPaths=/etc/resolv.conf /etc/hosts /etc/nsswitch.conf /etc/gai.conf
BindReadOnlyPaths=/etc/passwd /etc/group
BindReadOnlyPaths=/var/www
BindPaths=/var/log/nginx /var/lib/nginx /var/cache/nginx /run
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
# --- Namespaces / privilèges ---
PrivateDevices=true
PrivateMounts=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
ProtectClock=true
ProtectHostname=true
ProtectProc=invisible
ProcSubset=pid
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
RemoveIPC=true
UMask=0077
# --- Réseau ---
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
# --- Syscalls ---
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources @obsolete @debug @mount @cpu-emulation @swap @reboot @raw-io @module
[Install]
WantedBy=multi-user.target
```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
gitlab/merge_request_templates/Default.md. Le no