Skip to content

SSH Tunnel

This example shows using an SSH tunnel to set up port forwarding between ports that are each on the loopback interface of the respective side, which prevents them from being used from any external connections. This is a critical piece of securely implementing the remote Docker socket

Changable values
Variable Description
docker-tunnel-remote1.service Service name
docker-tunnel-client Comment on the tunnel private key
/root/.ssh/tunnel Local path to the private key for the tunnel
42375 Local port to forward from
dockeruser User on the remote system
192.168.1.110 IP address of the remote system
2375 Remote port to forward to
Create key
ssh-keygen -t ed25519 -f /root/.ssh/tunnel -N "" -C "docker-tunnel-client"
/etc/systemd/system/docker-tunnel-remote1.service
[Unit]
Description=SSH tunnel for remote Docker host remote1
After=network-online.target
Wants=network-online.target

[Service]
User=root
ExecStart=/usr/bin/ssh -N \
    -i /root/.ssh/tunnel \
    -o IdentitiesOnly=yes \
    -o ExitOnForwardFailure=yes \
    -o ServerAliveInterval=60 \
    -o ServerAliveCountMax=3 \
    -L 127.0.0.1:42375:127.0.0.1:2375 [email protected]
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
Detailed explanation
-N
Do not execute a remote command; used for port forwarding only.
-i /root/.ssh/tunnel
Specifies the private key to use as the identity.
-o IdentitiesOnly=yes
Prevents any SSH agent keys from being used, and forces the use of the specified identity.
-o ExitOnForwardFailure=yes
Exit if port forwarding setup fails, preventing silent failure.
-o ServerAliveInterval=60
Send keepalive messages every 60 seconds to detect dropped connections.
-o ServerAliveCountMax=3
Allow up to 3 missed keepalive responses before disconnecting.
-L 127.0.0.1:42375:127.0.0.1:2375
Forward local port 42375 to remote port 2375 on the loopback interface, tunneling Docker API traffic.
[email protected]
Remote user and host to connect to. Change this as necessary.

Only other services running under the same user (root in this case) will have access to the tunnel.

The remote host key needs to be in the known_hosts file

This will prompt you to add the host key to the known_hosts file.

Load and enable the service
sudo systemctl daemon-reload && \
sudo systemctl enable --now docker-tunnel-remote1.service && \
systemctl status docker-tunnel-remote1.service
Test tunnel
curl -sS http://127.0.0.1:42375/version | jq .