Restricted shell for SSH-only Git accounts.
git shell is a restricted login shell that only speaks Git. Set it as the git user's login shell on a server so SSH keys can push/fetch but cannot get an interactive shell.
Think of it as a tiny allow-list dispatcher: SSH hands it a command string, it accepts only git-upload-pack, git-receive-pack, git-upload-archive (plus anything you drop into git-shell-commands/), and rejects everything else.
git-shell [-c <command>]
# /etc/passwd entry
git:x:1001:1001::/home/git:/usr/bin/git-shell
# ad-hoc allow-list
~git/git-shell-commands/<name> # executable scripts callable by name
~git/git-shell-commands/no-interactive-login # custom banner on bare ssh| Flag | What it does |
|---|---|
-c <cmd> | Run the given Git command string (this is what sshd passes in) |
(no args) | Interactive mode; runs scripts from git-shell-commands/ if present, else exits |
git-shell-commands/help | Optional script listed when the user types help |
git-shell-commands/no-interactive-login | If present, controls the message shown for bare ssh logins |
chsh -s /usr/bin/git-shell git | ⚠️ Activates the restriction for the git user — verify SSH still works first |
git user has no interactive shellgit@host:repo.gitecho /usr/bin/git-shell | sudo tee -a /etc/shells && sudo chsh -s /usr/bin/git-shell gitgit-shell -c 'git-upload-pack /srv/git/repo.git'sudo install -m 755 mkrepo.sh ~git/git-shell-commands/mkrepossh git@127.0.0.1 mkrepo new-projectgit accountgit-shell for anything beyond a handful of reposgit-shell-commands/ minimal and audited; every script there is effectively a privilege boundary/usr/bin/git-shell to /etc/shells — chsh will refuse on most distrosgit-shell provides per-repo ACLs; it doesn't — it's all-or-nothing per Unix usergit user with bash 'just for setup' and never switching backHit each option, then Check answers. Score is recorded; Next is always open.