Sign inSign up

erwinmaastilaa/simple-bastion

By erwinmaastilaa

•Updated 10 months ago

Image
Security
Developer tools
Web servers
0

1.3K

erwinmaastilaa/simple-bastion repository overview

⁠Bastion SSH + Web Key Manager

A lightweight Debian-based bastion container that:

  • runs OpenSSH for secure SSH access
  • exposes a clean web UI to add/remove authorized_keys
  • stores keys on a persistent volume, so access is preserved across restarts
  • can be used as a jump host for internal services, tunnels, and database access
  • supports CSRF-protected web login
  • supports transient web access (expose 8080 only when needed)

⁠Features

  • šŸ”‘ Key-only SSH bastion (no password auth)
  • šŸ” Persistent authorized_keys via volume
  • 🌐 Web UI with login + CSRF protection
  • šŸ’¾ No restart required when adding/removing keys
  • 🪪 Default admin password with bcrypt override
  • šŸ›”ļø MOTD login banner supported
  • 🧱 Minimal, portable, Docker-first design

⁠Ports

PortPurpose
22SSH server (always exposed)
8080Web admin UI (expose temporarily)

Example during admin tasks:

-p 22:22
-p 8080:8080

Then disable/close port 8080 when done.


⁠Volumes

Volume mount pathPurpose
/etc/sshPersistent SSH host keys
/tmpWritable temp on read-only rootfs
/authorized_keysPersistent authorized keys file

Example volume setup:

docker volume create bastion_ssh
docker volume create bastion_tmp
docker volume create bastion_auth

⁠Environment Variables

VariableDefaultDescription
AUTHORIZED_KEYS(empty)Initial SSH keys (newline-separated).
AUTHORIZED_KEYS_PATH/authorized_keys/authorized_keysPath to the managed key file.
BASTION_USERbastionSSH login user.
SSH_PORT22SSH port inside container.
APP_PORT8080Web UI port.
ADMIN_USERNAMEadminWeb UI login.
ADMIN_PASSWORD_BCRYPTbcrypt hash of ChangeMe!Override in production!
SESSION_SECRETauto-created if missingNeeded for CSRF + sessions.
⁠Generate a bcrypt admin password
python3 - <<'PY'
import bcrypt
print(bcrypt.hashpw(b"MyStrongAdminPassword!", bcrypt.gensalt()).decode())
PY

⁠SSH Permission Requirements

OpenSSH refuses loose permissions.
entrypoint.sh enforces:

/authorized_keys                  → 0700 bastion:bastion
/authorized_keys/authorized_keys  → 0600 bastion:bastion

This prevents:

Authentication refused: bad ownership or modes for directory /authorized_keys

⁠Quick Start

⁠1. Build
docker build -t nexaa/bastion-key-manager:latest .
⁠2. Run (with web UI enabled)
docker run -d --name bastion \
  -p 22:22 \
  -p 8080:8080 \
  -v bastion_ssh:/etc/ssh \
  -v bastion_tmp:/tmp \
  -v bastion_auth:/authorized_keys \
  -e AUTHORIZED_KEYS="$(cat ~/.ssh/id_ed25519.pub)" \
  nexaa/bastion-key-manager:latest
⁠3. Access

SSH:

ssh bastion@localhost

Web UI:

http://localhost:8080

Default credentials:

admin / ChangeMe!

āš ļø Override this in production!


⁠Production Example

ADMIN_HASH=$(python3 - <<'PY'
import bcrypt
print(bcrypt.hashpw(b"MyStrongAdminPassword123!", bcrypt.gensalt()).decode())
PY)

docker run -d --name bastion \
  -p 22:22 \
  -p 8080:8080 \
  -v bastion_ssh:/etc/ssh \
  -v bastion_tmp:/tmp \
  -v bastion_auth:/authorized_keys \
  -e AUTHORIZED_KEYS="$(cat ~/.ssh/id_ed25519.pub)" \
  -e ADMIN_USERNAME=admin \
  -e ADMIN_PASSWORD_BCRYPT="$ADMIN_HASH" \
  -e SESSION_SECRET="$(python3 - <<'PY'
import secrets; print(secrets.token_hex(32))
PY
)" \
  --read-only \
  --cap-drop ALL --cap-add NET_BIND_SERVICE \
  --security-opt no-new-privileges \
  --restart=always \
  nexaa/bastion-key-manager:latest

⁠Typical Usage

⁠Use as a Jump Host for a Database

Tunnel through the bastion:

ssh -L 3307:db.internal:3306 bastion@<host>

Connect locally:

mysql -h 127.0.0.1 -P 3307 -u user -p

Keys can be modified through the web UI without restarting the container.


⁠Security Notes

  • Only expose port 8080 when needed.
  • Use IP allow-listing for the UI if possible.
  • Always set a custom admin password hash.
  • SSH is key-only; root login disabled.
  • All key operations logged:
[audit] user=erwin action=add key_suffix='...'

⁠MOTD Banner Support

Place your banner at /etc/motd.

Example:

Welcome to the Nexaa Bastion Host!
SSH access is managed via the Web UI.

Avoid double MOTD by setting in sshd_config:

PrintMotd no
UsePAM yes

Tag summary

Content type

Image

Digest

sha256:b830218fa…

Size

63.3 MB

Last updated

10 months ago

docker pull erwinmaastilaa/simple-bastion