@@ -171,8 +171,37 @@ RUN ARCH=$(dpkg --print-architecture) \
171171 && apt-get clean \
172172 && rm -rf /var/lib/apt/lists/*
173173
174- # Create docker startup script
174+ # Install and configure OpenSSH server (replaces the ghcr.io/devcontainers/features/sshd feature).
175+ # Host keys must never be baked into this shared base image (every container/Codespace built
176+ # from it would otherwise share one static key pair), so they are stripped here and regenerated
177+ # fresh at container startup instead, by docker-init.sh via `ssh-keygen -A`.
178+ RUN apt-get update \
179+ && apt-get install -y --no-install-recommends openssh-server openssh-sftp-server \
180+ && mkdir -p /run/sshd \
181+ && sed -i -E \
182+ -e 's/^#?Port .*/Port 2222/' \
183+ -e 's/^#?PasswordAuthentication .*/PasswordAuthentication no/' \
184+ -e 's/^#?PubkeyAuthentication .*/PubkeyAuthentication yes/' \
185+ -e 's/^#?UsePAM .*/UsePAM yes/' \
186+ /etc/ssh/sshd_config \
187+ && /usr/sbin/sshd -t \
188+ && rm -f /etc/ssh/ssh_host_* \
189+ && apt-get clean \
190+ && rm -rf /var/lib/apt/lists/*
191+
192+ # Create docker startup script.
193+ # NOTE: This script is the image's ENTRYPOINT, but Codespaces/devcontainer tooling
194+ # overrides the entrypoint at container start, so it never runs there — it only
195+ # runs under plain `docker run`. On Codespaces sshd is started by
196+ # .devcontainer/start-sshd.sh (postStartCommand) and dockerd by
197+ # .devcontainer/setup.sh (postAttachCommand) instead. Keep these in sync.
175198RUN echo '#!/bin/bash\n \
199+ # Regenerate SSH host keys if missing (never baked into the shared image)\n \
200+ sudo ssh-keygen -A > /dev/null\n \
201+ # Privilege-separation dir; /run can be tmpfs, wiping the build-time mkdir\n \
202+ sudo mkdir -p /run/sshd\n \
203+ # Start the SSH daemon (self-daemonizes; do not add -D here)\n \
204+ sudo /usr/sbin/sshd\n \
176205# Start docker daemon in background\n \
177206sudo dockerd > /dev/null 2>&1 &\n \
178207# Wait for docker to be ready\n \
0 commit comments