gslewis.id.au:~
The Bedlington Ape

Failing with git-http-backend on Rocky Linux 10

My problem is: I am unable to get git push to work with a repository using the git-http-backend CGI handler on Rocky Linux 10. My solution is: use something other than a RHEL 10-based distribution or something other than "Smart HTTP" to access the repository. I could get the git-http-backend method to work on Slackware, Rocky Linux 9, and Debian 13.6. These are my notes on what I tried, what worked, and what didn’t.

Why git-http-backend? If you want to self-host a git repository on a remote server the usual options are:

  • ssh — recommended, especially if you already do everything with SSH.
  • git — no authentication so only suitable for public read-only repositories.
  • http — can use standard HTTP authentication for restricted read/write access.

See the "Git on the Server" chapter of the Pro Git book for the details.

I needed to collaborate with a friend who isn’t a regular Linux or SSH user so I figured the simplest way to set up a non-public repository that we can both access is using the "Smart HTTP" protocol for git. I plan to host the repository on my personal VPS running Rocky Linux 10.

The packages I required on top of a minimal Rocky 10 install are:

  • httpd and httpd-tools
  • certbot and python3-certbot-apache (so I can enable SSL via LetsEncrypt)
  • git

At the time of testing, Rocky Linux 10.2 was providing httpd-2.4.63 and git-2.52.0.

Preparing the git repository for HTTP access

My repositories are located in /srv/git/ on the host. This directory and its repositories must belong to the web server’s group (in this case "apache") and be group-writeable in order for git push to have a chance of working.

### On my local PC
# Create a bare clone of the repository
git clone --bare my_proj my_proj.git

# Copy the bare repo to the remote host
scp -r my_proj.git gsl@server.gslewis.id.au:my_proj

### On the remote host, as root
# Move the repository to /srv/git
mv ~gsl/my_proj /srv/git/

# Set group and write permissions on all repos to the web server group
chgrp -R apache /srv/git/
chmod -R g+w /srv/git/

We also need to either disable SELinux or change the context of the /srv/git/ directory so that it can be read from and written to by the web server. I usually just disable SELinux (see /etc/selinux/config for instructions) but I did test (and fail) with SELinux enabled as well.

If we were using SSH with multiple users pushing to the repository, it would be necessary to re-init the repository as shared:

cd /srv/git/my_repo
git init --bare --shared

However, as I am using HTTP then all writes will be as the web server’s user so the repository doesn’t need to be shared.

To simplify matters, I also "disable" the git safe directory check by treating all repositories as safe, system-wide.

git config --system --add safe.directory "*"

This creates the /etc/gitconfig file if not already present.

Web server configuration

I am using Apache httpd as the web server with digest authentication to restrict access. Based on the Pro Git chapter on Smart HTTP, the basic <VirtualHost> entry I created was:

/etc/httpd/conf.d/default.conf
 <VirtualHost _default_:443>
    ServerName https://server.gslewis.id.au

    # A bunch of SSL-related directives for LetsEncrypt certs.

    SetEnv GIT_PROJECT_ROOT /srv/git
    SetEnv GIT_HTTP_EXPORT_ALL
    SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
    ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/

    <Location /git>
        AuthName "Git Access"
        AuthType Digest
        AuthUserFile /etc/httpd/auth/git-users.htdigest
        Require valid-user
    </Location>
</VirtualHost>

This configures git-http-backend as the CGI script handler for the URL path /git/ which will match repositories in the /srv/git directory.

For each user I want to grant access to the repositories, I use htdigest to populate the git-users.htdigest file.

# Create the htdigest file and add myself (gsl)
htdigest -c /etc/httpd/auth/git-users.htdigest "Git Access" gsl

Git clone and push

Given I have my repository at /srv/git/my_repo, I can now clone it as follows which works as expected, prompting for a username and password that was added to the htdigest file.

