diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Reorganize the tree into vendor/ and custom/
Diffstat (limited to 'custom/servers/nginx.conf')
| -rw-r--r-- | custom/servers/nginx.conf | 193 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 file changed, 193 insertions, 0 deletions
diff --git a/custom/servers/nginx.conf b/custom/servers/nginx.conf new file mode 100644 index 0000000..76ac260 --- /dev/null +++ b/custom/servers/nginx.conf @@ -0,0 +1,193 @@ +# nginx configuration for cgit. +# +# nginx cannot run CGI programs itself, so a small bridge called fcgiwrap +# runs the cgit.cgi binary and speaks FastCGI to nginx. Starting fcgiwrap is +# covered in the notes at the end of this file. +# +# Paths assumed below, edit them to match your install. +# cgit CGI binary /usr/lib/cgit/cgit.cgi +# static assets /usr/share/cgit (cgit.css cgit.js cgit.png favicon.ico robots.txt) +# cgit config /etc/cgitrc +# public URL https://git.example.org/ (cgit at the domain root) +# +# cgit is one CGI executable. It learns the repository and the page from +# 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. + + +# --- Optional HTTP to HTTPS redirect ---------------------------------------- +# Delete this whole server block if you serve plain HTTP only. +server { + listen 80; + listen [::]:80; + server_name git.example.org; + + # ACME http-01 challenge files, if you use certbot in webroot mode. + location ^~ /.well-known/acme-challenge/ { + root /var/www/html; + } + + # Everything else moves to HTTPS. + location / { + return 301 https://$host$request_uri; + } +} + + +# --- Main site -------------------------------------------------------------- +# Written for TLS on 443. For a quick plain-HTTP test, change the two listen +# lines to port 80, delete the redirect block above, and delete the four ssl +# lines below. Everything else stays the same. +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name git.example.org; + + ssl_certificate /etc/letsencrypt/live/git.example.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/git.example.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + # --- Security headers --------------------------------------------------- + # These sit here, not in cgit, because they must also cover the static + # assets nginx serves directly. 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. 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'" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer" always; + # Enable only once you serve HTTPS exclusively, since it is hard to undo. + #add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; + + # 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. + root /usr/share/cgit; + + # Upload cap for large form posts. Snapshots are generated rather than + # uploaded, so this does not limit them. + client_max_body_size 64m; + + access_log /var/log/nginx/cgit.access.log; + error_log /var/log/nginx/cgit.error.log; + + # --- Static assets, served directly ------------------------------------- + # 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. + location ~ ^/(cgit\.css|cgit\.js|cgit\.png|favicon\.ico|robots\.txt)$ { + expires 30d; + access_log off; + try_files $uri =404; + } + + # --- cgit, the catch-all ------------------------------------------------ + # 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 / { + # nginx's standard FastCGI parameters, some of which are overridden + # below. A later fastcgi_param wins, so include order does not matter. + include fastcgi_params; + + # The program fcgiwrap runs. It must be the cgit binary itself, not + # $document_root$fastcgi_script_name, which would try to run a repo + # path and is the usual cause of a failed request. + fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi; + + # cgit builds its link base, the virtual root, from SCRIPT_NAME. The + # stock parameters set SCRIPT_NAME to the whole request path, which + # would make cgit prepend that path to every link. Served at the + # domain root the script has no prefix, so force SCRIPT_NAME empty and + # cgit uses / as its base. A sub-path install sets it instead, see the + # end of this file. + fastcgi_param SCRIPT_NAME ""; + + # How cgit learns the repository and page. At the domain root the + # whole request path is the PATH_INFO. + fastcgi_param PATH_INFO $uri; + + # Page options such as h=branch, id=sha and the snapshot format. + fastcgi_param QUERY_STRING $query_string; + + # Where the static assets live, kept consistent with root above. + fastcgi_param DOCUMENT_ROOT $document_root; + + # The browser's Host header, so cgit builds clone URLs against the + # name the visitor used rather than server_name. + fastcgi_param HTTP_HOST $http_host; + + # Which config cgit reads. It checks CGIT_CONFIG and falls back to the + # compiled-in /etc/cgitrc. Setting it makes the location explicit and + # lets you move cgitrc without recompiling. + fastcgi_param CGIT_CONFIG /etc/cgitrc; + + # The real scheme, so cgit builds correct https clone URLs. + fastcgi_param HTTPS $https if_not_empty; + + # Hand off to the fcgiwrap socket. See the notes for how to create it. + # A TCP fcgiwrap would use for example 127.0.0.1:9000 here. + fastcgi_pass unix:/run/fcgiwrap.socket; + + # Large outputs such as snapshot tarballs and blame on big files can + # take a while, so give cgit room and stream rather than buffer. + fastcgi_read_timeout 300s; + fastcgi_buffering off; + } +} + + +# --- Notes, starting fcgiwrap ----------------------------------------------- +# cgit is a CGI binary and fcgiwrap is the CGI to FastCGI bridge nginx talks +# to. On Debian and Ubuntu the packaged systemd socket provides +# /run/fcgiwrap.socket, so enabling it is enough. +# apt install fcgiwrap +# systemctl enable --now fcgiwrap.socket +# The socket must be readable by nginx's user. The packaged unit runs fcgiwrap +# as www-data, which nginx also uses on those systems. Without systemd you can +# run +# spawn-fcgi -s /run/fcgiwrap.socket -M 660 -- /usr/sbin/fcgiwrap +# or run fcgiwrap over TCP and point fastcgi_pass at 127.0.0.1:9000. + + +# --- Alternative, serving cgit under a sub-path ----------------------------- +# To serve cgit at https://git.example.org/cgit/ instead of the root, split +# the URL so SCRIPT_NAME is the prefix and PATH_INFO is the rest. +# +# location /cgit/ { +# include fastcgi_params; +# fastcgi_split_path_info ^(/cgit)(/.*)$; +# fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi; +# fastcgi_param SCRIPT_NAME $fastcgi_script_name; +# fastcgi_param PATH_INFO $fastcgi_path_info; +# fastcgi_param QUERY_STRING $query_string; +# fastcgi_param HTTP_HOST $http_host; +# fastcgi_param CGIT_CONFIG /etc/cgitrc; +# fastcgi_param HTTPS $https if_not_empty; +# fastcgi_pass unix:/run/fcgiwrap.socket; +# } +# +# Serve the assets from the sub-path too, again anchored to the exact names. +# +# location ~ ^/cgit/(cgit\.css|cgit\.js|cgit\.png|favicon\.ico|robots\.txt)$ { +# alias /usr/share/cgit/$1; +# expires 30d; +# access_log off; +# } +# +# cgit's default css=/cgit.css and logo=/cgit.png point at the domain root, so +# under a sub-path also set css=/cgit/cgit.css and logo=/cgit/cgit.png in +# cgitrc. cgit derives the /cgit prefix from SCRIPT_NAME. If links come out +# wrong, pin it in cgitrc with virtual-root=/cgit/. |
