nginx + git-http-backend on CentOS 7

2019-01-29 - Fixed a lot of stupid errors. Had too many cups of coffee and lost my ability to proofread apparently. Going to write up a followup post with enabling SSL and installing GitWeb as well.

Up until this point, I’ve been using my Guacamole server to SSH in to my web server and edit my posts using Vim. I use VSCode for basically everything else, so it’d be way more convenient to edit my posts in that, and then use git to push them to my server and have Jekyll automatically rebuild the site. Having the option to use HTTP as well as SSH is preferable considering I do a lot of work away from my main laptop, and SSH isn’t always an option.

I’m going to assume you already have a working nginx installation. There are a lot of other tutorials out there that explain this better than I could. I’d suggest this one from DigitalOcean. You’ll also need git installed. If you don’t have it, run:

yum install git-core

git configuration

To start, you’ll want to get a git directory set up. I chose to use /var/git as my root. htpasswd will generate an htpasswd file for something to authenticate against.

mkdir /var/git
htpasswd -c /etc/nginx/htpasswd <user name>
chown -R nginx:nginx /var/git
chmod 700 /etc/nginx/htpasswd

FCGI configuration

CentOS 7 doesn’t offer fcgiwrap in its repos, so we’ll have to build it from source.

yum install fcgi-devel spawn-fcgi
git clone https://github.com/gnosek/fcgiwrap.git
cd fcgiwrap
autoreconf -i
./configure
make
make install

fcgiwrap should have compiled and should now exist at /usr/local/sbin/fcgiwrap. Now we need to configure /etc/sysconfig/spawn-fcgi to start fcgiwrap.

# You must set some working options before the "spawn-fcgi" service will work.
# If SOCKET points to a file, then this file is cleaned up by the init script.
#
# See spawn-fcgi(1) for all possible options.

FCGI_SOCKET=/var/run/fcgiwrap.socket
FCGI_PROGRAM=/usr/local/sbin/fcgiwrap
FCGI_USER=nginx
FCGI_GROUP=nginx
FCGI_EXTRA_OPTIONS="-M 0770"
OPTIONS="-u $FCGI_USER -g $FCGI_GROUP -s $FCGI_SOCKET -S $FCGI_EXTRA_OPTIONS -F 1 -P /var/run/spawn-fcgi.pid -- $FCGI_PROGRAM"

At this point, we can start and enable spawn-fcgi (systemctl enable spawn-fcgi && systemctl start spawn-fcgi). The only thing that should remain is configuring nginx.

nginx configuration

Configuration on nginx’s side is pretty normal, with some additional git configuration:

server {
        listen       80;
        listen       [::]:80;
        server_name  git.uvclay.com
        root         /var/git;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    index index.html;

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

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }

    location ~ (/.*) {
        client_max_body_size 0;
        auth_basic "Git Login";
        auth_basic_user_file "/etc/nginx/htpasswd";
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param GIT_PROJECT_ROOT /var/git;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param PATH_INFO $1;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
    }
}

Test your configuration file (nginx -t) and ensure that there are no errors, and then restart nginx (systemctl restart nginx). If you hit git.your.website, you should be prompted with a basic auth window. To test that you’re able to push to your repo, run:

mkdir /var/git/test.git
cd /var/git/test.git
git init --bare
git update-server-info
echo "test" > testfile
git add testfile
git commit -m 'This is a test.'
git remote add origin git.your.website/test.git
git push origin master

If all goes well, you should be prompted for a username and password, and git should push your test file properly. Check the repo on your server and hopefully everything checks out. I didn’t cover SSL configuration, but Let’s Encrypt, specifically certbot, has documentation on configuring nginx on CentOS 7 and automating certificate renewal.