stagit

static git page generator
git clone https://git.awy.one/stagit
Log | Files | Refs | README | LICENSE

commit 2f3f377efaa4ebd1c37be9a52333ea7adc34f57a
parent 263db88c61de2ed322c8e211046eac864977acbe
Author: awy <awy@awy.one>
Date:   Sun, 26 Apr 2026 18:08:39 +0300

docker

Diffstat:
ADockerfile | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocker-compose.yml | 12++++++++++++
Adocker/config.rc | 6++++++
Adocker/entrypoint.sh | 36++++++++++++++++++++++++++++++++++++
Adocker/git-scripts/create | 3+++
Adocker/git-scripts/rebuild | 3+++
Adocker/nginx.conf | 24++++++++++++++++++++++++
Adocker/post-receive | 20++++++++++++++++++++
Adocker/sshd_config | 14++++++++++++++
Adocker/style.css | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 366 insertions(+), 0 deletions(-)

diff --git a/Dockerfile b/Dockerfile @@ -0,0 +1,85 @@ +FROM alpine:latest AS build + +RUN apk add --no-cache \ + build-base \ + git \ + go \ + libgit2-dev \ + md4c-dev + +RUN git clone https://github.com/alecthomas/chroma /tmp/chroma && \ + cd /tmp/chroma && \ + git checkout v2.14.0 && \ + cd cmd/chroma && \ + CGO_ENABLED=0 go build -o /tmp/install/usr/local/bin/chroma-v2 . + +RUN git clone https://codeberg.org/awy/stagit /tmp/stagit && \ + cd /tmp/stagit && \ + make CFLAGS="-O2" && \ + make install DESTDIR=/tmp/install + +FROM alpine:latest + +RUN apk add --no-cache \ + git \ + git-daemon \ + openssh-server \ + libgit2 \ + md4c \ + fcgiwrap \ + nginx \ + spawn-fcgi \ + su-exec \ + ca-certificates + +RUN addgroup -S git && \ + adduser -S -G git -h /home/git -s /usr/bin/git-shell git && \ + sed -i 's/^git:!:/git:*:/' /etc/shadow + +RUN mkdir -p /home/git/.ssh && \ + mkdir -p /home/git/git-shell-commands && \ + chmod 700 /home/git/.ssh + +RUN mkdir -p /home/git/hooks +COPY docker/git-scripts/create /home/git/git-shell-commands +COPY docker/git-scripts/rebuild /home/git/git-shell-commands +RUN chown -R git:git /home/git + +COPY --from=build /tmp/install/usr/local/bin/stagit /usr/local/bin/stagit +COPY --from=build /tmp/install/usr/local/bin/stagit-index /usr/local/bin/stagit-index +COPY --from=build /tmp/install/usr/local/bin/stagit-gen-index /usr/local/bin/stagit-gen-index +COPY --from=build /tmp/install/usr/local/bin/stagit-newrepo /usr/local/bin/stagit-newrepo +COPY --from=build /tmp/install/usr/local/bin/stagit-rebuild-all /usr/local/bin/stagit-rebuild-all +COPY --from=build /tmp/install/usr/local/bin/chroma-v2 /usr/local/bin/chroma-v2 +COPY docker/sshd_config /etc/ssh/sshd_config + +RUN mkdir -p \ + /srv/git/repos \ + /srv/git/repos/template \ + /var/www/git \ + /run/nginx \ + /run/fcgiwrap && \ + chown -R git:git /srv/git /var/www/git /run/fcgiwrap && \ + chmod +x \ + /usr/local/bin/stagit \ + /usr/local/bin/stagit-index \ + /usr/local/bin/stagit-gen-index \ + /usr/local/bin/stagit-newrepo \ + /usr/local/bin/stagit-rebuild-all \ + /usr/local/bin/chroma-v2 + +COPY docker/config.rc /home/git/config.rc +COPY docker/post-receive /home/git/hooks/post-receive +COPY docker/nginx.conf /etc/nginx/http.d/default.conf +COPY docker/entrypoint.sh /entrypoint.sh +COPY docker/style.css /var/www/git/style.css + +RUN chown git:git \ + /home/git/config.rc \ + /var/www/git/style.css && \ + chmod +x \ + /entrypoint.sh + +EXPOSE 80 + +CMD ["/entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml @@ -0,0 +1,12 @@ +services: + stagit: + image: stagit:latest + container_name: stagit + restart: unless-stopped + ports: + - "2222:22" + volumes: + - ./repos:/srv/git + - ./www:/var/www/git + - ./ssh/authorized_keys:/home/git/.ssh/authorized_keys + - ./ssh/hostkeys:/etc/ssh/hostkeys diff --git a/docker/config.rc b/docker/config.rc @@ -0,0 +1,6 @@ +GIT_HOME="/srv/git" +WWW_HOME="/var/www/git" +CLONE_URI="https://git.example.com" +DEFAULT_OWNER="cat" +DEFAULT_DESCRIPTION="description" +GIT_USER="git" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/sh +set -eu + +mkdir -p /run/nginx /run/fcgiwrap /run/sshd /etc/ssh/hostkeys +chown -R git:git /run/fcgiwrap +chown -R git:git /srv/git +chown -R git:git /var/www/git +chown -R git:git /home/git/.ssh + +# Generate persistent SSH host keys only once +if [ ! -f /etc/ssh/hostkeys/ssh_host_ed25519_key ]; then + ssh-keygen -t ed25519 -f /etc/ssh/hostkeys/ssh_host_ed25519_key -N '' +fi + +if [ ! -f /etc/ssh/hostkeys/ssh_host_rsa_key ]; then + ssh-keygen -t rsa -b 4096 -f /etc/ssh/hostkeys/ssh_host_rsa_key -N '' +fi + +chmod 700 /home/git/.ssh +chmod 600 /home/git/.ssh/authorized_keys +chmod 600 /etc/ssh/hostkeys/ssh_host_*_key +chmod 644 /etc/ssh/hostkeys/ssh_host_*_key.pub + +spawn-fcgi \ + -s /run/fcgiwrap/fcgiwrap.sock \ + -U nginx \ + -G nginx \ + -u git \ + -g git \ + -- /usr/bin/fcgiwrap + +su-exec git:git stagit-rebuild-all + +/usr/sbin/sshd + +nginx -g 'daemon off;' diff --git a/docker/git-scripts/create b/docker/git-scripts/create @@ -0,0 +1,3 @@ +#!/bin/sh + +stagit-newrepo "$1" "$2" "$3" diff --git a/docker/git-scripts/rebuild b/docker/git-scripts/rebuild @@ -0,0 +1,3 @@ +#!/bin/sh + +stagit-rebuild-all diff --git a/docker/nginx.conf b/docker/nginx.conf @@ -0,0 +1,24 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + server_name _; + + root /var/www/git; + index index.html; + + location / { + try_files $uri $uri/ =404; + } + + # clone by http + location ~ /.+/(info/refs|git-upload-pack) { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend; + fastcgi_param PATH_INFO $uri; + fastcgi_param GIT_HTTP_EXPORT_ALL ""; + fastcgi_param GIT_PROJECT_ROOT /srv/git; + fastcgi_param HOME /srv/git; + fastcgi_pass unix:/run/fcgiwrap/fcgiwrap.sock; + } +} diff --git a/docker/post-receive b/docker/post-receive @@ -0,0 +1,20 @@ +#!/bin/sh +# Author: Cale "poptart" Black +# License: MIT + +set -euf +. /home/git/config.rc +export LC_CTYPE='en_US.UTF-8' +src="$(pwd)" +name=$(basename "$src") +dst="$WWW_HOME/$(basename "$name" '.git')" +mkdir -p "$dst" +cd "$dst" || exit 1 +echo "[stagit] building $dst" +/usr/local/bin/stagit "$src" +echo "[stagit] linking $dst" +ln -sf log.html index.html +ln -sf ../style.css style.css +ln -sf ../logo.png logo.png +echo "[stagit] updating index" +/usr/local/bin/stagit-gen-index diff --git a/docker/sshd_config b/docker/sshd_config @@ -0,0 +1,14 @@ +Port 22 +HostKey /etc/ssh/hostkeys/ssh_host_ed25519_key +HostKey /etc/ssh/hostkeys/ssh_host_rsa_key +PermitRootLogin no +PubkeyAuthentication yes +PasswordAuthentication no +KbdInteractiveAuthentication no +X11Forwarding no +PrintMotd no +AcceptEnv LANG LC_* COLORTERM NO_COLOR +Subsystem sftp /usr/lib/openssh/sftp-server +ClientAliveInterval 120 +AllowUsers git +AuthorizedKeysFile .ssh/authorized_keys diff --git a/docker/style.css b/docker/style.css @@ -0,0 +1,163 @@ +body { + color: #000; + background-color: #fff; + font-family: monospace; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 1em; + margin: 0; +} + +img, h1, h2 { + vertical-align: middle; +} + +a:target { + background-color: #ccc; +} + +img { + border: 0; +} + +a.d, +a.h, +a.i, +a.line { + text-decoration: none; +} + +/* +a { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +}*/ + +#blob a { + color: #777; +} + +#blob a:hover { + color: blue; + text-decoration: none; +} + +table thead td { + font-weight: bold; +} + +table td { + padding: 0 0.4em; +} + +#content table td { + vertical-align: top; + white-space: nowrap; +} + +#branches tr:hover td, +#tags tr:hover td, +#index tr:hover td, +#log tr:hover td, +#files tr:hover td { + background-color: #eee; +} + +#index tr td:nth-child(2), +#tags tr td:nth-child(3), +#branches tr td:nth-child(3), +#log tr td:nth-child(2) { + white-space: normal; +} + +td.num { + text-align: right; +} + +.desc { + color: #777; +} + +hr { + border: 0; + border-top: 1px solid #777; + height: 1px; +} + +pre { + font-family: monospace; +} + +pre a.h { + color: #00a; +} + +.A, +span.i, +pre a.i { + color: #070; +} + +.D, +span.d, +pre a.d { + color: #e00; +} + +pre a.h:hover, +pre a.i:hover, +pre a.d:hover { + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + body { + background-color: #000; + color: #bdbdbd; + } + hr { + border-color: #222; + } + a { + color: #56c8ff; + } + a:target { + background-color: #222; + } + .desc { + color: #aaa; + } + #blob a { + color: #555; + } + #blob a:target { + color: #eee; + } + #blob a:hover { + color: #56c8ff; + } + pre a.h { + color: #00cdcd; + } + .A, + span.i, + pre a.i { + color: #00cd00; + } + .D, + span.d, + pre a.d { + color: #cd0000; + } + #branches tr:hover td, + #tags tr:hover td, + #index tr:hover td, + #log tr:hover td, + #files tr:hover td { + background-color: #111; + } +}