How single-user Git-over-SSH works
I had to read through so much source code to figure this out
Have you ever wondered how GitHub, GitLab, Gogs, Gitea, and so on allow multiple users to push and pull data from repos with only one unix user? Perhaps you want to know how this is done so you can write your own version of the aforementioned type of software that doesn't suck. That's how I got here. Anyway, this is how it's done:
OpenSSH gives you an option (ForceCommand in /etc/ssh/sshd_config) to force
the use of a particular command on connection, overriding the one the client
actually wants to run. When this option is set, the client's "intended command"
gets stored in an environment variable called $SSH_ORIGINAL_COMMAND. This can
be used to force the execution of your own script (or binary) that allows and
disallows "intended commands" each time anyone tries to do anything with this
account over SSH.
Additionally, the ~/.ssh/authorized_keys file allows you to specify
a per-key forced command. This means that you can set an option (say,
--with-key) for the per-key override that isn't present in the global
override in /etc/ssh/sshd_config. Now, in your forced command, you can
disallow write access to connections that are missing the --with-key argument,
since it's only present if a user has uploaded an SSH key.
Even further, you can provide the --with-key argument a key_id value that
allows your software to know exactly which key was used for this connection.
With that information, you can associate the SSH key with a user account and,
for example, allow them extra read/write access to their private repositories
and extra write access to their public ones. It's up to your software to keep
a database of key_id <-> SSH key <-> user associations, however.
While you're messing with the sshd_config, you'll need to add
PermitEmptyPasswords yes and you'll probably also want to add
DisableForwarding yes. Thankfully, you can restrict the effects of those two
options to apply only to your software's user and not to everyone on the server
by using a Match section. All together, your sshd_config will have a new
section like this:
Match User your_software_user
PermitEmptyPasswords yes
DisableForwarding yes
ForceCommand /path/to/your/software
References
man 5 sshd_configfor/etc/ssh/sshd_configoptionsman 8 sshdfor~/.ssh/authorized_keysfile format and options- Both of the above for the uses of the
$SSH_ORIGINAL_COMMANDenvironment variable - The Gogs codebase for reverse-engineering all of the above