Add tested rootless SSH passthrough configuration to the docs #8057

Closed
opened 2025-11-02 07:52:32 -06:00 by GiteaMirror · 8 comments
Owner

Originally created by @rmsc on GitHub (Oct 31, 2021).

Feature Description

I found a simple and effective way to set up an SSH passthrough that works with the rootless docker image. It leverages the AuthorizedKeysCommand configuration in sshd, and doesn't require mounting the ~/.ssh directory or synchronizing the authorized_keys file between host and container. It also works fine with the internal gitea ssh server.

I've tested it under podman, but it should work with docker as well. I can write and submit a PR for the rootless documentation.

I suspect it would also work for the rootfull docker image, but haven't tested. It's a lot simpler to setup than the current method, so if valid it could also replace it.

The details are as follows for podman, but will likely work for docker by just changing the binary name:

In the host, create an executable containing the following, replacing with the actual name of the container:

# cat /usr/bin/gitea-shell
#!/bin/bash
/usr/bin/podman exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" <container-name> bash "$@"

Then set it as the shell for the gitea user (git in this case) on the host:

# usermod -s /usr/bin/gitea-shell git

Finally add the following to /etc/ssh/sshd_config, also replacing with the actual container name:

Match User git
  AuthorizedKeysCommandUser git
  AuthorizedKeysCommand /usr/bin/podman exec -i <container-name> /usr/local/bin/gitea keys -c /etc/gitea/app.ini -u %u -t %t -k %k

Don't forget to restart sshd for these settings to take effect:

# systemctl restart sshd

And that's it.

EDIT: forgot to remove the -t options from podman exec. These can modify the output and break the git protocol.

Screenshots

No response

Originally created by @rmsc on GitHub (Oct 31, 2021). ### Feature Description I found a simple and effective way to set up an SSH passthrough that works with the rootless docker image. It leverages the AuthorizedKeysCommand configuration in sshd, and doesn't require mounting the `~/.ssh` directory or synchronizing the `authorized_keys` file between host and container. It also works fine with the internal gitea ssh server. I've tested it under podman, but it should work with docker as well. I can write and submit a PR for the rootless documentation. I suspect it would also work for the rootfull docker image, but haven't tested. It's a lot simpler to setup than the current method, so if valid it could also replace it. The details are as follows for podman, but will likely work for docker by just changing the binary name: In the host, create an executable containing the following, replacing <container-name> with the actual name of the container: ```bash # cat /usr/bin/gitea-shell #!/bin/bash /usr/bin/podman exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" <container-name> bash "$@" ``` Then set it as the shell for the gitea user (`git` in this case) on the host: ```bash # usermod -s /usr/bin/gitea-shell git ``` Finally add the following to `/etc/ssh/sshd_config`, also replacing <container-name> with the actual container name: ```bash Match User git AuthorizedKeysCommandUser git AuthorizedKeysCommand /usr/bin/podman exec -i <container-name> /usr/local/bin/gitea keys -c /etc/gitea/app.ini -u %u -t %t -k %k ``` Don't forget to restart sshd for these settings to take effect: ```bash # systemctl restart sshd ``` And that's it. EDIT: forgot to remove the `-t` options from `podman exec`. These can modify the output and break the git protocol. ### Screenshots _No response_
Author
Owner

@zeripath commented on GitHub (Oct 31, 2021):

Do feel like putting writing this up in to a PR?

The file to edit is: https://github.com/go-gitea/gitea/blob/main/docs/content/doc/installation/with-docker-rootless.en-us.md

@zeripath commented on GitHub (Oct 31, 2021): Do feel like putting writing this up in to a PR? The file to edit is: https://github.com/go-gitea/gitea/blob/main/docs/content/doc/installation/with-docker-rootless.en-us.md
Author
Owner

@rmsc commented on GitHub (Oct 31, 2021):

PR created. I've tried to keep the style consistent with the rest of the docs, but may have missed something. Comments and edits are welcome 😄

@rmsc commented on GitHub (Oct 31, 2021): PR created. I've tried to keep the style consistent with the rest of the docs, but may have missed something. Comments and edits are welcome :smile:
Author
Owner

@rmsc commented on GitHub (Nov 1, 2021):

Addressed by #17508

