diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Refresh the server configs and drop `unsafe-inline`
The inline handlers and the auto-submitting selects are gone, so
`script-src` no longer needs it, and t0004 now checks that the three
configs pin the same policy.
Diffstat (limited to 'custom/servers/nginx.conf')
| -rw-r--r-- | custom/servers/nginx.conf | 73 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 file changed, 30 insertions, 43 deletions
diff --git a/custom/servers/nginx.conf b/custom/servers/nginx.conf index cf1e49f..3ffa2ba 100644 --- a/custom/servers/nginx.conf +++ b/custom/servers/nginx.conf @@ -16,8 +16,7 @@ # PATH_INFO and reads page options such as h= and id= from QUERY_STRING, so # nginx must pass PATH_INFO through to the binary. cgit builds its own link # base from SCRIPT_NAME. The five static assets are served straight off disk -# and must never be routed through cgit. Passing PATH_INFO through is the -# single most important part of the config below. +# and must never be routed through cgit. # # nginx cannot run CGI programs itself, so a small bridge called fcgiwrap runs # the cgit.cgi binary and speaks FastCGI to nginx. Nothing below works until @@ -48,11 +47,10 @@ events { http { - # nginx's compiled-in type table knows only text/html, and the usual - # "include mime.types" would pull in a second file. Exactly five static - # files are served off disk, so their types are declared here instead and - # this config keeps standing on its own. Everything else nginx returns - # comes from cgit, which sets its own Content-Type. + # nginx's built-in type table covers none of these five extensions, and + # the usual "include mime.types" would pull in a second file, so the five + # types are declared here. Everything else nginx returns comes from cgit, + # which sets its own Content-Type. types { text/css css; text/javascript js; @@ -80,14 +78,11 @@ http { gzip_types text/css text/javascript text/plain application/atom+xml; - # Requests carrying a Host header this config does not serve, a raw IP or - # an invented name from a scanning bot, land in these two blocks and are - # dropped without a response. cgit keys its page cache on the Host header - # so clone URLs stay honest, which means every invented hostname reaching - # it would mint a cache entry of its own and evict a real page to make - # room. Refusing strangers here keeps the cache to the names the site - # actually answers to. 444 is nginx shorthand for closing the connection - # without replying. + # Requests carrying a Host header this config does not serve are dropped + # without a response. cgit keys its page cache on the Host header, so + # every invented hostname reaching it would mint a cache entry of its + # own and evict a real page. 444 is nginx shorthand for closing the + # connection without replying. server { listen 80 default_server; listen [::]:80 default_server; @@ -158,8 +153,9 @@ http { # Site-wide security headers sit here because they must also cover the # static assets nginx serves directly. cgit itself sends only the # headers the proxy cannot supply. Those are Status, Content-Type, - # Content-Length and Content-Disposition on downloads, a no-store - # Cache-Control on unauthenticated responses, the auth filter's + # Content-Length and Content-Disposition on downloads, Location on + # redirects, a no-store Cache-Control on unauthenticated responses, + # the auth filter's # Set-Cookie, and on raw repository bytes a nosniff of its own next to # the stricter policy "default-src 'none'". Everything else, this # policy included, is the proxy's job. @@ -170,13 +166,13 @@ http { # construct that rewrites response headers here could strip the # protection cgit puts on raw repository content. # - # cgit loads only its own /cgit.js and uses inline style on the - # diffstat bars, so script-src stays self while style-src allows - # inline. form-action self covers the login form, the only form cgit + # form-action self covers the login form, the only form cgit # renders. always applies them to error responses too. If you enable # the gravatar or libravatar avatar filter, add its host to img-src, # for example https://www.gravatar.com or https://seccdn.libravatar.org. - add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'" always; + # A head-include or repo.head-content that injects a <style> block + # needs 'unsafe-inline' added to style-src. + add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer" always; @@ -203,8 +199,7 @@ http { # The document root is the directory that holds the static assets. cgit # emits absolute links to /cgit.css and /cgit.png by default, so those - # files must resolve at the root of the URL space. Pointing root at the - # asset directory makes /cgit.css map to /usr/share/cgit/cgit.css. + # files must resolve at the root of the URL space. root /usr/share/cgit; # The only request body cgit ever reads is the auth-filter login form, @@ -216,15 +211,11 @@ http { error_log /var/log/nginx/cgit.error.log; # Match the assets by their exact root-level names, never by bare - # extension. cgit routes on PATH_INFO and a repository can hold files - # ending in .css or .png, so /myrepo/tree/style.css and /myrepo/plain/ - # logo.png are real cgit URLs. A broad extension match would capture - # those, look for them on disk, and return 404 before cgit could render - # them. Anchoring the regex at the start of the path matches /cgit.css - # but not /myrepo/tree/cgit.css, so it can never shadow a repository - # file. An nginx regex location is matched before the prefix location - # below, so these assets win for their exact URLs and cgit wins for the - # rest. + # extension. A repository can hold files ending in .css or .png, and + # /myrepo/tree/style.css is a real cgit URL a broad match would + # capture and 404. The regex anchored at ^/ matches /cgit.css but + # never /myrepo/tree/cgit.css, and a regex location beats the prefix + # location below, so assets win their exact URLs and cgit the rest. location ~ ^/(cgit\.css|cgit\.js|cgit\.png|favicon\.ico|robots\.txt)$ { expires 30d; access_log off; @@ -234,13 +225,10 @@ http { # Everything that is not a static asset above is a cgit URL, the repo # index, a repository, a page within a repository, a snapshot, a feed. location / { - # The CGI environment. This is normally "include fastcgi_params", - # which would be a second file, so the list is written out here. - # Of all of it cgit itself reads only CGIT_CONFIG, PATH_INFO, - # QUERY_STRING, SCRIPT_NAME, REQUEST_METHOD, CONTENT_LENGTH, - # HTTP_HOST, HTTPS, SERVER_NAME, SERVER_PORT, HTTP_COOKIE and - # HTTP_REFERER. The cookie and referer arrive on their own, since - # nginx forwards request headers as HTTP_* without being asked. + # The CGI environment, normally "include fastcgi_params", written + # out here so this config stands alone. The cookie and referer + # arrive on their own, since nginx forwards request headers as + # HTTP_* without being asked. # The program fcgiwrap runs. It must be the cgit binary itself, not # $document_root$fastcgi_script_name, which would try to run a repo @@ -291,8 +279,7 @@ http { fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; - # Hand off to the fcgiwrap socket. A TCP fcgiwrap would use for - # example 127.0.0.1:9000 here. + # Hand off to the fcgiwrap socket. fastcgi_pass unix:/run/fcgiwrap.socket; # Large outputs such as snapshot tarballs and blame on big files @@ -300,8 +287,8 @@ http { fastcgi_read_timeout 300s; fastcgi_buffering off; - # cgit sends no caching headers of its own, so browsers refetch - # dynamic pages and cgit's internal cache keeps that cheap. Do not + # Ordinary cgit pages carry no caching headers, so browsers + # refetch them and cgit's internal cache keeps that cheap. Do not # add a blanket expires or Cache-Control in this location. It # would fight the no-store cgit puts on the login page and could # let one visitor's page be served to another from a shared cache. |
