$ tutorials --list

# Tutorials

Start-to-finish walkthroughs for the tasks people get stuck on. Every step links to official docs. Read them and verify before running anything in production.

πŸ’Έ Put a real hard cap on GCP spending

A GCP budget only sends alerts β€” it never stops usage. This wires a budget to a function that actually disables billing when you cross the line. Use it on sandbox/learning projects where an overrun is worse than an outage.

Trade-off: disabling billing stops resources (VMs, databases). That's the point for a lab project β€” never do this on something serving real traffic.
  1. Create a budget with a threshold. Billing β†’ Budgets & alerts β†’ Create budget, scope it to the project, set the amount and alert thresholds (e.g. 50/90/100%).
  2. Give the budget a Pub/Sub topic. On the budget's last step, expand Manage notifications and connect it to a new Pub/Sub topic (e.g. billing-alerts). This publishes a message every time spend updates.
  3. Deploy a function subscribed to that topic that calls the Cloud Billing API to detach the billing account:
    # the function's core call (Node/Python client shown in the docs) billing.projects.updateBillingInfo({ name: 'projects/PROJECT_ID', requestBody: { billingAccountName: '' } // '' = disable billing })
  4. Grant the function's service account the billing role. It needs roles/billing.projectManager (or Billing Account Admin) to detach billing.
  5. Test with a low budget. Temporarily set a tiny amount, confirm the function fires and billing detaches, then reset. Re-enabling billing later is a one-click console action.

Docs: disable billing with notifications Β· related fix: budgets don't cap spending.

πŸ” Create a least-privilege service account (no keys)

The safe default for workloads: a dedicated service account with only the roles it needs, attached to the resource β€” never a downloaded JSON key.

  1. Create the service account:
    gcloud iam service-accounts create my-app-sa \ --display-name="My app runtime SA"
  2. Grant only the roles it needs, scoped as tightly as possible (project shown; prefer resource-level where supported):
    gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:my-app-sa@PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/storage.objectViewer"
  3. Attach the SA to the workload instead of exporting a key. For Cloud Run: --service-account=my-app-sa@…; for a VM: set it as the instance service account; for GKE: use Workload Identity.
  4. Let the client libraries find it automatically. On Google infrastructure, Application Default Credentials use the attached SA with zero config β€” no key file to leak.
  5. Verify what it can do with the Policy Troubleshooter or:
    gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" \ --filter="bindings.members:my-app-sa@PROJECT_ID.iam.gserviceaccount.com"

Docs: best practices for service accounts Β· Workload Identity Federation.

⚑ Deploy a container to Cloud Run (without the PORT error)

The #1 Cloud Run failure is "container failed to start and listen on the port." Get it right the first time.

  1. Listen on 0.0.0.0:$PORT. Read the port from the environment β€” never hardcode 3000/8080 or bind to 127.0.0.1:
    const port = process.env.PORT || 8080; app.listen(port, '0.0.0.0');
  2. Enable the APIs once:
    gcloud services enable run.googleapis.com \ artifactregistry.googleapis.com cloudbuild.googleapis.com
  3. Deploy straight from source (Cloud Build builds & pushes the image for you):
    gcloud run deploy my-service \ --source . --region REGION \ --service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com
  4. Choose access. Add --allow-unauthenticated for a public site; omit it and grant callers roles/run.invoker for a private service.
  5. If it still fails to start, read the startup stack trace in Cloud Logging, test the image locally with docker run -e PORT=8080 -p 8080:8080 IMAGE, and raise the startup timeout if init is slow.

Docs: deploying to Cloud Run Β· container runtime contract Β· related fix: PORT error.

☸️ Connect kubectl to a new GKE cluster