Clone the repository over HTTPS
gsl@sula:~/workspace$ git clone https://server.gslewis.id.au/git/my_repo
Cloning into 'my_repo'...
Username for 'https://server.gslewis.id.au': gsl
Password for 'https://gsl@server.gslewis.id.au':
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 17 (delta 8), reused 15 (delta 6), pack-reused 0 (from 0)
Receiving objects: 100% (17/17), 6.30 KiB | 6.30 MiB/s, done.
Resolving deltas: 100% (8/8), done.

All fine and dandy. Now make a change, commit it and push it up to the server.

Push a change back to the server
gsl@sula:~/workspace/my_repo$ git commit -a -m "Testing push"
[master 5fb4dbb] Testing push
 1 file changed, 1 insertion(+)

gsl@sula:~/workspace/my_repo$ git push
Username for 'https://server.gslewis.id.au': gsl
Password for 'https://gsl@server.gslewis.id.au':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 288 bytes | 288.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
remote: error: unable to create temporary file: Operation not permitted
remote: fatal: failed to write object
error: remote unpack failed: unpack-objects abnormal exit
To https://server.gslewis.id.au/git/my_repo
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'https://server.gslewis.id.au/git/my_repo'

I spent the best part of a day fiddling around on the usually correct assumption that I had done something wrong (which still may be the case) but my RHEL sysadmin and git knowledge was not sufficient to fix the problem.

As far as I can tell, the problem isn’t with the Apache setup: there is no push-related message in the error_log and the entries in the access_log is the expected sequence of GET and POST requests starting with the "401 Unauthorized" GET request that leads to the prompt for htdigest username and password.

/var/log/httpd/access_log
... - [14/Aug/2026:14:37:38 +1000] "GET /git/my_repo/info/refs?service=git-receive-pack HTTP/1.1" 401 381 "-" "git/2.55.0"
... gsl [14/Aug/2026:14:37:43 +1000] "GET /git/my_repo/info/refs?service=git-receive-pack HTTP/1.1" 200 224 "-" "git/2.55.0"
... gsl [14/Aug/2026:14:37:43 +1000] "POST /git/my_repo/git-receive-pack HTTP/1.1" 200 197 "-" "git/2.55.0"

I can see that the /srv/git/my_repo/objects directory in the bare repository has its timestamp updated to match the time of the POST request but nothing is changed within that directory. Where exactly git is trying to create the temporary file, I don’t know. The httpd process has a systemd-provided "PrivateTmp" directory under /tmp.

As mentioned above, I also tried re-enabling SELinux, on the very unlikely possibility that actually having SELinux on would fix a problem. This involved installing the policycoreutils-python-utils package to get the semanage utility which I could then use to set the context of the /srv/git directory so that it was readable and writeable by the httpd process.

semanage fcontext -a -t httpd_sys_rw_content_t "/srv/git(/.*)?"
restorecon -vR /srv/git/

Not surprisingly, I get the exact same git push error as with SELinux disabled.

What works?

My initial assumption was that something was wrong with git-http-backend, with my Apache configuration, or with my file and directory permissions. Before giving up, I thought I would try another distribution. Recall that Rocky Linux 10.2 was using httpd-2.4.63 and git-2.52.0.

First up was Slackware64-current with httpd-2.4.68 and git-2.55.0. I setup Apache on a laptop (no SSL) and repeated the git repository setup process. Both the git clone and the git push steps worked fine.

I then tried a bunch of server distributions in QEMU VMs with user networking.

  • Debian 13.6 (httpd-2.4.68, git-2.47.3) worked.
  • Almalinux 10.2 (httpd-2.4.63, git-2.52.0) failed.
  • Rocky Linux 9.8 (httpd-2.4.62, git-2.52.0) worked.

The conclusion then is that the problem is with RHEL 10 and its derivatives or with my lack of knowledge of how to properly adminster them. The choice I have to make is either stick to Rocky 10 and use SSH to access the repository or switch to a distribution in which the "Smart HTTP" method works.

The Bedlington Ape Back to the home page