shell Git Command Guide
The git shell command provides a restricted shell environment that only allows Git operations, making it ideal for securing remote Git access. It restricts users to Git commands only, preventing general shell access while allowing full Git repository operations.
git shell Syntax:
Section titled “git shell Syntax:”git shell [-c <command>]Options:
Section titled “Options:”| Option | Description |
|---|---|
-c <command> | Execute specific command in git shell |
Parameters:
Section titled “Parameters:”None - operates as interactive shell or executes single command
Understanding Git Shell:
Section titled “Understanding Git Shell:”Restricted Shell Environment:
Section titled “Restricted Shell Environment:”Git Shell Restrictions:├── Only Git commands allowed├── No general shell access├── No file system browsing├── No arbitrary command execution├── Controlled Git operations only└── Secure remote accessShell Operation Modes:
Section titled “Shell Operation Modes:”Git Shell Modes:├── Interactive: Provides Git command prompt├── Single Command: Execute one Git command├── SSH Integration: Used with SSH forced commands├── User Restriction: Limits user capabilities└── Audit Trail: Logs all Git operationsSecurity Model:
Section titled “Security Model:”Security Architecture:├── SSH Key Authentication: Required for access├── Command Whitelisting: Only Git commands permitted├── Path Restriction: Limited to Git repositories├── No Shell Escapes: Cannot break out to system shell└── Access Logging: All operations are loggedBasic Git Shell Operations:
Section titled “Basic Git Shell Operations:”Interactive Shell Usage:
Section titled “Interactive Shell Usage:”# Start interactive git shellgit shell
# Git shell prompt (limited commands)git> git --versiongit> git statusgit> exitSingle Command Execution:
Section titled “Single Command Execution:”# Execute single git commandgit shell -c "git --version"
# Run git statusgit shell -c "git status"
# Execute complex git commandgit shell -c "git log --oneline -5"SSH Integration:
Section titled “SSH Integration:”# SSH with git shell (server side)# In ~/.ssh/authorized_keys:command="git shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@host
# Client connects normallyssh git@server# Automatically enters git shellAdvanced Git Shell Scenarios:
Section titled “Advanced Git Shell Scenarios:”Server Configuration:
Section titled “Server Configuration:”# Configure git shell as user shellsudo usermod -s /usr/bin/git-shell gituser
# Create git user with restricted shellsudo useradd -m -s /usr/bin/git-shell gituser
# Setup SSH keys for git usersudo -u gituser mkdir -p /home/gituser/.sshsudo -u gituser chmod 700 /home/gituser/.ssh
# Add authorized keyssudo -u gituser tee /home/gituser/.ssh/authorized_keys << EOFcommand="git shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... developer@company.comEOFRepository Access Control:
Section titled “Repository Access Control:”# Setup repository with git shell accesssudo mkdir -p /srv/git/project.gitsudo chown gituser:gituser /srv/git/project.gitsudo -u gituser git init --bare /srv/git/project.git
# Configure repository permissionssudo -u gituser chmod -R 755 /srv/git/project.git
# Client accessgit clone git@server:/srv/git/project.gitMulti-Repository Setup:
Section titled “Multi-Repository Setup:”# Setup multiple repositoriessudo mkdir -p /srv/gitsudo chown gituser:gituser /srv/git
# Create repositoriessudo -u gituser mkdir /srv/git/repo1.git /srv/git/repo2.gitsudo -u gituser git init --bare /srv/git/repo1.gitsudo -u gituser git init --bare /srv/git/repo2.git
# Client access to specific reposgit clone git@server:repo1.gitgit clone git@server:repo2.gitCustom Git Shell Commands:
Section titled “Custom Git Shell Commands:”# Create custom git shell commandssudo mkdir -p /usr/local/lib/git-shell-commands
# Add custom commandsudo tee /usr/local/lib/git-shell-commands/help << 'EOF'#!/bin/bashecho "Available commands:"echo " git-receive-pack <repo> - Push to repository"echo " git-upload-pack <repo> - Pull from repository"echo " git-upload-archive <repo> - Archive repository"echo " help - Show this help"EOF
sudo chmod +x /usr/local/lib/git-shell-commands/helpConfiguration and Best Practices:
Section titled “Configuration and Best Practices:”Git Shell Configuration:
Section titled “Git Shell Configuration:”# Configure git shell behaviorexport GIT_SHELL_LOG=/var/log/git-shell.log # Log file location
# Configure allowed commandsGIT_SHELL_COMMANDS="/usr/local/lib/git-shell-commands"
# Configure repository pathsGIT_REPOS="/srv/git"
# Configure SSH optionsGIT_SHELL_SSH_OPTS="no-port-forwarding,no-X11-forwarding,no-agent-forwarding"Security Best Practices:
Section titled “Security Best Practices:”# Use dedicated git usersudo useradd -r -s /usr/bin/git-shell git
# Restrict SSH access# Only allow git operationscommand="git shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-X11-forwarding,no-agent-forwarding
# Use SSH keys only# Disable password authentication for git user
# Regular permission auditsfind /srv/git -type d -exec chmod 755 {} \;find /srv/git -type f -exec chmod 644 {} \;Access Control:
Section titled “Access Control:”# Per-user repository accesssudo -u gituser mkdir -p /srv/git/user-specificsudo -u gituser chmod 700 /srv/git/user-specific
# Group-based accesssudo groupadd git-developerssudo usermod -a -G git-developers gituser
# Repository permissionssudo chown -R gituser:git-developers /srv/git/project.gitsudo chmod -R 770 /srv/git/project.gitIntegration with Development Workflows:
Section titled “Integration with Development Workflows:”SSH Server Setup:
Section titled “SSH Server Setup:”#!/bin/bash# Complete git shell server setup
setup_git_server() { local git_user="git" local git_home="/home/$git_user" local repos_dir="/srv/git"
echo "Setting up Git server with git-shell..."
# Create git user sudo useradd -m -s /usr/bin/git-shell "$git_user"
# Setup SSH directory sudo -u "$git_user" mkdir -p "$git_home/.ssh" sudo -u "$git_user" chmod 700 "$git_home/.ssh"
# Setup repositories directory sudo mkdir -p "$repos_dir" sudo chown "$git_user:$git_user" "$repos_dir" sudo chmod 755 "$repos_dir"
# Configure SSH sudo tee /etc/ssh/sshd_config.d/git-shell.conf << EOF# Git shell configurationMatch User $git_user ForceCommand git shell -c "\$SSH_ORIGINAL_COMMAND" PermitTTY no PermitTunnel no AllowAgentForwarding no AllowTcpForwarding no X11Forwarding noEOF
# Restart SSH sudo systemctl restart sshd
echo "Git server setup complete" echo "Add SSH keys to $git_home/.ssh/authorized_keys" echo "Create repositories in $repos_dir"}
setup_git_serverRepository Management:
Section titled “Repository Management:”# Automated repository creationcreate_git_repo() { local repo_name="$1" local repos_dir="/srv/git" local git_user="git"
echo "Creating repository: $repo_name"
# Create bare repository sudo -u "$git_user" mkdir -p "$repos_dir/$repo_name.git" sudo -u "$git_user" git init --bare "$repos_dir/$repo_name.git"
# Set permissions sudo chown -R "$git_user:$git_user" "$repos_dir/$repo_name.git" sudo chmod -R 755 "$repos_dir/$repo_name.git"
# Initialize with post-receive hook for notifications sudo -u "$git_user" tee "$repos_dir/$repo_name.git/hooks/post-receive" << 'EOF'#!/bin/bashecho "Push received in $PWD" >> /var/log/git-pushes.logecho "User: $USER" >> /var/log/git-pushes.logecho "Command: $SSH_ORIGINAL_COMMAND" >> /var/log/git-pushes.logecho "---" >> /var/log/git-pushes.logEOF
sudo chmod +x "$repos_dir/$repo_name.git/hooks/post-receive"
echo "Repository created: $repo_name" echo "Clone URL: git@server:$repo_name.git"}
create_git_repo "my-project"Access Logging and Monitoring:
Section titled “Access Logging and Monitoring:”# Git shell access loggingsetup_logging() { echo "Setting up git shell logging..."
# Create log directory sudo mkdir -p /var/log/git-shell sudo chown git:git /var/log/git-shell
# Configure rsyslog for git shell sudo tee /etc/rsyslog.d/git-shell.conf << 'EOF'# Git shell logging:programname, isequal, "git-shell" /var/log/git-shell/auth.log& stopEOF
sudo systemctl restart rsyslog
# Custom git shell wrapper for logging sudo tee /usr/local/bin/git-shell-logged << 'EOF'#!/bin/bashLOG_FILE="/var/log/git-shell/$(date +%Y%m%d).log"echo "$(date): $USER@$SSH_CLIENT: $SSH_ORIGINAL_COMMAND" >> "$LOG_FILE"
/usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"EOF
sudo chmod +x /usr/local/bin/git-shell-logged sudo ln -sf /usr/local/bin/git-shell-logged /usr/bin/git-shell}
setup_loggingTroubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”SSH Connection Issues:
Section titled “SSH Connection Issues:”# Test SSH connectionssh -T git@server
# Check SSH key setupssh-keygen -l -f ~/.ssh/id_rsa.pub
# Verify authorized_keys formatcat ~/.ssh/authorized_keys
# Check SSH server configurationssh -v git@serverPermission Issues:
Section titled “Permission Issues:”# Check repository permissionsls -la /srv/git/project.git/
# Fix ownershipsudo chown -R git:git /srv/git/project.git
# Check file permissionsfind /srv/git/project.git -type f -exec ls -l {} \; | head -5
# Verify git user accesssudo -u git ls -la /srv/git/Command Execution Issues:
Section titled “Command Execution Issues:”# Test git shell directlysudo -u git /usr/bin/git-shell -c "git --version"
# Check PATH in git shellsudo -u git /usr/bin/git-shell -c "echo \$PATH"
# Verify git commands worksudo -u git /usr/bin/git-shell -c "which git"
# Check for missing commandssudo -u git /usr/bin/git-shell -c "git --help | head -5"Repository Access Issues:
Section titled “Repository Access Issues:”# Test repository accesssudo -u git git ls-remote /srv/git/project.git
# Check repository validitysudo -u git git --git-dir=/srv/git/project.git fsck
# Verify remote setupgit remote -v
# Test push accessgit push git@server:project.git mainLogging and Debugging:
Section titled “Logging and Debugging:”# Check git shell logstail -f /var/log/git-shell/auth.log
# Enable verbose SSH loggingssh -vv git@server
# Debug git operationsGIT_TRACE=1 git clone git@server:project.git
# Check system logsjournalctl -u sshd | grep gitReal-World Usage Examples:
Section titled “Real-World Usage Examples:”Enterprise Git Server Setup:
Section titled “Enterprise Git Server Setup:”#!/bin/bash# Enterprise-grade git server with git-shell
enterprise_git_server() { echo "=== Enterprise Git Server Setup ==="
# Server configuration GIT_USER="git" GIT_HOME="/home/$GIT_USER" REPOS_BASE="/srv/git/repositories" LOG_DIR="/var/log/git-server"
# Create git user sudo useradd -r -m -d "$GIT_HOME" -s /usr/bin/git-shell "$GIT_USER"
# Setup directories sudo mkdir -p "$REPOS_BASE" "$LOG_DIR" sudo chown "$GIT_USER:$GIT_USER" "$REPOS_BASE" "$LOG_DIR"
# Configure SSH sudo tee /etc/ssh/sshd_config.d/git-server.conf << EOFMatch User $GIT_USER ForceCommand /usr/local/bin/git-shell-wrapper PermitTTY no PermitTunnel no AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no PasswordAuthentication noEOF
# Create git shell wrapper sudo tee /usr/local/bin/git-shell-wrapper << 'EOF'#!/bin/bashLOG_FILE="/var/log/git-server/$(date +%Y%m%d).log"
# Log the accessecho "$(date '+%Y-%m-%d %H:%M:%S') $USER $SSH_CLIENT $SSH_ORIGINAL_COMMAND" >> "$LOG_FILE"
# Execute git commandexec /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"EOF
sudo chmod +x /usr/local/bin/git-shell-wrapper
# Setup log rotation sudo tee /etc/logrotate.d/git-server << EOF/var/log/git-server/*.log { daily rotate 30 compress missingok notifempty create 644 $GIT_USER $GIT_USER}EOF
# Restart services sudo systemctl restart sshd sudo systemctl restart logrotate
echo "Enterprise git server setup complete" echo "Add developer SSH keys to $GIT_HOME/.ssh/authorized_keys"}
enterprise_git_serverRepository Access Control System:
Section titled “Repository Access Control System:”# Advanced access control with git-shell
access_control_system() { echo "=== Git Repository Access Control ==="
# Configuration CONTROL_FILE="/etc/git-access-control.conf" ALLOWED_USERS="/etc/git-allowed-users"
# Create control script sudo tee /usr/local/bin/git-access-control << 'EOF'#!/bin/bashREPO_PATH="$1"USER="$2"
# Check if user is allowedif ! grep -q "^$USER$" /etc/git-allowed-users; then echo "Access denied: User $USER not authorized" exit 1fi
# Check repository permissionsREPO_NAME=$(basename "$REPO_PATH" .git)USER_PERMS="/etc/git-repo-perms/$REPO_NAME"
if [ -f "$USER_PERMS" ]; then if ! grep -q "^$USER:" "$USER_PERMS"; then echo "Access denied: User $USER not authorized for $REPO_NAME" exit 1 fi
# Check operation permissions USER_LINE=$(grep "^$USER:" "$USER_PERMS") PERMS=$(echo "$USER_LINE" | cut -d: -f2)
case "$SSH_ORIGINAL_COMMAND" in *git-receive-pack*) if [[ "$PERMS" != *"write"* ]]; then echo "Access denied: No write permission for $REPO_NAME" exit 1 fi ;; *git-upload-pack*) if [[ "$PERMS" != *"read"* ]]; then echo "Access denied: No read permission for $REPO_NAME" exit 1 fi ;; esacfi
# Log accessecho "$(date): $USER accessed $REPO_NAME ($SSH_ORIGINAL_COMMAND)" >> /var/log/git-access.log
# Allow accessexec /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"EOF
sudo chmod +x /usr/local/bin/git-access-control
# Setup permission files sudo mkdir -p /etc/git-repo-perms sudo tee /etc/git-allowed-users << 'EOF'alicebobcharlieEOF
# Example repo permissions sudo tee /etc/git-repo-perms/secret-project << 'EOF'alice:read,writebob:readEOF
echo "Access control system configured" echo "Update /etc/git-allowed-users and /etc/git-repo-perms/*"}
access_control_systemCI/CD Integration:
Section titled “CI/CD Integration:”# Git shell for CI/CD systems
ci_cd_integration() { echo "=== CI/CD Git Shell Integration ==="
# Create CI user sudo useradd -r -m -d /home/ci -s /usr/bin/git-shell ci
# Setup SSH for CI sudo -u ci mkdir -p /home/ci/.ssh sudo -u ci chmod 700 /home/ci/.ssh
# CI-specific authorized keys sudo -u ci tee /home/ci/.ssh/authorized_keys << 'EOF'command="/usr/local/bin/ci-git-shell",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... ci-server@company.comEOF
# Create CI git shell sudo tee /usr/local/bin/ci-git-shell << 'EOF'#!/bin/bashLOG_FILE="/var/log/ci-git.log"
# Validate CI operationscase "$SSH_ORIGINAL_COMMAND" in *git-upload-pack*) # Allow pulls echo "$(date): CI pull by $USER" >> "$LOG_FILE" ;; *git-receive-pack*) # Restrict pushes - only allow to specific branches if [[ "$SSH_ORIGINAL_COMMAND" == *refs/heads/ci/* ]]; then echo "$(date): CI push to ci/ branch by $USER" >> "$LOG_FILE" else echo "CI can only push to ci/* branches" exit 1 fi ;; *) echo "Command not allowed for CI user" exit 1 ;;esac
# Execute commandexec /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"EOF
sudo chmod +x /usr/local/bin/ci-git-shell
echo "CI/CD git shell integration complete" echo "CI can now safely access repositories"}
ci_cd_integrationBackup and Recovery System:
Section titled “Backup and Recovery System:”# Git shell for backup operations
backup_system() { echo "=== Git Backup System ==="
# Create backup user sudo useradd -r -m -d /home/backup -s /usr/bin/git-shell backup
# Setup backup repositories BACKUP_ROOT="/srv/git-backups" sudo mkdir -p "$BACKUP_ROOT" sudo chown backup:backup "$BACKUP_ROOT"
# Backup script sudo tee /usr/local/bin/git-backup << 'EOF'#!/bin/bashSOURCE_REPO="$1"BACKUP_NAME="$(basename "$SOURCE_REPO" .git)-$(date +%Y%m%d-%H%M%S)"
echo "Creating backup: $BACKUP_NAME"
# Create backup directorysudo -u backup mkdir -p "/srv/git-backups/$BACKUP_NAME"
# Mirror repositorysudo -u backup git clone --mirror "$SOURCE_REPO" "/srv/git-backups/$BACKUP_NAME"
# Compress backupcd /srv/git-backupstar czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME"rm -rf "$BACKUP_NAME"
echo "Backup created: /srv/git-backups/${BACKUP_NAME}.tar.gz"
# Cleanup old backups (keep last 7 days)find /srv/git-backups -name "*.tar.gz" -mtime +7 -deleteEOF
sudo chmod +x /usr/local/bin/git-backup
# Scheduled backup sudo tee /etc/cron.daily/git-backups << 'EOF'#!/bin/bash# Daily git repository backups
REPOS="/srv/git/*.git"BACKUP_SCRIPT="/usr/local/bin/git-backup"
for repo in $REPOS; do if [ -d "$repo" ]; then $BACKUP_SCRIPT "$repo" fidoneEOF
sudo chmod +x /etc/cron.daily/git-backups
echo "Git backup system configured" echo "Daily backups will be created in /srv/git-backups"}
backup_systemMonitoring and Alerting:
Section titled “Monitoring and Alerting:”# Git shell monitoring and alerting
monitoring_system() { echo "=== Git Shell Monitoring ==="
# Setup monitoring script sudo tee /usr/local/bin/git-monitor << 'EOF'#!/bin/bashLOG_FILE="/var/log/git-shell/monitor.log"ALERT_EMAIL="admin@company.com"
# Monitor active connectionsACTIVE_CONNECTIONS=$(netstat -tn | grep :22 | grep ESTABLISHED | wc -l)echo "$(date): Active SSH connections: $ACTIVE_CONNECTIONS" >> "$LOG_FILE"
# Check disk usageDISK_USAGE=$(df /srv/git | tail -1 | awk '{print $5}' | sed 's/%//')if [ "$DISK_USAGE" -gt 90 ]; then echo "ALERT: Disk usage high ($DISK_USAGE%)" | mail -s "Git Server Disk Alert" "$ALERT_EMAIL"fi
# Check repository integrityfor repo in /srv/git/*.git; do if ! sudo -u git git --git-dir="$repo" fsck --quiet >/dev/null 2>&1; then echo "ALERT: Repository corruption in $(basename "$repo")" | mail -s "Git Repository Corruption" "$ALERT_EMAIL" fidone
# Monitor access patternsTODAY=$(date +%Y%m%d)ACCESS_COUNT=$(grep "$TODAY" /var/log/git-shell/auth.log | wc -l)echo "$(date): Daily access count: $ACCESS_COUNT" >> "$LOG_FILE"
# Alert on unusual activityif [ "$ACCESS_COUNT" -gt 1000 ]; then echo "ALERT: High access volume ($ACCESS_COUNT requests today)" | mail -s "Git Server High Activity" "$ALERT_EMAIL"fiEOF
sudo chmod +x /usr/local/bin/git-monitor
# Setup cron monitoring sudo tee /etc/cron.hourly/git-monitoring << 'EOF'#!/bin/bash/usr/local/bin/git-monitorEOF
sudo chmod +x /etc/cron.hourly/git-monitoring
# Setup log directories sudo mkdir -p /var/log/git-shell sudo chown git:git /var/log/git-shell
echo "Git shell monitoring configured" echo "Hourly monitoring reports in /var/log/git-shell/"}
monitoring_systemWhat’s the difference between git shell and regular shell?
Section titled “What’s the difference between git shell and regular shell?”git shell restricts users to Git commands only, preventing general system access. Regular shell allows full system access.
How do I configure SSH to use git shell?
Section titled “How do I configure SSH to use git shell?”Set user’s shell to git-shell: sudo usermod -s /usr/bin/git-shell username
Can git shell execute arbitrary commands?
Section titled “Can git shell execute arbitrary commands?”No, git shell only allows Git commands. Any other commands are rejected.
How do I setup git shell for multiple users?
Section titled “How do I setup git shell for multiple users?”Create separate system users, each with git-shell as their shell, and manage SSH keys individually.
What’s the difference between git shell and gitolite?
Section titled “What’s the difference between git shell and gitolite?”gitolite is a more advanced access control system built on git shell. git shell is the basic restricted shell.
Can I customize allowed commands in git shell?
Section titled “Can I customize allowed commands in git shell?”Yes, place custom commands in /usr/local/lib/git-shell-commands/ directory.
How do I log git shell activities?
Section titled “How do I log git shell activities?”Configure syslog or use wrapper scripts to log all git shell operations.
Can git shell work with HTTP?
Section titled “Can git shell work with HTTP?”No, git shell is designed for SSH access only.
How do I troubleshoot git shell connection issues?
Section titled “How do I troubleshoot git shell connection issues?”Check SSH configuration, verify user shell setting, and test with ssh -v git@server
Can git shell restrict access to specific repositories?
Section titled “Can git shell restrict access to specific repositories?”Use SSH forced commands or custom git shell wrappers to implement repository-level access control.
What’s the performance impact of git shell?
Section titled “What’s the performance impact of git shell?”Minimal - it’s just a command wrapper. Git operations themselves determine performance.
Can git shell work with Git LFS?
Section titled “Can git shell work with Git LFS?”Yes, git shell allows all Git operations, including LFS commands.
How do I migrate from regular shell to git shell?
Section titled “How do I migrate from regular shell to git shell?”Change user shell with usermod, ensure SSH keys are properly configured, test access.
Applications of the git shell command
Section titled “Applications of the git shell command”- Secure Remote Access: Provide Git-only access to servers without full shell access
- Repository Hosting: Run Git servers with restricted user capabilities
- CI/CD Security: Allow automated systems Git access without shell privileges
- Access Control: Implement basic user isolation for Git operations
- Audit Trails: Log all Git operations for compliance and monitoring
- Backup Systems: Enable secure backup operations with limited access
- Development Environments: Provide controlled Git access in shared environments
- Enterprise Security: Meet security requirements for Git server deployments