Persist SSH host key across restarts

- Remove key generation from Dockerfile (was causing new key each build)
- Add ssh_keys volume mount in docker-compose
- Generate key at runtime only if it doesn't exist
- No more clearing known_hosts after updates!
This commit is contained in:
Greg Hendrickson
2026-01-27 18:46:13 +00:00
parent 0ada6cb418
commit 39afbadf91
3 changed files with 23 additions and 4 deletions

View File

@@ -20,12 +20,10 @@ RUN useradd -m shellmate && \
mkdir -p /etc/shellmate && \
chown shellmate:shellmate /etc/shellmate
# Switch to shellmate user and generate SSH key
USER shellmate
RUN ssh-keygen -t ed25519 -f /etc/shellmate/ssh_host_key -N ""
EXPOSE 22
# Key is generated at runtime (see entrypoint) or mounted from volume
ENV STOCKFISH_PATH=/usr/games/stockfish
CMD ["shellmate-server"]

View File

@@ -8,6 +8,8 @@ services:
- SHELLMATE_REDIS_URL=redis://redis:6379
- SHELLMATE_DATABASE_URL=postgresql://shellmate:shellmate@postgres:5432/shellmate
- STOCKFISH_PATH=/usr/games/stockfish
volumes:
- ssh_keys:/etc/shellmate
depends_on:
- redis
- postgres
@@ -47,3 +49,4 @@ services:
volumes:
redis_data:
postgres_data:
ssh_keys:

View File

@@ -466,6 +466,20 @@ async def run_chess_game(process, session: TerminalSession, username: str, oppon
await asyncio.sleep(3)
def ensure_host_key(key_path: str) -> None:
"""Generate SSH host key if it doesn't exist."""
import subprocess
if not os.path.exists(key_path):
logger.info(f"Generating SSH host key at {key_path}")
os.makedirs(os.path.dirname(key_path), exist_ok=True)
subprocess.run([
"ssh-keygen", "-t", "ed25519",
"-f", key_path, "-N", ""
], check=True)
logger.info("SSH host key generated")
async def start_server(
host: str = "0.0.0.0",
port: int | None = None,
@@ -475,6 +489,10 @@ async def start_server(
port = port or int(os.environ.get("SHELLMATE_SSH_PORT", "2222"))
host_keys = host_keys or ["/etc/shellmate/ssh_host_key"]
# Ensure host key exists (generate if needed)
for key_path in host_keys:
ensure_host_key(key_path)
logger.info(f"Starting ShellMate SSH server on {host}:{port}")
server = await asyncssh.create_server(