This guide is pretty much a modified version of the git book instructions for Debian specifically.
It also includes setting up a cgit web frontend that allows you to view your git repositories conveniently on the web.
I'm assuming you already have a VPS with Debian installed and a domain purchased with proper DNS records pointing git.example.com to your server IP. If not, I recommend you do research on what all that means.
ssh root@example.com
apt install git
sudo adduser git
usermod -aG sudo git
su git
cd
mkdir .ssh && chmod 700 .ssh
touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
To copy your home computer's ssh id to your server (assuming you have one generated), run this command on your home computer:
ssh-copy-id git@example.com
Now let's create an example git repository and try to push from our home computer.
On your server, as the git user, run these commands to create a repo.
sudo mkdir /srv/git
cd /srv/git
sudo mkdir repo.git
cd repo.git
git init --bare
Ensure the repo is owned by the git user and group. Otherwise, git commands on your home computer error.
chown -R git:git /srv/git
On your home computer, setup a git repo as well.
mkdir repo
cd repo
git init --bare
git remote add origin git@example.com:/srv/git/repo.git
Make some changes. For example, create a file, and try git push. It should work.
touch file.txt
git add .
git commit -m "changes"
git push origin master
The final step is to prevent a remote login as git@example.com from acquiring a normal shell on the server.
This step isn't strictly necessary and can probably be skipped if you're the only one using git on your server.
First, check the location of the git shell. Then, append the output to /etc/shells.
which git-shell
vim /etc/shells
G
o
/usr/bin/git-shell
:wq
Now set the shell for the git user to git-shell.
sudo chsh git -s $(which git-shell)
Finally, prevent port forwarding by prepending this to each key in ~/.ssh/authorized_keys in the git user directory.
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
Attempting to login as git using ssh git@example.com should output an error and close the connection, such as this one:
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to example.com closed.
Perfect!
At this point, your git server is fully usable, and you can begin to push, pull, etc. However, you might also want a frontend to browse your repositories and make them discoverable on the web.
apt install nginx certbot fcgiwrap cgit
Generate a tls certificate for your git domain, then create a cron job to auto renew it.
certbot certonly --standalone --register-unsafely-without-email -d git.example.com
crontab -e
Append this line to the file crontab opens:
0 0 1 * * certbot --nginx renew
Next, edit the nginx config. This is an example of what works for me. My config file is located at /etc/nginx/nginx.conf.
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate "/etc/letsencrypt/live/git.example.com/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/git.example.com/privkey.pem";
ssl_trusted_certificate "/etc/letsencrypt/live/git.example.com/chain.pem";
server_name git.example.com;
root /usr/share/cgit;
location ~* ^.+\.(css|js|png|ico)$ {
root /usr/share/cgit;
expires 30d;
}
location / {
try_files $uri @cgit;
}
location @cgit {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
fastcgi_param PATH_INFO $uri;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_pass unix:/run/fcgiwrap.socket;
}
}
}
Now it's time to edit the cgit config to make the frontend your own. Mine is located at /etc/cgitrc. Here's an example of my config:
#
# cgit config
# see cgitrc(5) for details
# copy your logo into /usr/share/cgit and change the file name here
logo=/logo.webp
root-title=example
root-desc=a web frontend for my git repositories
favicon=
css=/cgit.css
# for clean repository names
remove-suffix=1
clone-prefix=https://git.example.com
scan-path=/srv/git/
virtual-root=/
It's possible you need to add the nginx user to the www-data group (root if you never created one). Otherwise, the frontend will display 502 Bad Gateway instead of cgit.
Run this command to do so:
usermod -aG www-data <nginx-user>
If you followed the steps, you now have a working self-hosted git server and read-only frontend to view and share your repositories. Personally, I feel like this was a pretty simple setup and is definitely worth investing time into for the purpose of decentralization (as long as you chose something like AWS as your cloud provider lol).