GCP: add minimal container deployment with scripts
Co-Authored-By: Warp <agent@warp.dev>
This commit is contained in:
parent
ff382f6b68
commit
c063ce3e3a
80
Dockerfile.production
Normal file
80
Dockerfile.production
Normal file
@ -0,0 +1,80 @@
|
||||
# ============================================
|
||||
# Dockerfile.production
|
||||
# Minimal multi-stage build for GCP deployment
|
||||
# Final image: ~150-200MB
|
||||
# ============================================
|
||||
|
||||
# --------------------------------------------
|
||||
# Stage 1: Builder
|
||||
# --------------------------------------------
|
||||
FROM node:22-bookworm AS builder
|
||||
|
||||
# Install Bun (required for build scripts)
|
||||
RUN curl -fsSL https://bun.sh/install | bash
|
||||
ENV PATH="/root/.bun/bin:${PATH}"
|
||||
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files for dependency caching
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
|
||||
COPY ui/package.json ./ui/package.json
|
||||
COPY patches ./patches
|
||||
COPY scripts ./scripts
|
||||
|
||||
# Install ALL dependencies (including dev for build)
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source and build
|
||||
COPY . .
|
||||
RUN pnpm build
|
||||
|
||||
# Build UI
|
||||
ENV CLAWDBOT_PREFER_PNPM=1
|
||||
RUN pnpm ui:install
|
||||
RUN pnpm ui:build
|
||||
|
||||
# Prune dev dependencies for production
|
||||
RUN pnpm prune --prod
|
||||
|
||||
# --------------------------------------------
|
||||
# Stage 2: Production (Minimal)
|
||||
# --------------------------------------------
|
||||
FROM node:22-bookworm-slim AS production
|
||||
|
||||
# Only essential runtime packages
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get clean
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only production artifacts
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/package.json ./
|
||||
COPY --from=builder /app/assets ./assets
|
||||
COPY --from=builder /app/skills ./skills
|
||||
COPY --from=builder /app/extensions ./extensions
|
||||
COPY --from=builder /app/docs ./docs
|
||||
|
||||
# Copy UI build output if present
|
||||
COPY --from=builder /app/ui/dist ./ui/dist
|
||||
|
||||
# Create non-root user (node user already exists in node image)
|
||||
RUN chown -R node:node /app
|
||||
USER node
|
||||
|
||||
# Gateway port
|
||||
EXPOSE 18789
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=60s --timeout=5s --retries=2 \
|
||||
CMD curl -sf http://localhost:18789/health || exit 1
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
CMD ["node", "dist/index.js", "gateway", "--bind", "lan", "--port", "18789"]
|
||||
@ -15,6 +15,51 @@ Run a persistent Clawdbot Gateway on a GCP Compute Engine VM using Docker, with
|
||||
If you want "Clawdbot 24/7 for ~$5-12/mo", this is a reliable setup on Google Cloud.
|
||||
Pricing varies by machine type and region; pick the smallest VM that fits your workload and scale up if you hit OOMs.
|
||||
|
||||
---
|
||||
|
||||
## Minimal container deployment (scripted)
|
||||
|
||||
For a streamlined deployment with a smaller image (~150MB), use the provided scripts:
|
||||
|
||||
```bash
|
||||
cd scripts/gcp
|
||||
|
||||
# 1. Create a NEW GCP project (use a unique name)
|
||||
./setup-project.sh clawdbot-$(date +%Y%m%d) us-east1
|
||||
|
||||
# 2. Store secrets (interactive prompts)
|
||||
./store-secrets.sh
|
||||
|
||||
# 3. Build production image
|
||||
./build-push.sh local # or: ./build-push.sh cloud
|
||||
|
||||
# 4. Deploy
|
||||
./deploy-vm.sh # e2-micro (free tier)
|
||||
./deploy-vm.sh e2-small # 2GB RAM
|
||||
|
||||
# 5. Connect via IAP tunnel
|
||||
./connect.sh
|
||||
```
|
||||
|
||||
This uses `Dockerfile.production` (multi-stage build) and deploys with:
|
||||
- No public IP (secure IAP tunnel access)
|
||||
- Secrets in GCP Secret Manager
|
||||
- Container-optimized VM with auto-restart
|
||||
|
||||
See `scripts/gcp/README.md` for full details.
|
||||
|
||||
**Cost comparison:**
|
||||
|
||||
| Option | Monthly Cost | Notes |
|
||||
|--------|--------------|-------|
|
||||
| e2-micro VM | $0 (free tier) | 1 vCPU shared, 1GB RAM |
|
||||
| e2-small VM | ~$13/mo | 2 vCPU shared, 2GB RAM |
|
||||
| Cloud Run | ~$0-5/mo | Pay per request, scales to 0 |
|
||||
|
||||
---
|
||||
|
||||
The rest of this guide covers manual setup with full control over the Docker configuration.
|
||||
|
||||
## What are we doing (simple terms)?
|
||||
|
||||
- Create a GCP project and enable billing
|
||||
|
||||
61
scripts/gcp/README.md
Normal file
61
scripts/gcp/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# GCP Deployment Scripts
|
||||
|
||||
Minimal container deployment for Clawdbot on Google Cloud Platform.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Create a NEW GCP project and enable APIs
|
||||
./setup-project.sh clawdbot-$(date +%Y%m%d) us-east1
|
||||
|
||||
# 2. Store secrets (interactive)
|
||||
./store-secrets.sh
|
||||
|
||||
# 3. Build and push production image
|
||||
./build-push.sh local # Build locally, push to GCR
|
||||
./build-push.sh cloud # Build on Cloud Build (no local Docker)
|
||||
|
||||
# 4. Deploy
|
||||
./deploy-vm.sh # Compute Engine (free tier: e2-micro)
|
||||
./deploy-vm.sh e2-small # Compute Engine with more RAM
|
||||
./deploy-cloudrun.sh # Cloud Run (pay per request)
|
||||
|
||||
# 5. Connect
|
||||
./connect.sh # IAP tunnel to Gateway
|
||||
./ssh.sh # SSH into VM
|
||||
./logs.sh --follow # View container logs
|
||||
```
|
||||
|
||||
## Cost Comparison
|
||||
|
||||
| Option | Monthly Cost | Notes |
|
||||
|--------|--------------|-------|
|
||||
| e2-micro VM | $0 (free tier) | 1 vCPU shared, 1GB RAM, always on |
|
||||
| e2-small VM | ~$13/mo | 2 vCPU shared, 2GB RAM |
|
||||
| Cloud Run | ~$0-5/mo | Pay per request, auto-scales to 0 |
|
||||
|
||||
## Files
|
||||
|
||||
- `setup-project.sh` - Enable APIs, create service account, firewall rules
|
||||
- `store-secrets.sh` - Store API keys in Secret Manager
|
||||
- `build-push.sh` - Build production image and push to GCR
|
||||
- `deploy-vm.sh` - Deploy to Compute Engine with container
|
||||
- `deploy-cloudrun.sh` - Deploy to Cloud Run
|
||||
- `connect.sh` - IAP tunnel to Gateway port
|
||||
- `ssh.sh` - SSH into VM via IAP
|
||||
- `logs.sh` - View container logs
|
||||
|
||||
## Production Image
|
||||
|
||||
Uses `Dockerfile.production` (multi-stage build):
|
||||
- Builder stage: Full Node.js + Bun for compilation
|
||||
- Production stage: `node:22-bookworm-slim` (~150-200MB final)
|
||||
- Runs as non-root user
|
||||
- Health check endpoint
|
||||
|
||||
## Security
|
||||
|
||||
- No public IP (access via IAP tunnel)
|
||||
- Secrets stored in Secret Manager
|
||||
- Dedicated service account with minimal permissions
|
||||
- Shielded VM with Secure Boot
|
||||
48
scripts/gcp/build-push.sh
Executable file
48
scripts/gcp/build-push.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build and push production Docker image to GCR
|
||||
# Usage: ./build-push.sh [local|cloud]
|
||||
set -euo pipefail
|
||||
|
||||
BUILD_MODE="${1:-local}"
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE="gcr.io/${PROJECT_ID}/clawdbot:latest"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
echo "Building image: $IMAGE"
|
||||
echo "Build mode: $BUILD_MODE"
|
||||
echo ""
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
if [[ "$BUILD_MODE" == "cloud" ]]; then
|
||||
# Build on GCP Cloud Build (no local Docker needed)
|
||||
echo "Building on Cloud Build..."
|
||||
gcloud builds submit \
|
||||
--tag "$IMAGE" \
|
||||
--timeout=1800s \
|
||||
-f Dockerfile.production \
|
||||
.
|
||||
else
|
||||
# Build locally and push
|
||||
echo "Building locally..."
|
||||
docker build \
|
||||
-f Dockerfile.production \
|
||||
-t "$IMAGE" \
|
||||
.
|
||||
|
||||
echo ""
|
||||
echo "Pushing to GCR..."
|
||||
docker push "$IMAGE"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Image pushed: $IMAGE"
|
||||
echo ""
|
||||
echo "Next: Deploy with ./deploy-vm.sh or ./deploy-cloudrun.sh"
|
||||
27
scripts/gcp/connect.sh
Executable file
27
scripts/gcp/connect.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Connect to Clawdbot Gateway via IAP tunnel
|
||||
# Usage: ./connect.sh [VM_NAME]
|
||||
set -euo pipefail
|
||||
|
||||
VM_NAME="${1:-clawdbot-vm}"
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
REGION=$(gcloud config get-value compute/region 2>/dev/null)
|
||||
ZONE="${REGION}-b"
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting IAP tunnel to Clawdbot Gateway"
|
||||
echo " VM: $VM_NAME"
|
||||
echo " Zone: $ZONE"
|
||||
echo ""
|
||||
echo "Access at: http://localhost:18789"
|
||||
echo "Press Ctrl+C to disconnect"
|
||||
echo ""
|
||||
|
||||
gcloud compute start-iap-tunnel "$VM_NAME" 18789 \
|
||||
--local-host-port=localhost:18789 \
|
||||
--zone="$ZONE" \
|
||||
--project="$PROJECT_ID"
|
||||
71
scripts/gcp/deploy-cloudrun.sh
Executable file
71
scripts/gcp/deploy-cloudrun.sh
Executable file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy Clawdbot to Cloud Run (pay-per-request, scales to zero)
|
||||
# Usage: ./deploy-cloudrun.sh
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
REGION=$(gcloud config get-value compute/region 2>/dev/null)
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE="gcr.io/${PROJECT_ID}/clawdbot:latest"
|
||||
SA_EMAIL="clawdbot-sa@${PROJECT_ID}.iam.gserviceaccount.com"
|
||||
SERVICE_NAME="clawdbot"
|
||||
|
||||
echo "Deploying Clawdbot to Cloud Run"
|
||||
echo " Project: $PROJECT_ID"
|
||||
echo " Region: $REGION"
|
||||
echo " Image: $IMAGE"
|
||||
echo ""
|
||||
|
||||
# Build secret references
|
||||
SECRETS=""
|
||||
if gcloud secrets describe anthropic-api-key &>/dev/null; then
|
||||
SECRETS="${SECRETS}ANTHROPIC_API_KEY=anthropic-api-key:latest,"
|
||||
fi
|
||||
if gcloud secrets describe openai-api-key &>/dev/null; then
|
||||
SECRETS="${SECRETS}OPENAI_API_KEY=openai-api-key:latest,"
|
||||
fi
|
||||
if gcloud secrets describe clawdbot-gateway-token &>/dev/null; then
|
||||
SECRETS="${SECRETS}CLAWDBOT_GATEWAY_TOKEN=clawdbot-gateway-token:latest,"
|
||||
fi
|
||||
|
||||
# Remove trailing comma
|
||||
SECRETS="${SECRETS%,}"
|
||||
|
||||
# Deploy
|
||||
gcloud run deploy "$SERVICE_NAME" \
|
||||
--image="$IMAGE" \
|
||||
--platform=managed \
|
||||
--region="$REGION" \
|
||||
--memory=512Mi \
|
||||
--cpu=1 \
|
||||
--min-instances=0 \
|
||||
--max-instances=1 \
|
||||
--port=18789 \
|
||||
--no-allow-unauthenticated \
|
||||
--service-account="$SA_EMAIL" \
|
||||
${SECRETS:+--set-secrets="$SECRETS"}
|
||||
|
||||
echo ""
|
||||
echo "Deployment complete!"
|
||||
echo ""
|
||||
|
||||
# Get service URL
|
||||
SERVICE_URL=$(gcloud run services describe "$SERVICE_NAME" --region="$REGION" --format='value(status.url)')
|
||||
echo "Service URL: $SERVICE_URL"
|
||||
echo ""
|
||||
echo "Note: Cloud Run requires authentication. Use:"
|
||||
echo " gcloud run services add-iam-policy-binding $SERVICE_NAME \\"
|
||||
echo " --region=$REGION \\"
|
||||
echo " --member='user:YOUR_EMAIL' \\"
|
||||
echo " --role='roles/run.invoker'"
|
||||
echo ""
|
||||
echo "Or for public access (not recommended):"
|
||||
echo " gcloud run services add-iam-policy-binding $SERVICE_NAME \\"
|
||||
echo " --region=$REGION \\"
|
||||
echo " --member='allUsers' \\"
|
||||
echo " --role='roles/run.invoker'"
|
||||
67
scripts/gcp/deploy-vm.sh
Executable file
67
scripts/gcp/deploy-vm.sh
Executable file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy Clawdbot to GCP Compute Engine VM with Container-Optimized OS
|
||||
# Usage: ./deploy-vm.sh [MACHINE_TYPE]
|
||||
set -euo pipefail
|
||||
|
||||
MACHINE_TYPE="${1:-e2-micro}"
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
REGION=$(gcloud config get-value compute/region 2>/dev/null)
|
||||
ZONE="${REGION}-b"
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE="gcr.io/${PROJECT_ID}/clawdbot:latest"
|
||||
SA_EMAIL="clawdbot-sa@${PROJECT_ID}.iam.gserviceaccount.com"
|
||||
VM_NAME="clawdbot-vm"
|
||||
|
||||
echo "Deploying Clawdbot Gateway"
|
||||
echo " Project: $PROJECT_ID"
|
||||
echo " Region: $REGION"
|
||||
echo " Zone: $ZONE"
|
||||
echo " Machine type: $MACHINE_TYPE"
|
||||
echo " Image: $IMAGE"
|
||||
echo ""
|
||||
|
||||
# Check if VM exists
|
||||
if gcloud compute instances describe "$VM_NAME" --zone="$ZONE" &>/dev/null; then
|
||||
echo "VM already exists. Updating container..."
|
||||
gcloud compute instances update-container "$VM_NAME" \
|
||||
--zone="$ZONE" \
|
||||
--container-image="$IMAGE"
|
||||
echo ""
|
||||
echo "Container updated. Restarting VM..."
|
||||
gcloud compute instances reset "$VM_NAME" --zone="$ZONE"
|
||||
else
|
||||
echo "Creating new VM..."
|
||||
gcloud compute instances create-with-container "$VM_NAME" \
|
||||
--project="$PROJECT_ID" \
|
||||
--zone="$ZONE" \
|
||||
--machine-type="$MACHINE_TYPE" \
|
||||
--network-interface=network-tier=STANDARD,subnet=default,no-address \
|
||||
--shielded-secure-boot \
|
||||
--shielded-vtpm \
|
||||
--shielded-integrity-monitoring \
|
||||
--container-image="$IMAGE" \
|
||||
--container-restart-policy=always \
|
||||
--container-env=NODE_ENV=production,GATEWAY_PORT=18789,GATEWAY_BIND=0.0.0.0 \
|
||||
--metadata=enable-oslogin=TRUE \
|
||||
--tags=clawdbot \
|
||||
--boot-disk-size=10GB \
|
||||
--boot-disk-type=pd-standard \
|
||||
--service-account="$SA_EMAIL" \
|
||||
--scopes=https://www.googleapis.com/auth/cloud-platform
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Deployment complete!"
|
||||
echo ""
|
||||
echo "Machine type costs (approximate):"
|
||||
echo " e2-micro: Free tier eligible (1 vCPU shared, 1GB RAM)"
|
||||
echo " e2-small: ~\$13/mo (2 vCPU shared, 2GB RAM)"
|
||||
echo " e2-medium: ~\$25/mo (2 vCPU, 4GB RAM)"
|
||||
echo ""
|
||||
echo "Connect with: ./connect.sh"
|
||||
echo "Or manually: gcloud compute start-iap-tunnel $VM_NAME 18789 --local-host-port=localhost:18789 --zone=$ZONE"
|
||||
29
scripts/gcp/logs.sh
Executable file
29
scripts/gcp/logs.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
# View Clawdbot container logs on GCP VM
|
||||
# Usage: ./logs.sh [VM_NAME] [--follow]
|
||||
set -euo pipefail
|
||||
|
||||
VM_NAME="${1:-clawdbot-vm}"
|
||||
FOLLOW="${2:-}"
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
REGION=$(gcloud config get-value compute/region 2>/dev/null)
|
||||
ZONE="${REGION}-b"
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Fetching logs from $VM_NAME..."
|
||||
|
||||
if [[ "$FOLLOW" == "--follow" ]] || [[ "$FOLLOW" == "-f" ]]; then
|
||||
gcloud compute ssh "$VM_NAME" \
|
||||
--zone="$ZONE" \
|
||||
--tunnel-through-iap \
|
||||
--command="sudo journalctl -u konlet-startup -f"
|
||||
else
|
||||
gcloud compute ssh "$VM_NAME" \
|
||||
--zone="$ZONE" \
|
||||
--tunnel-through-iap \
|
||||
--command="sudo journalctl -u konlet-startup -n 100"
|
||||
fi
|
||||
84
scripts/gcp/setup-project.sh
Executable file
84
scripts/gcp/setup-project.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create and setup a NEW GCP project for Clawdbot deployment
|
||||
# Usage: ./setup-project.sh PROJECT_ID [REGION]
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ID="${1:-}"
|
||||
REGION="${2:-us-east1}"
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Usage: $0 PROJECT_ID [REGION]"
|
||||
echo "Example: $0 clawdbot-$(date +%Y%m%d) us-east1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Creating NEW GCP project: $PROJECT_ID in region: $REGION"
|
||||
echo ""
|
||||
|
||||
# Create the project
|
||||
if gcloud projects describe "$PROJECT_ID" &>/dev/null; then
|
||||
echo "Project $PROJECT_ID already exists, using it..."
|
||||
else
|
||||
echo "Creating project $PROJECT_ID..."
|
||||
gcloud projects create "$PROJECT_ID" --name="Clawdbot Gateway"
|
||||
fi
|
||||
|
||||
# Set as active project
|
||||
gcloud config set project "$PROJECT_ID"
|
||||
gcloud config set compute/region "$REGION"
|
||||
|
||||
# Check billing
|
||||
echo ""
|
||||
echo "Checking billing..."
|
||||
BILLING=$(gcloud billing projects describe "$PROJECT_ID" --format='value(billingEnabled)' 2>/dev/null || echo "false")
|
||||
if [[ "$BILLING" != "True" ]]; then
|
||||
echo ""
|
||||
echo "WARNING: Billing is not enabled for this project."
|
||||
echo "Enable billing at: https://console.cloud.google.com/billing/linkedaccount?project=$PROJECT_ID"
|
||||
echo ""
|
||||
read -rp "Press Enter after enabling billing to continue..."
|
||||
fi
|
||||
|
||||
# Enable required APIs
|
||||
echo "Enabling required APIs..."
|
||||
gcloud services enable \
|
||||
compute.googleapis.com \
|
||||
secretmanager.googleapis.com \
|
||||
containerregistry.googleapis.com \
|
||||
cloudbuild.googleapis.com \
|
||||
iap.googleapis.com
|
||||
|
||||
# Create service account
|
||||
SA_NAME="clawdbot-sa"
|
||||
SA_EMAIL="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
|
||||
|
||||
echo "Creating service account: $SA_NAME"
|
||||
if ! gcloud iam service-accounts describe "$SA_EMAIL" &>/dev/null; then
|
||||
gcloud iam service-accounts create "$SA_NAME" \
|
||||
--display-name="Clawdbot Service Account"
|
||||
else
|
||||
echo "Service account already exists"
|
||||
fi
|
||||
|
||||
# Create firewall rule for IAP
|
||||
echo "Creating firewall rule for IAP..."
|
||||
if ! gcloud compute firewall-rules describe allow-iap-clawdbot &>/dev/null; then
|
||||
gcloud compute firewall-rules create allow-iap-clawdbot \
|
||||
--direction=INGRESS \
|
||||
--priority=1000 \
|
||||
--network=default \
|
||||
--action=ALLOW \
|
||||
--rules=tcp:18789,tcp:22 \
|
||||
--source-ranges=35.235.240.0/20 \
|
||||
--target-tags=clawdbot
|
||||
else
|
||||
echo "Firewall rule already exists"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Project setup complete!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Store secrets: ./store-secrets.sh"
|
||||
echo " 2. Build and push image: ./build-push.sh"
|
||||
echo " 3. Deploy VM: ./deploy-vm.sh"
|
||||
19
scripts/gcp/ssh.sh
Executable file
19
scripts/gcp/ssh.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
# SSH into Clawdbot VM via IAP
|
||||
# Usage: ./ssh.sh [VM_NAME]
|
||||
set -euo pipefail
|
||||
|
||||
VM_NAME="${1:-clawdbot-vm}"
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
REGION=$(gcloud config get-value compute/region 2>/dev/null)
|
||||
ZONE="${REGION}-b"
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Connecting to $VM_NAME via IAP tunnel..."
|
||||
gcloud compute ssh "$VM_NAME" \
|
||||
--zone="$ZONE" \
|
||||
--tunnel-through-iap
|
||||
71
scripts/gcp/store-secrets.sh
Executable file
71
scripts/gcp/store-secrets.sh
Executable file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
# Store secrets in GCP Secret Manager
|
||||
# Usage: ./store-secrets.sh
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
|
||||
|
||||
if [[ -z "$PROJECT_ID" ]]; then
|
||||
echo "Error: No GCP project configured. Run: gcloud config set project PROJECT_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Storing secrets for project: $PROJECT_ID"
|
||||
echo ""
|
||||
|
||||
# Function to create or update a secret
|
||||
create_secret() {
|
||||
local name="$1"
|
||||
local prompt="$2"
|
||||
|
||||
echo -n "$prompt: "
|
||||
read -rs value
|
||||
echo ""
|
||||
|
||||
if [[ -z "$value" ]]; then
|
||||
echo "Skipping $name (empty value)"
|
||||
return
|
||||
fi
|
||||
|
||||
if gcloud secrets describe "$name" &>/dev/null; then
|
||||
echo "$value" | gcloud secrets versions add "$name" --data-file=-
|
||||
echo "Updated secret: $name"
|
||||
else
|
||||
echo "$value" | gcloud secrets create "$name" --data-file=-
|
||||
echo "Created secret: $name"
|
||||
fi
|
||||
}
|
||||
|
||||
# Gateway token
|
||||
echo "Enter your Gateway token (generate with: openssl rand -hex 32)"
|
||||
create_secret "clawdbot-gateway-token" "Gateway token"
|
||||
|
||||
# Anthropic API key (optional)
|
||||
echo ""
|
||||
echo "Enter your Anthropic API key (optional, press Enter to skip)"
|
||||
create_secret "anthropic-api-key" "Anthropic API key"
|
||||
|
||||
# OpenAI API key (optional)
|
||||
echo ""
|
||||
echo "Enter your OpenAI API key (optional, press Enter to skip)"
|
||||
create_secret "openai-api-key" "OpenAI API key"
|
||||
|
||||
# Grant service account access to secrets
|
||||
SA_EMAIL="clawdbot-sa@${PROJECT_ID}.iam.gserviceaccount.com"
|
||||
|
||||
echo ""
|
||||
echo "Granting secret access to service account..."
|
||||
|
||||
for secret in clawdbot-gateway-token anthropic-api-key openai-api-key; do
|
||||
if gcloud secrets describe "$secret" &>/dev/null; then
|
||||
gcloud secrets add-iam-policy-binding "$secret" \
|
||||
--member="serviceAccount:$SA_EMAIL" \
|
||||
--role="roles/secretmanager.secretAccessor" \
|
||||
--quiet 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Secrets configured!"
|
||||
echo ""
|
||||
echo "Verify with: gcloud secrets list"
|
||||
Loading…
Reference in New Issue
Block a user