Files
2026-07-13 13:30:30 +08:00

175 lines
10 KiB
Markdown

# Project Livewire - Google Cloud Run Deployment Guide
This guide provides step-by-step instructions for deploying the Project Livewire client and server components as containerized services on Google Cloud Run. This setup is recommended for a scalable and managed production-like environment.
## Prerequisites
1. **Google Cloud Project:** You need an active Google Cloud project.
2. **Google Cloud SDK (`gcloud`):** Installed and authenticated.
* [Install Guide](https://cloud.google.com/sdk/docs/install)
* Login: `gcloud auth login`
* Set your project: `gcloud config set project YOUR_GOOGLE_CLOUD_PROJECT` (Replace `YOUR_GOOGLE_CLOUD_PROJECT`)
3. **Enabled APIs:** Ensure the following APIs are enabled in your project:
* Cloud Build API (`cloudbuild.googleapis.com`)
* Cloud Run API (`run.googleapis.com`)
* Secret Manager API (`secretmanager.googleapis.com`)
* IAM API (`iam.googleapis.com`)
* Container Registry API (`containerregistry.googleapis.com`) or Artifact Registry API (`artifactregistry.googleapis.com`)
* (Optional) Vertex AI API (`aiplatform.googleapis.com`) - If using the Vertex AI endpoint.
* (Optional) Cloud Functions API (`cloudfunctions.googleapis.com`) - For deploying tools.
* (Optional) Google Calendar API (`calendar-json.googleapis.com`) - For the calendar tool function.
```bash
gcloud services enable run.googleapis.com cloudbuild.googleapis.com secretmanager.googleapis.com iam.googleapis.com containerregistry.googleapis.com aiplatform.googleapis.com cloudfunctions.googleapis.com calendar-json.googleapis.com
```
4. **Deployed Cloud Functions:** The backend server relies on Cloud Functions for tool integration (weather, calendar).
* Deploy these functions first by following the **[Cloud Functions Setup Guide](../cloud-functions/README.md)**.
* You do *not* need the function URLs in an `.env` file for Cloud Run deployment if you configure them via Secret Manager or pass them during backend deployment (though storing them in secrets is common).
5. **Git Repository:** You should have the Project Livewire code cloned locally.
## Setup Steps
### 1. Create Backend Service Account
The Cloud Run service for the backend needs an identity to securely access other Google Cloud services like Secret Manager.
```bash
# Define service account name (optional, adjust if needed)
export BACKEND_SA_NAME="livewire-backend"
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
# Create the service account
gcloud iam service-accounts create ${BACKEND_SA_NAME} \
--description="Service account for Project Livewire backend Cloud Run service" \
--display-name="Livewire Backend SA"
# Grant Secret Manager access to the service account
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member="serviceAccount:${BACKEND_SA_NAME}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
# (Optional) Grant Vertex AI User role if using Vertex AI endpoint
# gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
# --member="serviceAccount:${BACKEND_SA_NAME}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
# --role="roles/aiplatform.user"
```
### 2. Store Secrets in Secret Manager
Securely store API keys and potentially other sensitive configuration. The backend service account will access these.
* **Google Gemini API Key:**
```bash
# Replace YOUR_GEMINI_API_KEY with your actual key
echo -n "YOUR_GEMINI_API_KEY" | \
gcloud secrets create GOOGLE_API_KEY --replication-policy="automatic" --data-file=-
```
* **OpenWeather API Key (for weather tool):**
```bash
# Replace YOUR_OPENWEATHER_API_KEY with your actual key
echo -n "YOUR_OPENWEATHER_API_KEY" | \
gcloud secrets create OPENWEATHER_API_KEY --replication-policy="automatic" --data-file=-
```
* **(Optional) Store Cloud Function URLs:** You can also store function URLs as secrets if preferred.
```bash
# Example for Weather Function URL
# echo -n "YOUR_WEATHER_FUNCTION_URL" | \
# gcloud secrets create WEATHER_FUNCTION_URL --replication-policy="automatic" --data-file=-
```
*(Note: The current `server/config/config.py` primarily expects URLs from environment variables, but could be adapted to read them from secrets if desired).*
### 3. Deploy the Backend Server to Cloud Run
This uses Cloud Build (`server/cloudbuild.yaml`) to build the Docker image and deploy it to Cloud Run.
```bash
# Navigate to the project root directory
cd /path/to/project-livewire
# Submit the build and deployment job
# This uses the configuration in server/cloudbuild.yaml
# It sets GOOGLE_CLOUD_PROJECT and the service account during deployment
gcloud builds submit --config server/cloudbuild.yaml
```
* **What `server/cloudbuild.yaml` does:**
* Builds a Docker image using `server/Dockerfile`.
* Pushes the image to Google Container Registry (or Artifact Registry).
* Deploys the image to Cloud Run as a service named `livewire-backend`.
* Sets the region (default `us-central1` - modify YAML if needed).
* Allows unauthenticated access (for easy client connection - **consider restricting access in production**).
* Sets the container port to `8081`.
* Sets environment variables (`GOOGLE_CLOUD_PROJECT`, `LOG_LEVEL`). You can add more here (like `GOOGLE_GENAI_USE_VERTEXAI=true`, `GOOGLE_CLOUD_LOCATION`, or Function URLs if not using secrets).
* Assigns the `livewire-backend` service account created earlier.
### 4. Get the Backend Service URL
After the deployment finishes, retrieve the URL of the backend service.
```bash
# Replace us-central1 if you deployed to a different region
export BACKEND_URL=$(gcloud run services describe livewire-backend --platform managed --region us-central1 --format 'value(status.url)')
# Verify the URL (should start with https://...)
echo "Backend URL: ${BACKEND_URL}"
```
**Important:** The client needs the **WebSocket** version of this URL (replace `https://` with `wss://`).
### 5. Deploy the Frontend Client to Cloud Run
This uses Cloud Build (`client/cloudbuild.yaml`) to build the client's Docker image (which uses nginx to serve static files) and deploy it. We pass the backend's WebSocket URL to the build process.
```bash
# Navigate to the project root directory (if not already there)
cd /path/to/project-livewire
# Construct the WebSocket URL for the backend
export WSS_BACKEND_URL=$(echo ${BACKEND_URL} | sed 's|https://|wss://|')
echo "WebSocket Backend URL: ${WSS_BACKEND_URL}"
# Submit the build and deployment job for the frontend
# Pass the WebSocket URL as a substitution variable
gcloud builds submit --config client/cloudbuild.yaml \
--substitutions=_BACKEND_URL="${WSS_BACKEND_URL}"
```
* **What `client/cloudbuild.yaml` does:**
* Builds a Docker image using `client/Dockerfile`.
* Pushes the image to Google Container Registry (or Artifact Registry).
* Deploys the image to Cloud Run as a service named `livewire-ui`.
* Sets the region (default `us-central1` - modify YAML if needed).
* Allows unauthenticated access.
* Sets the container port to `8080`.
* **Crucially:** It expects the `_BACKEND_URL` substitution. This URL is injected into the `nginx.conf` file *during the build process* so the client-side JavaScript can potentially fetch it or be configured accordingly. *(Self-correction: The current client JS hardcodes `ws://localhost:8081`. This needs adjustment for cloud deployment. A common pattern is to have the frontend fetch config from a `/config` endpoint served by nginx, which gets the URL via the build arg/env var, or embed it directly in the HTML/JS during build).*
* *Modification needed:* The client code (`client/src/api/gemini-api.js`) needs to be updated to dynamically use the backend URL provided during deployment, rather than hardcoding `ws://localhost:8081`. This could involve fetching a config file or having the build process replace a placeholder. The `cloudbuild.yaml` substitution provides the URL, but the client needs to *use* it. A simple approach for this setup might be to modify `client/cloudbuild.yaml` to directly replace the placeholder in `gemini-api.js` using `sed` before building the image.
### 6. Get the Frontend Service URL
Retrieve the URL for the deployed UI service.
```bash
# Replace us-central1 if you deployed to a different region
export FRONTEND_URL=$(gcloud run services describe livewire-ui --platform managed --region us-central1 --format 'value(status.url)')
# Print the URL
echo "Frontend URL: ${FRONTEND_URL}"
```
### 7. Access the Application
Open the `FRONTEND_URL` in your web browser to use the deployed Project Livewire application.
## Troubleshooting
* **Cloud Build Failures:**
* Check the Cloud Build logs in the Google Cloud Console for detailed error messages.
* Ensure the Cloud Build service account has necessary permissions (e.g., to push to Container Registry, deploy to Cloud Run).
* **Cloud Run Service Errors:**
* Check the "Logs" tab for your `livewire-backend` and `livewire-ui` services in the Cloud Run section of the Google Cloud Console.
* **Backend:** Look for errors related to Secret Manager access (check IAM roles), API key validity, connection issues to Gemini, or problems calling Cloud Functions. Ensure `GOOGLE_CLOUD_PROJECT` is correctly passed or available.
* **Frontend:** Look for nginx errors or issues serving files. Ensure the backend URL was correctly passed during the build and is accessible.
* **Connection Issues (Client <-> Server):**
* Verify the WebSocket URL used by the client correctly points to the `wss://` version of the `livewire-backend` service URL.
* Ensure both Cloud Run services allow ingress traffic (e.g., `--allow-unauthenticated` was used, or appropriate authentication is configured if restricted). Check firewall rules if applicable.
* **Secret Manager Access Denied:** Double-check that the `livewire-backend` service account has the `roles/secretmanager.secretAccessor` role assigned in IAM.
* **Quota Errors:** Monitor API usage (Gemini, Cloud Functions, etc.) in the Google Cloud Console. You might be hitting free tier limits or project quotas.