Create AWS Elastic IP Addresses

The aws:ec2/eip:Eip resource, part of the Pulumi AWS provider, allocates Elastic IP addresses and manages their association 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 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 an EC2 instance by ID. The domain property must be set to “vpc” for VPC-based Elastic IPs. The IP address remains associated even when the instance stops, allowing you to maintain the same public endpoint.

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 property targets a specific network interface rather than an instance. The associateWithPrivateIp property maps each Elastic IP to one of the interface’s private IPs. This allows a single 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 specifies a BYOIP pool ID. AWS allocates the Elastic IP from your organization’s address range. This maintains IP address continuity when migrating workloads to AWS.

Allocate an IP from an IPAM-managed pool

AWS IPAM (IP Address Manager) provides centralized IP address management across accounts and regions. Elastic IPs can be allocated from IPAM pools for consistent address governance.

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 enforces allocation policies and tracks IP usage 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 IP allocation and association 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 resource 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 when associating an EIP with a NAT Gateway or Load Balancer?
Don’t use networkInterface to associate EIPs with aws.lb.LoadBalancer or aws.ec2.NatGateway. Instead, use the allocationId property available in those resources to let AWS manage the association.
Can I specify both instance and networkInterface when creating 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 is my EIP association failing during creation?
EIPs may require an Internet Gateway to exist before association. Use dependsOn to create an explicit dependency on the IGW resource.
Association & Attachment
How do I associate an EIP with a specific private IP address on my instance?
Use associateWithPrivateIp to specify which primary or secondary private IP address to associate with. If not specified, the EIP associates with the primary private IP.
Can I attach multiple EIPs to the same network interface?
Yes. Assign different private IPs to the network interface, then create separate EIPs with associateWithPrivateIp pointing to each private IP.
IP Address Pools & Allocation
What's the difference between publicIpv4Pool and address?
Both allocate from BYOIP pools, but if you specify both, only address is used. Use publicIpv4Pool to allocate any IP from a pool, or address to request a specific IP.
How do I allocate an EIP from my own IP address pool (BYOIP)?
Set publicIpv4Pool to your BYOIP pool identifier, or use address to specify an exact IP from the pool. Both options require VPC EIPs (domain: "vpc").
How do I allocate an EIP from an IPAM pool?
Set ipamPoolId to the ID of an IPAM pool that has an Amazon-provided or BYOIP public IPv4 CIDR provisioned to it.
VPC & Configuration
Can I apply tags to my Elastic IP?
Yes, but only for VPC EIPs. Use the tags property to assign tags. Tags in provider defaultTags will be merged with resource-level tags.

Using a different cloud?

Explore networking guides for other cloud providers: