— Bruce Schneier, Secrets and Lies (2000)
[!abstract]- Summary
Documents the private-VM access pattern that was originally validated against stoxx-vm in bq-wh-nb, using gcloud compute ssh, gcloud compute scp, gcloud compute start-iap-tunnel, and OS Login.
SSH access via IAP
Use gcloud compute ssh ... --tunnel-through-iap for interactive shells, non-interactive --command runs, privileged diagnostics with sudo, and one-off --project overrides
Read OS Login-derived usernames, POSIX IDs, service state, kernel details, memory, disks, and filesystem output to confirm both identity and host health
File transfer via SCP
Upload single files, download remote files, transfer multiple files, and copy directories recursively with gcloud compute scp
Use /tmp/ as a staging area and follow with sudo cp and sudo chown when the real destination is owned by root or a service account
IAP tunnel architecture
Trace how gcloud opens the tunnel to tunnel.cloudproxy.app, how IAM and firewall prerequisites gate access, and why the VM never needs a public IP for SSH or SCP
Forward local ports to private services with gcloud compute start-iap-tunnel or SSH -L, including local 1435 to remote SQL Server port 1433
OS Login configuration
Enable enable-oslogin=TRUE at project level, verify commonInstanceMetadata.items, inspect gcloud compute os-login describe-profile, and map Google identities to POSIX accounts
Compare IAM-bound OS Login with metadata-based SSH keys for identity binding, key lifecycle, 2FA support, auditability, and multi-project access
Operations and safety
Warnings: IAP requires roles/iap.tunnelResourceAccessor, firewall access from 35.235.240.0/20, correct OS Login roles, and separate ownership handling for remote file writes
Recommendations table: the OS Login comparison matrix contrasts identity binding, short-lived keys, 2FA, audit trail, multi-project behavior, and service-account limitations
Troubleshooting: 5 failure modes covering SSH timeouts, Permission denied (publickey), slow SCP transfers, remote-path permission errors, and stale host keys after VM recreation
Live-run boundary
The original VM behind these SSH and SCP examples is no longer available for rerun. On 2026-04-15, the source project bq-wh-nb reported lifecycleState: DELETE_REQUESTED, so the stoxx-vm shell and file-transfer transcripts in this note remain historical operator examples.
This refresh only reran read-only commands that still make sense without a live VM, especially gcloud compute os-login describe-profile and the current local gcloud help surfaces for ssh, scp, and start-iap-tunnel.
Glossary
IAP (Identity-Aware Proxy)
A Google Cloud access layer that evaluates IAM identity and policy before permitting traffic to protected resources such as private Compute Engine VMs.
In this note, IAP is the security boundary that lets stoxx-vm stay off the public internet while still allowing authenticated SSH, SCP, and TCP forwarding.
Private does not mean unreachable
IAP replaces public exposure with identity-gated access. The VM stays private, but it is still reachable through Google’s proxy once IAM and firewall requirements are satisfied.
IAP tunnel
An encrypted transport path from the local gcloud client through Google’s proxy layer to the VM’s private IP and target port.
It matters because every SSH, SCP, and forwarded-port example in this note depends on that tunnel rather than on direct ingress to the VM.
Tunnel needs prerequisites
The tunnel does not bypass misconfiguration. Missing IAM permissions, disabled APIs, or absent firewall rules will still prevent access.
gcloud compute ssh
The Google Cloud CLI command that opens an SSH session or runs remote commands against a Compute Engine VM.
The note uses it for interactive administration, one-shot diagnostics, privileged sudo checks, and SSH-based port forwarding through IAP.
More than interactive shells
gcloud compute ssh is also a remote-execution wrapper. --command turns it into a non-interactive automation tool rather than only a login experience.
OS Login
A Compute Engine access model that maps IAM identities to POSIX users and manages short-lived SSH credentials for them.
It matters here because the VM access path is tied to the user’s Google identity instead of to long-lived metadata keys distributed across instances.
Roles still decide login
Enabling OS Login alone does not grant shell access. The user also needs the appropriate IAM role such as roles/compute.osLogin or roles/compute.osAdminLogin.
Metadata-based SSH key
A traditional SSH public key stored in project or instance metadata and matched to a username on the VM.
The note contrasts this legacy model with OS Login to show why persistent keys are less suitable for normal human access.
Key lifecycle is manual
Metadata keys remain valid until someone removes them. That makes cleanup, auditing, and user offboarding weaker than IAM-bound OS Login flows.
POSIX account
The Linux user identity on the VM defined by a username, UID, GID, home directory, and group membership.
It matters because OS Login materializes the authenticated Google identity as a concrete Linux account that owns files and runs processes on the guest.
Username is derived
OS Login derives the Linux username from the Google identity, typically replacing @ and . with underscores. That mapping explains usernames such as alexper_recovery_gmail_com.
gcloud compute scp
The Google Cloud CLI command that copies files between a local machine and a Compute Engine VM over SSH.
The note uses it for uploads, downloads, multi-file transfers, and recursive directory copies that all travel through the same IAP-backed access path.
Remote path permissions apply
gcloud compute scp authenticates as your VM user, not as root. A target directory can still reject the write even when the tunnel and authentication are correct.
SCP
Secure Copy Protocol, a file-transfer protocol that operates over SSH.
It matters in this note because gcloud compute scp wraps SCP semantics while handling the GCP-specific identity and tunneling details for you.
Same trust path as SSH
SCP is not a separate access plane here. It reuses the same SSH and IAP trust path as the shell sessions.
Serial console
A text console exposed through the VM’s virtual serial port, independent of normal network SSH access.
It matters as the fallback access method when guest networking, SSH configuration, or the operating system itself prevents standard SSH logins.
Use as break-glass path
Serial console access is mainly for recovery scenarios. It is most valuable when normal SSH is broken, not as the default administration workflow.
Port forwarding
A tunneling pattern that binds a local TCP port and relays traffic to a port on the remote VM.
The note uses it to reach SQL Server on stoxx-vm from local tools without exposing the database port publicly.
Local client stays unchanged
With port forwarding active, the local application still connects to localhost. The tunnel handles the translation to the VM’s private service port.
gcloud compute start-iap-tunnel
The Google Cloud CLI command that opens a raw TCP tunnel through IAP to a chosen VM port.
It matters because it supports non-SSH protocols such as SQL Server while preserving the same private-network and IAM-controlled access model.
Tunnel stays foregrounded
The command keeps running until you terminate it. Closing the process immediately tears down access for any local client using the forwarded port.
WebSocket tunnel
The underlying transport IAP uses between the local client and Google’s proxy endpoint for TCP forwarding.
It matters because it explains why private-port access can work over standard outbound connectivity from the local workstation without opening inbound SSH on the VM.
Proxy endpoint is fixed
The client connects to Google’s IAP endpoint, not directly to the VM. Google then forwards the traffic internally to the guest network interface.
SSH Access via IAP
gcloud compute ssh is the standard method for connecting to Compute Engine VMs. All access routes through Google’s Identity-Aware Proxy (IAP), which authenticates your gcloud credentials against IAM before establishing the tunnel — no firewall rules exposing SSH to the public internet are required.
gcloud compute ssh | connect to a VM
Connects to a Compute Engine VM over an IAP tunnel using your gcloud identity. The IAP proxy terminates the public connection and forwards traffic internally to the VM’s private IP on the target port (default: 22).
Interactive SSH session
When you need a shell on the VM for interactive debugging, package installation, or service inspection. It is typically triggered by first access after VM creation, troubleshooting a running workload, or manual maintenance. Runs from a local terminal with gcloud authenticated. The --tunnel-through-iap flag routes the connection through Google’s internal network. Read-only from the perspective of the tunnel — the SSH session itself is read-write on the VM. Establish an interactive shell on stoxx-vm without requiring the VM to have a public IP address.
Open an interactive SSH session on stoxx-vm through IAP.
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.8.0-1048-gcp x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of Sun Apr 12 18:52:16 UTC 2026 System load: 0.06 Processes: 119 Usage of /: 4.6% of 48.27GB Users logged in: 0 Memory usage: 6% IPv4 address for ens4: 10.132.0.8 Swap usage: 0%alexper_recovery_gmail_com@stoxx-vm:~$
The banner shows Ubuntu 22.04.5 LTS running on a GCP-optimized kernel (6.8.0-1048-gcp). The ens4 interface has private IP 10.132.0.8 — no external IP exists. The OS Login username alexper_recovery_gmail_com is derived from the authenticated Google identity, confirming OS Login is active (not a metadata-based SSH key).
No Public IP Required
Using --tunnel-through-iap means the VM can have no external IP address at all. This eliminates an entire attack surface — the VM is completely unreachable from the public internet, yet you can still SSH into it using your gcloud credentials. The stoxx-vm was created with --no-address specifically for this reason.
Remote command execution
When you need to inspect VM resources or run a health check without starting an interactive session. It is typically triggered by automated monitoring scripts, CI/CD pipelines, or quick diagnostic one-liners. The --command flag runs the string in a non-interactive shell and returns stdout to the caller. The session terminates after the command completes. Chain multiple commands with && so each runs only if the previous succeeded. Retrieve system information, memory, disk layout, and block devices from stoxx-vm in a single invocation.
Run a chained diagnostic command on stoxx-vm to inspect hostname, kernel, memory, disk usage, and block device layout.
The e2-medium machine type provides 3.8 GiB RAM with no swap configured. The 50 GB pd-balanced boot disk (sda) is partitioned into a 49.9 GB root partition (sda1) with 5% used (2.2 GB), a 4 MB BIOS boot partition (sda14), and a 106 MB EFI partition (sda15). The tmpfs at /run/user/1137701540 is the per-user tmpfs for the OS Login UID. Five snap-based loop devices are mounted for core Ubuntu packages and the google-cloud-cli. When additional persistent disks are attached (see disks-and-snapshots), they appear as sdb, sdc, etc. in the lsblk output.
Remote command with sudo
When the diagnostic requires root privileges — inspecting running services, reading protected logs, or modifying system configuration. It is typically triggered by service health verification, post-deployment smoke test, or investigating a failed startup script. sudo inside --command runs the command as root on the VM. OS Login users with roles/compute.osAdminLogin have passwordless sudo; users with roles/compute.osLogin do not. List all running systemd services on stoxx-vm to verify the expected baseline after boot.
List all active systemd services on stoxx-vm using sudo.
UNIT LOAD ACTIVE SUB DESCRIPTION chrony.service loaded active running chrony, an NTP client/server cron.service loaded active running Regular background program processing daemon dbus.service loaded active running D-Bus System Message Bus getty@tty1.service loaded active running Getty on tty1 google-guest-agent.service loaded active running Google Compute Engine Guest Agent google-osconfig-agent.service loaded active running Google OSConfig Agent multipathd.service loaded active running Device-Mapper Multipath Device Controller networkd-dispatcher.service loaded active running Dispatcher daemon for systemd-networkd polkit.service loaded active running Authorization Manager rsyslog.service loaded active running System Logging Service serial-getty@ttyS0.service loaded active running Serial Getty on ttyS0 snapd.service loaded active running Snap Daemon ssh.service loaded active running OpenBSD Secure Shell server systemd-journald.service loaded active running Journal Service systemd-logind.service loaded active running User Login Management systemd-networkd.service loaded active running Network Configuration systemd-resolved.service loaded active running Network Name Resolution systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files ubuntu-advantage.service loaded active running Ubuntu Pro Background Auto Attach unattended-upgrades.service loaded active running Unattended Upgrades Shutdown user@1137701540.service loaded active running User Manager for UID 113770154021 loaded units listed.
21 services are running on the baseline Ubuntu 22.04 image. Key GCP-specific services: google-guest-agent.service (manages metadata, network interfaces, and accounts), google-osconfig-agent.service (applies OS policies and patch management), and serial-getty@ttyS0.service (enables serial console access as a fallback when SSH is unreachable). The ssh.service confirms the OpenSSH server is running and accepting connections on port 22. The user@1137701540.service is the per-user systemd manager for the OS Login UID.
SSH with project override
When your active gcloud configuration points to a different project and you need to SSH into a VM in bq-wh-nb without switching configurations. It is typically triggered by multi-project environments where VMs are spread across projects. The --project flag overrides the active project for this command only. All other flags behave identically. Reach stoxx-vm from a session configured for a different project.
SSH into stoxx-vm with an explicit project override.
The --project=bq-wh-nb flag targets the correct project regardless of the active gcloud configuration. The output confirms OS Login is mapping the Google identity to UID 1137701540 — the same UID visible in the systemd output above.
OS Login vs Metadata-Based SSH Keys
GCP offers two SSH key management models:
OS Login (recommended): binds VM access to IAM identities. SSH keys are short-lived and automatically managed by gcloud. Users are created as POSIX accounts derived from their Google identity (e.g., alexper_recovery_gmail_com). Supports 2FA via enable-oslogin-2fa=true. Enabled via enable-oslogin=true in project or instance metadata.
Metadata-based keys: traditional SSH public keys stored in project or instance metadata. Each key grants access to any VM in scope. Keys persist until manually removed and are not tied to IAM identity or lifecycle.
OS Login is the production standard. Metadata-based keys remain useful for service accounts or environments where OS Login is not available.
Flag
Syntax
Description
--zone
--zone=europe-west1-b
Zone where the VM is located. Required unless a default zone is set in gcloud config.
--tunnel-through-iap
--tunnel-through-iap
Route SSH through IAP — the VM does not need a public IP address.
--command
--command="<cmd>"
Run a command non-interactively and exit. Stdout is returned to the caller.
--port
--port=22
SSH port on the VM. Default: 22.
--ssh-key-expiry
--ssh-key-expiry=1h
Lifetime of the temporary SSH key when using OS Login. Default: 5 minutes.
--project
--project=bq-wh-nb
Override the active gcloud project for this command only.
--ssh-flag
--ssh-flag="-v"
Pass additional flags to the underlying SSH client (e.g., -v for verbose, -L for port forwarding).
--internal-ip
--internal-ip
Connect directly to the VM’s internal IP (requires VPN or same-VPC connectivity). Mutually exclusive with --tunnel-through-iap.
File Transfer via SCP
gcloud compute scp wraps SCP over the IAP tunnel, allowing you to copy files between your local machine and a VM without the VM needing a public IP. The hostname:path convention mirrors standard scp syntax — the remote side is prefixed with the VM name. The transfer patterns here complement the general data-transfer commands.
Keep shell startup files quiet for SCP
scp and other non-interactive SSH flows are brittle if .bashrc, .profile, or similar startup files print banners, prompts, or debug text. Extra output on startup can corrupt the protocol stream and turn a valid tunnel into a hanging or failed transfer.
gcloud compute scp | copy files to and from a VM
Securely copies files between a local machine and a Compute Engine VM over the IAP tunnel using the same credential model as gcloud compute ssh. The hostname: prefix on a path designates the remote side — omitting it means local.
Upload a single file
When deploying a script, config, or data file to the VM for execution or processing. It is typically triggered by initial provisioning, deploying updated SQL schemas, or uploading configuration files. The source path is local, the destination is prefixed with the VM name. The destination directory must be writable by the OS Login user — use /tmp/ when unsure. Copy bronze_schema.sql from the local ESG/db/ddl/ directory to /tmp/ on stoxx-vm.
The progress bar shows the file name, bytes transferred, transfer rate, and completion percentage. The 12.8 kB file was uploaded over the IAP tunnel in under one second.
Download a file from VM
When retrieving logs, configuration snapshots, or data files from the VM. It is typically triggered by collecting diagnostics, backing up configuration before changes, or pulling processed output. The source is prefixed with the VM name (remote), the destination is a local path. The file must be readable by the OS Login user on the VM. Download the /etc/os-release file from stoxx-vm to verify the OS version locally.
Download /etc/os-release from stoxx-vm to the local /tmp/ directory.
When deploying several related files (e.g., a set of SQL DDL scripts) to the VM in a single invocation. It is typically triggered by batch deployment of schema files, configuration updates, or multi-file patches. List all source files sequentially before the destination. The destination must be a directory on the VM, not a file path. Copy bronze_schema.sql and silver_schema.sql to /tmp/ on stoxx-vm in one command.
Upload two DDL scripts to /tmp/ on stoxx-vm in a single invocation.
Both files are transferred sequentially over the same IAP tunnel connection. Each file shows its own progress line.
Recursive directory copy
When deploying an entire directory tree (e.g., a DDL folder, a configuration directory) to the VM. It is typically triggered by initial provisioning, full schema deployment, or syncing a local project directory. The --recurse flag is required when the source is a directory — omitting it results in an error. The target directory must already exist on the VM. Copy the entire db/ddl/ directory (4 SQL files) to /tmp/ddl/ on stoxx-vm.
Target Directory Must Exist on the VM
gcloud compute scp --recurse does not create the target directory automatically. If the target path does not exist, the transfer fails with unable to open errors. Create the directory first with gcloud compute ssh --command="mkdir -p /tmp/ddl".
Create the Target Directory Before Recursive Copy
Always run mkdir -p on the VM before a recursive SCP:
Files are owned by the OS Login user (alexper_recovery_gmail_com) with group-writable permissions. The parent /tmp/ is world-writable (drwxrwxrwt) as expected.
Permission workaround — SCP to /tmp then sudo cp
When the target directory on the VM is owned by root or a service user and your OS Login user does not have write access. It is typically triggered by deploying files to /opt/, /etc/, or any directory not owned by your user. gcloud compute scp authenticates as your OS Login user. Directories owned by root (e.g., /opt/stoxx/ddl/) will reject writes. The workaround is a two-step process: SCP to /tmp/ (world-writable), then SSH with sudo cp to move the file and sudo chown to set ownership. Deploy bronze_schema.sql to /opt/stoxx/ddl/ on stoxx-vm, a root-owned directory.
SCP Fails When Target Directory Is Not Owned by Your User
If the destination is owned by root or a service user, gcloud compute scp will fail with a permission denied error. Attempting to SCP directly to /opt/stoxx/ddl/ will fail because the directory is owned by root.
SCP to /tmp First, Then sudo cp to Target
Always SCP files to /tmp/ (world-writable) first, then SSH in and use sudo cp to move them to the restricted destination. Follow with sudo chown to set the correct ownership.
Step 1 — SCP the file to /tmp/ on the VM:
Upload bronze_schema.sql to /tmp/ as a staging area.
The file is now owned by root:root in the restricted directory /opt/stoxx/ddl/. The ls -la confirms correct ownership and permissions (-rw-r--r--).
Flag
Syntax
Description
--zone
--zone=europe-west1-b
Zone where the VM is located. Required unless a default zone is set.
--tunnel-through-iap
--tunnel-through-iap
Route SCP through IAP — the VM does not need a public IP address.
--recurse
--recurse
Copy a directory and its contents recursively. Required when the source is a directory.
--port
--port=22
SSH port on the VM. Default: 22.
--project
--project=bq-wh-nb
Override the active gcloud project for this command only.
--compress
--compress
Enable compression during transfer. Useful for large text files over slow connections.
IAP Tunnel Architecture
All gcloud compute ssh and gcloud compute scp traffic routes through Google’s Identity-Aware Proxy. IAP terminates the inbound connection, validates your gcloud credentials against IAM, and forwards traffic to the VM over Google’s internal network — the VM never receives a direct external connection.
Architecture diagram
When --tunnel-through-iap is set, gcloud opens an IAP-encrypted WebSocket to tunnel.cloudproxy.app, which Google routes internally to the VM’s private IP on the target port (default: 22).
flowchart LR
A["Your Machine<br>gcloud compute ssh"] -->|"IAM auth<br>WebSocket"| B["Google IAP Proxy<br>tunnel.cloudproxy.app"]
B -->|"Internal<br>GCP network"| C["stoxx-vm<br>10.132.0.8<br>port 22"]
style A fill:#292e42,stroke:#565f89
style B fill:#24283b,stroke:#7aa2f7
style C fill:#292e42,stroke:#565f89
For the full tunnel mechanics including port forwarding and troubleshooting, see iap-tunneling.
Prerequisites
The following must be in place before --tunnel-through-iap will work:
Prerequisite
Detail
IAM role
roles/iap.tunnelResourceAccessor on the project, folder, or individual VM resource. Project Owner and Editor roles implicitly include this permission.
An ingress rule allowing IAP’s IP range 35.235.240.0/20 on TCP port 22 (for SSH) or the target port (for other services). The default VPC includes default-allow-ssh which allows TCP 22 from 0.0.0.0/0 — this is broader than needed but satisfies the IAP requirement.
VM network tag
If the firewall rule uses target tags, the VM must carry the matching tag. stoxx-vm uses the iap-ssh tag for this purpose.
Port forwarding for SQL Server
When you need to connect a local application (e.g., SSMS, Azure Data Studio, sqlcmd) to a service running on the VM that has no public IP. It is typically triggered by database management, query execution, or data loading against SQL Server on stoxx-vm (see sql-server-on-compute-engine). gcloud compute start-iap-tunnel maps a local TCP port to a remote port on the VM through IAP. The tunnel remains open until the process is terminated (Ctrl+C). The local application connects to localhost:<local-port> and the tunnel forwards traffic to the VM’s <remote-port>. Map local port 1435 to SQL Server port 1433 on stoxx-vm, enabling local tools to connect to the database.
Start an IAP tunnel mapping local port 1435 to SQL Server port 1433 on stoxx-vm.
Testing if tunnel connection works.Listening on port [1435].
The tunnel is now active. Connect your SQL client to localhost:1435 — traffic is encrypted and routed through IAP to port 1433 on stoxx-vm. The tunnel process runs in the foreground; press Ctrl+C to close it.
An alternative using SSH port forwarding achieves the same result through gcloud compute ssh:
Forward local port 1435 to SQL Server port 1433 using SSH -L flag.
This opens an interactive SSH session with the port forwarding active in the background. The -L 1435:localhost:1433 flag tells SSH to listen on local port 1435 and forward traffic to localhost:1433 on the remote side (the VM). The tunnel closes when the SSH session ends.
Flag
Syntax
Description
<instance>
stoxx-vm
The VM to tunnel to. First positional argument.
<port>
1433
Remote port on the VM. Second positional argument.
--local-host-port
--local-host-port=localhost:1435
Local address and port to bind. Default: localhost:0 (random port).
--zone
--zone=europe-west1-b
Zone where the VM is located.
--project
--project=bq-wh-nb
Override the active gcloud project.
OS Login Configuration
OS Login maps IAM identities to POSIX accounts on VMs. When enabled, gcloud compute ssh uses short-lived, IAM-managed SSH keys instead of persistent keys stored in instance metadata. OS Login also provides centralized access auditing through Cloud Audit Logs and supports two-factor authentication.
Enable OS Login at project level
During initial project setup or when migrating from metadata-based SSH keys to OS Login. It is typically triggered by first-time project configuration, security hardening, or compliance requirement. gcloud compute project-info add-metadata sets metadata at the project level, which applies to all VMs in the project unless overridden by instance-level metadata. This is a state-changing command but does not require VM restarts — the change takes effect on the next SSH connection. Enable OS Login for all VMs in bq-wh-nb so that SSH access is bound to IAM identity.
Enable OS Login at the project level for bq-wh-nb.
OS Login is now enabled at the project level. All VMs in bq-wh-nb will use OS Login unless an individual VM overrides this with enable-oslogin=false in its instance metadata.
Verify OS Login profile
After enabling OS Login to confirm your identity is correctly mapped to POSIX accounts across projects. It is typically triggered by first SSH after enabling OS Login, troubleshooting authentication failures, or auditing cross-project access. gcloud compute os-login describe-profile reads the OS Login profile for the authenticated identity. This is a read-only command. Inspect the POSIX account mapping and SSH public keys associated with the current gcloud identity.
Describe the OS Login profile for the current authenticated user.
The live profile now shows four project-scoped POSIX accounts for the same Google identity, including the historical bq-wh-nb mapping. The username remains alexper_recovery_gmail_com across projects, while the UID and GID vary per project-scoped OS Login account. The sshPublicKeys section also confirms multiple active SSH public keys tied to the current identity rather than to one VM.
SSH after OS Login
gcloud compute ssh works transparently with OS Login enabled — no syntax changes are required. The only visible difference is the POSIX username on the VM, which is derived from the Google identity rather than a locally-configured username.
The whoami output confirms the OS Login username. The uid and gid match the values from os-login describe-profile. With OS Login, the VM’s /etc/passwd is dynamically managed by the google-guest-agent — you do not need to create or manage user accounts manually.
When to Use Each SSH Key Model
Criteria
OS Login
Metadata-based keys
Identity binding
IAM identity → POSIX account
SSH key → username (no IAM link)
Key lifecycle
Short-lived, auto-managed by gcloud
Persistent until manually removed
2FA support
Yes (enable-oslogin-2fa=true)
No
Audit trail
Cloud Audit Logs per SSH session
Metadata change logs only
Multi-project
One profile per identity, per-project POSIX accounts
Separate key distribution per project
Service accounts
Not supported — use metadata keys
Supported
Use OS Login for all human access. Use metadata-based keys only for service accounts or automation that cannot use OS Login.
GCP VM SSH and File Transfer Troubleshooting
Symptom
Common Cause
Diagnostic Steps
SSH connection timeout
VM is not running, IAP firewall rule missing, or roles/iap.tunnelResourceAccessor not granted.
1. gcloud compute instances describe stoxx-vm --format="value(status)" — must be RUNNING. 2. gcloud compute firewall-rules list --filter="sourceRanges:35.235.240.0/20" — must allow TCP 22. 3. Check IAM bindings: gcloud projects get-iam-policy bq-wh-nb --filter="bindings.role:roles/iap.tunnelResourceAccessor".
Permission denied (publickey)
OS Login misconfiguration, stale SSH keys, or missing roles/compute.osLogin IAM role.
1. Verify OS Login is enabled: gcloud compute instances describe stoxx-vm --format="value(metadata.items.filter(key:enable-oslogin))". 2. Check your OS Login profile: gcloud compute os-login describe-profile. 3. Re-authenticate: gcloud auth login --update-adc.
SCP slow transfers
Large files over the IAP tunnel without compression.
1. Add --compress to enable SSH compression for text-heavy transfers. 2. For large binary files, consider gsutil cp to a Cloud Storage bucket and gsutil cp from the VM instead of SCP. 3. Check VM network throughput: gcloud compute instances describe stoxx-vm --format="value(machineType)" — e2-medium provides up to 2 Gbps.
SCP permission denied
Target directory on VM not writable by OS Login user.
Use the /tmp/ → sudo cp → sudo chown workaround documented in the SCP section above.
Host key verification failed
VM was recreated with the same name but a different host key.
Remove the stale entry: ssh-keygen -R compute.<instance-id>. The next SSH connection will prompt to accept the new key.
Related
vm-lifecycle — starting, stopping, and resizing the VMs you SSH into
disks-and-snapshots — using serial console as a fallback when SSH is unreachable