Title: How to Create a Private MySQL Database on AWS RDS and Connect From an EC2 Instance
Subtitle: I built a managed database that only one server can reach, then proved it by failing to connect from my own laptop. Here is every step.
Introduction
Imagine a company stores customer data in a database that accepts connections from anywhere in the world. Automated scanners find open databases within hours, and it is one of the most common ways data leaks happen.
This lab fixes that. I built a managed MySQL database on AWS RDS, placed it behind a security group that trusts only one application server, and then proved it was private by trying, and failing, to connect from my own laptop. This guide covers each step, the concepts behind it, and the errors to watch for.
The Architecture in Plain English
- The client VM is an Ubuntu server on EC2 that runs the application.
- RDS (Relational Database Service) is AWS’s managed database service. Managed means AWS runs the operating system, patching, backups, and hardware, while you only use the database.
- A security group is a firewall. The database’s group will allow port 3306 (MySQL) only from the client’s security group.
Step 1: Launch the Client VM
- In EC2, launch an instance and name it
db-client, Choose Ubuntu (22.04 or 24.04), and a free tier eligible t3.micro or t2.micro. - Choose an existing key pair, or create one and save the
.pemfile safely. - Keep the default VPC and allow SSH from My IP only. Never use
0.0.0.0/0. - Launch, then note the instance’s security group name.
Step 2: Create the Database
- In RDS, create a database, choose Full configuration, and select MySQL.
- Pick the Free tier template and Single DB instance.
- Set the identifier to
lab-db, the master username toadmin, and a strong password. Never commit it to Git or show it in screenshots. - Choose db.t3.micro, 20 GB of storage, and untick storage autoscaling so the disk cannot grow and surprise you.
- Under Connectivity, choose Don’t connect to an EC2 compute resource, which lets you create the firewall rules by hand and understand them. Use the default VPC, set Public access to No, and create a new security group named
rds-lab-sg. - Under Additional configuration, set the initial database name to
labdband turn off automated backups and Enhanced Monitoring for the lab. - Click Create database. It takes 5 to 10 minutes.
Step 3: Lock Down Access With Least Privilege
While the database builds, open EC2, Security Groups, rds-lab-sg, and edit inbound rules. Remove any wide-open rule and add one: type MySQL/Aurora (port 3306), source the client VM’s security group, selected from the list, not typed as an IP. Now only machines wearing the client’s badge can reach the database, and the rule survives IP address changes.
Step 4: Connect and Run SQL
- When the status shows Available, copy the database Endpoint from its details page.
- SSH into the client from your own terminal. The easiest way to get the exact command is the instance’s Connect, SSH client tab.
- Install the MySQL client and connect:
sudo apt update && sudo apt install mysql-client -y
mysql -h YOUR_ENDPOINT -u admin -p- Enter your password. You should see the
mysql>prompt. Then run:
SHOW DATABASES;
USE labdb;CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
course VARCHAR(50)
);INSERT INTO students (name, course)
VALUES ('Your Name', 'Engineering');SELECT * FROM students;
Step 5: Prove It Is Private
From your own laptop, try the same connection (or test the port with Test-NetConnection YOUR_ENDPOINT -Port 3306 in Windows PowerShell). It should hang and time out, because the database has no public access and its firewall trusts only the client VM. A timeout here means the lock works.
Errors to Watch For
Connection timed out from the client. The security group source is wrong, or the two resources are in different VPCs. Check the rds-lab-sg rule first.
Get CloudSecGenuis’s stories in your inbox
Join Medium for free to get updates from this writer.
Access denied for user. The username or password is wrong. The username isadmin, and the password is the one you set at creation.
mysql: command not found. The client package did not install. Run the install command again.
Cannot log in to the client by SSH. Check that you are using the right .pem file (the key pair name is on the instance’s Details tab) and the client’s public IP. Also, your own IP may have changed since you set the SSH rule.
The security group does not show in the source list. Both groups must be in the same VPC.
A syntax error when pasting SQL. Copying from a PDF can turn straight quotes into curly ones. Retype the quotes.
The free tier option is missing. Pick the smallest db.t3.micro and delete it as soon as you finish.
Clean Up (This Part Costs Money If You Skip It)
RDS bills while it runs, even when idle. Delete lab-db first, and untick the final snapshot and retained backups options. Then terminate the db-client instance, deleterds-lab-sg, and check that both consoles are empty.
Key Takeaways
- Keep databases off the public internet
- Let one security group reference another, instead of hard-coding IP addresses
- A timeout from the outside is proof the lock works
- Managed services remove work you would otherwise do yourself
- Always clean up billable resources








