summaryrefslogtreecommitdiff
path: root/git-shell + cgit.md
blob: b84b6c237f0d330d789f0672b399cad9c7e6140d (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
Full guide: lightweight Git server on OpenBSD (git-shell + cgit)

This guide describes how to set up a light, secure, fully working Git server on OpenBSD. When you finish you will have:

    SSH access to your repositories for push/pull (dedicated user, key‑only authentication).

    A cgit web interface for browsing repositories at https://git.yourdomain.com.

    An automatically renewed Let’s Encrypt SSL certificate.

All steps are performed on the OpenBSD server via SSH (preferably over a VPN, if direct SSH is blocked by your firewall rules).
0. Prerequisites

    You have an OpenBSD server with a working httpd, pf, and a VPN tunnel (for example, the VPN network is 10.0.0.1 – adjust as needed).

    Other websites may already be running on your server; their configuration in /etc/httpd.conf must be preserved.

    A DNS A record for git.yourdomain.com points to your server’s public IP address (e.g., 203.0.113.10) and proxy/CDN (like Cloudflare’s orange cloud) is turned off (grey cloud / DNS‑only).

    You have root access or can execute doas.

1. Install Git and create the dedicated user
bash

doas pkg_add git

Create a dedicated user that will own the repositories. In this guide we use the username gituser – you may choose any name.
bash

doas adduser

Answer the prompts as follows:

    username : gituser

    full name : Git Server

    shell : ksh (we will change it to git-shell later)

    home : /home/gituser

    password : leave empty (only key‑based login will be used)

Set up the home directory:
bash

doas mkdir -p /home/gituser/.ssh
doas chmod 700 /home/gituser/.ssh
doas touch /home/gituser/.ssh/authorized_keys
doas chmod 600 /home/gituser/.ssh/authorized_keys
doas chown -R gituser:gituser /home/gituser

2. Configure SSH keys for the administrator

You need an SSH key pair that will be used to push to and manage the repositories.

    If you already have a key, copy its public part (e.g. ~/.ssh/id_ed25519.pub) to the server.

    If not, generate one on your local machine:

bash

ssh-keygen -t ed25519 -C "git admin key"

Assume the public key file is now available on the server at, for example, /tmp/your_key.pub. Add it to the gituser account with the necessary restrictions:
bash

echo 'no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ' | doas tee /home/gituser/.ssh/authorized_keys
doas cat /tmp/your_key.pub | doas tee -a /home/gituser/.ssh/authorized_keys
doas chown gituser:gituser /home/gituser/.ssh/authorized_keys
doas chmod 600 /home/gituser/.ssh/authorized_keys

Change the user’s shell to git-shell – this forbids interactive logins and only allows Git operations:
bash

doas chpass -s git-shell gituser

Test the connection from your local machine (adjust the IP or VPN address accordingly):
bash

ssh gituser@10.0.0.1

You should see a message like “PTY allocation request failed” (login is blocked) with no password prompt.
3. Create the repositories directory
bash

doas mkdir -p /var/www/git-repos
doas chown -R gituser:www /var/www/git-repos
doas chmod 750 /var/www/git-repos

Create a symbolic link so developers can use the short path /git:
bash

doas ln -sf /var/www/git-repos /git

Initialise a bare test repository:
bash

doas -u gituser git init --bare /var/www/git-repos/my_project.git

Now from your local machine you can push to it (replace the host address):
bash

git remote add origin gituser@10.0.0.1:/git/my_project.git
git push -u origin master

4. Install cgit and prepare the chroot

Install cgit:
bash

doas pkg_add cgit

Create the cgit configuration file:
bash

doas mkdir -p /var/www/conf
doas tee /var/www/conf/cgitrc << 'EOF'
scan-path=/git-repos
css=/cgit.css
logo=/cgit.png
enable-index-links=1
enable-http-clone=1
root-title=My Git Repositories
root-desc=Public projects
snapshots=tar.gz
readme=:README.md
EOF

Copy static assets (logo, CSS) – these are shipped with the cgit package:
bash

doas cp /var/www/cgit/cgit.png /var/www/cgit/ 2>/dev/null || true
doas cp /var/www/cgit/cgit.css /var/www/cgit/ 2>/dev/null || true
doas chown -R www:www /var/www/cgit

Add the web server user (www) to the gituser group so cgit can read the repositories:
bash

doas usermod -G www,gituser www
doas chmod 750 /var/www/git-repos
doas find /var/www/git-repos -type d -exec chmod 750 {} \;
doas find /var/www/git-repos -type f -exec chmod 640 {} \;

Critical step – because httpd on OpenBSD runs cgit inside a chroot at /var/www, you must copy the git binary and all its dependencies into that chroot:
bash

doas mkdir -p /var/www/usr/local/bin /var/www/usr/local/libexec /var/www/usr/lib /var/www/usr/local/lib /var/www/dev

# Copy git
doas cp /usr/local/bin/git /var/www/usr/local/bin/

# Copy the dynamic linker and required libraries
doas cp /usr/libexec/ld.so /var/www/usr/libexec/
for lib in $(ldd /usr/local/bin/git | awk '/\/usr\// {print $NF}' | sort -u); do
    doas mkdir -p "/var/www/$(dirname "$lib")"
    doas cp "$lib" "/var/www/$lib"
done

# Create /dev/null (needed even for reading operations)
doas mknod /var/www/dev/null c 2 2
doas chmod 666 /var/www/dev/null

Verify that git works inside the chroot:
bash

doas chroot /var/www /usr/local/bin/git --version

You should see the git version number. If the command fails, double‑check the copied libraries.
5. Configure httpd for the cgit subdomain

Edit /etc/httpd.conf and add the following blocks at the end (be careful to use only multi‑line location stanzas, no single‑line shortcuts):
text

# --- git.yourdomain.com (cgit) ---
server "git.yourdomain.com" {
    listen on egress port 80
    location * {
        block return 301 "https://$HTTP_HOST$REQUEST_URI"
    }
}

server "git.yourdomain.com" {
    listen on egress tls port 443
    log style combined
    log access "git-access.log"

    tls {
        certificate "/etc/ssl/git.yourdomain.com.fullchain.pem"
        key "/etc/ssl/private/git.yourdomain.com.key"
    }

    location "/cgit.css" {
        root "/cgit"
        no fastcgi
    }

    location "/cgit.png" {
        root "/cgit"
        no fastcgi
    }

    location "/*" {
        root "/cgi-bin/cgit.cgi"
        fastcgi socket "/run/slowcgi.sock"
    }

    location "/.git*" {
        block
    }
}

Check the syntax and restart httpd:
bash

doas httpd -n
doas rcctl restart httpd

6. SSL certificate for the subdomain

Add a section to /etc/acme-client.conf (if it does not already exist):
text

domain git.yourdomain.com {
    domain key "/etc/ssl/private/git.yourdomain.com.key"
    domain full chain certificate "/etc/ssl/git.yourdomain.com.fullchain.pem"
    sign with letsencrypt
}

Issue the certificate:
bash

doas acme-client -v git.yourdomain.com
doas rcctl restart httpd

To renew the certificate automatically every week, append these lines to /etc/weekly.local:
bash

echo 'acme-client -v git.yourdomain.com' | doas tee -a /etc/weekly.local
echo 'rcctl restart httpd' | doas tee -a /etc/weekly.local

7. Start slowcgi and final verification
bash

doas rcctl enable slowcgi
doas rcctl start slowcgi
doas rcctl restart httpd

Open your browser and go to https://git.yourdomain.com. You should see the cgit page listing your repositories (initially only the test repository my_project.git).

If you see “No repositories found”, clear the cgit cache:
bash

doas rm -rf /var/cache/cgit/*
doas rcctl restart slowcgi httpd

Everything is ready! Your personal Git server is now fully operational.
Replace every placeholder (gituser, git.yourdomain.com, your_server_ip, etc.) with your actual values throughout the configuration.