Skip to content

Instantly share code, notes, and snippets.

@pwillis-els
Last active October 23, 2020 03:22
Show Gist options
  • Save pwillis-els/446f00b6df5caf033dd86ae951eb3938 to your computer and use it in GitHub Desktop.
Save pwillis-els/446f00b6df5caf033dd86ae951eb3938 to your computer and use it in GitHub Desktop.
Run an sshd-enabled version of any Docker container so you can login to the container remotely and do work in it
#!/bin/sh
# Runs a detached Docker container with an entrypoint to run an sshd daemon.
CONTAINER_IMG="my-container-image:latest"
CONTAINER_USER="deploy" # the user the container runs as
CONTAINER_HOME="/home/$CONTAINER_USER" # home directory in the container
HOST_SSH_PORT="2222" # The port to export sshd to on localhost
CONTAINER_SSH_PORT="2222" # The port of sshd in the container
set -eu
# Before running this script, export an environment variable SSH_AUTHORIZED_KEY to
# the value of the SSH public key you want to login to the container.
# Then run the sshd container below.
#
# This will volume-map the host's docker.sock,
# make a persistent Terraform plugin cache,
# a persistent volume for miscellaneous uses,
# the SSH public key created above (so we can login with it),
# maps in the entrypoint to set up and start sshd,
# and exports the sshd port to the local host.
docker run \
--rm --detach \
-v sshd-persist:$CONTAINER_HOME/persist \
-e SSH_AUTHORIZED_KEY \
-v `pwd`/sshd-entrypoint.sh:/sbin/sshd-entrypoint.sh \
--entrypoint=/sbin/sshd-entrypoint.sh \
-p 127.0.0.1:$HOST_SSH_PORT:$CONTAINER_SSH_PORT \
"$CONTAINER_IMG"
# Now you can login from the Docker host with the following:
# ssh \
# -v \
# -o ForwardAgent=yes \
# -o IdentitiesOnly=yes \
# -i container-ssh-key.pem \
# -l $CONTAINER_USER \
# -p $HOST_SSH_PORT \
# 127.0.0.1
#
# Or you can use the Docker host as a bastion for the container, with the following:
# ssh \
# -o ProxyCommand="ssh -o IdentitiesOnly=yes -i ~/.ssh/docker-host.pem -p 22 docker-host-user@docker-host-ip -N -W %h:%p" \
# -i container-ssh-key.pem \
# -o IdentitiesOnly=yes \
# -o ForwardAgent=yes \
# -o CheckHostIP=no -o StrictHostKeyChecking=no \
# -p $HOST_SSH_PORT \
# -l $CONTAINER_USER \
# 127.0.0.1
#
# Note that with ForwardAgent=yes, your SSH keys have been forwarded into the container so you don't need to
# download them there.
#
# The CheckHostIP=no and StrictHostKeyChecking=no options are needed because the container's ssh host keys will
# change every time it starts. You may have to remove the previous host keys to get ForwardAgent to work again.
#
#!/bin/sh
# Install and run sshd in a Docker container
#
# The idea is to take any existing container, not have to rebuild or change it, and still
# run an ssh daemon inside it. Therefore we don't assume the container is running as root,
# so we set up and run sshd as whatever user the container runs as.
#
# We also assume the container contains openssh-server, but if not, we try to install it
# with a package manager. If the user isn't root and sudo isn't bundled, this will fail.
# You can try running the container as root to get around this (`docker run --user root`)
# The sshd port to listen on in the container. As this might be a non-root user, use a high port.
[ -n "${SSHD_PORT:-}" ] || SSHD_PORT="2222"
# Install sshd if it wasn't before. Try to use sudo if we're not root.
[ -n "${USER:-}" ] || USER="`id -un`"
[ ! "$USER" = "root" ] && command -v sudo && SUDO=sudo
if [ ! -x /usr/sbin/sshd ] ; then
command -v apk && $SUDO apk add --update --no-cache openssh-server # Alpine
command -v apt-get && $SUDO apt-get update && $SUDO apt-get install -y openssh-server # Debian
command -v yum && $SUDO yum -y install openssh-server # CentOS
fi
# Here we don't mess with the .ssh folder too much in case you want to volume-mount
# your own .ssh folder into the container. If you don't volume-mount in the
# $HOME/.ssh_key.pub file, .ssh will be left alone. You can also set the environment
# variable SSH_AUTHORIZED_KEY to your public key and this will be added to .ssh/authorized_keys
mkdir -p .ssh
[ -n "${SSH_AUTHORIZED_KEY:-}" ] && printf "%s\n" "$SSH_AUTHORIZED_KEY" >> .ssh/authorized_keys
[ -r "$HOME/.ssh_key.pub" ] && cat "$HOME/.ssh_key.pub" >> .ssh/authorized_keys
# Compose the sshd_config file
mkdir -p .sshd/etc/ssh
ssh-keygen -A -f .sshd # generate new SSH host keys
cd .sshd ; CWD="`pwd`"
echo "Port $SSHD_PORT
PasswordAuthentication no
PermitUserEnvironment yes" > sshd_config
for i in `ls etc/ssh/ssh_host_* | grep -v pub` ; do
echo "HostKey $CWD/$i" >> sshd_config
done
# Fix this user's login shell if it's currently set to nologin
( getent passwd "$USER" | grep -q nologin ) && $SUDO usermod -s /bin/sh "$USER"
# Unlock account but disable the password (only ssh keys allowed)
$SUDO usermod -p '*' "$USER"
# If you remove "-D" here it should run sshd in the background, but that means the container may
# stop running if no command is specified at runtime (we are overriding the entrypoint, remember).
# Try running sshd with sudo in case we want to try binding to low ports.
$SUDO /usr/sbin/sshd -D -e -f sshd_config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment