Skip to main content
This guide covers deploying Inbox Zero on a GCP Compute Engine VM using Cloudflare Tunnel for secure HTTPS access. Cloudflare Tunnel eliminates the need for a reverse proxy (Nginx/Caddy) and SSL certificate management — the tunnel connects outbound from your VM to Cloudflare’s edge, so no inbound firewall ports need to be opened. Why Cloudflare Tunnel?
  • HTTPS with no Nginx, Caddy, or Let’s Encrypt setup
  • No public inbound ports required — the VM only makes outbound connections
  • Free on Cloudflare’s free plan
  • Pairs naturally with GCP VMs running Gmail-integrated apps (same Google Cloud project)

Prerequisites

  • A Google Cloud account with billing enabled
  • A Cloudflare account (free tier) with a domain managed by Cloudflare DNS
  • SSH access to GCP (via gcloud CLI or browser-based SSH)

1. Create the Compute Engine VM

  1. Go to Compute Engine → VM instances → Create instance
  2. Name: inbox-zero (or your choice)
  3. Region/Zone: choose one close to your users
  4. Machine configuration:
    • Minimum: e2-medium (2 vCPU, 4 GB RAM) — add swap if using this size
    • Recommended: e2-standard-2 (2 vCPU, 8 GB RAM)
  5. Boot disk:
    • OS: Debian 12 or Ubuntu 24.04 LTS
    • Size: 20 GB minimum (Docker images + logs)
  6. Firewall: leave HTTP and HTTPS checkboxes unchecked — Cloudflare Tunnel handles all ingress
  7. Click Create

Optional: Reserve a static external IP

GCP external IPs change if the VM is stopped. If you need SSH access from a fixed address, reserve a static IP under VPC network → IP addresses and attach it to the VM. Cloudflare Tunnel does not require a static IP.

2. Install Docker and Docker Compose

SSH into the VM and run:

Add swap (required for e2-medium)

If you’re using e2-medium (4 GB RAM), add swap to avoid OOM kills:

3. Set Up Cloudflare Tunnel

Create the tunnel

In the Cloudflare dashboard:
  1. Go to Zero Trust → Networks → Tunnels → Add a tunnel
  2. Choose Cloudflared as the connector type
  3. Name the tunnel (e.g. inbox-zero)
  4. Follow the install instructions for Debian — copy the cloudflared install command shown in the dashboard and run it on your VM:
  1. Run the service install command shown in the dashboard. It looks like:
This registers cloudflared as a systemd service that starts automatically on boot.

Configure the public hostname

Back in the Cloudflare dashboard tunnel settings:
  1. Go to the Public Hostnames tab
  2. Click Add a public hostname
  3. Subdomain: e.g. inbox (resulting in inbox.yourdomain.com)
  4. Domain: your Cloudflare-managed domain
  5. Service: http://localhost:3000
  6. Save — Cloudflare automatically adds a CNAME DNS record
Your app will be reachable at https://inbox.yourdomain.com once the tunnel is running and the app is started.

4. Set Up Inbox Zero

When prompted, enter your full Cloudflare Tunnel URL as the base URL (e.g. https://inbox.yourdomain.com).

Option B: Manual

Key variables to set:
See the Environment Variables reference for the full list.

5. Start the Application

Check that all containers are up:
Startup takes 30–60 seconds. Once the web container logs show the Next.js server is ready, visit your Cloudflare URL.

6. Update Google OAuth Redirect URIs

In Google Cloud Console → APIs & Services → Credentials, open your OAuth client and add:
to the Authorized redirect URIs list.

Maintenance

Restart after a VM reboot

Both Docker (with --restart unless-stopped / Compose) and cloudflared run as systemd services and restart automatically. Verify with:

Update to the latest image

View logs

Troubleshooting

Tunnel shows as “Healthy” but site returns 502:
  • The app container may still be starting up — wait 60 seconds and refresh
  • Check docker logs inbox-zero-services-web-1 for startup errors
Cloudflare Tunnel disconnected:
  • Check journalctl -u cloudflared for errors
  • Verify the VM has outbound internet access (should work by default on GCP)
Google OAuth redirect_uri_mismatch:
  • Ensure NEXT_PUBLIC_BASE_URL exactly matches the redirect URI registered in Google Cloud Console
  • Must match the Cloudflare hostname including https://
For other issues, see the Troubleshooting guide.