Fresh cluster, and kubectl says "you must be logged in." You just need credentials and the auth plugin.

  1. Install the auth plugin (required since kubectl 1.26):
    gcloud components install gke-gcloud-auth-plugin
  2. Fetch cluster credentials into kubeconfig:
    gcloud container clusters get-credentials CLUSTER \ --region REGION --project PROJECT_ID
  3. Verify connectivity:
    kubectl get nodes
  4. If you get 403s, grant your identity roles/container.developer (or container.admin) and make sure the Kubernetes Engine API is enabled.

Docs: cluster access for kubectl.

πŸ“§ Set up Workspace email on a brand-new domain

Get mail flowing to Gmail in the right order so you don't chase a "not receiving mail" ghost.

  1. Verify domain ownership. Admin console setup tool gives you a google-site-verification TXT record β€” paste the exact value into your registrar's DNS (host @).
  2. Replace MX records. Delete any legacy MX entries and add Google's single MX host (smtp.google.com, priority 1 on new setups). Only Google's MX should remain.
  3. Activate Gmail from the setup tool once records are in place. DNS can take up to 72 hours to propagate.
  4. Confirm delivery by sending a test message in and out. If inbound fails, re-check that no old MX record is still present.
  5. Then set up email authentication (next tutorial) before you send anything at volume.

Docs: verify your domain Β· set up MX records.

βœ‰οΈ Set up SPF, DKIM & DMARC (in the right order)

Order matters. Authenticate first, enforce last β€” or you'll bounce your own mail. Since Feb 2024 Gmail requires this for reliable delivery.

  1. SPF β€” publish exactly one TXT record listing every sender:
    v=spf1 include:_spf.google.com ~all
    Keep total DNS lookups under 10. No Admin-console step needed.
  2. DKIM β€” Admin console β†’ Apps β†’ Gmail β†’ Authenticate email β†’ generate a 2048-bit key β†’ add the TXT record at your host β†’ return and click Start authentication.
  3. Let both settle for at least 48 hours and confirm they pass (check message headers: spf=pass, dkim=pass).
  4. DMARC β€” start at monitor only:
    v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
  5. Review reports, then tighten to p=quarantine and eventually p=reject once you've confirmed all legitimate mail aligns.

Docs: SPF Β· DKIM Β· DMARC Β· related fixes: email auth.

πŸ”’ Roll out 2-Step Verification without mass lockouts

Enforcing 2SV before people enroll locks everyone out at once. Sequence it.

  1. Prep admins first. Ensure 2+ super admins have recovery email/phone set, so a bad rollout can't lock you out of the console.
  2. Turn on allowance, not enforcement. Security β†’ Authentication β†’ 2-Step Verification β†’ allow users to turn it on.
  3. Announce + set an enrollment period. Give users a deadline (e.g. 2–4 weeks) to enroll a second factor.
  4. Enforce per-OU after the window, starting with a pilot OU. Prefer a grace period for new users.
  5. Plan for lost factors. Admins can issue backup codes (Directory β†’ Users β†’ Security). Note: "only security key" mode disables self-service backup codes β€” the admin must generate them.

Docs: deploy 2SV Β· avoid lockouts Β· related fix: 2SV lockouts.

πŸ“‚ Use shared drives so files survive offboarding

My Drive files are owned by the person β€” delete the account and they can orphan. Shared drives are owned by the org. Set teams up this way from day one.

  1. Enable shared drives for the right OU: Admin console β†’ Apps β†’ Google Workspace β†’ Drive and Docs β†’ Sharing settings / Manage shared drives.
  2. Create a shared drive per team and add members by group (not individuals) so membership tracks your directory.
  3. Set member roles deliberately β€” Manager, Content manager, Contributor, Commenter, Viewer.
  4. Move existing team files in. Ownership transfers to the shared drive (org-owned) so departures don't orphan anything.
  5. For any remaining My Drive files, transfer ownership before deleting a user β€” the delete flow offers a data transfer step.

Docs: set up shared drives Β· manage shared drives.

More coming. And our free CLI gcphelpit scans your Google Cloud project for the kinds of security, IAM, cost & reliability issues these guides help you avoid β€” each with a plain-English fix.