# =========================================================================== # docker-bastion — hardened sshd config # # Every authenticated session is routed through /etc/bastion/force-command, # which is generated at container start from $FORCE_COMMAND. The bastion # user has /sbin/nologin as its shell so there is no fallback if the # ForceCommand wrapper is missing or fails — the session simply ends. # =========================================================================== Port 22 AddressFamily any ListenAddress 0.0.0.0 ListenAddress :: # Host keys live in /etc/ssh/keys/ so they can survive image rebuilds via # a named volume. start-container generates them on first boot if missing. HostKey /etc/ssh/keys/ssh_host_ed25519_key HostKey /etc/ssh/keys/ssh_host_rsa_key # Privilege separation directory (Alpine default is /var/empty). StrictModes yes # Auth — public keys only, no passwords, no interactive prompts. # (UsePAM is omitted: Alpine's openssh-server is built without PAM support # and rejects the directive entirely. Without PAM compiled in, the no-PAM # behavior is already the default — nothing to disable.) PermitRootLogin no PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes AuthorizedKeysFile /home/%u/.ssh/authorized_keys # Surface reduction — no forwarding, no tunnels, no user env / rc files. AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no GatewayPorts no PermitTunnel no PermitUserEnvironment no PermitUserRC no # Logging. LogLevel VERBOSE SyslogFacility AUTH # Belt + suspenders: applies even if per-key command="" is missing. ForceCommand /etc/bastion/force-command