With this example, you can create a SSH and SFTP users. SFTP users are restricted to their "home" directories and defined as "non-interactive shell user" which means they cannot login to the server as a "normal" user. They are allowed to use sftp protocol only.


Structure


.
├── docker
│ ├── Dockerfile
│ ├── entrypoint.sh
│ ├── ssh_config
│ ├── sshd_config
│ └── user.sh
├── .env
└── docker-compose.yml

Files


.env


SSH_MASTER_USER=master
SSH_MASTER_PASS=master

docker-compose.yml


version: '3'

services:
server:
build:
context: ./docker
args:
SSH_MASTER_USER: ${SSH_MASTER_USER}
SSH_MASTER_PASS: ${SSH_MASTER_PASS}
hostname: server
ports:
- "2222:22"
volumes:
- ./uploads:/uploads

Dockerfile


FROM debian:9.5

ARG SSH_MASTER_USER
ARG SSH_MASTER_PASS

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
nano \
sudo \
openssh-server

COPY ssh_config /etc/ssh/ssh_config
COPY sshd_config /etc/ssh/sshd_config

COPY user.sh /usr/local/bin/user.sh
RUN chmod +x /usr/local/bin/user.sh
RUN /usr/local/bin/user.sh
RUN rm /usr/local/bin/user.sh

COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

CMD tail -f /dev/null

user.sh


This file creates master user, assigns /home/master as home, ssh as user group and sets master as password. Apart from all that, it grants rm, mkdir, chown, useradd, deluser and chpasswd command usages with the help of sudo command. This user now can create a new SSH user and revert what he has done. The sftp group will be used for new SFTP users.


#!/bin/bash
set -e

printf "\n\033[0;44m---> Creating SSH master user.\033[0m\n"

useradd -m -d /home/${SSH_MASTER_USER} -G ssh ${SSH_MASTER_USER} -s /bin/bash
echo "${SSH_MASTER_USER}:${SSH_MASTER_PASS}" | chpasswd
echo 'PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin"' >> /home/${SSH_MASTER_USER}/.profile

echo "${SSH_MASTER_USER} ALL=NOPASSWD:/bin/rm" >> /etc/sudoers
echo "${SSH_MASTER_USER} ALL=NOPASSWD:/bin/mkdir" >> /etc/sudoers
echo "${SSH_MASTER_USER} ALL=NOPASSWD:/bin/chown" >> /etc/sudoers
echo "${SSH_MASTER_USER} ALL=NOPASSWD:/usr/sbin/useradd" >> /etc/sudoers
echo "${SSH_MASTER_USER} ALL=NOPASSWD:/usr/sbin/deluser" >> /etc/sudoers
echo "${SSH_MASTER_USER} ALL=NOPASSWD:/usr/sbin/chpasswd" >> /etc/sudoers

addgroup sftp

exec "$@"

entrypoint.sh


#!/bin/bash
set -e

printf "\n\033[0;44m---> Starting the SSH server.\033[0m\n"

service ssh start
service ssh status

exec "$@"

sshd_config


ChallengeResponseAuthentication no
UsePAM no
PrintMotd no
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitTunnel no

Subsystem sftp internal-sftp
Match Group sftp
ChrootDirectory %h
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitTunnel no
ForceCommand internal-sftp

ssh_config


# Prevents "Are you sure you want to continue connecting (yes/no)?" question while connecting to the server.
# The host IP below is the client machine where the ssh command is issued from.
# Host 192.168.99.*
# StrictHostKeyChecking no
# UserKnownHostsFile=/dev/null

Host *
HashKnownHosts yes
GSSAPIAuthentication yes

Test


Run container


$ docker-compose up -d

IMAGE COMMAND PORTS NAMES
sftp_server "/usr/local/bin/entr…" 0.0.0.0:2222->22/tcp sftp_server_1

SSH user login


Remember this user is responsible for creating new SSH and SFTP users.


$ ssh master@container-ip -p 22 # Password is master

Add a new SFTP user


Login as "master" user and run commands below.


$ sudo mkdir /uploads/inanzzz
$ sudo mkdir /uploads/inanzzz/upload
$ sudo useradd -d /uploads/inanzzz -G sftp inanzzz -s /usr/sbin/nologin
$ echo "inanzzz:inanzzz" | sudo chpasswd
$ sudo chown inanzzz:sftp -R /uploads/inanzzz/upload

SFTP user login


$ sftp inanzzz@container-ip
sftp>

Client connection test


I am running the container in a Vagrant box and its IP address is 192.168.99.30. I had to add CONTAINER_IP localhost to /etc/hosts file in Vagrant box. Open up a FTP client (e.g. FileZilla) and use values below to connect.


- Host: 192.168.99.30
- Port: 2222
- Protocol: SFTP
- Logon Type: Ask for password
- Username: inanzzz
- Password: inanzzz