feat(software/hosting-a-git-server): complete

This commit is contained in:
Barrett Ruth 2025-05-14 13:50:17 -04:00
parent 731ad1f1f8
commit 87e2851324
4 changed files with 181 additions and 0 deletions

View file

@ -0,0 +1,137 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles/common.css" />
<link rel="stylesheet" href="/styles/post.css" />
<link rel="icon" type="image/webp" href="/public/logo.webp" />
<link href="/public/prism/prism.css" rel="stylesheet" />
<link href="/public/prism/prism-theme.css" rel="stylesheet" />
<script defer src="/public/prism/prism.js"></script>
<title>hosting a git server</title>
</head>
<body class="graph-background">
<site-header></site-header>
<main class="main">
<div class="post-container">
<header class="post-header">
<h1 class="post-title">hosting a git server</h1>
<p class="post-meta">
<time datetime="2025-05-7">7/05/2025</time>
</p>
</header>
<article class="post-article">
<h2>why</h2>
<p>
No reason. Perhaps to host personal files in the future. AWS's
<a href="" target="_blank">micro free tier</a> is great, too.
</p>
<h2>what</h2>
<ul>
<li>Write my own git web ui</li>
<li>Support clones from my own website</li>
<li>Host private files on my git ui</li>
</ul>
<h2>the process</h2>
<ol>
<p>
I detail self-hosting a git server on an AWS t2.micro instance
("free" for 1 year) as of May 2025.
<a
href="https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols"
target="_blank"
>Git's instructions</a
>
were vastly outdated so hopefully this saves a lucky reader some
time.
</p>
<li>
Create the ec2 instance with setup wizard and add {in,out}bound
rules for {SSH,HTTP,HTTPS,your ip} in the wizard security group.
</li>
<li>
Use an elastic ip (free) to address public ip
reassigning&mdash;this is a bother when ssh'ing (new verb?) into
the box locally and/or configuring an Apache HTTP server.
</li>
<li>Understand bare git repositories and the ssh protocol.</li>
<li>
Configure an keypair and ssh in (the official instructions are
fine for this). I moved it to <code>~/.ssh</code> and added an
alias in <code>~/.ssh/config</code> for convenience. Clone a repo
on the server to test.
</li>
<li>
Set up a git daemon for <code>git://</code> protocol cloning at
your own risk.
</li>
<li>Set up an Apache HTTPD server.</li>
<li>
Configure file permissions for the new user:
<ol>
<li><code>sudo chown -R git:git /srv/git</code></li>
<li><code>sudo chgrp -R apache /srv/git</code></li>
</ol>
</li>
<li>
To deal with "dubious ownership" issues when cloning with HTTPS, I
needed to add <b>exactly</b> the following configuration to
<code>/etc/gitconfig</code>.
<i>No group permission finagling will work</i>! Git only allows
cloning repositories that are owned by the user. If you wish to
clone via SSH with, say, user A, this same user must also be
employed by your HTTP server to clone the files (customize
HTTPD/whatever you're using accordingly).
</li>
<div class="code" data-file="gitconfig.git"></div>
<li>
Security-wise, set up TLS/HTTPS with
<a href="https://letsencrypt.org/" target="_blank"
>Let's Encrypt</a
>. Further, only allow authorized people to actually
<i>push</i> to the server. The following is my HTTPD configuration
file
<code>/etc/apache/conf.d/git-server.conf</code>
hosting the web ui at the root and clone urls at
<code>/git</code>:
</li>
<div class="code" data-file="git-server.apacheconf"></div>
<li>
There are a variety of choices for web ui, including
<a href="https://git.zx2c4.com/cgit/" target="_blank">cgit</a>,
<a href="https://git-scm.com/docs/gitweb" target="_blank">gitweb</a>
(I do not recommend this&mdash;the scripts are ancient and require
manual tuning), and some even heavier options that allow for
further customization. I am not a fan of viewing code on the web,
so you cannot in
<a href="https://git.barrettruth.com" target="_blank"
>my custom ui</a
>. I spin up a simple python server to walk the projects in
<code>/srv/git</code> and configured a systemd service to run it
in the ec2 box:
</li>
<div class="code" data-file="git-server-ui.systemd">
</div>
</ol>
<h2>lessons</h2>
<ul>
<li>
<b>It feels great to do things yourself</b>: I used GPT-4o for
linux server command help, that was about it
</li>
<li>
<b>Always ask "what is this?" before using something</b>: this
would've saved me hours of realizing a 12 year old perl script
should not have been running my git ui.
</li>
</ul>
</article>
</div>
</main>
<site-footer></site-footer>
<script src="/scripts/common.js"></script>
<script src="/scripts/post.js"></script>
</body>
</html>

View file

@ -0,0 +1,12 @@
[Unit]
Description=Git Server UI
After=network.target
[Service]
User=apache
WorkingDirectory=/srv/git/git-server-ui
ExecStart=/root/.local/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 --chdir /srv/git wsgi:app
Restart=on-failure
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,30 @@
<VirtualHost *:443>
ServerName <servername>
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/<servername>/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/<servername>/privkey.pem
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv REMOTE_USER $REDIRECT_REMOTE_USER
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
<Directory "/usr/libexec/git-core">
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Require all granted
AllowOverride None
</Directory>
<Files "git-http-backend">
AuthType Basic
AuthName "Git Access"
AuthUserFile /srv/git/.htpasswd
Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
Require valid-user
</Files>
ProxyPassMatch ^/git/ !
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
</VirtualHost>

View file

@ -0,0 +1,2 @@
[safe]
directory = *