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