Your EC2 instance is assigned a fixed public IP from a list of Elastic IPs. But Amazon charges a considerable amount of money for the Elastic IP. Is there a way to automatically update the IP address of a DNS record defined in Amazon Route53 from the EC2 instance? Yes, there is, and it’s not hard. You can write a “bootstrap” script that is executed when the instance is started. The script will update the public DNS record according to the public IP of the instance.
1. Allow EC2 changing Route53 records
Detailed instructions for creating an IAM role
Log into your AWS management console.
Proceed to AIM (“Identity and Access Management”). Click on Roles. Click on Create role.
Select AWS service as the trusted entity type.
Select EC2 for the Use Case, then select EC2 (“Allows EC2 instances to call AWS services on your behalf”)
In the Permission policies, select AmazonRoute53FullAccess.
Click on Next: Tags (optional step, you can add tags to organize and manage your role).
Click on Next: Review.
Name your role. Choose a name that makes sense for its purpose, like EC2Route53UpdateRole.
(Optional) Add a description that explains the role’s purpose, like “Allows EC2 instances to update Route 53 DNS records.”
Review your choices and click on Create role.
Finalize and use the Role
After creating the role, you need to attach it to your EC2 instance:
- Go back to the EC2 dashboard.
- Select your instance.
- Choose Actions, navigate to Security, and select Modify IAM role.
- Choose the IAM role you created (EC2Route53UpdateRole) from the drop-down menu and save your changes.
By assigning this role to your EC2 instance, you have given it permission to make changes to the DNS records of Route53. This is important so that the bootstrap script works as intended and your instance automatically updates the associated DNS entry on restart.
2. Create a bootstrap script
Place the following script in your EC2 instance:
#!/bin/bash
# =====================================================================================
# This script performs update of Route53 DNS record with current IP of an EC2 instance.
# Alex Radzishevsky, http://radzishevsky.info
# 2024-03-03
# =====================================================================================
#
# - Read and understand this script
# - Edit it according to your needs
# - Make it a bootstrap script: * in Amazon Linux, place it inside
# /var/lib/cloud/scripts/per-boot
# * in Ubuntu, create a systemd service file
# Get current public IP of the instance
IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
# A function to update a single "A" record within DNS,
# A domain name and the an ID of the hosting EC2 instance are conveyed via function
# arguments (see below).
# 1st argument: ID of the EC2 instance hosting the domain. Use this command in the
# EC2 instanc to list all zones using (requires AWS CLI):
# aws route53 list-hosted-zones
# Find the right record in the list related to the domain you need.
# 2nd argument: Your domain for which you'd like to change the IP
update_single_record() {
HOSTED_ZONE_ID=$1
RECORD_SET_NAME="$2." # domain name must end with a dot
TTL=60
# Form JSON structure to update DNS record
JSON_STR="{\"Changes\":[{\"Action\":\"UPSERT\",\"ResourceRecordSet\":{\"Name\":\"$RECORD_SET_NAME\",\"Type\":\"A\",\"TTL\":$TTL,\"ResourceRecords\":[{\"Value\":\"$IP\"}]}}]}"
# Update the Route53 record
aws route53 change-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --change-batch "$JSON_STR"
}
# updating multiple domain records one after another
update_single_record "Z29472984792374983FF" "mydomain.com"
update_single_record "Z29472984792374983FF" "another.mydomain.com"
Save it as route53-update.sh.
Now you have to make sure that the script is executed every time the instance is (re)started.
Make the script executable with chmod.
For Amazon Linux, just place the script in: /var/lib/cloud/scripts/per-boot
For Ubuntu Linux, create a service file and use systemd.