Github is probably the most famous and most used hoster for git repositories. It does not only provide hosting for the repository itself, but it also provides ticket management, wikis, website hosting, ci integration, binary hosting for releases and more.

What I don't like is to depend on it. With every feature of github I use, it becomes more difficult to host my projects myself. While I can mirgrate most things (code, releases, issues, wiki pages) with an medium effort some things are mostly out of my control. With that I mean the build scripts of maintainers pointing to github as the officіal project page and using github as source for their builds and other external things, that now assume, that github is the official page.

While the features of github are pretty neat, I really don't like the risk of github changing in a way that would make hosting my projects there unfavorable. I still remember the debacle with SourceForge.

On the other hand github became the de facto standard for OSS hosting. When a project does not have a github page, it might seem old and outdated. I also think that github makes contributions from other people much more likely, because it's just so convenient.

A (partial) solution

So what do I do now? Github was in the past the official home of my projects. How can I cange that?

I plan to migrate away in small steps. The first one is to host the code myself. But I still want the code to be available on github. I want an automatic way to reflect all changes in my self-hosted git repository on github.

To do this I added an git hook to the repositories I host:

$GIT_DIR/hooks/post-receive
#!/bin/bash

if git push github -f --mirror; then
        echo 'Successfully mirrored to github'
else
        echo 'Error while mirroring to github'
fi

Here "github" is the name of the remote that points to my project on github. But how does authentification work?

Since ssh іs used for pushing the default ssh key of the user is used. But who is the user? It should be the user of the httpd process. To be really sure I used the following hook first:

$GIT_DIR/hooks/post-receive
#!/bin/bash

echo $(id)

After a test commit I got the following response on the client:

Counting objects: 62, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (50/50), done.
Writing objects: 100% (62/62), 15.50 KiB | 1.11 MiB/s, done.
Total 62 (delta 4), reused 10 (delta 0)
remote: uid=33(http) gid=33(http) groups=33(http)
To https://git.serra.dynamic-dns.net/ballot/
 + 96cef0d...3da39d3 master ->; master (forced update)

The http user had no ssh key yet so I created one. For me the easiest way to do that was to log in as the http user and configure these things:

chsh -s /bin/bash http
su - http
ssh-keygen -t ed25519 -C "$(whoami)@$(hostname)-$(date -I)"
chsh -s /bin/nologin http

Now I get the following output when pushing to my remote:

Counting objects: 62, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (50/50), done.
Writing objects: 100% (62/62), 15.50 KiB | 992.00 KiB/s, done.
Total 62 (delta 4), reused 10 (delta 0)
remote: To github.com:Serranya/ballot.git
remote:  + 865cdfa...575156d master -> master (forced update)
remote:  * [new branch]      github/master -> github/master
remote:  * [new branch]      github/reportsBug -> github/reportsBug
remote: Successfully mirrored to github
To https://git.serra.dynamic-dns.net/ballot/
 + 865cdfa...575156d master -> master (forced update)