{"slug": "i-drive-a-cloud-coding-agent-from-my-phone-through-the-browser", "title": "I drive a cloud coding agent from my phone through the browser", "summary": "A developer configured Google Cloud's Identity-Aware Proxy (IAP) in front of a Cloud Run service running a coding agent in a web terminal, enabling access from a phone browser via Google sign-in. The setup solves the autoscaling issue where Tailscale bypassed Cloud Run's front end, causing idle timeouts, while IAP keeps the instance alive during active WebSocket connections. The approach works for any CLI coding agent and requires three gcloud commands plus a custom OAuth client for personal projects without an organization.", "body_md": "**tl;dr:** I put Google’s Identity-Aware Proxy in front of a Cloud Run service\nrunning a coding agent in a web terminal. Now I open a URL on my phone, sign in\nwith my Google account, and I’m talking to the agent.\n\n**Source:** [github.com/ykdojo/antigravity-cloud-run](https://github.com/ykdojo/antigravity-cloud-run)\n\nThis builds on my [containerized dev environments\nsetup](ephemeral-dev-environments.md): the agent runs with\n`--dangerously-skip-permissions`\n\ninside a container on Cloud Run, reachable\nthrough a web terminal. The missing piece was using it away from my laptop.\n\nThis particular setup was done for Antigravity CLI, but it should work for pretty much any other CLI coding agent.\n\nMy sessions already join my Tailscale network, so the obvious route was the Tailscale app on the phone. It works, but there’s a catch: tailnet traffic bypasses Cloud Run’s front end entirely, so the autoscaler thinks the service is idle and reclaims the instance after about 15 minutes, mid-use. The only fix is pinning the instance with min-instances=1, which costs money around the clock whether I’m using it or not.\n\nIAP flips that. Identity-Aware Proxy is Google Cloud’s managed sign-in gate:\nyou put it in front of a service, and only the Google accounts you allowlist\nget through. You open the service’s regular `run.app`\n\nURL, sign in, and you’re\nat the terminal. The terminal’s\nWebSocket is a real ingress request, so opening the tab wakes the instance,\nkeeps it alive while you’re connected, and lets it scale back to zero when you\nclose the tab.\n\nIf you want the instance to never die, deploy with min-instances=1 and it never scales down to zero.\n\nEnabling IAP on the service itself is three commands:\n\n```\ngcloud run services update SERVICE --region REGION --iap\n\ngcloud run services add-iam-policy-binding SERVICE --region REGION \\\n  --member serviceAccount:service-PROJECT_NUMBER@gcp-sa-iap.iam.gserviceaccount.com \\\n  --role roles/run.invoker\n\ngcloud beta iap web add-iam-policy-binding --resource-type=cloud-run \\\n  --service SERVICE --region REGION \\\n  --member user:YOU@gmail.com --role roles/iap.httpsResourceAccessor\n```\n\nIf your project lives in a Google Cloud organization, you may be done. Mine doesn’t, so I needed to take a long detour. In case you need to go through the same thing, here is what I went through.\n\nAfter enabling IAP, every request returned a 502 with this body:\n\n```\nEmpty Google Account OAuth client ID(s)/secret(s).\n```\n\nThe reason: IAP’s Google-managed OAuth client only authenticates\nusers **inside your organization**. A personal project has no organization, so\nthere is no client at all, which is why it says “empty”. External users need a custom OAuth\nclient handed to IAP. Four steps, mostly console clicks:\n\n**Branding** (console, Google Auth Platform → Overview → Get started): app\nname, support email, audience External, agree to the API user-data policy.\n\n`https://iap.googleapis.com/v1/oauth/clientIds/CLIENT_ID:handleRedirect`\n\n.\nNote that Google now shows the secret only at creation time, so grab it\nthen.**Hand the client to IAP**, at the project level so every IAP service in\nthe project inherits it:\n\n```\n# iap_settings.yaml\naccess_settings:\n  oauth_settings:\n    client_id: CLIENT_ID\n    client_secret: CLIENT_SECRET\ngcloud iap settings set iap_settings.yaml --project PROJECT\n```\n\nDelete the yaml afterwards. IAP stores the secret as a hash.\n\nThe change takes effect in seconds: the 502 is gone, and the service URL redirects to a Google sign-in instead. On the phone: open the service URL, pick your Google account, and the terminal loads.\n\nOne thing stops working: `gcloud run services proxy`\n\n, which is how my\ndashboard embeds cloud terminals locally on my laptop. IAP rejects the proxy’s tokens, and\non a no-organization project there’s no clean way around it.\n\nSo it’s a per-session choice, and I made it a flag: my deploy script takes\n`-i`\n\nto bring a session up with IAP, and the dashboard shows those sessions\nas an “open in browser” link instead of an embedded terminal. Default is no\nIAP.\n\nHere’s a `phone`\n\nsession with IAP next to a `laptop`\n\nsession without it. The\nIAP one opens in a browser tab; the other one connects through the local\nproxy and gets embedded in the dashboard:\n\nIt’s a checkbox when creating a session too, off by default:\n\nThe basic functionality works: I can open a session from my phone, type a task, and watch it run. A couple of rough edges I’m hoping to address later.\n\nScrolling isn’t great. It’s a terminal in a browser tab, so scrolling back through output on a touchscreen is fiddlier than it should be.\n\nFont size is the other one. I can’t get it to set properly on the phone. It works in every other browser I tried, so I’m not sure what’s different there yet.", "url": "https://wpnews.pro/news/i-drive-a-cloud-coding-agent-from-my-phone-through-the-browser", "canonical_source": "https://ykdojo.github.io/antigravity-cloud-run/posts/phone-access-iap.html", "published_at": "2026-07-27 15:44:35+00:00", "updated_at": "2026-07-27 15:52:41.896755+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents"], "entities": ["Google Cloud", "Identity-Aware Proxy", "Cloud Run", "Tailscale", "Antigravity CLI", "Google Auth Platform"], "alternates": {"html": "https://wpnews.pro/news/i-drive-a-cloud-coding-agent-from-my-phone-through-the-browser", "markdown": "https://wpnews.pro/news/i-drive-a-cloud-coding-agent-from-my-phone-through-the-browser.md", "text": "https://wpnews.pro/news/i-drive-a-cloud-coding-agent-from-my-phone-through-the-browser.txt", "jsonld": "https://wpnews.pro/news/i-drive-a-cloud-coding-agent-from-my-phone-through-the-browser.jsonld"}}