How to Assign a Public IP (Non-Elastic) to an Existing AWS EC2 Instance


2 views

When launching an EC2 instance in AWS, you have the option to enable Auto-assign Public IP during creation. This automatically assigns a public IPv4 address from AWS's pool to your instance. But what if you initially launched your instance without this option and now need to assign a public IP?

AWS doesn't provide a direct way to assign a standard public IP (non-Elastic) to an existing instance through the console or API. The public IPs from AWS's pool are only assignable during instance launch. Here's why this limitation exists:

  • Non-Elastic IPs are tied to the instance's lifecycle
  • They cannot be manually associated/disassociated like Elastic IPs
  • The assignment happens at the network interface level during provisioning

While you can't directly assign a public IP after launch, here are practical workarounds:

1. Create a New ENI with Public IP

You can create a new Elastic Network Interface (ENI) with public IP assignment enabled, then attach it to your running instance:


# Create new ENI with public IP enabled
aws ec2 create-network-interface \
    --subnet-id subnet-12345678 \
    --groups sg-12345678 \
    --associate-public-ip-address

# Attach to existing instance
aws ec2 attach-network-interface \
    --network-interface-id eni-12345678 \
    --instance-id i-12345678 \
    --device-index 1

2. Use Elastic IP Instead

While you specifically asked about non-Elastic IPs, Elastic IPs provide more flexibility:


# Allocate new Elastic IP
aws ec2 allocate-address --domain vpc

# Associate with instance
aws ec2 associate-address \
    --instance-id i-12345678 \
    --allocation-id eipalloc-12345678

3. Recreate the Instance

The most straightforward solution is to create a new instance with public IP enabled, then migrate your data:


# Create new instance with public IP
aws ec2 run-instances \
    --image-id ami-12345678 \
    --instance-type t2.micro \
    --subnet-id subnet-12345678 \
    --associate-public-ip-address
  • Public IPs from AWS's pool change when you stop/start instances
  • ENI approach may require routing changes in your instance
  • Always test in a non-production environment first

For more permanent solutions, consider:

  • Using a NAT Gateway for outbound internet access
  • Placing instances behind a Load Balancer
  • Implementing a bastion host architecture

Many developers face this scenario: you launched an EC2 instance without enabling "Auto-assign Public IP" and now need to attach a public IP address - not an Elastic IP, but the standard public IP from AWS's pool. While launching a new instance is one solution, here's how to do it on a running instance.

AWS provides two types of public IPs:

  • Auto-assigned Public IP: Temporary address from AWS pool (changes on stop/start)
  • Elastic IP: Persistent address you can attach/detach

The key is that public IP assignment is controlled at the subnet level. Here's how to update it:


# Using AWS CLI
aws ec2 modify-subnet-attribute \
    --subnet-id subnet-12345678 \
    --map-public-ip-on-launch

However, this only affects new instances. For existing instances:

Since AWS doesn't allow direct assignment of public IPs to running instances, you'll need to:

  1. Stop the instance (note: this may change other attributes)
  2. Modify the network interface:

# First, get the network interface ID
aws ec2 describe-instances --instance-id i-1234567890abcdef0

# Then modify the attribute
aws ec2 modify-network-interface-attribute \
    --network-interface-id eni-12345678 \
    --no-associate-public-ip-address

After stopping, you can:


# Start the instance with auto-assign enabled
aws ec2 start-instances --instance-id i-1234567890abcdef0

Another method is to create a new ENI with public IP assignment enabled:


# Create new ENI with public IP
aws ec2 create-network-interface \
    --subnet-id subnet-12345678 \
    --groups sg-12345678 \
    --associate-public-ip-address

# Attach to instance
aws ec2 attach-network-interface \
    --network-interface-id eni-12345678 \
    --instance-id i-1234567890abcdef0 \
    --device-index 1
  • Stopping instances may change underlying hardware
  • Public IPs are released when instance stops
  • Consider Elastic IP if you need persistence
  • Always test in non-production environments first