Securely expose remote services via SSH tunnels inside Docker and/or to your Tailscale Tailnet !
Find a file
2025-02-24 01:54:00 +01:00
docker Update Dockerfile.tailscale 2025-02-24 01:54:00 +01:00
docker-compose.yaml Create docker-compose.yaml 2025-02-21 01:44:39 +01:00
LICENSE Initial commit 2025-02-21 01:34:30 +01:00
README.md Update README.md 2025-02-21 18:20:07 +01:00
ssh-tunnel.webp Add files via upload 2025-02-21 01:49:38 +01:00
THIRD-PARTY-LICENCES Update THIRD-PARTY-LICENCES 2025-02-21 01:40:46 +01:00

🛡️ SSH Tunnel - Secure Remote Access via SSH Tunnels

SSH Tunnel Logo

🚀 Quick Start

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

📌 Why this image?

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.

🔥 Use Cases:

  • Securely connect to remote databases (PostgreSQL, MySQL, MariaDB).
  • Access internal services (Redis, Elasticsearch, APIs) via SSH.
  • Securely tunnel any service without exposing it publicly.

🚀 How to Use

1 Run with 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).

2 Using 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

2.2 Using Host Network Mode (Alternative)

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?

  • Custom network (default) → If services are inside Docker.
  • Host mode → If you want to expose the tunnel outside Docker.

🚀 Using with Tailscale

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

Run with 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 (You can generate a key here: Tailscale Keys).
  • 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.
  • 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. {.is-info}

Without a persistent storage for /var/lib/tailscale after the initial key expire, the container will not be able to connect to your Tailnet. {.is-warning}


Using 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:443"
      LOCAL_PORTS: "15432 8443"
      TAILSCALE_AUTH_KEY: "your-tailscale-auth-key"
    volumes:
      - /path/to/id_rsa:/tmp/id_rsa:ro
      - ssh_tunnel_tailscale_data:/var/lib/tailscale # Persistent Tailscale state, needed after initial key expiration
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    ports:
      - "15432:15432" # (Optional) Also expose port on local network
      - "8443:8443"   # (Optional) Also expose port on local network
volumes:
  ssh_tunnel_tailscale_data: # Named volume for Tailscale state

📌 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 (You can generate a key here: Tailscale Keys).
  • 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.
  • 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. {.is-info}

Without a persistent storage for /var/lib/tailscale after the initial key expire, the container will not be able to connect to your Tailnet. {.is-warning}


📌 Why use this image?

Secure: No need to expose services publicly.
Simple: Just set environment variables and run.
Multi-Arch: Works on x86_64 (Intel/AMD) and ARM64 (Oracle Cloud, Raspberry Pi, etc.).
Lightweight: Uses Alpine Linux for minimal resource usage.


📦 Pull & Run

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!


🔖 Tags & Keywords

This image can be used for:

  • 🛡️ SSH Tunneling
  • 🔌 Networking & Proxy
  • 🔒 Security & Encryption
  • 🗄️ Database Access (PostgreSQL, MySQL, MariaDB, etc.)
  • 🏗️ Remote Service Exposure in Docker

📜 Third-Party Licenses

This project is based on:

📜 License

This project is licensed under the MIT License.
You are free to use, modify, and distribute it.
Read the full license here.


🤖 AI Assistance & Acknowledgment

  • This project was built with the help of an AI-powered assistant (LLM) to improve structure, efficiency, and documentation clarity.
  • A big thank to Xénophée for the inspiration that started this project.

🏗️ How to Build the Image

If you want to build this image yourself, follow these steps:

1 Clone the Repository

git clone https://github.com/RipleyBooya/ssh-tunnel.git
cd ssh-tunnel

2 Build for Multi-Architecture (amd64 & arm64)

docker buildx build --platform linux/amd64,linux/arm64 \
  -t dockerhub_account/ssh-tunnel:latest \
  --push .

3 Verify the Image

docker buildx imagetools inspect dockerhub_account/ssh-tunnel:latest

4 Test Locally

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! 🚀