21

Despite all the links I've found on how to configure git/nginx to get my repos, I can't make them work.

I followed this tutorial, Git repository over HTTP WebDAV with nginx, but the user/password restriction doesnt' work. Anyone can clone the repository.

I'm from a configuration using SVN + Apache + DAV_SVN, with a file for password (created with htpasswd), and a file for the authz. I'd like to do the same, using git+nginx. How's that possible ?

Thanks for your help!

Jasper
  • 11,590
  • 6
  • 38
  • 55
Cyril N.
  • 38,875
  • 36
  • 142
  • 243

3 Answers3

22

Take a look at the following article, http://www.toofishes.net/blog/git-smart-http-transport-nginx/

It provides a sample nginx config:

http {
    ...
    server {
        listen       80;
        server_name  git.mydomain.com;

        location ~ /git(/.*) {
            # fcgiwrap is set up to listen on this host:port
            fastcgi_pass  localhost:9001;
            include       fastcgi_params;
            fastcgi_param SCRIPT_FILENAME     /usr/lib/git-core/git-http-backend;
            # export all repositories under GIT_PROJECT_ROOT
            fastcgi_param GIT_HTTP_EXPORT_ALL "";
            fastcgi_param GIT_PROJECT_ROOT    /srv/git;
            fastcgi_param PATH_INFO           $1;
        }
    }
}

What this does is pass your repo which is located after /git in the url, to /usr/lib/git-core/git-http-backend. Example, http://git.mydomain.com/git/someapp would point to the someapp repository. This repo would be located in /srv/git/someapp as defined in the fastcgi_param of GIT_PROJECT_ROOT and can be changed to fit your server.

This is very useful and you can apply HttpAuthBasicModule to nginx to password protect your repo's access via HTTP.

Edit: If you are missing git-http-backend, you can install the git-core package on Ubuntu/Debian or on RPM based platforms look at How can git be installed on CENTOS 5.5?

Community
  • 1
  • 1
Mike Mackintosh
  • 13,917
  • 6
  • 60
  • 87
  • I followed this example to set up git on nginx. However each time I try clone repo I end up with error: `fatal: http://:9000/git/test.git/info/refs not valid: is this a git re pository?` There are no errors is /var/log/nginx/error.log and in access log I can see: - - [03/Oct/2015:08:35:42 +0200] "GET /git/test.git/info/refs?service=git-upload-pack HTTP/1.1" 200 424859 "-" "git/1.9.4.msysgit.1" Did you run into similar problem maybe? Thanks, Janusz – Janusz Grabis Oct 03 '15 at 06:42
  • no, but make sure its a bare repository created with `git init --bare`. ie, don't host checked out code, unless you are doing `git clone --bare` - other than that, the googles should help – Mike Mackintosh Oct 03 '15 at 18:21
  • I eventually found example that worked for me: http://serverfault.com/questions/483726/how-to-make-git-smart-http-transport-work-on-nginx. Thanks. – Janusz Grabis Oct 03 '15 at 19:46
  • 1
    **ALSO**, run `git update-server-info` on the bare repository, I was getting 404's for an `.git/info/refs` file that this will generate. – ThorSummoner Apr 22 '16 at 22:46
  • In case you're curious, http://stackoverflow.com/a/40313590/107158 illustrates how to configure `git-http-backend` to enable *anonymous read access but authenticated write access*. – Derek Mahar Oct 31 '16 at 16:21
  • 1
    In my case, the fcgi didn't listen on any port but socket, all I had to do was to change `fastcgi_pass localhost:9001;` to `fastcgi_pass unix:/run/fcgiwrap.socket;` – Galvani Jan 19 '17 at 10:00
  • Thanks @ThorSummoner, that was indeed the solution for my case. I'm unclear why this was necessary though, as similar setups seemed to always already have that file. I wonder if something changed in git causing this file not to exist by default any more – Confusion Aug 04 '20 at 07:29
20

Here is a full configuration for Git over HTTP, with TLS encryption, Basic Auth, and GitWeb. I assume that the repositories' root is in /home/git. You should replace example.com with your domain.

# Remove this block if you don't want TLS
server {
    listen 80;
    server_name git.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen       443 ssl; # Replace 443 ssl by 80 if you don't want TLS
    server_name  git.example.com;
    root         /usr/share/gitweb; # Remove if you don't want Gitweb

    error_log  /home/git/nginx-error.log;
    access_log /home/git/nginx-access.log;

    # Remove ssl_* lines if you don't want TLS
    ssl_certificate           /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key       /etc/letsencrypt/live/git.example.com/privkey.pem;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

    # Remove auth_* if you don't want HTTP Basic Auth
    auth_basic "example Git";
    auth_basic_user_file /etc/nginx/.htpasswd;

    # static repo files for cloning over https
    location ~ ^.*\.git/objects/([0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+.(pack|idx))$ {
        root /home/git/;
    }

    # requests that need to go to git-http-backend
    location ~ ^.*\.git/(HEAD|info/refs|objects/info/.*|git-(upload|receive)-pack)$ {
        root /home/git/;

        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
        fastcgi_param SCRIPT_FILENAME   /usr/lib/git-core/git-http-backend;
        fastcgi_param PATH_INFO         $uri;
        fastcgi_param GIT_PROJECT_ROOT  $document_root;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param REMOTE_USER $remote_user;
        include fastcgi_params;
    }

    # Remove all conf beyond if you don't want Gitweb
    try_files $uri @gitweb;
    location @gitweb {
        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
        fastcgi_param SCRIPT_FILENAME   /usr/share/gitweb/gitweb.cgi;
        fastcgi_param PATH_INFO         $uri;
        fastcgi_param GITWEB_CONFIG     /etc/gitweb.conf;
        include fastcgi_params;
   }
}

You have to install Git, Gitweb and FastCgiWrap :

sudo apt-get install git gitweb fcgiwrap

For TLS, I use Let's Encrypt free certificates.

sudo letsencrypt certonly -d git.example.com --rsa-key-size 4096

To access Gitweb, just browse to git.example.com. You will also need to configure it to set the repositories' root :

sudo vim /etc/gitweb.conf

In order to get HTTP Basic Auth, you have to use the htpasswd command to add users to /etc/nginx/.htpasswd:

sudo apt-get install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd username

Remove the -c switch the next time you run the command, because it only creates the file (Nginx doesn't have a .htpasswd file by default in its configuration directory).

If you want something more complex, powerful, GitHub-like, check Gitlab.

jww
  • 97,681
  • 90
  • 411
  • 885
Morgan Touverey Quilling
  • 4,181
  • 4
  • 29
  • 41
0

Adding more details, we need 3 components: nginx, git-http-backend and fcgiwrap.

  • git-http-backend is a standalone excutable binary can be built from https://github.com/git/git . It's the official solution for handling git http/https access, I don't know if it is the best one that exists.
  • Nginx do not have a built-in general FastCGI server(or I failed to find how to use nginx's fastcgi_bind correctly). So another fastcgi server should be used, like fcgiwarp( a good manual https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/ )
  • Use fastcgi_pass unix:/tmp/cgi.sock; in nginx config (reference to other answers)

fastcgi is not a must, and git-http-backend is not write only for fastcgi, and fastcgi is not simplest nor performance one. for examples, I wrote a servlet to interact between nginx and git-http-backend, using nginx's proxy_pass, it also works!

Braiam
  • 1
  • 11
  • 47
  • 78
neoedmund
  • 561
  • 7
  • 15