summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dockerignore2
-rw-r--r--Dockerfile45
-rw-r--r--auth.conf10
-rw-r--r--cgitrc18
-rw-r--r--create-repo.sh43
-rw-r--r--entrypoint.sh50
-rw-r--r--git-http-backend.cgi8
-rw-r--r--healthz1
-rw-r--r--lighttpd.conf43
-rw-r--r--sshd_config17
10 files changed, 237 insertions, 0 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..5dc1898
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+demo/
+.git/
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..d92efca
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,45 @@
+FROM alpine:3.22.4
+
+RUN apk add --no-cache \
+ cgit \
+ git \
+ git-daemon \
+ lighttpd \
+ lighttpd-mod_auth \
+ openssh-server \
+ tini
+
+RUN addgroup -g 1000 -S git \
+ && adduser -u 1000 -S -D -G git -h /var/lib/git -s /usr/bin/git-shell git \
+ && adduser git tty\
+ && passwd -u git \
+ && mkdir -p \
+ /etc/git-host/secrets \
+ /usr/local/libexec \
+ /var/lib/git \
+ /run/git-host/secrets \
+ /run/lighttpd \
+ /run/sshd \
+ /var/tmp/lighttpd \
+ /var/www/localhost/htdocs \
+ && chown -R git:git /var/lib/git
+
+COPY entrypoint.sh /usr/local/bin/entrypoint.sh
+COPY git-http-backend.cgi /usr/local/libexec/git-http-backend.cgi
+COPY create-repo.sh /usr/local/bin/create-repo
+COPY sshd_config /etc/ssh/sshd_config
+COPY cgitrc /etc/cgitrc
+COPY lighttpd.conf /etc/lighttpd/lighttpd.conf
+COPY auth.conf /etc/lighttpd/auth.conf
+COPY healthz /var/www/localhost/htdocs/healthz
+
+RUN chmod 0755 /usr/local/bin/entrypoint.sh /usr/local/libexec/git-http-backend.cgi /usr/local/bin/create-repo \
+ && chown git:git /var/lib/git /run/lighttpd /var/tmp/lighttpd /var/www/localhost/htdocs \
+ && chmod 0755 /run/git-host /run/git-host/secrets \
+ && grep -q "^git:" /etc/passwd \
+ && lighttpd -tt -f /etc/lighttpd/lighttpd.conf
+
+EXPOSE 8080 2222
+VOLUME ["/var/lib/git"]
+
+ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/entrypoint.sh"]
diff --git a/auth.conf b/auth.conf
new file mode 100644
index 0000000..39c7550
--- /dev/null
+++ b/auth.conf
@@ -0,0 +1,10 @@
+auth.backend = "htpasswd"
+auth.backend.htpasswd.userfile = "/run/git-host/secrets/htpasswd"
+
+$HTTP["querystring"] =~ "(^|&)service=git-receive-pack(&|$)" {
+ auth.require = ("" => ("method" => "basic", "realm" => "Git Host", "require" => "valid-user"))
+}
+
+$HTTP["url"] =~ "^/git/.*/git-receive-pack$" {
+ auth.require = ("" => ("method" => "basic", "realm" => "Git Host", "require" => "valid-user"))
+}
diff --git a/cgitrc b/cgitrc
new file mode 100644
index 0000000..02c5e8e
--- /dev/null
+++ b/cgitrc
@@ -0,0 +1,18 @@
+css=/cgit.css
+logo=/cgit.png
+favicon=/favicon.ico
+scan-path=/var/lib/git
+remove-suffix=1
+enable-http-clone=1
+snapshots=tar.gz zip
+root-title=Repositories
+root-desc=Simple Git host
+section-from-path=1
+clone-url=http://$HTTP_HOST/git/%n.git
+clone-url=ssh://git@$HTTP_HOST:%n.git
+about-filter=/usr/lib/cgit/filters/about-formatting.sh
+enable-log-filecount=1
+enable-log-linecount=1
+enable-commit-graph=1
+max-stats=quarter
+virtual-root=/cgit/
diff --git a/create-repo.sh b/create-repo.sh
new file mode 100644
index 0000000..5bc213a
--- /dev/null
+++ b/create-repo.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+set -eu
+
+GIT_REPO_ROOT="${GIT_REPO_ROOT:-/var/lib/git}"
+GIT_USER="${GIT_USER:-git}"
+GIT_GROUP="${GIT_GROUP:-git}"
+
+usage() {
+ echo "usage: create-repo <name> [description]" >&2
+ echo "example: create-repo myrepo 'My application repository'" >&2
+ exit 64
+}
+
+[ "$#" -ge 1 ] || usage
+
+name="$1"
+description="${2:-Unnamed repository}"
+
+case "${name}" in
+ */* | .* | *" "* | *".."* )
+ echo "invalid repository name: ${name}" >&2
+ exit 64
+ ;;
+esac
+
+case "${name}" in
+ *.git) repo_name="${name}" ;;
+ *) repo_name="${name}.git" ;;
+esac
+
+repo_path="${GIT_REPO_ROOT}/${repo_name}"
+
+if [ -e "${repo_path}" ]; then
+ echo "repository already exists: ${repo_path}" >&2
+ exit 1
+fi
+
+install -d -o "${GIT_USER}" -g "${GIT_GROUP}" "${repo_path}"
+git init --bare "${repo_path}" >/dev/null
+printf '%s\n' "${description}" > "${repo_path}/description"
+chown -R "${GIT_USER}:${GIT_GROUP}" "${repo_path}"
+
+echo "created ${repo_path}"
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100644
index 0000000..3737a7e
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+set -Eeuo pipefail
+
+# Copy over the secrets to fix permissions
+mkdir -p /run/git-host/secrets
+cp /etc/git-host/secrets/authorized_keys /run/git-host/secrets/authorized_keys
+cp /etc/git-host/secrets/htpasswd /run/git-host/secrets/htpasswd
+cp /etc/git-host/secrets/ssh_host_ed25519_key /run/git-host/secrets/ssh_host_ed25519_key
+cp /etc/git-host/secrets/ssh_host_ed25519_key.pub /run/git-host/secrets/ssh_host_ed25519_key.pub
+cp /etc/git-host/secrets/ssh_host_rsa_key /run/git-host/secrets/ssh_host_rsa_key
+cp /etc/git-host/secrets/ssh_host_rsa_key.pub /run/git-host/secrets/ssh_host_rsa_key.pub
+chown -R root:root /run/git-host/secrets
+chown root:git /run/git-host/secrets/authorized_keys
+chown root:git /run/git-host/secrets/htpasswd
+chown root:root /run/git-host/secrets/ssh_host_ed25519_key
+chown root:root /run/git-host/secrets/ssh_host_ed25519_key.pub
+chown root:root /run/git-host/secrets/ssh_host_rsa_key
+chown root:root /run/git-host/secrets/ssh_host_rsa_key.pub
+chmod 0755 /run/git-host /run/git-host/secrets
+chmod 0640 /run/git-host/secrets/authorized_keys
+chmod 0640 /run/git-host/secrets/htpasswd
+chmod 0600 /run/git-host/secrets/ssh_host_ed25519_key
+chmod 0644 /run/git-host/secrets/ssh_host_ed25519_key.pub
+chmod 0600 /run/git-host/secrets/ssh_host_rsa_key
+chmod 0644 /run/git-host/secrets/ssh_host_rsa_key.pub
+
+# Validate
+/usr/sbin/sshd -t -f /etc/ssh/sshd_config
+lighttpd -tt -f /etc/lighttpd/lighttpd.conf
+
+# Start servers
+/usr/sbin/sshd -D -e -f /etc/ssh/sshd_config &
+sshd_pid=$!
+
+lighttpd -D -f /etc/lighttpd/lighttpd.conf &
+lighttpd_pid=$!
+
+# Wait for them to end, kill if either does
+terminate() {
+ kill "${sshd_pid}" "${lighttpd_pid}" 2>/dev/null || true
+}
+
+trap terminate INT TERM
+
+status=0
+wait -n "${sshd_pid}" "${lighttpd_pid}" || status=$?
+terminate
+wait "${sshd_pid}" 2>/dev/null || true
+wait "${lighttpd_pid}" 2>/dev/null || true
+exit "${status}"
diff --git a/git-http-backend.cgi b/git-http-backend.cgi
new file mode 100644
index 0000000..960ebc0
--- /dev/null
+++ b/git-http-backend.cgi
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -eu
+
+export GIT_PROJECT_ROOT="${GIT_PROJECT_ROOT:-/var/lib/git}"
+export GIT_HTTP_EXPORT_ALL="${GIT_HTTP_EXPORT_ALL:-1}"
+export HOME="${HOME:-/home/git}"
+
+exec /usr/libexec/git-core/git-http-backend
diff --git a/healthz b/healthz
new file mode 100644
index 0000000..9766475
--- /dev/null
+++ b/healthz
@@ -0,0 +1 @@
+ok
diff --git a/lighttpd.conf b/lighttpd.conf
new file mode 100644
index 0000000..cd9d562
--- /dev/null
+++ b/lighttpd.conf
@@ -0,0 +1,43 @@
+server.modules = (
+ "mod_alias",
+ "mod_auth",
+ "mod_authn_file",
+ "mod_cgi",
+ "mod_rewrite",
+ "mod_setenv"
+)
+
+server.bind = "0.0.0.0"
+server.port = 8080
+server.username = "git"
+server.groupname = "git"
+server.document-root = "/var/www/localhost/htdocs"
+server.pid-file = "/run/lighttpd/lighttpd.pid"
+
+index-file.names = ("index.html")
+
+alias.url = (
+ "/cgit.cgi" => "/usr/share/webapps/cgit/cgit.cgi",
+ "/cgit.css" => "/usr/share/webapps/cgit/cgit.css",
+ "/cgit.png" => "/usr/share/webapps/cgit/cgit.png",
+ "/cgit" => "/usr/share/webapps/cgit/cgit.cgi",
+ "/favicon.ico" => "/usr/share/webapps/cgit/favicon.ico",
+ "/robots.txt" => "/usr/share/webapps/cgit/robots.txt",
+ "/git" => "/usr/local/libexec/git-http-backend.cgi"
+)
+
+url.rewrite-once = (
+ "^/$" => "/cgit"
+)
+
+cgi.assign = (
+ ".cgi" => ""
+)
+
+setenv.add-environment = (
+ "CGIT_CONFIG" => "/etc/cgitrc",
+ "GIT_PROJECT_ROOT" => "/var/lib/git",
+ "GIT_HTTP_EXPORT_ALL" => "1"
+)
+
+include "/etc/lighttpd/auth.conf"
diff --git a/sshd_config b/sshd_config
new file mode 100644
index 0000000..3b5c369
--- /dev/null
+++ b/sshd_config
@@ -0,0 +1,17 @@
+Port 2222
+ListenAddress 0.0.0.0
+HostKey /run/git-host/secrets/ssh_host_ed25519_key
+HostKey /run/git-host/secrets/ssh_host_rsa_key
+PidFile /run/sshd/sshd.pid
+AuthorizedKeysFile /run/git-host/secrets/authorized_keys
+PasswordAuthentication no
+KbdInteractiveAuthentication no
+ChallengeResponseAuthentication no
+PermitRootLogin no
+PermitTunnel no
+AllowTcpForwarding no
+X11Forwarding no
+PermitTTY no
+PrintMotd no
+AllowUsers git
+Subsystem sftp internal-sftp