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/<name>" to match the new BOOTSTRAP_ROOT (was /opt/).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 05:11:39 +00:00
parent 782c2b183d
commit 4a9f207fe8
5 changed files with 7 additions and 3 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ dist
.DS_Store
.vite
coverage
secrets/

View File

@@ -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 ./

View File

@@ -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');

View File

@@ -103,7 +103,7 @@ export function CreateProjectModal({ open, onOpenChange }: Props) {
/>
{name && (
<div className="text-xs text-muted-foreground font-mono">
Folder: /opt/{folderPreview || <span className="text-destructive">(empty after sanitization)</span>}
Folder: /opt/projects/{folderPreview || <span className="text-destructive">(empty after sanitization)</span>}
</div>
)}
</div>

View File

@@ -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: