diff options
| -rw-r--r-- | Dockerfile | 32 | ||||
| -rw-r--r-- | cgitrc | 2 | ||||
| -rw-r--r-- | delete-repo | 47 | ||||
| -rwxr-xr-x | entrypoint.sh | 32 | ||||
| -rw-r--r-- | help | 19 | ||||
| -rw-r--r-- | init-repo | 38 | ||||
| -rw-r--r-- | list | 28 | ||||
| -rw-r--r-- | no-interactive-login | 11 | ||||
| -rw-r--r-- | sshd_code_user.conf | 28 |
9 files changed, 232 insertions, 5 deletions
@@ -40,13 +40,37 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-pygments \ tini \ curl \ + openssh-server \ + locales \ && rm -rf /var/lib/apt/lists/* +# Generate locale to fix git locale warnings +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen + COPY --from=build_stage /var/www/html/cgit /var/www/html/cgit -RUN mkdir -p /var/lib/git/repositories \ - && chown -R www-data:www-data /var/www/html/cgit \ - && chown -R www-data:www-data /var/lib/git +RUN mkdir -p /var/lib/git/repositories + +RUN useradd -m -d /var/lib/git/repositories -s /usr/bin/git-shell code + +# Store git-shell-commands in a persistent location (will be copied to home on startup) +RUN mkdir -p /usr/local/share/git-shell-commands +COPY init-repo /usr/local/share/git-shell-commands/init-repo +COPY delete-repo /usr/local/share/git-shell-commands/delete-repo +COPY help /usr/local/share/git-shell-commands/help +COPY list /usr/local/share/git-shell-commands/list +COPY no-interactive-login /usr/local/share/git-shell-commands/no-interactive-login +RUN chmod +x /usr/local/share/git-shell-commands/* + +RUN mkdir -p /run/sshd \ + && mkdir -p /etc/ssh/sshd_config.d + +COPY sshd_code_user.conf /etc/ssh/sshd_config.d/code_user.conf + +RUN chown -R www-data:www-data /var/www/html/cgit \ + && chown -R code:code /var/lib/git/repositories \ + && chmod 755 /var/lib/git \ + && chmod 755 /var/lib/git/repositories RUN rm /etc/nginx/sites-enabled/default @@ -63,6 +87,6 @@ RUN chown -R www-data:www-data /run/sock COPY static /var/www/html/cgit/static -EXPOSE 80 +EXPOSE 80 22 HEALTHCHECK CMD ["curl", "http://localhost:80"] ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"] @@ -1,4 +1,4 @@ -clone-url=ssh://git@src.liz.coffee:2222/$CGIT_REPO_URL +clone-url=https://code.liz.coffee/$CGIT_REPO_URL root-title=/home/liz/src root-desc=⋆⭒˚.⋆ 🐧 <3 ⋆⭒˚.⋆ diff --git a/delete-repo b/delete-repo new file mode 100644 index 0000000..0eecf4c --- /dev/null +++ b/delete-repo @@ -0,0 +1,47 @@ +#!/bin/sh +# Helper script for git-shell to delete bare repositories +# Usage: ssh code@host delete-repo <repo-name> + +if [ $# -ne 1 ]; then + echo "Usage: delete-repo <repo-name>" + echo "Example: delete-repo myproject.git" + exit 1 +fi + +REPO_NAME="$1" + +# Ensure it ends with .git +case "$REPO_NAME" in + *.git) ;; + *) REPO_NAME="${REPO_NAME}.git" ;; +esac + +REPO_DIR="$HOME/$REPO_NAME" + +if [ ! -e "$REPO_DIR" ]; then + echo "Error: Repository '$REPO_NAME' does not exist" + exit 1 +fi + +if [ ! -d "$REPO_DIR" ]; then + echo "Error: '$REPO_NAME' is not a directory" + exit 1 +fi + +# Safety check - make sure it looks like a git repository +if [ ! -f "$REPO_DIR/config" ] || [ ! -d "$REPO_DIR/objects" ]; then + echo "Error: '$REPO_NAME' does not appear to be a git repository" + exit 1 +fi + +echo "WARNING: This will permanently delete the repository '$REPO_NAME'" +echo "Type 'yes' to confirm deletion:" +read -r confirmation + +if [ "$confirmation" = "yes" ]; then + rm -rf "$REPO_DIR" + echo "Repository '$REPO_NAME' has been deleted" +else + echo "Deletion cancelled" + exit 1 +fi diff --git a/entrypoint.sh b/entrypoint.sh index 5bdcede..58aea85 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,6 +2,38 @@ set -e +# Set up git-shell-commands in the repositories directory (volume-safe) +echo "Setting up git-shell-commands..." +mkdir -p /var/lib/git/repositories/git-shell-commands +cp -r /usr/local/share/git-shell-commands/* /var/lib/git/repositories/git-shell-commands/ +chmod +x /var/lib/git/repositories/git-shell-commands/* +chown -R code:code /var/lib/git/repositories +chmod 755 /var/lib/git/repositories + +# Verify setup +echo "Git-shell commands installed:" +ls -la /var/lib/git/repositories/git-shell-commands/ + +# Set up SSH host keys (with volume support) +echo "Setting up SSH host keys..." +mkdir -p /etc/ssh/host_keys + +# Check if host keys are mounted from a volume, if not generate them +if [ -f /etc/ssh/host_keys/ssh_host_rsa_key ]; then + echo "Using existing host keys from volume..." + cp /etc/ssh/host_keys/ssh_host_* /etc/ssh/ +else + echo "Generating new SSH host keys..." + ssh-keygen -A + # Copy generated keys to the persistent location if it's writable + if [ -w /etc/ssh/host_keys ]; then + cp /etc/ssh/ssh_host_* /etc/ssh/host_keys/ 2>/dev/null || true + fi +fi + +echo "Starting SSH daemon..." +/usr/sbin/sshd + echo "Starting fcgiwrap..." su -l www-data -s /bin/bash -c "/usr/sbin/fcgiwrap -s unix:/run/sock/fcgiwrap.socket" & @@ -0,0 +1,19 @@ +#!/bin/sh +# Help command for git-shell + +cat <<'EOF' +Available commands: + init-repo <name> [description] - Initialize a new bare git repository + delete-repo <name> - Delete a repository (requires confirmation) + list - List all repositories + help - Show this help message + +Examples: + init-repo myproject.git "My awesome project" + delete-repo myproject.git + list + +To push to a repository: + git remote add origin ssh://code@host:2222/myproject.git + git push origin main +EOF diff --git a/init-repo b/init-repo new file mode 100644 index 0000000..5749866 --- /dev/null +++ b/init-repo @@ -0,0 +1,38 @@ +#!/bin/sh +# Helper script for git-shell to initialize bare repositories +# Usage: ssh code@host init-repo <repo-name> [description] + +if [ $# -lt 1 ] || [ $# -gt 2 ]; then + echo "Usage: init-repo <repo-name> [description]" + echo "Example: init-repo myproject.git" + echo "Example: init-repo myproject.git 'A repo with foo'" + exit 1 +fi + +REPO_NAME="$1" +DESCRIPTION="$2" + +# Ensure it ends with .git +case "$REPO_NAME" in + *.git) ;; + *) REPO_NAME="${REPO_NAME}.git" ;; +esac + +REPO_DIR="$HOME/$REPO_NAME" + +if [ -e "$REPO_DIR" ]; then + echo "Error: Repository '$REPO_NAME' already exists" + exit 1 +fi + +echo "Initializing bare repository: $REPO_NAME" +git init --bare "$REPO_DIR" + +# Add description if provided +if [ -n "$DESCRIPTION" ]; then + echo "$DESCRIPTION" > "$REPO_DIR/description" + echo "Description set: $DESCRIPTION" +fi + +echo "Repository initialized at: $REPO_DIR" +echo "You can now push to it with: git remote add origin ssh://code@host/$REPO_NAME" @@ -0,0 +1,28 @@ +#!/bin/sh +# List all git repositories + +echo "Available repositories:" +echo "" + +cd "$HOME" || exit 1 + +# Count only .git repositories +repo_count=$(find . -maxdepth 1 -type d -name "*.git" | wc -l) + +if [ "$repo_count" -eq 0 ]; then + echo " (no repositories yet)" + echo "" + echo "Create one with: init-repo <name>" +else + for repo in *.git; do + if [ -d "$repo" ]; then + echo " $repo" + if [ -f "$repo/description" ]; then + desc=$(cat "$repo/description") + if [ "$desc" != "Unnamed repository; edit this file 'description' to name the repository." ]; then + echo " → $desc" + fi + fi + fi + done +fi diff --git a/no-interactive-login b/no-interactive-login new file mode 100644 index 0000000..52d8874 --- /dev/null +++ b/no-interactive-login @@ -0,0 +1,11 @@ +#!/bin/sh +# Git-shell interactive login banner +# When this executable exists, it's shown instead of the default message + +cat <<'EOF' +Welcome to the git repository server! + +Available commands: help, list, init-repo, delete-repo + +Run "help" for more information. +EOF diff --git a/sshd_code_user.conf b/sshd_code_user.conf new file mode 100644 index 0000000..19ef103 --- /dev/null +++ b/sshd_code_user.conf @@ -0,0 +1,28 @@ +# SSH configuration for the "code" user +# This user can only access git repositories and cannot read other system files + +# Explicitly deny root login +PermitRootLogin no + +# Deny user environment manipulation globally +PermitUserEnvironment no + +# Only allow the "code" user to login via SSH +AllowUsers code + +Match User code + # Only allow public key authentication + PubkeyAuthentication yes + PasswordAuthentication no + PermitEmptyPasswords no + + # Use authorized_keys from a volume mount (outside the repositories directory) + AuthorizedKeysFile /etc/ssh/authorized_keys_code + + # Restrict to necessary commands only - harden SSH + X11Forwarding no + AllowTcpForwarding no + AllowAgentForwarding no + PermitTunnel no + GatewayPorts no + PermitTTY yes |
