summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-12-05 21:43:18 -0800
committerElizabeth Hunt <me@liz.coffee>2025-12-05 22:19:52 -0800
commit8667f8615da479a8e9c4e8d5bb5987632d75bfaf (patch)
treee3b4bdb4ebe4f0010c90dd43970822bbe8f8d4a6
parent4cde5dedcf35f2d5850ce0479f25d29bac74daf7 (diff)
downloadwwwgit-8667f8615da479a8e9c4e8d5bb5987632d75bfaf.tar.gz
wwwgit-8667f8615da479a8e9c4e8d5bb5987632d75bfaf.zip
Add ssh server
-rw-r--r--Dockerfile32
-rw-r--r--cgitrc2
-rw-r--r--delete-repo47
-rwxr-xr-xentrypoint.sh32
-rw-r--r--help19
-rw-r--r--init-repo38
-rw-r--r--list28
-rw-r--r--no-interactive-login11
-rw-r--r--sshd_code_user.conf28
9 files changed, 232 insertions, 5 deletions
diff --git a/Dockerfile b/Dockerfile
index c310452..ecb4743 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -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"]
diff --git a/cgitrc b/cgitrc
index 124bd83..0ffd3a6 100644
--- a/cgitrc
+++ b/cgitrc
@@ -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" &
diff --git a/help b/help
new file mode 100644
index 0000000..28e383e
--- /dev/null
+++ b/help
@@ -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"
diff --git a/list b/list
new file mode 100644
index 0000000..43cc82b
--- /dev/null
+++ b/list
@@ -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