Complete guide for deploying MARP presentations to Google Cloud Run with custom domain talks.denhamparry.co.uk.
This repository automatically deploys presentations to Google Cloud Run using GitHub Actions when changes are pushed to the main branch.
Architecture:
GitHub → Docker Build → GHCR → Cloud Run → talks.denhamparry.co.uk
↓ ↓ ↓ ↓ ↓
Push Build Image Store Deploy Custom Domain
main (MARP) ghcr.io (London) (Cloudflare)
- Production URL: https://talks.denhamparry.co.uk
- Cloud Run Service:
https://talks-HASH-nw.a.run.app(auto-generated) - Region: europe-west1 (Belgium) - supports domain mappings
- Platform: Google Cloud Run (serverless)
- Cost: $0/month (within free tier)
-
Push slides to main branch
- Triggers
.github/workflows/docker-publish.yml - Builds Docker image with MARP slides
- Triggers
-
Publish to GitHub Container Registry
- Image tagged as
ghcr.io/denhamparry/talks:latest - Multi-architecture (amd64, arm64)
- Image tagged as
-
Deploy to Cloud Run
- Triggers
.github/workflows/cloudrun-deploy.yml - Deploys to europe-west1 (Belgium)
- Scales 0-10 instances automatically
- Triggers
-
Available globally
- HTTPS with managed SSL certificate
- Custom domain: talks.denhamparry.co.uk
- Global CDN via Cloudflare (optional)
This guide assumes you're setting up Cloud Run deployment from scratch. If already configured, skip to Usage.
- Google Cloud billing account
- gcloud CLI installed (
brew install google-cloud-sdkon macOS) - Cloudflare account with denhamparry.co.uk domain
- GitHub repository with admin access
# macOS
brew install google-cloud-sdk
# Authenticate
gcloud auth login
# Verify installation
gcloud --version# Create new project
gcloud projects create denhamparry-talks \
--name="Denhamparry Talks" \
--set-as-default
# Get billing account ID
gcloud billing accounts list
# Link billing account (replace with your account ID)
export BILLING_ACCOUNT_ID="XXXXXX-YYYYYY-ZZZZZZ"
gcloud billing projects link denhamparry-talks \
--billing-account=$BILLING_ACCOUNT_ID# Create budget alert for £10/month (~$12)
gcloud billing budgets create \
--billing-account=$BILLING_ACCOUNT_ID \
--display-name="Talks Monthly Budget" \
--budget-amount=12.00 \
--threshold-rule=percent=50 \
--threshold-rule=percent=90 \
--threshold-rule=percent=100 \
--threshold-rule=percent=110
# Enable cost tracking APIs
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable cloudbilling.googleapis.comBudget alerts will notify you at:
- 50% ($6) - Warning
- 90% ($10.80) - Critical
- 100% ($12) - Budget exceeded
- 110% ($13.20) - Over budget
export PROJECT_ID="denhamparry-talks"
# Enable Cloud Run API
gcloud services enable run.googleapis.com --project=$PROJECT_ID
# Enable Compute Engine API (required for domain mapping)
gcloud services enable compute.googleapis.com --project=$PROJECT_ID
# Enable Artifact Registry API
gcloud services enable artifactregistry.googleapis.com --project=$PROJECT_ID
# Enable IAM Service Account Credentials API (required for Workload Identity Federation)
gcloud services enable iamcredentials.googleapis.com --project=$PROJECT_IDImportant: The IAM Service Account Credentials API (iamcredentials.googleapis.com) is critical for Workload Identity Federation to impersonate service accounts. Without this API enabled, GitHub Actions authentication will succeed but Docker pushes to Artifact Registry will fail with a "Unable to acquire impersonated credentials" error.
Google Cloud Run requires images to be in Google Artifact Registry, not GitHub Container Registry.
CRITICAL: Region Consistency
The Artifact Registry repository MUST be in the same region as your Cloud Run service. Mismatched regions will cause deployment failures.
- ✅ europe-west1 (Belgium) - Recommended, supports domain mappings
- ❌ europe-west2 (London) - Does NOT support domain mappings
- ✅ us-central1 (Iowa) - Supports domain mappings
export REGION="europe-west1" # Belgium (supports domain mappings)
# IMPORTANT: Use the SAME region for:
# - Artifact Registry repository (this step)
# - Cloud Run service (Step 7)
# - GitHub Actions workflow (.github/workflows/cloudrun-deploy.yml)
# Create Artifact Registry repository
gcloud artifacts repositories create talks \
--repository-format=docker \
--location=$REGION \
--description="MARP presentation slides container images" \
--project=$PROJECT_ID
# Verify repository created
gcloud artifacts repositories describe talks \
--location=$REGION \
--project=$PROJECT_IDVerification Checklist:
- Repository created in correct region (
europe-west1) - Repository format is
DOCKER - Repository is accessible (describe command succeeds)
- No duplicate repositories in other regions (list all with
gcloud artifacts repositories list)
Clean Up Wrong-Region Repositories:
If you accidentally created repositories in the wrong region:
# List all repositories
gcloud artifacts repositories list --project=$PROJECT_ID
# Delete wrong-region repository (e.g., europe-west2)
gcloud artifacts repositories delete talks \
--location=europe-west2 \
--project=$PROJECT_ID \
--quietexport REGION="europe-west1" # Belgium (supports domain mappings)
export SERVICE_NAME="talks"
# Service account for Cloud Run service (runs the container)
gcloud iam service-accounts create cloudrun-talks-sa \
--display-name="Cloud Run Talks Service Account" \
--project=$PROJECT_ID
# Service account for GitHub Actions (deploys the service)
gcloud iam service-accounts create github-actions-cloudrun \
--display-name="GitHub Actions Cloud Run Deployer" \
--project=$PROJECT_ID
# Grant Cloud Run Admin permission to GitHub Actions service account
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:github-actions-cloudrun@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/run.admin"
# Grant Service Account User permission (required to deploy as service account)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:github-actions-cloudrun@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
# Grant Artifact Registry Writer permission (required to push images)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:github-actions-cloudrun@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/artifactregistry.writer"Workload Identity Federation allows GitHub Actions to authenticate to Google Cloud without storing service account keys.
# Get project number (needed for Workload Identity)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
# Create Workload Identity Pool
gcloud iam workload-identity-pools create github-pool \
--location="global" \
--display-name="GitHub Actions Pool" \
--project=$PROJECT_ID
# Create Workload Identity Provider for GitHub
gcloud iam workload-identity-pools providers create-oidc github-provider \
--location="global" \
--workload-identity-pool="github-pool" \
--issuer-uri="https://token.actions.githubusercontent.com" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
--attribute-condition="assertion.repository=='denhamparry/talks'" \
--project=$PROJECT_ID
# Bind service account to GitHub repository
gcloud iam service-accounts add-iam-policy-binding \
github-actions-cloudrun@$PROJECT_ID.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/attribute.repository/denhamparry/talks" \
--project=$PROJECT_ID
# Get Workload Identity Provider resource name (save this for GitHub Secrets)
gcloud iam workload-identity-pools providers describe github-provider \
--location="global" \
--workload-identity-pool="github-pool" \
--format="value(name)" \
--project=$PROJECT_IDSave the output (format: projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/providers/github-provider)
Cloud Run requires images in Artifact Registry (not GHCR) and must be built for amd64 architecture.
Important: If you're on Apple Silicon (M1/M2/M3), you must build for linux/amd64, not arm64.
# Configure Docker authentication for Artifact Registry
gcloud auth configure-docker $REGION-docker.pkg.dev
# Build image for amd64 architecture (required for Cloud Run)
docker build --platform linux/amd64 --target production -t talks:cloudrun .
# Tag for Artifact Registry
docker tag talks:cloudrun \
$REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latest
# Verify architecture is amd64 (not arm64)
docker inspect $REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latest --format='Architecture: {{.Architecture}}'
# Should output: Architecture: amd64
# Push to Artifact Registry
docker push $REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latest
# Deploy to Cloud Run from Artifact Registry
gcloud run deploy $SERVICE_NAME \
--image=$REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latest \
--platform=managed \
--region=$REGION \
--allow-unauthenticated \
--port=8080 \
--min-instances=0 \
--max-instances=10 \
--memory=256Mi \
--cpu=1 \
--timeout=60s \
--project=$PROJECT_ID
# Get service URL
gcloud run services describe $SERVICE_NAME \
--region=$REGION \
--format='value(status.url)' \
--project=$PROJECT_IDTest the service:
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --region=$REGION --format='value(status.url)')
curl "$SERVICE_URL/health"
# Should return: healthy
# Test a presentation
curl -I "$SERVICE_URL/"
# Should return: HTTP 200Common Issue: If you get "exec format error" or container fails to start, you pushed the wrong architecture. Fix it:
# Remove incorrect tag
docker rmi $REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latest
# Re-tag with correct amd64 image
docker tag talks:cloudrun $REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latest
# Push again
docker push $REGION-docker.pkg.dev/$PROJECT_ID/talks/talks:latestNote: After GitHub Actions is configured, the workflow will automatically build multi-architecture images and push to Artifact Registry on every deployment.
Add secrets to GitHub repository: Settings → Secrets and variables → Actions → New repository secret
-
GCP_WORKLOAD_IDENTITY_PROVIDER
- Value:
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/providers/github-provider - Get from Step 6 output
- Value:
-
GCP_SERVICE_ACCOUNT
- Value:
github-actions-cloudrun@denhamparry-talks.iam.gserviceaccount.com
- Value:
Important: Domain mappings are only supported in certain regions. If you deployed to europe-west2 (London), you must redeploy to europe-west1 (Belgium) or us-central1 (Iowa) first.
- Go to Google Cloud Console
- Navigate to Cloud Run → Manage Custom Domains
- Click Verify Domain
- Enter
denhamparry.co.uk(root domain) - Add verification TXT record to Cloudflare DNS:
- Type: TXT
- Name: @ (root)
- Value:
google-site-verification=...(from Console) - TTL: Auto
Note: Domain mapping commands require gcloud beta (not the stable GA version).
# Create domain mapping (use gcloud beta)
gcloud beta run domain-mappings create \
--service=$SERVICE_NAME \
--domain=talks.denhamparry.co.uk \
--region=$REGION \
--project=$PROJECT_ID
# Get DNS record requirements
gcloud beta run domain-mappings describe \
--domain=talks.denhamparry.co.uk \
--region=$REGION \
--format="value(status.resourceRecords)" \
--project=$PROJECT_IDAdd DNS record in Cloudflare for denhamparry.co.uk:
Type: CNAME
Name: talks
Target: ghs.googlehosted.com
TTL: Auto
Proxy status: DNS only (grey cloud) ← Important during setup
Important:
- Initially disable Cloudflare proxy (grey cloud icon)
- Wait for SSL certificate provisioning (5-15 minutes)
- After certificate is active, optionally enable proxy (orange cloud) for DDoS protection and CDN
# Check certificate status (repeat until Ready)
gcloud beta run domain-mappings describe \
--domain=talks.denhamparry.co.uk \
--region=$REGION \
--format="value(status.conditions)" \
--project=$PROJECT_ID
# When status shows "Ready", test the domain
curl https://talks.denhamparry.co.uk/healthCertificate provisioning typically takes 5-15 minutes.
- Make a change to a slide file (e.g.,
slides/example-presentation.md) - Commit and push to main branch
- Monitor GitHub Actions:
docker-publish.ymlbuilds and publishes imagecloudrun-deploy.ymldeploys to Cloud Run
- Access https://talks.denhamparry.co.uk
- Verify changes appear
After completing the initial setup, run these verification commands to ensure everything is configured correctly:
Check Region Consistency:
export PROJECT_ID="denhamparry-talks"
# 1. List all Artifact Registry repositories
echo "=== Artifact Registry Repositories ==="
gcloud artifacts repositories list --project=$PROJECT_ID
# 2. List all Cloud Run services
echo "=== Cloud Run Services ==="
gcloud run services list --project=$PROJECT_ID
# 3. Verify workflow configuration
echo "=== Workflow Configuration ==="
grep "REGION:" .github/workflows/cloudrun-deploy.yml
grep "ARTIFACT_REGISTRY:" .github/workflows/cloudrun-deploy.ymlExpected Results:
- ✅ Artifact Registry repository exists in
europe-west1ONLY - ✅ Cloud Run service exists in
europe-west1ONLY - ✅ Workflow
REGIONis set toeurope-west1 - ✅ Workflow
ARTIFACT_REGISTRYiseurope-west1-docker.pkg.dev
Check Service Account Permissions:
# Verify GitHub Actions service account has all required permissions
gcloud projects get-iam-policy $PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:github-actions-cloudrun@$PROJECT_ID.iam.gserviceaccount.com" \
--format="table(bindings.role)"Expected Roles:
- ✅
roles/artifactregistry.writer - ✅
roles/run.admin - ✅
roles/iam.serviceAccountUser
Check Required APIs:
# Verify all required APIs are enabled
gcloud services list --enabled --project=$PROJECT_ID \
--filter="name:(run.googleapis.com OR compute.googleapis.com OR artifactregistry.googleapis.com OR iamcredentials.googleapis.com)"Expected APIs:
- ✅
run.googleapis.com(Cloud Run API) - ✅
compute.googleapis.com(Compute Engine API) - ✅
artifactregistry.googleapis.com(Artifact Registry API) - ✅
iamcredentials.googleapis.com(IAM Service Account Credentials API)
Test Deployment:
# Test the deployed service
SERVICE_URL=$(gcloud run services describe talks \
--region=europe-west1 \
--project=$PROJECT_ID \
--format="value(status.url)")
echo "Service URL: $SERVICE_URL"
# Test health endpoint
curl -f "$SERVICE_URL/health"
# Test homepage
curl -f -I "$SERVICE_URL/"Configuration Checklist:
- Only one Artifact Registry repository (in
europe-west1) - Only one Cloud Run service (in
europe-west1) - Service account has all three required roles
- All four required APIs are enabled
- Workflow region matches infrastructure region
- Service responds to health checks
- GitHub Actions workflows pass successfully
- Custom domain configured and accessible (if applicable)
Clean Up Multiple Regions (if needed):
If verification shows services or repositories in wrong regions:
# Delete wrong-region Artifact Registry repositories
gcloud artifacts repositories delete talks \
--location=europe-west2 \
--project=$PROJECT_ID \
--quiet
# Delete wrong-region Cloud Run services
gcloud run services delete talks \
--region=europe-west2 \
--project=$PROJECT_ID \
--quiet
gcloud run services delete talks \
--region=us-central1 \
--project=$PROJECT_ID \
--quietAll presentations are available at:
- Production: https://talks.denhamparry.co.uk
- Direct Cloud Run URL:
https://talks-HASH-nw.a.run.app
Example presentations:
- https://talks.denhamparry.co.uk/example-presentation.html
- https://talks.denhamparry.co.uk/2025-12-04-cloud-native-manchester.html
Automatic deployment:
# Edit slides
vim slides/my-talk.md
# Commit and push
git add slides/my-talk.md
git commit -m "feat(slides): add new presentation"
git push origin main
# Wait 2-3 minutes for deployment
# Access at https://talks.denhamparry.co.uk/my-talk.htmlManual deployment:
# Deploy specific image tag
gcloud run deploy talks \
--image=ghcr.io/denhamparry/talks:main \
--region=europe-west1 \
--project=denhamparry-talksGitHub Actions:
# List recent workflow runs
gh run list --workflow=cloudrun-deploy.yml --limit=5
# View logs for latest run
gh run view --logCloud Run Console:
- Service Dashboard: https://console.cloud.google.com/run/detail/europe-west1/talks
- Metrics: https://console.cloud.google.com/run/detail/europe-west1/talks/metrics
- Logs: https://console.cloud.google.com/run/detail/europe-west1/talks/logs
Command line:
# View logs
gcloud run services logs read talks \
--region=europe-west1 \
--limit=50
# View service status
gcloud run services describe talks \
--region=europe-west1 \
--format="table(status.url,status.conditions)"Current configuration:
- Target: $0/month (within Cloud Run free tier)
- Free tier: 2 million requests/month, 360,000 GB-seconds/month
- Expected usage: ~1,000 requests/month (conference attendees)
- Budget limit: £10/month (~$12/month)
Cost breakdown:
| Resource | Usage | Cost |
|---|---|---|
| Cloud Run requests | 1,000/month | $0 (free tier) |
| Cloud Run compute | ~10 GB-seconds/month | $0 (free tier) |
| Network egress | ~1 GB/month | $0 (free tier) |
| SSL certificate | Managed | $0 (included) |
| Total | $0/month |
Cloud Console:
- Go to Billing Reports
- Select "denhamparry-talks" project
- View cost breakdown by service
Command line:
# View current month costs
gcloud billing projects describe denhamparry-talks \
--format="value(billingAccountName)"Budget alerts configured at:
- 50% ($6) - Email notification
- 90% ($10.80) - Email notification
- 100% ($12) - Email notification
- 110% ($13.20) - Email notification
Modify budget:
# List budgets
gcloud billing budgets list --billing-account=$BILLING_ACCOUNT_ID
# Update budget (if costs exceed expectations)
gcloud billing budgets update BUDGET_ID \
--billing-account=$BILLING_ACCOUNT_ID \
--budget-amount=20.00Symptoms:
- GitHub Actions workflow fails with "Permission denied" or "Authentication failed"
Solution:
-
Verify Workload Identity Provider is configured:
gcloud iam workload-identity-pools providers describe github-provider \ --location=global \ --workload-identity-pool=github-pool \ --project=denhamparry-talks
-
Check service account has correct permissions:
gcloud projects get-iam-policy denhamparry-talks \ --flatten="bindings[].members" \ --filter="bindings.members:github-actions-cloudrun@denhamparry-talks.iam.gserviceaccount.com"
-
Verify GitHub Secrets are correct:
- Go to repository Settings → Secrets → Actions
- Ensure
GCP_WORKLOAD_IDENTITY_PROVIDERandGCP_SERVICE_ACCOUNTare set
Symptoms:
- GitHub Actions workflow fails at "Push to Artifact Registry" step
- Error message: "Unable to acquire impersonated credentials"
- Error includes: "IAM Service Account Credentials API has not been used in project... or it is disabled"
- Error code: 403 PERMISSION_DENIED, reason: SERVICE_DISABLED
Root Cause:
The IAM Service Account Credentials API (iamcredentials.googleapis.com) is not enabled in your GCP project. This API is required for Workload Identity Federation to impersonate service accounts.
Solution:
-
Enable the IAM Service Account Credentials API:
gcloud services enable iamcredentials.googleapis.com --project=denhamparry-talksOr via GCP Console:
-
Wait 2-5 minutes for API enablement to propagate across GCP systems
-
Verify the API is enabled:
gcloud services list --enabled --project=denhamparry-talks --filter="name:iamcredentials.googleapis.com" -
Re-run the failed GitHub Actions workflow:
gh run rerun <RUN_ID> --failed
Prevention:
Ensure this API is included in Step 4 of the initial setup. This is now documented in the deployment guide.
Symptoms:
- GitHub Actions workflow fails at "Push to Artifact Registry" step
- Error message: "denied: Permission 'artifactregistry.repositories.uploadArtifacts' denied on resource"
- Error includes: "projects/PROJECT_ID/locations/REGION/repositories/REPOSITORY_NAME (or it may not exist)"
Root Causes:
This error has two possible causes:
- Artifact Registry repository doesn't exist in the specified region
- Service account lacks permissions to push to Artifact Registry
Solution:
Step 1: Check if repository exists in the correct region
# Check if repository exists
gcloud artifacts repositories describe talks \
--location=europe-west1 \
--project=denhamparry-talksIf you get "NOT_FOUND", create the repository:
gcloud artifacts repositories create talks \
--repository-format=docker \
--location=europe-west1 \
--description="MARP presentation slides container images" \
--project=denhamparry-talksStep 2: Verify region consistency
The Artifact Registry repository MUST be in the SAME region as specified in .github/workflows/cloudrun-deploy.yml:
# List all repositories and their regions
gcloud artifacts repositories list --project=denhamparry-talks
# Check Cloud Run service region
gcloud run services list --project=denhamparry-talksIf repositories exist in wrong regions, delete them:
# Delete wrong-region repository
gcloud artifacts repositories delete talks \
--location=WRONG_REGION \
--project=denhamparry-talks \
--quietStep 3: Grant Artifact Registry permissions
If repository exists but permissions are missing:
# Grant Artifact Registry Writer permission
gcloud projects add-iam-policy-binding denhamparry-talks \
--member="serviceAccount:github-actions-cloudrun@denhamparry-talks.iam.gserviceaccount.com" \
--role="roles/artifactregistry.writer"
# Verify permissions
gcloud projects get-iam-policy denhamparry-talks \
--flatten="bindings[].members" \
--filter="bindings.members:github-actions-cloudrun@denhamparry-talks.iam.gserviceaccount.com"Expected roles:
- ✅
roles/artifactregistry.writer - ✅
roles/run.admin - ✅
roles/iam.serviceAccountUser
Step 4: Re-run workflow
gh run rerun <RUN_ID> --failedPrevention:
- Create Artifact Registry repository in Step 4.5 BEFORE first deployment
- Ensure repository region matches Cloud Run service region
- Grant all required permissions in Step 5
Symptoms:
curl https://talks.denhamparry.co.ukreturns connection error or certificate error
Solution:
-
Check DNS propagation:
dig talks.denhamparry.co.uk # Should return CNAME to ghs.googlehosted.com -
Check certificate status:
gcloud beta run domain-mappings describe \ --domain=talks.denhamparry.co.uk \ --region=europe-west1 \ --format="value(status.conditions)" -
Wait 5-15 minutes for certificate provisioning if status is "CertificateProvisioning"
-
Ensure Cloudflare proxy is disabled (grey cloud) during initial setup
-
Check certificate via browser:
- Open https://talks.denhamparry.co.uk in browser
- Click lock icon → Certificate
- Issuer should be "Google Trust Services"
Symptoms:
- Deployment succeeds but
/healthendpoint returns 502 or 404
Solution:
-
Test health endpoint locally:
docker run -p 8080:8080 -e PORT=8080 ghcr.io/denhamparry/talks:latest & sleep 5 curl http://localhost:8080/health -
Check Cloud Run logs:
gcloud run services logs read talks \ --region=europe-west1 \ --limit=50 -
Verify nginx configuration uses
${PORT}:grep "listen \${PORT}" nginx.conf
Symptoms:
- First request after idle takes 2-5 seconds to respond
Explanation:
- This is expected behavior with
min-instances=0(scale to zero) - Saves costs by not running containers when idle
Solutions:
Option A: Accept cold start (recommended for low cost)
- No changes needed
- Acceptable for conference presentations
Option B: Always-on (costs ~£5/month)
gcloud run services update talks \
--min-instances=1 \
--region=europe-west1Symptoms:
- Build time >5 minutes
- Deployment slow
Solution:
-
Verify
.dockerignoreexcludes unnecessary files:cat .dockerignore
-
Check production image size:
docker images ghcr.io/denhamparry/talks:latest # Should be <100MB -
If image is large, rebuild with
--no-cache:docker build --target production --no-cache -t talks:test .
If presentations are large or complex:
# Update service resources
gcloud run services update talks \
--memory=512Mi \
--cpu=2 \
--region=europe-west1Cost impact: Increases compute costs, but still likely within free tier.
# Add environment variables
gcloud run services update talks \
--set-env-vars="CUSTOM_VAR=value" \
--region=europe-west1After SSL certificate is provisioned:
- Go to Cloudflare DNS settings
- Click the cloud icon for
talksrecord - Change from grey (DNS only) to orange (Proxied)
- Cloudflare now provides:
- DDoS protection
- Additional CDN caching
- Analytics
- Page Rules (optional)
Note: Cloudflare's "Flexible" SSL mode works with Cloud Run's managed certificates.
# List all revisions
gcloud run revisions list \
--service=talks \
--region=europe-west1
# Rollback to specific revision
gcloud run services update-traffic talks \
--to-revisions=talks-00001-abc=100 \
--region=europe-west1- Automatically provisioned by Google Cloud
- Auto-renewal (no manual intervention)
- Issuer: Google Trust Services
- Validity: 90 days (renewed automatically)
nginx configuration includes:
X-Frame-Options: SAMEORIGIN- Prevents clickjackingX-Content-Type-Options: nosniff- Prevents MIME sniffingX-XSS-Protection: 1; mode=block- XSS protectionContent-Security-Policy- Restricts resource loadingReferrer-Policy- Privacy protection
Current configuration: Unauthenticated access (--allow-unauthenticated)
To require authentication:
# Require authentication
gcloud run services update talks \
--no-allow-unauthenticated \
--region=europe-west1
# Grant access to specific users
gcloud run services add-iam-policy-binding talks \
--member="user:email@example.com" \
--role="roles/run.invoker" \
--region=europe-west1- Google Cloud Run Documentation
- Cloud Run Pricing
- Workload Identity Federation
- GitHub Actions for Google Cloud
- Cloudflare DNS Documentation
For issues with deployment:
- Check Troubleshooting section
- Review Cloud Run logs:
gcloud run services logs read talks --region=europe-west1 - Check GitHub Actions logs:
gh run view --log - Open an issue in the repository
Last Updated: 2025-12-03 Deployment Region: europe-west1 (Belgium) Platform: Google Cloud Run Note: Use europe-west1 or us-central1 for domain mapping support