How to Enforce SSH Authentication for Git Repositories on EC2 Instances


4 views

When setting up Git repositories on EC2 instances, many developers follow the standard practice of creating a git user and initializing bare repositories with git init --bare. However, this approach often leads to unexpected security vulnerabilities because:


# Default setup that doesn't enforce SSH auth
sudo adduser git
su git
cd /home/git
mkdir project.git
cd project.git
git init --bare

The critical oversight here is that Git's default protocol (git://) uses port 9418 without authentication. Even with SSH keys properly configured in ~/.ssh/authorized_keys, the repository remains accessible anonymously.

To enforce SSH-only access, we need to implement several security measures:


# 1. Disable git protocol in the daemon configuration
sudo nano /etc/git-daemon/conf

# Add these lines:
[daemon]
reuseaddr = true
base-path = /home/git
export-all = no
interpolated-path = no
enable = no  # This disables the git protocol

AWS security groups require specific rules to block unauthorized access:


# AWS CLI command to modify security groups
aws ec2 authorize-security-group-ingress \
  --group-id sg-xxxxxxxx \
  --protocol tcp \
  --port 22 \
  --cidr YOUR_IP_ADDRESS/32

# Explicitly revoke git protocol access
aws ec2 revoke-security-group-ingress \
  --group-id sg-xxxxxxxx \
  --protocol tcp \
  --port 9418 \
  --cidr 0.0.0.0/0

For individual repositories, modify the post-update hook to verify SSH connections:


#!/bin/sh
# File: /home/git/project.git/hooks/post-update

SSH_CONNECTION=$(env | grep SSH_CONNECTION)
if [ -z "$SSH_CONNECTION" ]; then
  echo "FATAL: This repository only accepts pushes via SSH"
  exit 1
fi

exec git update-server-info

For maximum security, restrict the git user to Git operations only:


# Modify the git user's shell configuration
sudo usermod -s /usr/bin/git-shell git

# Create required directories
sudo mkdir /home/git/git-shell-commands
sudo chmod 755 /home/git/git-shell-commands

# Add a custom message
echo "Interactive shell access disabled. Git operations only." | sudo tee /home/git/git-shell-commands/no-interactive-login

This setup ensures that all repository access must authenticate via SSH keys while maintaining the simplicity of Git operations. The configuration works particularly well in AWS environments where you need to balance security with developer productivity.


When setting up a Git repository on an EC2 instance using git init --bare, you might notice that cloning doesn't require SSH authentication. This happens because Git's default protocol (git://) uses port 9418, which doesn't enforce authentication. Here's how to properly secure your repository.

First, ensure the Git daemon isn't running on port 9418:

sudo systemctl stop git-daemon.socket
sudo systemctl disable git-daemon.socket

Modify the repository's configuration to enforce SSH:

cd /path/to/your/repo.git
git config --local receive.denyNonFastForwards true
git config --local receive.denyDeletes true
git config --local core.sharedRepository group

Ensure only the git user can access the repository:

sudo chown -R git:git /path/to/your/repo.git
sudo chmod -R 750 /path/to/your/repo.git

Here's a sample /etc/ssh/sshd_config snippet for Git users:

Match User git
    PasswordAuthentication no
    PubkeyAuthentication yes
    AuthorizedKeysFile /home/git/.ssh/authorized_keys
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand git-shell -c "$SSH_ORIGINAL_COMMAND"

Verify SSH authentication is required:

git clone git@your-ec2-instance:/path/to/repo.git
# Should prompt for SSH key

For additional security, implement a pre-receive hook:

#!/bin/sh
# /path/to/repo.git/hooks/pre-receive
while read oldrev newrev refname; do
    if [ "$(git rev-parse --git-dir)" = "." ]; then
        echo "Direct pushes to this repository are not allowed"
        exit 1
    fi
done

Set up logging for SSH attempts:

sudo grep git /var/log/auth.log
# Or for newer systems:
sudo journalctl -u sshd | grep git