Skip to content

dmotte/docker-portmap-server-rootless

Repository files navigation

docker-portmap-server-rootless

icon

GitHub main workflow Docker Pulls

This is a 🐳 Docker image containing an OpenSSH server that can be used for remote port forwarding only (rootless version). This image is almost equivalent to dmotte/docker-portmap-server but it runs as a non-root user.

Inspired by: https://www.golinuxcloud.com/run-sshd-as-non-root-user-without-sudo/

📦 This image is also on Docker Hub as dmotte/portmap-server-rootless and runs on several architectures (e.g. amd64, arm64, ...). To see the full list of supported platforms, please refer to the .github/workflows/main.yml file. If you need an architecture which is currently unsupported, feel free to open an issue.

Usage

Note: this Docker image uses an unprivileged user to perform the remote port forwarding stuff. As a result, it will only be possible to use port numbers > 1024. However this is not a problem at all, since you can still leverage the Docker port exposure feature to bind to any port you want on your host (e.g. -p "80:8080").

The first things you need are host keys for the OpenSSH server and an SSH key pair for the client to be able to connect. See the usage example of dmotte/docker-portmap-server for how to get them.

In general, the use of this image is very similar to dmotte/docker-portmap-server, but:

  • the SSH key pairs go directly into the root of the /ssh-client-keys volume instead of subdirectories (because we have only a single regular user inside the container)
  • if you want the container to generate missing keys, the related volume(s) must be writable by the portmap user of the container; otherwise, the generated keys won't be written to the volume(s). For example, to change the owner user of the root of an empty volume, you can do something like:
docker volume create myvol
docker run --rm -v myvol:/v docker.io/library/busybox chown 100:101 /v

Tip: if you are using Podman and a mounted directory (bind mount) instead of a volume, this works too:

podman unshare chown 100:101 mydir

In the PERMIT_LISTEN environment variable you need to specify which ports can be bound, separated by spaces. Example: 8001 8002 8003

Finally, you can start the server:

docker run -it --rm \
    -v "$PWD/hostkeys:/ssh-host-keys" \
    -v "$PWD/myclientkey.pub:/ssh-client-keys/myclientkey.pub:ro" \
    -p80:8080 -p2222:2222 \
    -ePERMIT_LISTEN=8080 \
    dmotte/portmap-server-rootless

See dmotte/docker-portmap-server for further details on usage; it's very similar to this one.

For a more complex example, refer to the docker-compose.yml file.

Environment variables

List of supported environment variables:

Variable Required Description
KEEPALIVE_INTERVAL No (default: 30) Value for the ClientAliveInterval option of the OpenSSH server
PERMIT_LISTEN Yes Value for the PermitListen option of the OpenSSH server

Development

If you want to contribute to this project, you can use the following one-liner to rebuild the image and bring up the Docker-Compose stack every time you make a change to the code:

docker-compose down && docker-compose up --build