AWS EC2 Security Best Practices Hardening Your Node.js Server
Learn essential security best practices for AWS EC2 instances running Node.js applications from SSH key management and security groups to firewall configuration and regular updates.
AWS EC2 Security Best Practices
Securing your EC2 instance is critical when running a production Node.js application. This guide covers the essential security practices.
1. SSH Security
Use key-based authentication only:
# Ensure password authentication is disabled sudo nano /etc/ssh/sshd_config # Set: PasswordAuthentication no # Set: PermitRootLogin no sudo systemctl restart sshd
Restrict SSH to your IP: In the EC2 security group, set the SSH rule source to your specific IP address, not 0.0.0.0/0.
Use a non-root user:
Always connect as the ubuntu user and use sudo for privileged commands. Never run Node.js as root.
2. Security Group Rules
Follow the principle of least privilege:
| Port | Source | Purpose |
|---|---|---|
| 22 | Your IP only | SSH |
| 80 | 0.0.0.0/0 | HTTP (via Nginx) |
| 443 | 0.0.0./0 | HTTPS (via Nginx) |
| 3000 | Not open | Node.js (only via Nginx proxy) |
Never expose the Node.js port (3000) directly to the internet. All traffic should go through Nginx.
3. UFW Firewall
Enable Ubuntu's Uncomplicated Firewall as a second layer:
sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp # SSH sudo ufw allow 80/tcp # HTTP sudo ufw allow 443/tcp # HTTPS sudo ufw enable sudo ufw status verbose
4. Keep Software Updated
# Update all packages sudo apt update && sudo apt upgrade -y # Set up automatic security updates sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades
5. Disable Unused Services
# List running services sudo systemctl list-unit-files --type=service --state=running # Disable any service you don't need sudo systemctl disable <service-name> sudo systemctl stop <service-name>
6. Secure Environment Variables
- Never commit .env to Git (ensure .gitignore has .env)
- Use AWS Secrets Manager for production secrets
- Restrict file permissions:
chmod 600 .env - Don't echo secrets in logs
7. Fail2Ban for SSH Protection
sudo apt install -y fail2ban sudo systemctl enable fail2ban sudo systemctl start fail2ban
Fail2ban automatically bans IPs that show malicious signs (too many failed SSH login attempts).
8. Regular Security Audits
# Check for failed SSH logins sudo cat /var/log/auth.log | grep "Failed password" # Check Nginx access logs for suspicious activity sudo cat /var/log/nginx/access.log | grep -E "40[0-9]|50[0-9]" # Check PM2 logs for errors pm2 logs devtinder-api --lines 100
9. Enable Nginx Security Headers
server { # ... existing config ... add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; add_header X-XSS-Protection "1; mode=block"; add_header Referrer-Policy "strict-origin-when-cross-origin"; add_header Content-Security-Policy "default-src 'self'"; }
10. Use HTTPS Only
After setting up SSL with Let's Encrypt:
- Redirect all HTTP to HTTPS
- Set
secure: trueon cookies - Use HSTS header:
add_header Strict-Transport-Security "max-age=31536000" always;
11. Regular Backups
# Create EBS snapshots in AWS Console # Or use AWS CLI aws ec2 create-snapshot --volume-id vol-xxxxx --description "Daily backup"
Set up automated EBS snapshots in AWS Backup for disaster recovery.
12. Monitor Your Instance
- CloudWatch CPU, network, disk metrics
- PM2 monitoring
pm2 monitfor real-time app stats - Nginx logs Monitor access and error logs
- Uptime monitoring Use UptimeRobot or Pingdom for external monitoring
The Takeaway
EC2 security involves: SSH key-only auth restricted to your IP, security groups with least privilege, UFW firewall, regular updates, securing .env files, Fail2ban for SSH protection, Nginx security headers, HTTPS-only with HSTS, regular backups, and monitoring. Security is an ongoing process audit regularly and stay updated.
Use key-based authentication only (disable PasswordAuthentication in sshd_config), restrict SSH to your IP in the security group, disable root login (PermitRootLogin no), and use the ubuntu user with sudo for privileged commands. Never run Node.js as root.
No. Never expose the Node.js port (3000) directly to the internet. All traffic should go through Nginx on port 80/443, which proxies to localhost:3000. Only ports 22 (SSH from your IP), 80, and 443 should be open.
X-Frame-Options (SAMEORIGIN, prevents clickjacking), X-Content-Type-Options (nosniff, prevents MIME sniffing), X-XSS-Protection, Referrer-Policy, Content-Security-Policy, and Strict-Transport-Security (HSTS) for HTTPS-only.
Install unattended-upgrades (sudo apt install unattended-upgrades) and configure it with sudo dpkg-reconfigure -plow unattended-upgrades. This automatically installs security updates as they become available.
Fail2ban is a tool that monitors log files (like /var/log/auth.log) and automatically bans IPs that show malicious signs, such as too many failed SSH login attempts. Install it with sudo apt install fail2ban to protect against brute-force attacks.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

