<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pablo Reyes</title>
    <description>The latest articles on DEV Community by Pablo Reyes (@pabloplf).</description>
    <link>https://dev.to/pabloplf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4226981%2F08c58aa2-facc-4e99-aa6a-02df7caadec7.png</url>
      <title>DEV Community: Pablo Reyes</title>
      <link>https://dev.to/pabloplf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pabloplf"/>
    <language>en</language>
    <item>
      <title>How to connect to a private GCP database from your terminal, a coding agent or GitHub Actions</title>
      <dc:creator>Pablo Reyes</dc:creator>
      <pubDate>Fri, 06 Nov 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/pabloplf/connect-to-a-private-gcp-service-from-your-cli-coding-agent-or-github-actions-2gh5</link>
      <guid>https://dev.to/pabloplf/connect-to-a-private-gcp-service-from-your-cli-coding-agent-or-github-actions-2gh5</guid>
      <description>&lt;h2&gt;
  
  
  How do you connect to your private databases on GCP?
&lt;/h2&gt;

&lt;p&gt;When your databases on Google Cloud have only a private IP, you can't reach them from your laptop, coding agent or a GitHub Actions runner because they are outside the VPC.&lt;/p&gt;

&lt;p&gt;The usual fixes are a public IP, a VPN or a bastion VM that runs all the time. At my company, Pilef, we built bqto, an open source CLI that connects you to a private database without a public IP, without a VPN and without a VM left running forever.&lt;/p&gt;

&lt;p&gt;First I'll show how it works, and then how to use it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdxppaoo22x47loa1outv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdxppaoo22x47loa1outv.gif" alt="bqto connecting to a private Cloud SQL instance and deleting the VM with Ctrl-C" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How bqto works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;It checks that you are logged in to gcloud and that you have the IAP permission in the project.&lt;/li&gt;
&lt;li&gt;It asks the service's API for the private address of the instance you want to reach.&lt;/li&gt;
&lt;li&gt;It checks that the firewall rule lets Identity-Aware Proxy (IAP) reach port 22.&lt;/li&gt;
&lt;li&gt;It picks a zone and a subnet for the VM, and creates it.&lt;/li&gt;
&lt;li&gt;It opens an SSH connection to the VM through an IAP tunnel and forwards a local port (for example 15432) to the instance's private IP. Your database client or your app then connects to 127.0.0.1:15432.&lt;/li&gt;
&lt;li&gt;When you press Ctrl-C, it deletes the VM and tells you. If it can't, the VM has a deadline (30 minutes by default) and Google deletes it when the deadline passes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Access goes through your own IAM roles, so there are no SSH keys to share.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need before starting
&lt;/h2&gt;

&lt;p&gt;You need gcloud 550.0.0 or later, an instance with a private IP, and a firewall rule that lets IAP (35.235.240.0/20) reach port 22. The &lt;a href="https://github.com/pilef-co/bqto#requirements" rel="noopener noreferrer"&gt;README&lt;/a&gt; lists the APIs and roles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install bqto
&lt;/h3&gt;

&lt;p&gt;Pick one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/pilef-co/bqto/main/install.sh | sh
brew &lt;span class="nb"&gt;install &lt;/span&gt;pilef-co/tap/bqto
go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/pilef-co/bqto/cmd/bqto@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &amp;nbsp;Log in to gcloud
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud auth login
gcloud auth application-default login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Connect from your terminal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bqto connect &lt;span class="nt"&gt;--project&lt;/span&gt; your-project &lt;span class="nt"&gt;--service&lt;/span&gt; cloudsql &lt;span class="nt"&gt;--instance&lt;/span&gt; your-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When bqto prints &lt;code&gt;ready: 127.0.0.1:15432 --&amp;gt; ...&lt;/code&gt;, point your database client or your app to that address. When you are done, press Ctrl-C and bqto deletes the VM.&lt;/p&gt;

&lt;p&gt;For AlloyDB use &lt;code&gt;--service alloydb --instance region/your-cluster/your-primary&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For Memorystore, use &lt;code&gt;--service redis&lt;/code&gt; or &lt;code&gt;--service valkey&lt;/code&gt; with &lt;code&gt;--instance region/your-cache&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect from a coding agent
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install the skill
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add pilef-co/bqto &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask Claude Code, Codex or your favourite agent something about your data, like "Count the orders in orders-db. It's the Cloud SQL instance in your-project". The agent runs the query through a bqto session, and bqto deletes the VM when the query ends. You can also ask it to keep the session open for several queries. If the agent doesn't have the project or the database password, it asks you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect from GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Google's auth action signs the job in with Workload Identity Federation (WIF), so you don't store a service account key. Then the bqto action runs your command through a session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google-github-actions/auth@v3&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;workload_identity_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.WIF_PROVIDER }}&lt;/span&gt;
    &lt;span class="na"&gt;service_account&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;migrations@your-project.iam.gserviceaccount.com&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google-github-actions/setup-gcloud@v3&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pilef-co/bqto-action@v1&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;PGPASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DB_PASSWORD }}&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-project&lt;/span&gt;
    &lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-db&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./migrate up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/pilef-co/bqto-action#setup" rel="noopener noreferrer"&gt;action's README&lt;/a&gt; has the full workflow and the commands to set up WIF.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;macOS and Linux only.&lt;/li&gt;
&lt;li&gt;Each session creates a new VM, so it takes a minute or two before bqto is ready.&lt;/li&gt;
&lt;li&gt;It's not meant for bulk transfers, because IAP isn't built for them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;p&gt;bqto is open source (Apache-2.0): &lt;a href="https://github.com/pilef-co/bqto" rel="noopener noreferrer"&gt;https://github.com/pilef-co/bqto&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;bqto Pro, now in beta, also adds Cloud Run, Managed Kafka, Memorystore clusters and a Mac menu bar app: &lt;a href="https://bqto.dev/#pro" rel="noopener noreferrer"&gt;https://bqto.dev/#pro&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Questions and feedback are welcome in the comments. I hope bqto helps!&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>devops</category>
      <category>showdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
