Docker audit fixes #1

Merged
NotS1mp merged 9 commits from docker-audit-fixes into master 2026-09-24 15:21:57 +00:00
4 changed files with 47 additions and 2 deletions
Showing only changes of commit 22213a5592 - Show all commits
+7
View File
@@ -169,6 +169,13 @@ docker compose -f edge/compose.yml up -d
starting. Upstreams use the target's `container_name` (see "Running it" starting. Upstreams use the target's `container_name` (see "Running it"
above for why). Shared bits are in `edge/snippets/`. Check a change with above for why). Shared bits are in `edge/snippets/`. Check a change with
`docker exec edge-nginx nginx -t`, then `docker exec edge-nginx nginx -s reload`. `docker exec edge-nginx nginx -t`, then `docker exec edge-nginx nginx -s reload`.
- **Unknown hostnames** hit `01-default.conf`: port 80 closes the connection
(ACME challenges still work), port 443 refuses the TLS handshake. Nothing
reaches a project unless its vhost names the host.
- **TLS** settings (`snippets/tls.conf`) follow Mozilla's intermediate
profile and send HSTS with a 1-day `max-age`. Raise it once every hostname
is confirmed to work over https: browsers remember it, so a long value
can't be taken back quickly.
- **Certificates** are state, not versioned (`edge/certbot/`). To issue one - **Certificates** are state, not versioned (`edge/certbot/`). To issue one
for new hostnames (their DNS has to already point at the host): for new hostnames (their DNS has to already point at the host):
+25
View File
@@ -0,0 +1,25 @@
# Catch-all for Host headers no vhost claims (scanners, direct IP access,
# stale DNS). Without it nginx hands them to the first vhost it loaded,
# i.e. Gitea. ACME stays reachable here so a certificate for a new hostname
# can be issued before its vhost exists.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 444;
}
}
# No certificate to present for an unknown name, so refuse the handshake.
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
ssl_reject_handshake on;
}
+3 -1
View File
@@ -1,7 +1,9 @@
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # The edge is the first hop, so whatever X-Forwarded-For the client sent is
# made up: replace it instead of appending to it.
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
+12 -1
View File
@@ -1,2 +1,13 @@
# Mozilla "intermediate" profile, without the DHE suites (they'd need a
# dhparam file): forward secrecy on every connection, no CBC.
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5; 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;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Short max-age for now: raise it (e.g. 63072000) once every hostname is
# confirmed working over https. A location that sets its own add_header
# stops inheriting this one.
add_header Strict-Transport-Security "max-age=86400" always;