blob: 71c5b754a7fae61beb4caee7a5506f0b10de5e31 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
# SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
# https://git.progmasoft.com: cgit over read-only mirrors, and clones over smart HTTP with
# git-http-backend (upload-pack only). Installed as /etc/nginx/conf.d/git.conf.
limit_req_zone $binary_remote_addr zone=git_pages:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=git_clones:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=git_connections:10m;
server {
listen 80;
listen [::]:80;
server_name git.progmasoft.com;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/letsencrypt;
default_type text/plain;
}
location / {
return 308 https://git.progmasoft.com$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name git.progmasoft.com;
ssl_certificate /etc/letsencrypt/live/progmasoft.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/progmasoft.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
# Nothing is uploaded here: a clone sends only the list of what it wants.
client_max_body_size 1m;
limit_conn git_connections 8;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# cgit writes no scripts; its diffstat bars set their width in style attributes.
add_header Content-Security-Policy "default-src 'none'; style-src-elem 'self'; style-src-attr 'unsafe-inline'; img-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'" always;
location ^~ /static/ {
alias /srv/git/www/static/;
expires 1d;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'none'; style-src 'self'" always;
}
location = /robots.txt {
default_type text/plain;
return 200 "User-agent: *\nDisallow: /*/snapshot/\nDisallow: /*/log/\nDisallow: /*/diff/\nDisallow: /*/patch/\n";
}
# Pushing is never possible: no receive-pack, and the dumb protocol is off.
location ~ ^/[A-Za-z0-9._-]+/git-receive-pack$ {
return 403;
}
location ~ ^/(?<git_repo>[A-Za-z0-9._-]+?)(?:\.git)?/(?<git_path>info/refs|git-upload-pack)$ {
set $git_service "";
if ($git_path = "info/refs") {
set $git_service $arg_service;
}
if ($git_path = "git-upload-pack") {
set $git_service "git-upload-pack";
}
if ($git_service != "git-upload-pack") {
return 403;
}
limit_req zone=git_clones burst=10 nodelay;
fastcgi_pass unix:/run/fcgiwrap/fcgiwrap-cgit.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend;
fastcgi_param GIT_PROJECT_ROOT /srv/git/mirrors;
# No GIT_HTTP_EXPORT_ALL: only mirrors git-mirror marks with git-daemon-export-ok are served.
fastcgi_param PATH_INFO /$git_repo.git/$git_path;
fastcgi_param REMOTE_USER "";
# The mirrors belong to gitmirror and are read as cgit; only this backend trusts them.
fastcgi_param GIT_CONFIG_COUNT 1;
fastcgi_param GIT_CONFIG_KEY_0 safe.directory;
fastcgi_param GIT_CONFIG_VALUE_0 /srv/git/mirrors/*;
fastcgi_read_timeout 300s;
# Nginx buffers the pack (to a file when it is large), so a slow reader never stalls
# git-http-backend behind fcgiwrap.
fastcgi_buffering on;
fastcgi_max_temp_file_size 2048m;
}
location / {
limit_req zone=git_pages burst=40 nodelay;
# The menus of cgit (branch, diff options) submit themselves from inline handlers, which the
# policy above blocks; their buttons ("switch", "reload") do the same without a script.
sub_filter "" "";
sub_filter_once off;
fastcgi_pass unix:/run/fcgiwrap/fcgiwrap-cgit.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/cgi-bin/cgit;
fastcgi_param CGIT_CONFIG /etc/cgitrc;
fastcgi_param PATH_INFO $uri;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_read_timeout 60s;
}
}
|