@rmsc commented on GitHub (Nov 1, 2021): Addressed by #17508
Author
Owner

@peterbabic commented on GitHub (Jan 7, 2022):

  1. What user:group should the gitea-shell be? If owned entirely by root:root, a a git user trying to login cannot even execute this file.
  2. More importantly, how can a git user access a rootless Docker socket owned a by a different non-root user that owns the Gitea rootless container in question? I cannot even list rootless containers as a root proper on the host, not to mention multi-user access to a single rootless container.
@peterbabic commented on GitHub (Jan 7, 2022): 1. What user:group should the `gitea-shell` be? If owned entirely by root:root, a a git user trying to login cannot even execute this file. 1. More importantly, how can a `git` user access a rootless Docker socket owned a by a different non-root user that owns the Gitea rootless container in question? I cannot even list rootless containers as a root proper on the host, not to mention multi-user access to a single rootless container.
Author
Owner

@rmsc commented on GitHub (Jan 7, 2022):

  1. What user:group should the gitea-shell be? If owned entirely by root:root, a a git user trying to login cannot even execute this file.

I think in most cases root:root ownership and permissions set to 0755 should work fine. It's a shell after all, just like bash.

2. More importantly, how can a `git` user access a rootless Docker socket owned a by a different non-root user that owns the Gitea rootless container in question? I cannot even list rootless containers as a root proper on the host, not to mention multi-user access to a single rootless container.

In simple terms, that's indeed a limitation of the method: you must login to the host account owning the container.

Can't you just login as the user owning the container, instead of as git?

There may be a way of "aliasing" your user to git, but I haven't tested it. Try it at your own risk. It involves creating a git user with the same UID/GID as the user owning the container, and with the same home directory.

@rmsc commented on GitHub (Jan 7, 2022): > 1. What user:group should the `gitea-shell` be? If owned entirely by root:root, a a git user trying to login cannot even execute this file. I think in most cases `root:root` ownership and permissions set to `0755` should work fine. It's a shell after all, just like bash. > 2. More importantly, how can a `git` user access a rootless Docker socket owned a by a different non-root user that owns the Gitea rootless container in question? I cannot even list rootless containers as a root proper on the host, not to mention multi-user access to a single rootless container. In simple terms, that's indeed a limitation of the method: you must login to the host account owning the container. Can't you just login as the user owning the container, instead of as `git`? There may be a way of "aliasing" your user to `git`, but I haven't tested it. **Try it at your own risk**. It involves creating a `git` user with the same UID/GID as the user owning the container, and with the same home directory.
Author
Owner

@peterbabic commented on GitHub (Jan 8, 2022):

Thank you for a quick answer. But my head still hurts from trying to wrap this around. If I had to either of the two steps, it wouldn't be a problem.

But how do I combine them? If I make only a single user running that rootless container and that user does not have a login shell, instead just a script then I have no way of managing that user. It would require some kind of way to switch the login shell to to either work as a SSH passtrough or as a login shell, but I currently do not see it working as both at the same time, as is.

Can you please confirm this observation, so I know my current understanding is correct?

UPDATE: I think I've found something relevant:

https://man.archlinux.org/man/core/openssh/sshd_config.5.en#AuthorizedKeysCommand
https://man.openbsd.org/sshd_config#AuthorizedKeysCommand

Specifies a program to be used to generate the list of allowed certificate principals as per AuthorizedPrincipalsFile. The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to AuthorizedPrincipalsCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used.

@peterbabic commented on GitHub (Jan 8, 2022): Thank you for a quick answer. But my head still hurts from trying to wrap this around. If I had to either of the two steps, it wouldn't be a problem. But how do I combine them? If I make only a single user running that rootless container and that user does not have a login shell, instead just a script then I have no way of managing that user. It would require some kind of way to switch the login shell to to either work as a SSH passtrough or as a login shell, but I currently do not see it working as both at the same time, as is. Can you please confirm this observation, so I know my current understanding is correct? **UPDATE:** I think I've found something relevant: https://man.archlinux.org/man/core/openssh/sshd_config.5.en#AuthorizedKeysCommand https://man.openbsd.org/sshd_config#AuthorizedKeysCommand > Specifies a program to be used to generate the list of allowed certificate principals as per AuthorizedPrincipalsFile. **The program must be owned by root, not writable by group or others** and specified by an absolute path. Arguments to AuthorizedPrincipalsCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used.
Author
Owner

