For a fast setup, run:
docker run -d -e SSH_HOST=your-server -e SSH_USER=user \
-v ~/.ssh/id_rsa:/tmp/id_rsa:ro ripleybooya/ssh-tunnel
This container was created to securely expose remote services via SSH tunnels.
Instead of exposing databases or other services to the public internet, this container allows you to create secure SSH tunnels inside a Docker network.
docker run
docker run -d --name ssh-tunnel \
-e SSH_HOST="your-server.com" \
-e SSH_USER="your-username" \
-e REMOTE_PORTS="127.0.0.1:5432 127.0.0.1:443" \
-e LOCAL_PORTS="15432 8443" \
-v /path/to/id_rsa:/tmp/id_rsa:ro \
--network=my_docker_network \
ripleybooya/ssh-tunnel
📌 Explanation:
SSH_HOST
: The remote server where SSH tunnels will be established.SSH_USER
: The SSH user on the remote server.REMOTE_PORTS
: Ports from the remote server (format: 127.0.0.1:PORT
).LOCAL_PORTS
: Ports inside the Docker container (mapped to REMOTE_PORTS
).LOGROTATE_FREQUENCY
: Logrotate Frequency (default to daily
).LOGROTATE_ROTATE
: Logrotate rotation to keep (default to 7
).LOGROTATE_COMPRESS
: Logrotate compression (default to compress
).-v /path/to/id_rsa:/tmp/id_rsa:ro
: Mounts your SSH key securely (using /tmp/id_rsa
for better permissions).docker-compose.yml
For easier management, use Docker Compose:
version: '3.8'
services:
ssh-tunnel:
image: ripleybooya/ssh-tunnel
container_name: ssh-tunnel
restart: always
networks:
- internal
environment:
SSH_HOST: "your-server.com"
SSH_USER: "your-username"
REMOTE_PORTS: "127.0.0.1:5432 127.0.0.1:443"
LOCAL_PORTS: "15432 8443"
volumes:
- /path/to/id_rsa:/tmp/id_rsa:ro
networks:
internal:
driver: bridge
If you need the ports to be accessible outside Docker, use network_mode: host
:
version: '3.8'
services:
ssh-tunnel:
image: ripleybooya/ssh-tunnel
container_name: ssh-tunnel
restart: always
network_mode: host # Uses the host network instead of a Docker network
environment:
SSH_HOST: "your-server.com"
SSH_USER: "your-username"
REMOTE_PORTS: "127.0.0.1:5432 127.0.0.1:443"
LOCAL_PORTS: "15432 8443"
volumes:
- /path/to/id_rsa:/tmp/id_rsa:ro
📌 Which mode to choose?
This version integrates Tailscale VPN for secure remote access & exposes the port to your tailnet.
To use the Tailscale version you need to append the tailscale
tag: ripleybooya/ssh-tunnel:tailscale
docker run
docker run -d --name ssh-tunnel-tailscale \
-e SSH_HOST="your-server.com" \
-e SSH_USER="your-username" \
-e REMOTE_PORTS="127.0.0.1:5432 127.0.0.1:443" \
-e LOCAL_PORTS="15432 8443" \
-e TAILSCALE_AUTH_KEY="your-tailscale-auth-key" \
-v /path/to/id_rsa:/tmp/id_rsa:ro \
-v /path/to/tailscale/persistent/data:/var/lib/tailscale # Persistent Tailscale state, needed after initial key expiration
-p 15432:15432 # (Optional) Also expose port on local network.
-p 8443:8443 # (Optional) Also expose port on local network.
--cap-add=NET_ADMIN \
--device /dev/net/tun:/dev/net/tun \
ripleybooya/ssh-tunnel:tailscale
📌 Explanation:
SSH_HOST
: The remote server where SSH tunnels will be established.SSH_USER
: The SSH user on the remote server.REMOTE_PORTS
: Ports from the remote server (format: 127.0.0.1:PORT
).LOCAL_PORTS
: Ports inside the Docker container (mapped to REMOTE_PORTS
).TAILSCALE_AUTH_KEY
: Initial Tailscale Authentication Key (optionnal)/!\ Must be empty if you want to use TAILSCALE_PARAM
.
(You can generate a key here: Tailscale Keys)
TAILSCALE_PARAM
: full control over tailscale up
options. Usefull if you plan to automate deployment with OAuth Client etc.(tailscale up command parameters & Registering new nodes using OAuth credentials).
LOGROTATE_FREQUENCY
: Logrotate Frequency (default to daily
).LOGROTATE_ROTATE
: Logrotate rotation to keep (default to 7
).LOGROTATE_COMPRESS
: Logrotate compression (default to compress
).-v /path/to/id_rsa:/tmp/id_rsa:ro
: Mounts your SSH key securely (using /tmp/id_rsa
for better permissions).-v /path/to/tailscale/persistent/data:/var/lib/tailscale
: Required for Persistent Tailscale state. (optionnal)
- Exposing ports with
-p PORT:PORT
is not mandatory to access the ports from a docker network or your Tailnet.- Only usefull if you want your ports to be exposed to the local network.
Without Registering new nodes using OAuth credentials or a persistent storage for
/var/lib/tailscale
after the initial key expire, the container will not be able to connect to your Tailnet.
docker-compose.yml
version: '3.8'
services:
ssh-tunnel-tailscale:
image: ripleybooya/ssh-tunnel:tailscale
container_name: ssh-tunnel-tailscale
restart: always
environment:
SSH_HOST: "your-server.com"
SSH_USER: "your-username"
REMOTE_PORTS: "127.0.0.1:5432 127.0.0.1:3306"
LOCAL_PORTS: "5432 3306"
TAILSCALE_PARAM: "--reset --auth-key='tskey-client-XXXXXXXXXXXXXXXXX-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY?ephemeral=true&preauthorized=true' --advertise-tags=tag:dba --hostname=TS-DB-ACCESS"
volumes:
- /path/to/id_rsa:/tmp/id_rsa:ro
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
📌 Explanation:
SSH_HOST
: The remote server where SSH tunnels will be established.SSH_USER
: The SSH user on the remote server.REMOTE_PORTS
: Ports from the remote server (format: 127.0.0.1:PORT
).LOCAL_PORTS
: Ports inside the Docker network (mapped to REMOTE_PORTS
).TAILSCALE_AUTH_KEY
: Initial Tailscale Authentication Key (optionnal)/!\ Must be empty if you want to use TAILSCALE_PARAM
.
(You can generate a key here: Tailscale Keys)
TAILSCALE_PARAM
: full control over tailscale up
options. Usefull if you plan to automate deployment with OAuth Client etc.(tailscale up command parameters & Registering new nodes using OAuth credentials).
LOGROTATE_FREQUENCY
: Logrotate Frequency (default to daily
).LOGROTATE_ROTATE
: Logrotate rotation to keep (default to 7
).LOGROTATE_COMPRESS
: Logrotate compression (default to compress
)./path/to/id_rsa:/tmp/id_rsa:ro
: Mounts your SSH key securely (using /tmp/id_rsa
for better permissions).ssh_tunnel_tailscale_data:/var/lib/tailscale
: Required for Persistent Tailscale state. (optionnal)
- Exposing ports with "
ports:
" is not mandatory to access the ports from a docker network or your Tailnet.- Only usefull if you want your ports to be exposed to the local network.
Without Registering new nodes using OAuth credentials or a persistent storage for
/var/lib/tailscale
after the initial key expire, the container will not be able to connect to your Tailnet.
This Docker image is rebuilt automatically every day to ensure it always includes:
⚠ Note: These daily builds do not necessarily mean changes to the project itself.
If you're looking for actual updates to the codebase, please refer to the commit history or the release tags.
docker pull ripleybooya/ssh-tunnel
docker run --rm -it ripleybooya/ssh-tunnel sh -c "uname -m && echo 'Container is working'"
🚀 Now your remote services are accessible through secure SSH tunnels!
This image can be used for:
This project is based on:
This project is licensed under the MIT License.
You are free to use, modify, and distribute it.
Read the full license here.
If you want to build this image yourself, follow these steps:
git clone https://github.com/RipleyBooya/ssh-tunnel.git
cd ssh-tunnel
amd64
& arm64
)docker buildx build --platform linux/amd64,linux/arm64 \
-t dockerhub_account/ssh-tunnel:latest \
--push .
docker buildx imagetools inspect dockerhub_account/ssh-tunnel:latest
docker run --rm -it dockerhub_account/ssh-tunnel sh -c "uname -m && echo 'Container is running successfully'"
Now your image is built and ready for use! 🚀
This project is open-source and welcomes contributions!
If you find any issues or have suggestions, feel free to open a GitHub issue or contribute! 🚀