Search code examples
gitnginxpushfastcgihttp-status-code-403

nginx and git-http-backend 403 on push


I am trying to setup a git server with stagit for the front end, git-http-backend for the back and using nginx between everything. I've found a config that works on my server in this answer (and by works, I mean nginx will serve html to any connection through a web browser, but lets me clone a repository if I use git clone https://git.website.com/test.git.

The problem I'm having, is that when I push this repository (whether that be from the server itself, or from my local computer) with an origin of https://git.website.com/test.git I receive a 403 error and I'm not sure why. Any ideas?

server {
    listen 80;
    listen [::]:80;

    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /etc/ssl/ssl-bundle.crt;
    ssl_certificate_key /etc/ssl/private/ssl-private.key;

    root /srv/git;

    index index.html index.htm index.nginx-debian.html;

    access_log /var/log/nginx/git.access.log;
    error_log /var/log/nginx/git.error.log;
    gzip off;

    location / {
        try_files $uri $uri/ =404;
    }

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

    # requests that need to go to git-http-backend
    location ~ ^.*/(HEAD|info/refs|objects/info/.*|git-(upload|receive)-pack)$ {
        root /srv/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;
    }   
}

I only started trying to use git-http-backend about two hours ago with multiple configs. It seems very difficult to get http to serve webpages normally but also allow for git to clone/push. Using a config as found here resulted in empty 200 OK responses...


Solution

  • After much trial and error I've taken the config from this answer and modified it to give me the following location rules:

    location / {
        if ($arg_service = git-receive-pack) {
            rewrite (/.*) /git_write/$1 last;
        }
    
        if ($uri ~ ^/.*/git-receive-pack$) {
            rewrite (/.*) /git_write/$1 last;
        }
    
        if ($arg_service = git-upload-pack) {
            rewrite (/.*) /git_read/$1 last;
        }
    
        if ($uri ~ ^/.*/git-upload-pack$) {
            rewrite (/.*) /git_read/$1 last;
        }
    }
    
    # pass PHP scripts to FastCGI server
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.3-fpm.sock;
    }
    
    location ~ /git_read/(.*) {
        include git-http-backend.conf;
    }
    
    # require auth to upload
    location ~ /git_write/(.*) {
        auth_basic "Pushing to Git repositories is restricted";
        auth_basic_user_file /etc/nginx/htpasswd;
        include git-http-backend.conf;
    }
    

    Where /etc/nginx/git-http-backend.conf reads:

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

    Problem solved.