Skip to content

Commit 6c91582

Browse files
committed
fix: set ttyd password in VM metadata during creation
GCP metadata API is read-only from within the VM, so we now: - Generate ttyd password before VM creation - Set it in metadata during VM creation - Startup script reads password from metadata instead of generating it
1 parent 68cb3f1 commit 6c91582

1 file changed

Lines changed: 24 additions & 9 deletions

File tree

src/lib/gcp.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ function sanitizeForGCP(str: string): string {
7070
return str.toLowerCase().replace(/[^a-z0-9-]/g, "-");
7171
}
7272

73+
// Generate a random alphanumeric password
74+
function generateRandomPassword(length: number): string {
75+
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
76+
let result = '';
77+
const randomBytes = new Uint8Array(length);
78+
crypto.getRandomValues(randomBytes);
79+
for (let i = 0; i < length; i++) {
80+
result += chars[randomBytes[i] % chars.length];
81+
}
82+
return result;
83+
}
84+
7385
function getInstanceName(username: string, instanceId: string = DEFAULT_INSTANCE_ID): string {
7486
const sanitizedUser = sanitizeForGCP(username);
7587
const sanitizedId = sanitizeForGCP(instanceId);
@@ -229,6 +241,9 @@ export async function createDevEnvironment(
229241

230242
const now = new Date().toISOString();
231243
const hasSnap = await snapshotExists(username);
244+
245+
// Generate ttyd password upfront (metadata API is read-only, so we can't set it from startup script)
246+
const ttydPassword = generateRandomPassword(16);
232247

233248
// Determine which machine configs to try
234249
// If user specified a machine type, use only that one
@@ -315,9 +330,13 @@ export async function createDevEnvironment(
315330
key: "instance-id",
316331
value: instanceId,
317332
},
333+
{
334+
key: "ttyd-password",
335+
value: ttydPassword,
336+
},
318337
{
319338
key: "startup-script",
320-
value: getStartupScript(username, hasSnap, token),
339+
value: getStartupScript(username, hasSnap, token, ttydPassword),
321340
},
322341
],
323342
},
@@ -749,7 +768,7 @@ async function waitForOperation(operationName: string): Promise<void> {
749768
throw new Error("Operation timed out");
750769
}
751770

752-
function getStartupScript(username: string, isRestore: boolean = false, githubToken?: string): string {
771+
function getStartupScript(username: string, isRestore: boolean = false, githubToken?: string, ttydPassword?: string): string {
753772
// GitHub token credential setup for developer user
754773
const devTokenSetup = githubToken
755774
? `
@@ -1010,13 +1029,9 @@ echo "✓ Frontend service started on port 3000" >> /var/log/startup.log
10101029
# Start ttyd web terminal service
10111030
echo "Starting ttyd web terminal..." >> /var/log/startup.log
10121031
1013-
# Generate a random password for ttyd authentication (use more bytes to ensure 16 chars after filtering)
1014-
TTYD_PASSWORD=$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 16)
1015-
1016-
# Store the password in VM metadata for the dashboard to retrieve
1017-
curl -X PUT "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ttyd-password" \\
1018-
-H "Metadata-Flavor: Google" \\
1019-
-d "\$TTYD_PASSWORD" 2>/dev/null || true
1032+
# Get ttyd password from metadata (set during VM creation)
1033+
TTYD_PASSWORD=$(curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/ttyd-password 2>/dev/null || echo "defaultpass")
1034+
echo "ttyd password retrieved from metadata" >> /var/log/startup.log
10201035
10211036
# Start ttyd on port 7681 with authentication
10221037
# -W: Writable (allow input)

0 commit comments

Comments
 (0)