SSH Manager Pro Get the app

Google Cloud setup

IAP reaches instances from Google's own network, so the instance needs no public IP — but it does need a firewall rule for the proxy range, and OS Login enabled.

1. Enable the APIs

gcloud services enable compute.googleapis.com iap.googleapis.com \
  oslogin.googleapis.com --project YOUR_PROJECT

2. Choose how you authenticate

Option A: Browser Login (Google Account) — Recommended

Sign in with your standard Google account directly from the app. No JSON keys to download, manage, or transfer to your phone.

  1. Ensure your Google user account has the required IAM roles on the project:
    gcloud projects add-iam-policy-binding YOUR_PROJECT \
      --member "user:YOUR_EMAIL@gmail.com" \
      --role roles/iap.tunnelResourceAccessor
    
    gcloud projects add-iam-policy-binding YOUR_PROJECT \
      --member "user:YOUR_EMAIL@gmail.com" \
      --role roles/compute.osLogin
  2. In the app, open Settings → Google Cloud, tap the Browser Login (Google) tab, enter your Project ID, and tap Sign in with Google Account.
  3. Complete authorization in your browser. The loopback server completes sign-in automatically, or you can switch to Manual Code Entry to paste the redirect URL or authorization code.

Option B: Service Account (JSON)

If you prefer a dedicated machine identity or need automated service account authentication:

gcloud iam service-accounts create sshmanager-app \
  --display-name "SSH Manager app" --project YOUR_PROJECT

gcloud projects add-iam-policy-binding YOUR_PROJECT \
  --member "serviceAccount:sshmanager-app@YOUR_PROJECT.iam.gserviceaccount.com" \
  --role roles/iap.tunnelResourceAccessor

gcloud projects add-iam-policy-binding YOUR_PROJECT \
  --member "serviceAccount:sshmanager-app@YOUR_PROJECT.iam.gserviceaccount.com" \
  --role roles/compute.osLogin

gcloud iam service-accounts keys create key.json \
  --iam-account sshmanager-app@YOUR_PROJECT.iam.gserviceaccount.com

In Settings → Google Cloud, select Service Account (JSON) and paste or import the key.json file.

4. Allow the proxy range

IAP connects from a fixed range, and only that range needs access:

gcloud compute firewall-rules create allow-iap-ssh \
  --network YOUR_NETWORK --allow tcp:22 \
  --source-ranges 35.235.240.0/20 --project YOUR_PROJECT

If this is the only SSH rule, nothing on the public internet can reach port 22 at all — which is the point.

5. Enable OS Login

gcloud compute instances add-metadata YOUR_INSTANCE \
  --metadata enable-oslogin=TRUE --zone YOUR_ZONE --project YOUR_PROJECT

Without this the instance only honours keys baked into metadata, and the app's per-connection key is ignored.

6. Add a host

Choose Google Cloud, enter the instance name and zone. Leave the username blank — OS Login assigns one and the app reads it back.

Deploy with Terraform / OpenTofu (Zero Public IP VM)

This complete OpenTofu / Terraform blueprint provisions a completely private Debian VM with no external IP, a firewall rule allowing only Google's proxy range, and a service account with minimal IAP and OS Login permissions:

# Network and private subnet
resource "google_compute_network" "vpc" {
  name                    = "sshmanager-net"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "subnet" {
  name          = "sshmanager-subnet"
  ip_cidr_range = "10.10.0.0/24"
  region        = "us-central1"
  network       = google_compute_network.vpc.id
}

# Firewall: allow SSH ONLY from Google's IAP proxy range
resource "google_compute_firewall" "iap_ssh" {
  name          = "allow-iap-ssh"
  network       = google_compute_network.vpc.name
  source_ranges = ["35.235.240.0/20"]

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }
}

# VM with NO public IP: network_interface has no access_config block
resource "google_compute_instance" "vm" {
  name         = "sshmanager-vm"
  machine_type = "e2-micro"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12"
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.subnet.id
  }

  metadata = {
    enable-oslogin = "TRUE"
  }
}

# Service account with only two roles: tunnel and OS login
resource "google_service_account" "app" {
  account_id   = "sshmanager-app"
  display_name = "SSH Manager IAP Service Account"
}

resource "google_project_iam_member" "tunnel" {
  project = var.project_id
  role    = "roles/iap.tunnelResourceAccessor"
  member  = "serviceAccount:${google_service_account.app.email}"
}

resource "google_project_iam_member" "oslogin" {
  project = var.project_id
  role    = "roles/compute.osLogin"
  member  = "serviceAccount:${google_service_account.app.email}"
}

resource "google_service_account_key" "key" {
  service_account_id = google_service_account.app.name
}

output "instance_name" {
  value = google_compute_instance.vm.name
}

output "zone" {
  value = google_compute_instance.vm.zone
}

output "service_account_key_json" {
  value     = base64decode(google_service_account_key.key.private_key)
  sensitive = true
}

Apply the configuration and extract the sensitive service account key directly to your clipboard:

tofu init
tofu apply -var project_id=YOUR_PROJECT
tofu output -raw service_account_key_json | pbcopy

Paste the JSON key into Settings → Google Cloud in SSH Manager Pro, add a host with the instance name and zone, and leave the username blank — OS Login assigns your username automatically.

Run tofu destroy -var project_id=YOUR_PROJECT when you want to tear down the resources.

If it fails

403 opening the tunnel
Almost always the missing tunnelResourceAccessor role, rather than a wrong instance name.
"OS Login returned no POSIX account"
The service account or user is missing roles/compute.osLogin.
Tunnel opens, SSH times out
The firewall rule for 35.235.240.0/20 is missing or on the wrong network.