Every production EC2 instance needs proper user management and file permissions. Running everything as root is a security disaster waiting to happen. Setting up dedicated users for applications, configuring sudo access correctly, and applying proper file permissions are foundational security practices for any cloud server.
# Check who is logged in
whoami
id
w
# Create a new user
sudo adduser deploy # Interactive, creates home dir
sudo useradd -m -s /bin/bash webuser # Non-interactive
# Add user to sudo group (Ubuntu)
sudo usermod -aG sudo deploy
# Add user to docker group (to run docker without sudo)
sudo usermod -aG docker ubuntu
# View all users
cat /etc/passwd
getent passwd # All users including system users
# Switch to another user
sudo su - deploy # Switch with environment
sudo -u deploy bash # Run command as another user
# As the new user
sudo su - deploy
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Add the team member's public key
echo "ssh-ed25519 AAAA... teammate@company.com" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# Now the team member can connect:
# ssh deploy@your-server-ip
# (using their private key)
# Web server files
sudo chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# Application directory
sudo mkdir /opt/myapp
sudo chown ubuntu:ubuntu /opt/myapp
# Logs directory writable by app user
sudo mkdir /var/log/myapp
sudo chown deploy:deploy /var/log/myapp
# SSH private key -- MUST be 600
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh
# Scripts that need to be executed
chmod 755 /usr/local/bin/myapp-start.sh
# Edit sudoers safely (never edit /etc/sudoers directly!)
sudo visudo
# Common sudo configurations:
# Full sudo access:
ubuntu ALL=(ALL:ALL) ALL
# Passwordless sudo for ubuntu user:
ubuntu ALL=(ALL) NOPASSWD:ALL
# Specific commands only:
deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp
deploy ALL=(ALL) NOPASSWD: /usr/bin/docker
# Add to /etc/sudoers.d/ instead of main file
echo "deploy ALL=(ALL) NOPASSWD: /bin/systemctl" | sudo tee /etc/sudoers.d/deploy
Best practice: create your own user with sudo, add your SSH key, test you can log in, then disable ubuntu password auth. Never delete ubuntu user entirely on EC2 -- it is used for instance recovery. Disable password auth instead: passwd -l ubuntu
Create a user for them (adduser developer). Add their public key to ~/.ssh/authorized_keys in their home. Add them to sudo if needed. Never share your own private key -- each person gets their own key pair.
adduser is a friendly Debian/Ubuntu script that prompts for info and creates home directory automatically. useradd is the lower-level command requiring manual flags (-m for home dir, -s for shell). Both work; adduser is easier for interactive use.
Check /var/log/auth.log for sudo entries. grep "sudo" /var/log/auth.log. journalctl _COMM=sudo shows sudo audit logs. Enable auditd for more comprehensive auditing: sudo apt install auditd.
sudo userdel username removes the user. sudo userdel -r username removes user AND their home directory. Check for processes owned by user first: ps aux | grep username. Kill any running processes before deletion.
In Part 5, we install and configure Nginx web server on EC2 -- serving your first web application from the cloud.
# Create system user for an application (no login, no home)
sudo useradd --system --no-create-home --shell /usr/sbin/nologin appuser
# Create user for a web service
sudo useradd -r -s /bin/false -d /var/www/myapp www-appuser
sudo mkdir -p /var/www/myapp
sudo chown www-appuser:www-appuser /var/www/myapp
# List all users with login shells (real users)
grep -v "nologin\|false" /etc/passwd | cut -d: -f1
# Lock an account when employee leaves
sudo passwd -l former_employee # Lock
sudo usermod -L former_employee # Lock (alternative)
sudo usermod -e 1 former_employee # Expire immediately
# Check login history
last ubuntu # Show login history
lastb # Failed login attempts
who # Currently logged in users
# /etc/sudoers.d/devops-team
# NEVER edit /etc/sudoers directly -- use visudo or sudoers.d/
# Allow ubuntu user full sudo (standard EC2 setup)
ubuntu ALL=(ALL:ALL) NOPASSWD:ALL
# Allow deploy user to only restart specific services
deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp
deploy ALL=(ALL) NOPASSWD: /bin/systemctl status myapp
deploy ALL=(ALL) NOPASSWD: /usr/bin/docker ps
# Allow monitoring user to read logs
monitor ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/*
monitor ALL=(ALL) NOPASSWD: /bin/journalctl
# Verify sudoers file is valid before saving
sudo visudo -c # Check for syntax errors
AWS Systems Manager Session Manager is the modern, more secure alternative to SSH for EC2 access. It requires no open SSH port (22), no key pair management, and provides full audit logging of every command through CloudTrail.
# Install SSM agent (pre-installed on Amazon Linux and Ubuntu 20.04+)
sudo snap install amazon-ssm-agent --classic
sudo systemctl enable --now snap.amazon-ssm-agent.amazon-ssm-agent
# Attach IAM role with AmazonSSMManagedInstanceCore policy to EC2
# Connect from your machine (no SSH port needed):
aws ssm start-session --target i-1234567890abcdef
# Port forward through SSM (no SSH needed)
aws ssm start-session --target i-1234567890abcdef --document-name AWS-StartPortForwardingSession --parameters portNumber=5432,localPortNumber=5432