In standalone configurations prior to introducing an Application Load Balancer (ALB) to handle high-volume application traffic, or in AWS infrastructure setups aimed at minimizing initial build costs, manual certificate renewals and ambiguous network designs directly cause service outages. Particularly in configurations where a web server and a database coexist on a single EC2 instance, strict implementation is required for security group definitions conforming to the principle of least privilege, an automated SSL/TLS certificate renewal pipeline via Certbot, and a periodic backup mechanism.
This document systematically organizes the concrete procedures ranging from network perimeter design in AWS, EC2 instance initialization, automated certificate renewal using Certbot, to automated DB dump transfers to an S3 bucket, alongside technical troubleshooting for issues that may arise in production operations.
1. Network Perimeter and Security Group Configuration
Proper segregation of Virtual Private Clouds (VPCs) and subnets forms the foundation of cloud infrastructure security. This configuration applies a 10.0.0.0/16 CIDR block, clearly separating the boundary between public and private subnets.
🛠️ Security Group (Stateful) Configuration Requirements
- Web Server Security Group (
sg-web): - HTTP (Port 80): Source
0.0.0.0/0 - HTTPS (Port 443): Source
0.0.0.0/0 - SSH (Port 22): Source
<admin ip="">/32(Fully open to0.0.0.0/0is strictly prohibited) - Database Security Group (
sg-db): - MySQL (Port 3306) or PostgreSQL (Port 5432): Associate with the security group ID of
sg-webrather than specifying source IP addresses directly
2. EC2 Instance Provisioning and Initialization
After launching an Ubuntu LTS-based EC2 instance, modify the permissions of the key pair for remote access, optimize the system time zone, and create a swap space to avoid OOM panics caused by memory exhaustion.
chmod 400 my-key.pem
ssh -i my-key.pem ubuntu@<ec2_public_ip>
# Set the timezone
sudo timedatectl set-timezone Asia/Tokyo
# Create swap space (2GB)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
3. SSL/TLS Certificate Issuance and Automated Renewal via Certbot
Because AWS Certificate Manager (ACM) requires integration with an ALB, a single-EC2 configuration applies Let’s Encrypt (Certbot) to terminate the SSL/TLS handshake directly on Nginx.
💡 Certbot Setup Procedure
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
# Certificate issuance and automatic Nginx configuration
sudo certbot --nginx -d example.com -d www.example.com
The validity period of a Let’s Encrypt certificate is 90 days. When the Certbot package is installed, a systemd timer (certbot.timer) is automatically registered, executing renewal checks twice daily. To perform manual operational verification, execute the following dry-run command.
sudo certbot renew --dry-run
4. Automation of Database Backups and S3 Synchronization
To mitigate the risk of data loss resulting from a Single Point of Failure (SPOF), construct a backup script that automatically transfers DB dumps generated inside the EC2 instance to an S3 bucket via the AWS CLI.
#!/bin/bash
# /usr/local/bin/db-backup.sh
SET_DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/tmp/db_backups"
FILE_NAME="db_backup_${SET_DATE}.sql.gz"
S3_BUCKET="s3://my-db-backup-bucket-prod"
mkdir -p ${BACKUP_DIR}
# Generate database dump
mysqldump -u root -p'DB_PASSWORD_HERE' --all-databases | gzip > ${BACKUP_DIR}/${FILE_NAME}
# Transfer to S3
aws s3 cp ${BACKUP_DIR}/${FILE_NAME} ${S3_BUCKET}/${FILE_NAME}
# Delete local temporary file
rm -f ${BACKUP_DIR}/${FILE_NAME}
Grant execution permissions to the created script and register it in crontab for scheduled execution.
0 3 * * * /usr/local/bin/db-backup.sh > /dev/null 2>&1
Configure a lifecycle rule on the S3 bucket to automatically delete objects 30 days after creation, thereby optimizing storage costs.
Troubleshooting
⚠️ 1. Certbot Renewal Challenge Failure (HTTP-01 Challenge Failure)
- Symptom:
Timeout during connect (HTTP)or404 Not Founderrors are returned when runningcertbot renew. - Cause: Inbound traffic on Port 80 is not open in the security group, or routing configuration for
.well-known/acme-challenge/in Nginx is incorrect. - Resolution: Verify that Port 80 is open in the security group inbound rules. Re-verify static file path references in the Nginx configuration file (
/etc/nginx/sites-available/default) and restore the configuration for thecertbot --nginxplugin.
⚠️ 2. AWS CLI Transfer Failure via cron
- Symptom: Files upload successfully to S3 during manual script execution, but uploads are skipped during automated execution by cron.
- Cause: The environment variable
PATHand the path toAWS_CONFIG_FILEare not properly resolved within the cron execution environment. - Resolution: Use full-path notation such as
/usr/local/bin/awswithin the script, or explicitly declareexport PATH=$PATH:/usr/local/binandexport AWS_SHARED_CREDENTIALS_FILE=/home/ubuntu/.aws/credentialsat the beginning of the script.
⚠️ 3. OOM Crash During Package Updates
- Symptom: The console hangs during the execution of
apt update && apt upgrade. - Cause: Physical memory is exhausted on small instances such as t3.micro, triggering the Linux kernel’s OOM Killer.
- Resolution: Prior to executing updates, use the
swapon --showcommand to verify that swap space is properly allocated.
Verification Protocols
After completing the setup of each component, verify the operational status of services and automated renewal timers using the following verification commands.
$ systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
Active: active (waiting) since Sun 2026-10-25 09:00:12 KST; 6 days ago
Trigger: Sat 2026-10-31 18:42:11 KST; 4h 12min left
Triggers: ● certbot.service
$ ss -tulpn | grep -E ':(80|443)'
tcp LISTEN 0 512 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
tcp LISTEN 0 512 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1234,fd=7))
$ swapon --show
NAME TYPE BASE_SIZE USED PRIO
/swapfile file 2G 128M -2
$ curl -I https://example.com
HTTP/2 200
server: nginx/1.18.0 (Ubuntu)
date: Sat, 31 Oct 2026 14:30:00 GMT
content-type: text/html
strict-transport-security: max-age=31536000; includeSubDomains
Operational Notes
- OS Patch Management: Batch updates for all packages (
apt upgrade -y) carry the risk of breaking existing dependency libraries. Maintain an operational policy restricted to security patch applications (dnf update --securityorunattended-upgrades). - Certificate Expiration Monitoring: Even when the automated renewal timer operates properly, scenarios exist where renewal processing fails due to domain DNS configuration changes or external network restrictions. Integrating external monitoring (such as Prometheus Blackbox Exporter) that triggers an alert when certificate validity falls below 30 days is strongly recommended.</ec2_public_ip>