diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce 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.conf73
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.