Self-Hosted Git

Git was distributed before GitHub existed.

Why Do This

You own your code, not Microsoft. Git-over-HTTP is a solved problem from 2005. Adding webapp layers between you and your repositories is cargo cult programming.

Setup

Directory structure: bare repositories in /srv/git/, optional static pages elsewhere.

cd /srv/git
git clone --bare /path/to/existing/project project.git
cd project.git
git config http.receivepack false 
chown -R www-data:www-data /srv/git

apt install fcgiwrap
systemctl enable --now fcgiwrap

Nginx example configuration:

server {
    listen 443 ssl;
    server_name git.domain.com;
    
    # Git smart HTTP
    location ~ ^/repos/(.+\.git/.+)$ {
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
        fastcgi_param GIT_PROJECT_ROOT /srv/git;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param PATH_INFO /$1;
    }
    
    # Everything else (your static pages)
    location / {
        proxy_pass http://localhost:8080;
    }
}

Test and reload:

nginx -t
systemctl reload nginx

Usage

Clone works like any git repository:

git clone https://git.domain.com/repos/project.git

Update the bare repo manually:

cd /your/working/project
git push /srv/git/project.git main

Result

Standard git protocol, zero vendor lock-in, minimal attack surface. Works with every git client since 2005. Will work unchanged for the next 20 years.

No pull requests, no JavaScript, no database. Just git being git.