@rmsc commented on GitHub (Jan 8, 2022):

But how do I combine them? If I make only a single user running that rootless container and that user does not have a login shell, instead just a script then I have no way of managing that user. It would require some kind of way to switch the login shell to to either work as a SSH passtrough or as a login shell, but I currently do not see it working as both at the same time, as is.

Ah I now understand your problem. Here's how I do it:

  • I have the git user own the container, but have no ssh access to the host (only the to guest, arguably more secure)
  • I have another user for system management, say me, with permissions to run sudo -u git

Then if you want a bash shell running under the git user, it's a matter of doing something like this:

$ ssh me@host 'sudo -u git bash'

UPDATE: I think I've found something relevant:

https://man.archlinux.org/man/core/openssh/sshd_config.5.en#AuthorizedKeysCommand https://man.openbsd.org/sshd_config#AuthorizedKeysCommand

You got it, the two steps have different purposes. The AuthorizedKeysCommand is meant as a way of validating ssh keys against those on the gitea database inside the container. The gitea-shell is an ssh passthrough to the container, AFTER the keys have been validated.

@rmsc commented on GitHub (Jan 8, 2022): > But how do I combine them? If I make only a single user running that rootless container and that user does not have a login shell, instead just a script then I have no way of managing that user. It would require some kind of way to switch the login shell to to either work as a SSH passtrough or as a login shell, but I currently do not see it working as both at the same time, as is. Ah I now understand your problem. Here's how I do it: - I have the `git` user own the container, but have no ssh access to the host (only the to guest, arguably more secure) - I have another user for system management, say `me`, with permissions to run `sudo -u git` Then if you want a bash shell running under the `git` user, it's a matter of doing something like this: ``` $ ssh me@host 'sudo -u git bash' ``` > **UPDATE:** I think I've found something relevant: > > https://man.archlinux.org/man/core/openssh/sshd_config.5.en#AuthorizedKeysCommand https://man.openbsd.org/sshd_config#AuthorizedKeysCommand You got it, the two steps have different purposes. The `AuthorizedKeysCommand` is meant as a way of validating ssh keys against those on the gitea database inside the container. The `gitea-shell` is an ssh passthrough to the container, AFTER the keys have been validated.
Author
Owner

@peterbabic commented on GitHub (Jan 8, 2022):

After three days it finally works. I too do not make a root access over ssh, but instead on a dedicated user, as you mentioned.

Most of my problems were related to the absence of the environmental variables:

export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

Which resolves to:

export DOCKER_HOST=unix:///run/user/1000/docker.sock

Such an environmental variable has to be present for both docker exec commands, which you described as "two steps". This means I had to create two separate executable scripts, which export the variable before calling docker, because AuthorizedKeysCommand requires an absolute path where the env variables cannot be prepended. This made the setup working.

I was even able to login into the git user from root by specifying a shell (my other issue mentioned above), which overrides our script:

su -l git -s /bin/bash

But this way, the XDG_RUNTIME_DIR is not available, so the DOCKER_HOST collapses just to:

unix:///docker.sock

And has to be re-exported to a correct value to use docker commands. Leaving these notes here for a further reference.

@peterbabic commented on GitHub (Jan 8, 2022): After three days it finally works. I too do not make a root access over ssh, but instead on a dedicated user, as you mentioned. Most of my problems were related to the absence of the environmental variables: `export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock` Which resolves to: `export DOCKER_HOST=unix:///run/user/1000/docker.sock` Such an environmental variable has to be present for both `docker exec` commands, which you described as "two steps". This means I had to create two separate executable scripts, which export the variable before calling docker, because `AuthorizedKeysCommand` requires an absolute path where the env variables cannot be prepended. This made the setup working. I was even able to login into the `git` user from root by specifying a shell (my other issue mentioned above), which overrides our script: `su -l git -s /bin/bash` But this way, the XDG_RUNTIME_DIR is **not** available, so the DOCKER_HOST collapses just to: `unix:///docker.sock` And has to be re-exported to a correct value to use `docker` commands. Leaving these notes here for a further reference.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#8057