Private vs Public IP Addresses in GCP | Internal, External, Static, and Ephemeral
Every VM in GCP gets a private internal IP automatically. External public IPs are optional, and most VMs in a well-designed environment should not have one. Understanding the difference between private and public, and between ephemeral and static, is one of the first things that unlocks a clearer mental model of how GCP networking works.
Simple explanation
These two concepts answer different questions:
- Private vs public: who can reach this address?
- Static vs ephemeral: does this address stay the same?
A private (internal) IP is an RFC 1918 address drawn from your subnet. It is only reachable within your VPC and any networks connected to it. Nothing on the public internet can send traffic to it directly.
A public (external) IP is an internet-routable address. Anyone on the internet can attempt to connect to it, subject to your firewall rules. This is optional. Most VMs do not need one.
A static address is reserved explicitly and persists even when the VM is stopped or restarted. An ephemeral address is temporary: assigned when the resource starts and released when it stops.
A private IP is like an internal phone extension at a company. Colleagues inside the building can call it, but no one outside can. A public IP is like a number listed in the phone book: anyone can dial, and your firewall rules decide who gets answered.
Whether that number is permanent or gets reassigned when the person moves desks is a separate question. That is the static vs ephemeral distinction.
These two dimensions are independent. An internal address can be static or ephemeral. An external address can be static or ephemeral. A database server typically has a static internal IP. A load balancer typically has a static external IP. A short-lived dev VM might have an ephemeral external IP. All four combinations exist and make sense in different situations.
How IP addresses work in GCP
When you create a VM, GCP’s DHCP service assigns it an internal IP from the subnet you selected. That subnet belongs to a VPC network. Every VM in GCP must live in a subnet. There is no network without one.
External IPs are assigned separately, only if you request one. If you leave the external IP field blank when creating a VM, the VM has no public address at all. GCP does not silently attach one.
A VM does not actually see its own external IP inside the OS. External IPs exist at the network edge, where GCP performs 1-to-1 NAT before traffic reaches the VM. If you run ip addr inside a VM, you will only see the internal address. The external IP is a property of the network interface, not the VM itself.
A few things worth understanding before you go further:
- VPC boundaries control reachability. VMs in the same VPC can communicate using internal IPs across regions. VMs in different VPCs cannot communicate privately unless you connect them via VPC Peering or Shared VPC.
- Firewall rules apply to all traffic, not just external. Even VM-to-VM traffic within a VPC is subject to firewall policy. See Firewall Rules Explained for how ingress and egress rules work.
- Having no external IP is a stronger guarantee than a restrictive firewall. A firewall rule can be misconfigured or modified by mistake. A VM with no external IP cannot receive inbound internet traffic by any route. There is simply no address for internet hosts to send to.
- Public vs private is separate from static vs ephemeral. You can mix and match freely. The two dimensions do not constrain each other.
Private vs public IP addresses
| Private (internal) | Public (external) | |
|---|---|---|
| Reachability | Within VPC and connected networks | Internet-routable |
| Assigned automatically? | Yes, every VM always gets one | No, optional and must be requested |
| Typical use | App servers, databases, workers, internal APIs | Web servers, load balancers, bastion hosts |
| Security exposure | Low, not reachable from the internet | Higher, inbound attempts are possible |
| Outbound internet | Only via Cloud NAT | Direct outbound access |
| Address range | RFC 1918 (10.x, 172.16.x, 192.168.x) | Google-owned public ranges |
If a resource does not need to receive traffic from the internet, and does not need to initiate outbound internet connections on its own, it should have no external IP. Most internal services fit that description: app servers, databases, caches, background workers.
For VMs that need outbound internet access but should not be reachable inbound, use Cloud NAT. For VMs that only need to reach Google APIs, use Private Google Access instead, which never touches the public internet at all.
Ephemeral vs static IP addresses
Static and ephemeral are about persistence, not visibility. This applies equally to internal and external addresses.
| Ephemeral | Static | |
|---|---|---|
| Persistence | Released when the VM stops or is deleted | Reserved independently of VM state |
| Default? | Yes, the default for both internal and external | No, must be explicitly reserved |
| Cost | Free | Free when attached to a running resource; charged when idle |
| Best for | Dev VMs, batch jobs, short-lived workloads | Databases, load balancers, DNS-backed services |
| Applies to | Both internal and external addresses | Both internal and external addresses |
You reserve a static address with gcloud compute addresses create. You can specify a region (for regional VMs), global (for global load balancers), and whether it is internal or external.
# Reserve a static external IP in a region
gcloud compute addresses create web-server-ip \
--region=us-central1
# Reserve a static global external IP (for global load balancers)
gcloud compute addresses create my-global-ip \
--global
# Reserve a static internal IP at a specific address
gcloud compute addresses create db-internal-ip \
--region=us-central1 \
--subnet=db-subnet \
--addresses=10.0.2.5
# List all reserved addresses (check for idle ones)
gcloud compute addresses listStatic IPs reserved but not attached to a running resource incur an idle IP charge. After stopping or deleting a VM with a reserved static IP, either delete the reservation or reassign it elsewhere. These charges are small but persistent and easy to miss across multiple projects.
When to use each option
If a VM does not need to receive traffic from the internet, skip the external IP entirely. If it needs outbound internet access, use Cloud NAT rather than a public IP. Assign a public IP only when inbound internet traffic is genuinely required.
Internal app server connecting to a database
Both should have only internal IPs. The app connects to the database’s internal address. No external IP is needed on either. If the database restarts and could get a new address, reserve a static internal IP to keep the connection config stable.
Publicly reachable web server
One external IP, ideally on a load balancer rather than the VM itself. The load balancer holds the stable public address and backend VMs remain private. If the web server is standalone, assign a static external IP so DNS records do not break on restart. See Creating Your First VM for where external IPs are configured at creation time.
Private VM that needs to download packages
No external IP on the VM. Configure Cloud NAT on the subnet region instead. Cloud NAT translates outbound connections from the private IP to a shared public NAT address. The VM remains unreachable from the internet while still being able to reach apt, yum, Docker Hub, or any external API.
Admin SSH access to private VMs
Rather than assigning a public IP to every admin VM, use Identity-Aware Proxy (IAP) tunneling. IAP lets you open an SSH connection to a VM without an external IP using your Google identity and IAM permissions. See SSH Access in Compute Engine for both IAP and bastion host approaches.
Load balancer frontend address
Reserve a static external IP and assign it to the load balancer. Backend VMs stay private. The static address is what you put in DNS. Load balancers are long-lived, so a static address here prevents DNS drift as VMs are replaced or rotated.
Private VM that only needs Google APIs
Enable Private Google Access on the subnet. This lets the VM reach Cloud Storage, BigQuery, and other Google APIs without any internet path. No external IP and no Cloud NAT needed for those destinations.
Common mistakes
- Assigning external IPs to every VM by default. It is easy to click through VM creation and leave the external IP on. In production, most VMs should not have one. Removing unnecessary external IPs reduces attack surface more reliably than relying purely on firewall rules. See Network Security Best Practices for a fuller picture.
- Assuming private-only VMs can reach the internet automatically. A VM with no external IP has no outbound internet path by default. Package managers, Docker pulls, and calls to external APIs will all fail silently or time out. Set up Cloud NAT if those VMs need outbound internet access.
- Hardcoding an ephemeral internal IP in application config. Ephemeral internal IPs can change when a VM restarts. Any application, DNS record, or firewall rule using a hardcoded ephemeral address will break after the next restart. Reserve a static internal IP for any resource that others connect to by address.
- Leaving idle static IPs after deleting or stopping VMs. GCP charges for static IPs that are reserved but not attached to a running resource. Audit with
gcloud compute addresses listperiodically and delete reservations that are no longer needed. - Treating firewall rules as equivalent to having no external IP. A firewall rule blocks traffic, but rules can have bugs, be modified by mistake, or have exceptions that slip through. A VM with no external IP cannot receive inbound internet traffic regardless of firewall state. Both layers are useful; they are not interchangeable.
Clearing up the most common confusion
Private vs public and static vs ephemeral are two completely independent dimensions. The confusion usually comes from hearing “static IP” and “public IP” used interchangeably, when they describe entirely different properties.
Here is a concrete way to think through the four combinations:
- Private + static: a database VM with a reserved internal IP. Not reachable from the internet, and the address never changes on restart. The right choice for any database or internal service.
- Public + static: a load balancer with a reserved external IP. Internet-routable and stable for DNS records. The standard pattern for production web traffic.
- Public + ephemeral: a dev web server with a temporary external IP. Internet-reachable but the address changes on restart. Fine for short-lived testing. Not suitable for production DNS.
- Private + ephemeral: the default for most VMs. A background worker or app server that only talks to other VMs in the same VPC. No internet exposure, no persistent address needed.
When you hear “static IP”: is it internal or external? When you hear “public IP”: is it static or ephemeral? Keeping these two questions separate prevents most of the confusion around GCP address types.
If you are troubleshooting connectivity and not sure which type of address is involved, Troubleshooting Network Issues covers how to inspect VM network interfaces and verify what addresses are actually assigned.
Summary
- Private (internal) IPs are RFC 1918 addresses used within a VPC and are not reachable from the internet
- Public (external) IPs are internet-routable and optional; most VMs should not have one
- Ephemeral IPs are temporary and released on VM stop or delete; static IPs are reserved and persist
- Both internal and external addresses can be either static or ephemeral; these are independent choices
- Static IPs attached to running resources are free; idle reserved IPs incur a charge
- Use Cloud NAT for outbound internet access on private VMs; use Private Google Access to reach Google APIs without any internet path
- Reserve static internal IPs for databases and any service that other applications connect to by address
Frequently asked questions
What is the difference between private and public IP addresses in GCP?
Private (internal) IPs are RFC 1918 addresses drawn from your subnet. They are only reachable within your VPC and connected networks. Nothing on the public internet can reach them directly. Public (external) IPs are internet-routable addresses, optionally assigned to a VM or load balancer. You only need an external IP if a resource must accept inbound internet traffic or initiate outbound connections without Cloud NAT.
Can a private VM reach the internet?
Not by default. A VM with only an internal IP has no outbound internet path. To give private VMs outbound internet access for package downloads, container image pulls, or external API calls, configure Cloud NAT on the subnet region. Cloud NAT handles outbound connections without exposing the VM to inbound traffic from the internet.
Does a static IP have to be public?
No. Static and ephemeral describe persistence, not visibility. You can reserve a static internal IP for a database server so its address never changes when the VM restarts. You can also reserve a static external IP for a load balancer or web server. Both internal and external addresses can be either ephemeral or static.
When should I reserve a static internal IP?
Reserve a static internal IP for any resource that other services connect to by address: databases, internal API servers, caches. If a VM restarts and its ephemeral internal IP changes, every application that has the old IP hardcoded will fail to connect. Reserving a static internal IP prevents that problem without exposing the VM to the internet.
What happens to an ephemeral IP when a VM is stopped?
An ephemeral external IP is released when a VM is stopped or deleted. The next time it starts, it receives a different IP. Ephemeral internal IPs behave the same way. If your VM needs a consistent address across restarts, for DNS records, application configs, or firewall rules, reserve it as static before stopping the VM.