Create AWS Elastic IP Addresses

The aws:ec2/eip:Eip resource, part of the Pulumi AWS provider, allocates Elastic IP addresses and optionally associates them with EC2 instances or network interfaces. This guide focuses on two capabilities: instance and network interface association, and BYOIP and IPAM pool allocation.

Elastic IPs require an Internet Gateway in the VPC before association, though examples don’t show this dependency explicitly. The examples are intentionally small. Combine them with your own VPC infrastructure, Internet Gateways, and dependency management.

Associate an Elastic IP with an EC2 instance

Most deployments allocate an Elastic IP and attach it to an instance, giving the instance a stable public address that persists across stops and starts.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const lb = new aws.ec2.Eip("lb", {
    instance: web.id,
    domain: "vpc",
});
import pulumi
import pulumi_aws as aws

lb = aws.ec2.Eip("lb",
    instance=web["id"],
    domain="vpc")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ec2.NewEip(ctx, "lb", &ec2.EipArgs{
			Instance: pulumi.Any(web.Id),
			Domain:   pulumi.String("vpc"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var lb = new Aws.Ec2.Eip("lb", new()
    {
        Instance = web.Id,
        Domain = "vpc",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.Eip;
import com.pulumi.aws.ec2.EipArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var lb = new Eip("lb", EipArgs.builder()
            .instance(web.id())
            .domain("vpc")
            .build());

    }
}
resources:
  lb:
    type: aws:ec2:Eip
    properties:
      instance: ${web.id}
      domain: vpc

The instance property attaches the Elastic IP to a specific EC2 instance. The domain property must be set to “vpc” for VPC-based Elastic IPs. The IP remains associated even if you stop and restart the instance, unlike the ephemeral public IPs AWS assigns by default.

Attach multiple Elastic IPs to one network interface

Applications that need multiple public IPs on a single instance can attach several Elastic IPs to one network interface, each mapped to a different private IP.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const multi_ip = new aws.ec2.NetworkInterface("multi-ip", {
    subnetId: main.id,
    privateIps: [
        "10.0.0.10",
        "10.0.0.11",
    ],
});
const one = new aws.ec2.Eip("one", {
    domain: "vpc",
    networkInterface: multi_ip.id,
    associateWithPrivateIp: "10.0.0.10",
});
const two = new aws.ec2.Eip("two", {
    domain: "vpc",
    networkInterface: multi_ip.id,
    associateWithPrivateIp: "10.0.0.11",
});
import pulumi
import pulumi_aws as aws

multi_ip = aws.ec2.NetworkInterface("multi-ip",
    subnet_id=main["id"],
    private_ips=[
        "10.0.0.10",
        "10.0.0.11",
    ])
one = aws.ec2.Eip("one",
    domain="vpc",
    network_interface=multi_ip.id,
    associate_with_private_ip="10.0.0.10")
two = aws.ec2.Eip("two",
    domain="vpc",
    network_interface=multi_ip.id,
    associate_with_private_ip="10.0.0.11")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		multi_ip, err := ec2.NewNetworkInterface(ctx, "multi-ip", &ec2.NetworkInterfaceArgs{
			SubnetId: pulumi.Any(main.Id),
			PrivateIps: pulumi.StringArray{
				pulumi.String("10.0.0.10"),
				pulumi.String("10.0.0.11"),
			},
		})
		if err != nil {
			return err
		}
		_, err = ec2.NewEip(ctx, "one", &ec2.EipArgs{
			Domain:                 pulumi.String("vpc"),
			NetworkInterface:       multi_ip.ID(),
			AssociateWithPrivateIp: pulumi.String("10.0.0.10"),
		})
		if err != nil {
			return err
		}
		_, err = ec2.NewEip(ctx, "two", &ec2.EipArgs{
			Domain:                 pulumi.String("vpc"),
			NetworkInterface:       multi_ip.ID(),
			AssociateWithPrivateIp: pulumi.String("10.0.0.11"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var multi_ip = new Aws.Ec2.NetworkInterface("multi-ip", new()
    {
        SubnetId = main.Id,
        PrivateIps = new[]
        {
            "10.0.0.10",
            "10.0.0.11",
        },
    });

    var one = new Aws.Ec2.Eip("one", new()
    {
        Domain = "vpc",
        NetworkInterface = multi_ip.Id,
        AssociateWithPrivateIp = "10.0.0.10",
    });

    var two = new Aws.Ec2.Eip("two", new()
    {
        Domain = "vpc",
        NetworkInterface = multi_ip.Id,
        AssociateWithPrivateIp = "10.0.0.11",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.NetworkInterface;
import com.pulumi.aws.ec2.NetworkInterfaceArgs;
import com.pulumi.aws.ec2.Eip;
import com.pulumi.aws.ec2.EipArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var multi_ip = new NetworkInterface("multi-ip", NetworkInterfaceArgs.builder()
            .subnetId(main.id())
            .privateIps(            
                "10.0.0.10",
                "10.0.0.11")
            .build());

        var one = new Eip("one", EipArgs.builder()
            .domain("vpc")
            .networkInterface(multi_ip.id())
            .associateWithPrivateIp("10.0.0.10")
            .build());

        var two = new Eip("two", EipArgs.builder()
            .domain("vpc")
            .networkInterface(multi_ip.id())
            .associateWithPrivateIp("10.0.0.11")
            .build());

    }
}
resources:
  multi-ip:
    type: aws:ec2:NetworkInterface
    properties:
      subnetId: ${main.id}
      privateIps:
        - 10.0.0.10
        - 10.0.0.11
  one:
    type: aws:ec2:Eip
    properties:
      domain: vpc
      networkInterface: ${["multi-ip"].id}
      associateWithPrivateIp: 10.0.0.10
  two:
    type: aws:ec2:Eip
    properties:
      domain: vpc
      networkInterface: ${["multi-ip"].id}
      associateWithPrivateIp: 10.0.0.11

The NetworkInterface resource defines multiple private IPs on a single interface. Each Elastic IP uses networkInterface to target that interface and associateWithPrivateIp to specify which private IP receives the public address. This allows one instance to serve multiple public endpoints.

Allocate an IP from your own address pool

Organizations that bring their own IP address ranges to AWS can allocate Elastic IPs from those pools rather than using Amazon-provided addresses.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const byoip_ip = new aws.ec2.Eip("byoip-ip", {
    domain: "vpc",
    publicIpv4Pool: "ipv4pool-ec2-012345",
});
import pulumi
import pulumi_aws as aws

byoip_ip = aws.ec2.Eip("byoip-ip",
    domain="vpc",
    public_ipv4_pool="ipv4pool-ec2-012345")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ec2.NewEip(ctx, "byoip-ip", &ec2.EipArgs{
			Domain:         pulumi.String("vpc"),
			PublicIpv4Pool: pulumi.String("ipv4pool-ec2-012345"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var byoip_ip = new Aws.Ec2.Eip("byoip-ip", new()
    {
        Domain = "vpc",
        PublicIpv4Pool = "ipv4pool-ec2-012345",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.Eip;
import com.pulumi.aws.ec2.EipArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var byoip_ip = new Eip("byoip-ip", EipArgs.builder()
            .domain("vpc")
            .publicIpv4Pool("ipv4pool-ec2-012345")
            .build());

    }
}
resources:
  byoip-ip:
    type: aws:ec2:Eip
    properties:
      domain: vpc
      publicIpv4Pool: ipv4pool-ec2-012345

The publicIpv4Pool property references a BYOIP pool ID that you’ve previously advertised to AWS. This lets you maintain consistent public IPs when migrating workloads to AWS or meet compliance requirements for specific address ranges.

Allocate an IP from an IPAM-managed pool

Teams using AWS IPAM to centrally manage IP address allocation can provision Elastic IPs from IPAM pools that track usage across accounts and regions.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const ipam_ip = new aws.ec2.Eip("ipam-ip", {
    domain: "vpc",
    ipamPoolId: "ipam-pool-07ccc86aa41bef7ce",
});
import pulumi
import pulumi_aws as aws

ipam_ip = aws.ec2.Eip("ipam-ip",
    domain="vpc",
    ipam_pool_id="ipam-pool-07ccc86aa41bef7ce")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ec2.NewEip(ctx, "ipam-ip", &ec2.EipArgs{
			Domain:     pulumi.String("vpc"),
			IpamPoolId: pulumi.String("ipam-pool-07ccc86aa41bef7ce"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var ipam_ip = new Aws.Ec2.Eip("ipam-ip", new()
    {
        Domain = "vpc",
        IpamPoolId = "ipam-pool-07ccc86aa41bef7ce",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.Eip;
import com.pulumi.aws.ec2.EipArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var ipam_ip = new Eip("ipam-ip", EipArgs.builder()
            .domain("vpc")
            .ipamPoolId("ipam-pool-07ccc86aa41bef7ce")
            .build());

    }
}
resources:
  ipam-ip:
    type: aws:ec2:Eip
    properties:
      domain: vpc
      ipamPoolId: ipam-pool-07ccc86aa41bef7ce

The ipamPoolId property references an IPAM pool that has public IPv4 CIDR blocks provisioned. IPAM tracks which addresses are in use, preventing conflicts and providing visibility into IP allocation across your organization.

Beyond these examples

These snippets focus on specific Elastic IP features: instance and network interface association, and BYOIP and IPAM pool allocation. They’re intentionally minimal rather than full networking configurations.

The examples may reference pre-existing infrastructure such as EC2 instances, network interfaces, subnets, Internet Gateways (required but not shown), and BYOIP or IPAM pools for relevant examples. They focus on allocating and associating Elastic IPs rather than provisioning the surrounding infrastructure.

To keep things focused, common Elastic IP patterns are omitted, including:

  • Internet Gateway dependency management (dependsOn)
  • Private IP targeting (associateWithPrivateIp for single IPs)
  • Tags for cost tracking and organization
  • Network Border Group for Local Zone placement

These omissions are intentional: the goal is to illustrate how each Elastic IP feature is wired, not provide drop-in networking modules. See the Elastic IP resource reference for all available configuration options.

Let's create AWS Elastic IP Addresses

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Common Errors & Pitfalls
Why am I getting AuthFailure errors when associating an EIP with a NAT Gateway or Load Balancer?
Don’t use networkInterface to associate EIPs with aws.ec2.NatGateway or aws.lb.LoadBalancer. Instead, use the allocationId property available in those resources to let AWS manage the association.
Can I specify both instance and networkInterface for an EIP?
No. While the API won’t return an error, specifying both instance and networkInterface causes undefined behavior. Choose one or the other.
Why do I need to set dependsOn for the Internet Gateway?
EIPs may require the Internet Gateway to exist before association. Use dependsOn to create an explicit dependency on the IGW to avoid timing issues.
What happens if I specify both publicIpv4Pool and address?
Only address will be used. The API won’t error, but publicIpv4Pool is ignored when both are specified.
Association & Attachment
How do I attach multiple Elastic IPs to a single network interface?
Create multiple EIP resources with the same networkInterface ID, using associateWithPrivateIp to specify different private IPs (e.g., 10.0.0.10, 10.0.0.11) for each EIP.
How do I associate an EIP with a specific private IP address?
Use the associateWithPrivateIp property to specify the primary or secondary private IP. If not specified, the EIP associates with the primary private IP by default.
Should I use instance or networkInterface to attach an EIP?
Use instance for direct EC2 instance attachment, or networkInterface for attaching to a specific network interface. They’re mutually exclusive, so choose based on your use case.
IP Address Pools & Allocation
How do I allocate an EIP from my own IP address pool (BYOIP)?
Set publicIpv4Pool to your BYOIP pool identifier (e.g., ipv4pool-ec2-012345) and domain to vpc.
How do I allocate an EIP from an IPAM pool?
Set ipamPoolId to your IPAM pool ID (e.g., ipam-pool-07ccc86aa41bef7ce) and domain to vpc.
What's the difference between using address and publicIpv4Pool?
Both allocate from BYOIP pools, but address specifies an exact IP from the pool, while publicIpv4Pool lets AWS choose. If both are specified, address takes precedence.

Using a different cloud?

Explore networking guides for other cloud providers: