diff options
context:
space:
mode:
Diffstat (limited to 'custom/servers/nginx.conf')
-rw-r--r--custom/servers/nginx.conf193
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/.