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 "

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

"



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 "

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

"



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.