blog-2025-09-06-forgejo-ssh

# forgejo installation on dokploy

keywords: [forgejo] [docker] [dokploy] [ssh]

i'm running my own forgejo instance via dokploy (i.e. in a docker container). as i'm currently the only user and scale/performance isn't a problem, i opted for sqlite, so i didn't even have to set up a postgresql instance (which would have been trivial in dokploy anyway).

there was just one hickup: private repositories were not accessible via ssh. this is necessary for authenticating from dokploy if the goal is to redeploy on push:

1. git push to forgejo 
2. forgejo informs dokploy via webhook
3. dokploy pulls from forgejo, builds (with nixpacks) the app and deploys it

after a short while i found the reason: git with ssh inside of docker needs either its own ssh server with a custom port or ssh-passthrough configured [see the docs](https://docs.gitea.com/installation/install-with-docker#ssh-container-passthrough).

the custom port solution was recommended, but i opted for the "clean" ssh-passthrough route and subsequently lost several hours of my spare time (special thanks to [gemini] and [claude], without i'd never had made it even that far).

the steps outlined in the [gitea] documentation (forgejo is a fork of gitea) are a bit simplistic; in my case several more steps were necessary.

1. do _not_ map the ssh port for forgejo in the docker file
1. create a user `git`
2. create a script `ssh-shell` bash script in `git`s home directory. the contents is, roughly
```bash
  #!/bin/bash
  exec /usr/bin/docker exec -i -u git \
    --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" \
    forgejo /usr/local/bin/gitea --config=/data/gitea/conf/app.ini serv key-7
```
3. set the shell of the `git` user to the `ssh-shell` script
4. add your ssh key to the hosts and the forgejo-containers' `authorized_keys` (this is the icky part)

testing all this required a lot of use of `ssh -vT git@` until all parts aligned. the welcome message should then display `Hi yourusername! You've successfully authenticated, but Forgejo does not provide shell access.`.

now it worked, but only for my ssh key. if i added a second user to my forgejo instance i would have had to add their key to the `authorized_keys` file manually.

the problem here is the ssh authentication via `authorized_keys` - the entry with the public key must be present in the host and the forgejo containers authorized_keys file. this has to be solved through forgejo's key management. if the user adds an ssh key through the web interface, the application should write this into the containers `authorized_keys` file and the hosts `git` user should use the containers `authorized_keys` file instead of its own.

this is where i ran into the final problem that made me undo all progress and switch to the ports solution. the proper configuration would, in theory, be:

Host SSH config (`/etc/ssh/sshd_config`):
```
Match User git
    AuthorizedKeysCommand /usr/local/bin/forgejo-keys %u %k
    AuthorizedKeysCommandUser git
```
Key lookup script (`/usr/local/bin/forgejo-keys`):
```
#!/bin/bash
# This script fetches keys directly from Forgejo
docker exec -u git forgejo /usr/local/bin/gitea --config=/data/gitea/conf/app.ini admin user list-keys "$1" 2>/dev/null || true
``` 

the problem here is that the `gitea` executable doesn't have a `admin user list-leys` command. going through the [documentation](https://docs.gitea.com/administration/command-line#keys) now it seems the command was changed to 

```
AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k
```

for now i'm keeping the custom ssh server, though.

edited by: stefs at Saturday, September 6, 2025, 9:01:36 AM Coordinated Universal Time


view