Skip to content

Commit de2640b

Browse files
andystimeclaude
andcommitted
fix: prevent SSH zombie processes with --init flag
Problem: SSH daemon creates zombie (defunct) processes because container's PID 1 (sleep infinity) doesn't reap child processes. This prevents SSH connections from being properly handled. Solution: Add --init flag to docker run command, which: - Uses Docker's tini init process as PID 1 - Properly reaps zombie processes - Handles signals correctly - Allows SSH daemon to fork child processes successfully Also improved SSH config: - Removed deprecated UsePrivilegeSeparation option - Added ClientAliveInterval/CountMax for connection stability - Ensured UsePAM is enabled for proper authentication - Added proper ListenAddress configuration This fixes "Connection closed" errors when connecting to studio via SSH. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 36c8244 commit de2640b

4 files changed

Lines changed: 29 additions & 6 deletions

File tree

internal/studio/backend_colima.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ func (b *ColimaBackend) Create(ctx context.Context, opts *CreateOptions) (*Envir
386386
// Build docker run command
387387
args := []string{"run", "-d", "--name", containerName}
388388

389+
// Add --init flag to use tini init process
390+
// This prevents zombie processes and allows proper signal handling
391+
args = append(args, "--init")
392+
389393
// Add platform flag if specified
390394
if platform != "" {
391395
args = append(args, "--platform", platform)

internal/studio/backend_docker.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ func (b *DockerBackend) Create(ctx context.Context, opts *CreateOptions) (*Envir
157157
// Build docker run command
158158
args := []string{"run", "-d", "--name", containerName}
159159

160+
// Add --init flag to use tini init process
161+
// This prevents zombie processes and allows proper signal handling
162+
// Required for SSH daemon to properly fork child processes
163+
args = append(args, "--init")
164+
160165
// Add security options for SSH to work in containers
161166
// SSH's privilege separation requires certain capabilities that Docker's
162167
// default seccomp profile blocks, causing "mm_request_receive: bad msg_len" errors

internal/studio/backend_wsl.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ func (b *WSLBackend) Create(ctx context.Context, opts *CreateOptions) (*Environm
227227
// Build docker run command
228228
args := []string{"docker", "run", "-d", "--name", containerName}
229229

230+
// Add --init flag to use tini init process
231+
// This prevents zombie processes and allows proper signal handling
232+
args = append(args, "--init")
233+
230234
// Add local GPU passthrough if requested
231235
if opts.UseLocalGPU {
232236
args = append(args, "--gpus", "all")
@@ -642,21 +646,26 @@ chmod 700 /root/.ssh
642646
643647
cat > /etc/ssh/sshd_config << 'SSHD_EOF'
644648
Port 22
645-
Protocol 2
649+
AddressFamily any
650+
ListenAddress 0.0.0.0
646651
HostKey /etc/ssh/ssh_host_rsa_key
647652
HostKey /etc/ssh/ssh_host_ecdsa_key
648653
HostKey /etc/ssh/ssh_host_ed25519_key
649654
PermitRootLogin yes
650655
PubkeyAuthentication yes
656+
AuthorizedKeysFile .ssh/authorized_keys
651657
PasswordAuthentication yes
652658
PermitEmptyPasswords no
653659
ChallengeResponseAuthentication no
654-
UsePrivilegeSeparation no
655660
SyslogFacility AUTH
656661
LogLevel INFO
657662
X11Forwarding yes
658663
PrintMotd no
659664
AcceptEnv LANG LC_*
665+
TCPKeepAlive yes
666+
ClientAliveInterval 60
667+
ClientAliveCountMax 3
668+
UsePAM yes
660669
Subsystem sftp /usr/lib/openssh/sftp-server
661670
SSHD_EOF
662671

internal/studio/ssh_setup.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,22 @@ chmod 700 /root/.ssh
6161
cat > /etc/ssh/sshd_config << 'SSHD_EOF'
6262
# Basic configuration
6363
Port 22
64-
Protocol 2
64+
AddressFamily any
65+
ListenAddress 0.0.0.0
66+
67+
# Host keys
6568
HostKey /etc/ssh/ssh_host_rsa_key
6669
HostKey /etc/ssh/ssh_host_ecdsa_key
6770
HostKey /etc/ssh/ssh_host_ed25519_key
6871
6972
# Authentication
7073
PermitRootLogin yes
7174
PubkeyAuthentication yes
75+
AuthorizedKeysFile .ssh/authorized_keys
7276
PasswordAuthentication yes
7377
PermitEmptyPasswords no
7478
ChallengeResponseAuthentication no
7579
76-
# Privilege Separation
77-
UsePrivilegeSeparation no
78-
7980
# Logging
8081
SyslogFacility AUTH
8182
LogLevel INFO
@@ -84,6 +85,10 @@ LogLevel INFO
8485
X11Forwarding yes
8586
PrintMotd no
8687
AcceptEnv LANG LC_*
88+
TCPKeepAlive yes
89+
ClientAliveInterval 60
90+
ClientAliveCountMax 3
91+
UsePAM yes
8792
8893
# Subsystems
8994
Subsystem sftp /usr/lib/openssh/sftp-server

0 commit comments

Comments
 (0)