- Running SSH in an Alpine Docker Container
- Table of Contents
- Case study
- Configuring SSH
- Configuring user
- Installing SSH
- Running sshd
- Troubleshooting
- Wrapping up
- How to Install OpenSSH Server on Alpine Linux
- Installing OpenSSH in Alpine Linux
- Overview
- OpenSSH
- Service commands
- Fine tuning
- Firewalling and Port Changes
- Dropbear
- server
- client
- See also
- How to install OpenSSH server on Alpine Linux (including Docker)
- Installing OpenSSH server on Alpine Linux
- Installing OpenSSH on the Alpine Linux Docker container
Running SSH in an Alpine Docker Container
When deploying your web application you will likely be using Docker for containerization. Many base Docker images like Node or Python are running Alpine Linux. It is a great Linux distro that is secure and extremely lightweight. However many Docker images provide Alpine without its OpenRC init system. This causes a few issues when trying to run sidecar services with your primary process in a Docker Container.
Table of Contents
Case study
Let’s imagine that we have a remote server hosted somewhere. We are using this server for deploying our production application. To run the application in an isolated environment we are continerizing a Node.js/Python/nginx or any other app. To administrate processes we would want to have direct access to production environment — docker container in this case. SSH is the way to go here, but how should we setup it?
We could SSH into the remote server and then use docker exec but that would not be a particularly secure or elegant solution. Perhaps we should forward SSH connection to the Docker container itself?
Binding ports is fairly easy — we will bind not only port 443 (or any other port you might use for your use case) but also port 22. Run command would like something like docker run -p 443: -p 22:22 .
The more challenging part would setting up the actual SSH inside the container. We will take a simple Node.js Dockerfile as a base.
FROM node:12.22-alpine # added code goes here WORKDIR /app COPY . . RUN yarn RUN yarn build CMD ["yarn", "start"]
Configuring SSH
To reproduce the connection to a remote server we would be running this Docker image locally and connecting using localhost .
Configuring user
Firstly, in order to be able to login as root (or any other user) we would have to unlock the user and add authorized SSH keys (unless you would want to use text passwords to login which is very insecure).
# create user SSH configuration RUN mkdir -p /root/.ssh \ # only this user should be able to read this folder (it may contain private keys) && chmod 0700 /root/.ssh \ # unlock the user && passwd -u root
Now the root user is unlocked to be logged into and there is a folder for SSH configuration. However at the moment anyone can login as root since there is not password and password auth is enabled by default. Our goal would be to disable password auth and to add our public key as an authorized one for this user.
You may also use a different user for this purpose — just replace /root with the path to the desired users home directory and replace username.
# supply your pub key via `--build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)"` when running `docker build` ARG ssh_pub_key RUN echo "$ssh_pub_key" > /root/.ssh/authorized_keys
Installing SSH
Now in order to disable password auth via SSH we have to first install SSH. I will be using OpenSSH for this but other implementations should work similarly.
RUN apk add openrc openssh \ && ssh-keygen -A \ && echo -e "PasswordAuthentication no" >> /etc/ssh/sshd_config
Stripped Alpine Docker images like the Node one do not provide OpenRC by default so we should install it ourselves. Then generate host SSH keys so clients may authorize our container as an SSH host. Finally, append PasswordAuthentication no to the end of sshd_config to disable password auth via SSH.
For real applications you would invest in pre-generating host keys so that keys do not update every time a new container is built. However this and managing keys more elegantly is out of scope for this post.
At this point we may start the sshd service.
RUN rc-status \ # touch softlevel because system was initialized without openrc && touch /run/openrc/softlevel \ && rc-service sshd start
However when you run the container you would see something like kex_exchange_identification error. When docker exec into the container and execute rc-status you would see that sshd service is crashed.
Running sshd
Service is crashed because Alpine Docker images allow only a single process to be launched. It is actually a good concept that facilitates using microservices and creating docker compositions. However in this particular case there is not way to run SSH in a different container. To avoid that the actual ENTRYPOINT or CMD command should boot multiple processes.
FROM node:12.22-alpine ARG ssh_pub_key RUN mkdir -p /root/.ssh \ && chmod 0700 /root/.ssh \ && passwd -u root \ && echo "$ssh_pub_key" > /root/.ssh/authorized_keys \ && apk add openrc openssh \ && ssh-keygen -A \ && echo -e "PasswordAuthentication no" >> /etc/ssh/sshd_config \ && mkdir -p /run/openrc \ && touch /run/openrc/softlevel WORKDIR /app COPY . . RUN yarn RUN yarn build ENTRYPOINT ["sh", "-c", "rc-status; rc-service sshd start; yarn start"]
In this final Dockerfile I combined all previous RUN commands into a single one to reduce the amount of layers. Instead of running rc-status && rc-service sshd start in RUN we do that in ENTRYPOINT inside sh -c . This way Docker container will execute only a single process sh -c that would spawn childs.
As a side effect this Node.js application will not recieve SIGINT/SIGTERM signals (or any other signals from Docker) when stopping Docker container.
Run built container using docker run -p 7655:22 . In a different terminal instance run ssh root@localhost -p 7655 . Voila — you successfully SSHed into a Docker Container. Using SSH for your production app would be the same except you would be using its IP instead of localhost and a valid port.
To properly build and run container without an app around it replace yarn start with node and remove yarn / yarn build directives.
Troubleshooting
When any difficulties with running SSH may arise first try to docker exec into the container and check rc-status . sshd service should be started . If it has crashed or is not present you may not be starting it properly in ENTRYPOINT or have incorrect configuration in sshd_config . You may also be missing SSH host keys or use an already bound port.
To further troubleshoot you can run the container with docker run -p 7655:22 7656:10222 . Then docker exec and run $(which sshd) -Ddp 10222 . This would create another instance of sshd that would listen on a different port (10222) with verbose logging. From there you should see informational messages on why the process might crash.
If the process does not crash attempt connecting. Run ssh root@localhost -p 7656 on the Docker host machine. From this point you will see additional logs in your previous terminal window with details on why the connection has been refused.
Wrapping up
While this tutorial is pretty specific to running SSH in an Alpine Docker container, you may reuse this knowledge to run SSH in other Linux Docker distros. Or you may have better luck configuring other sidecar services inside an Alpine Docker container. In any case I hope you found what you were looking for in this post or learnt something new.
How to Install OpenSSH Server on Alpine Linux
OpenSSH server is an implementation of the SSH protocol, which comes with a collection of networking utilities based on the SSH protocol. The SSH protocol is a secure protocol that encrypts all traffic exchanged between a client and remote host using strong encryption methods.
By default, the OpenSSH server comes installed in modern Alpine Linux systems. However if by any chance, the OpenSSH server is not installed, then this guide is what you are looking for.
Installing OpenSSH in Alpine Linux
We will start off by refreshing repositories or updating the package index of Alpine Linux using the following apk command.
Next, search for the OpenSSH server in the official Alpine Linux to confirm its availability.
The output displays various OpenSSH packages that can be installed.
To install both the OpenSSH server and client and associated packages in Alpine Linux, run the command:
To confirm that the OpenSSH server is installed, run the command:
From the output, we can see that OpenSSH is installed.
With OpenSSH installed, enable it at system startup, start the service and confirm that the SSH service is running using the following commands.
$ rc-update add sshd $ service sshd start $ service sshd status
With SSH installed, you can now start making remote Linux connections using the following syntax:
In this example, we are connecting to a remote Debian server.
This leads us to the end of this article. In this tutorial, we walked you through a step-by-step procedure of how to install the OpenSSH server and client on Alpine Linux. Your feedback will be appreciated.
Overview
This article provides a short overview of SSH on Alpine Linux.
Note: This article describes two popular SSH implementations: OpenSSH and Dropbear. Either can be installed using the setup-sshd script, or by following the instructions below.
OpenSSH
OpenSSH is a popular SSH implementation for remote encrypted login to a machine. OpenSSH defines sshd as the daemon, and ssh as the client program.
Service commands
Enable the sshd service so that it starts at boot:
List services to verify sshd is enabled:
Start the sshd service immediately and create configuration files:
Note: If you are running from RAM, ensure you save your settings using the ‘lbu ci’ command as necessary. See Alpine local backup.
Fine tuning
You may wish to change the default configuration. This section describes some of the configuration options as examples, however it is by no means an exhaustive list. See the manual for full details.
The fine-tuning is done by editing /etc/ssh/sshd_config . Any line starting with «#» is ignored by sshd.
UseDNS no # By setting this to no, connection speed can increase. PasswordAuthentication no # Do not allow password authentication.
Other configuration options are shown in etc/ssh/sshd_config . The file includes comments that explain many of the options.
Firewalling and Port Changes
By default, sshd will communicate on TCP port 22.
Sometimes 22/tcp is blocked by a firewall over which you have no control. Changing the Port option to an unused port number in /etc/ssh/sshd_config may be useful in this situation.
Port 443 # Use whichever port number fits your needs
Note: Ensure the port you wish to use is not already in use by running netstat -lnp on the machine running sshd.
Restart sshd after making modifications to the configuration file:
Note: If you are running from RAM, ensure you save your settings using the ‘lbu ci’ command as necessary. See Alpine local backup.
Dropbear
Dropbear is a lightweight SSH client/server alternative to OpenSSH.
server
Add it to the default runlevel:
Use the following command to check all available server options:
The config file is located at /etc/conf.d/dropbear
client
In its simplest form it can be used like this:
(where x.x.x.x is the IP address of the remote machine).
Use dbclient -h to see all available options.
See also
How to install OpenSSH server on Alpine Linux (including Docker)
T his quick tutorial explains how to install and set up OpenSSH (SSHD) server and client on the Alpine Linux system. Further, you will learn how to build a Docker Linux container running sshd server based upon Alpine Linux image too.
Tutorial details | |
---|---|
Difficulty level | Easy |
Root privileges | Yes |
Requirements | Alpine Linux |
Est. reading time | 4 minutes |
Installing OpenSSH server on Alpine Linux
The procedure for setting up an ssh-server is as follows:
- Search for ssh package, run:
apk search openssh - Install OpenSSH server and client using the apk command:
apk add openssh - Enable the sshd service at boot time:
rc-update add sshd
Outputs:
* service sshd added to runlevel default
* Caching service dependencies . [ ok ] ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519 * Starting sshd . [ ok ]
Installing OpenSSH on the Alpine Linux Docker container
You only need to add the following to your Dockerfile:
RUN apk add —no-cache openssh
But, here is how to setup an ssh server within a docker container using Alpine Linux. Create a new Dockerfile:
FROM alpine:latest LABEL maintainer="Vivek Gite [email protected]" RUN apk add --update --no-cache openssh RUN echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config RUN adduser -h /home/vivek -s /bin/sh -D vivek RUN echo -n 'vivek:some_password_here' | chpasswd ENTRYPOINT ["/entrypoint.sh"] EXPOSE 22 COPY entrypoint.sh /
Create a new shell script named entrypoint.sh as follows:
#!/bin/sh ssh-keygen -A exec /usr/sbin/sshd -D -e "$@"