diff --git a/backend/src/services/deploy.ts b/backend/src/services/deploy.ts index d8c2d8e7..87d1f018 100644 --- a/backend/src/services/deploy.ts +++ b/backend/src/services/deploy.ts @@ -227,7 +227,7 @@ async function firstDeploy( checkAbort(previewId); - // Connect as root. Ubuntu user-data copies authorized_keys to root and enables root SSH. + // Ubuntu cloud images support command execution through their provisioned user. const sshSession = await connectSsh(instanceIp, privateKey, 300_000); activeSshSessions.set(previewId, sshSession); @@ -239,7 +239,7 @@ async function firstDeploy( await appendLog(previewId, `[PP] Bootstrap complete. Starting setup...\n`); if (repoConfig.aptPackages.length > 0) { - await runSshStep(previewId, sshSession, `DEBIAN_FRONTEND=noninteractive apt-get install -y ${repoConfig.aptPackages.join(" ")}`); + await runSshStep(previewId, sshSession, `sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ${repoConfig.aptPackages.join(" ")}`); } const giteaPat = user.giteaPAT ? decrypt(user.giteaPAT) : ""; @@ -344,7 +344,7 @@ async function redeploy( } } -const NVM_PREFIX = `export NVM_DIR="/root/.nvm"; source "$NVM_DIR/nvm.sh" 2>/dev/null;`; +const NVM_PREFIX = `export NVM_DIR="$HOME/.nvm"; source "$NVM_DIR/nvm.sh" 2>/dev/null;`; function withNvm(cmd: string): string { return `bash -c '${NVM_PREFIX} ${cmd.replace(/'/g, `'"'"'`)}'`; diff --git a/backend/src/services/ec2.ts b/backend/src/services/ec2.ts index 9fa6d48c..5497ef7f 100644 --- a/backend/src/services/ec2.ts +++ b/backend/src/services/ec2.ts @@ -127,26 +127,13 @@ systemctl enable docker systemctl start docker apt-get install -y docker-compose-plugin -# NVM + Node LTS (installed as root, available to root SSH sessions) -export HOME=/root -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash -export NVM_DIR="/root/.nvm" -source "$NVM_DIR/nvm.sh" -nvm install --lts -nvm alias default lts/* +# PP deploys as the image's supported SSH user. Give it Docker access and its +# own Node runtime rather than attempting to override Ubuntu's root SSH policy. +usermod -aG docker ubuntu +sudo -u ubuntu -H bash -lc 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash' +sudo -u ubuntu -H bash -lc 'export NVM_DIR="$HOME/.nvm"; source "$NVM_DIR/nvm.sh"; nvm install --lts; nvm alias default lts/*' -# Do not permit PP's root SSH session until every bootstrap step succeeded. -# That prevents PP from seeing SSH as ready while cloud-init is still mutating -# the host and turns the completion marker into a reliable readiness signal. touch /var/lib/pp-bootstrap-done -sed -i 's/^#*PermitRootLogin.*/PermitRootLogin without-password/' /etc/ssh/sshd_config -mkdir -p /root/.ssh -chmod 700 /root/.ssh -if [ -f /home/ubuntu/.ssh/authorized_keys ]; then - cp /home/ubuntu/.ssh/authorized_keys /root/.ssh/authorized_keys - chmod 600 /root/.ssh/authorized_keys -fi -systemctl reload sshd || service ssh reload `; export async function launchInstance(opts: { diff --git a/backend/src/services/ssh.ts b/backend/src/services/ssh.ts index 3974484a..4d23cad9 100644 --- a/backend/src/services/ssh.ts +++ b/backend/src/services/ssh.ts @@ -60,7 +60,7 @@ function tryConnect(host: string, privateKey: string, timeoutMs: number): Promis conn.connect({ host, port: 22, - username: "root", + username: "ubuntu", privateKey, readyTimeout: timeoutMs, keepaliveInterval: 10000,