From 4a9f207fe8775cd0862d34d45483797c02cb90e1 Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Sat, 16 May 2026 05:11:39 +0000 Subject: [PATCH] v1.5.1: bootstrap fixes (git + ssh in container, Tailscale host rewrite, /opt/projects label) - Dockerfile: install git + openssh-client in runtime image; pre-populate /root/.ssh/known_hosts with the Tailscale ssh-keyscan for 100.114.205.53:2222 (Gitea SSH). Without these, the bootstrap push step from inside the container fails with "command not found" or host-key prompts. - docker-compose.yml: mount ./secrets/boocode_gitea as /root/.ssh/id_ed25519:ro so the container can authenticate to Gitea over SSH for the initial push. - .gitignore: add secrets/ so the keypair never lands in the repo. - project_bootstrap.ts: rewrite the Gitea-returned ssh_url's hostname from git.indifferentketchup.com to 100.114.205.53 before adding it as origin, so the push hits the Tailscale interface that the known_hosts entry covers. - CreateProjectModal.tsx: preview label now reads "Folder: /opt/projects/" to match the new BOOTSTRAP_ROOT (was /opt/). Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 1 + Dockerfile | 3 ++- apps/server/src/services/project_bootstrap.ts | 3 ++- apps/web/src/components/CreateProjectModal.tsx | 2 +- docker-compose.yml | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 847767e..a3a9da5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist .DS_Store .vite coverage +secrets/ diff --git a/Dockerfile b/Dockerfile index 3279183..740514f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,8 @@ RUN pnpm deploy --filter=@boocode/server --prod --legacy /out/server FROM node:20-alpine AS runtime -RUN apk add --no-cache ripgrep +RUN apk add --no-cache ripgrep git openssh-client +RUN mkdir -p /root/.ssh && ssh-keyscan -p 2222 -H 100.114.205.53 git.indifferentketchup.com >> /root/.ssh/known_hosts && chmod 700 /root/.ssh && chmod 600 /root/.ssh/known_hosts WORKDIR /app COPY --from=builder /out/server ./ diff --git a/apps/server/src/services/project_bootstrap.ts b/apps/server/src/services/project_bootstrap.ts index c080549..bb8db76 100644 --- a/apps/server/src/services/project_bootstrap.ts +++ b/apps/server/src/services/project_bootstrap.ts @@ -146,7 +146,8 @@ export async function bootstrapProject( // Step 6: git remote add + push try { - await execFileAsync('git', ['remote', 'add', 'origin', repo.ssh_url], { cwd: fullPath }); + const sshUrl = repo.ssh_url.replace('git.indifferentketchup.com', '100.114.205.53'); + await execFileAsync('git', ['remote', 'add', 'origin', sshUrl], { cwd: fullPath }); await execFileAsync('git', ['push', '-u', 'origin', 'main'], { cwd: fullPath }); gitea_pushed = true; log.info({ folder }, 'project_bootstrap: pushed to gitea'); diff --git a/apps/web/src/components/CreateProjectModal.tsx b/apps/web/src/components/CreateProjectModal.tsx index e1d7c56..bb8ae95 100644 --- a/apps/web/src/components/CreateProjectModal.tsx +++ b/apps/web/src/components/CreateProjectModal.tsx @@ -103,7 +103,7 @@ export function CreateProjectModal({ open, onOpenChange }: Props) { /> {name && (
- Folder: /opt/{folderPreview || (empty after sanitization)} + Folder: /opt/projects/{folderPreview || (empty after sanitization)}
)} diff --git a/docker-compose.yml b/docker-compose.yml index 45dd681..e813045 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,6 +14,7 @@ services: # Writable mount only for the create-new-project bootstrap target. # Host must `mkdir -p /opt/projects` before container start. - /opt/projects:/opt/projects:rw + - ./secrets/boocode_gitea:/root/.ssh/id_ed25519:ro depends_on: - boocode_db networks: