← Course Index

Linux & SSH Essentials

~25 min · Foundations · Glossary →

Ref
Primary Source
DigitalOcean — Initial Server Setup with Ubuntu

The canonical guide to setting up a Linux server securely for the first time. Follow this whenever you spin up a new EC2 instance. DigitalOcean →

Why Linux?

Nearly every production server on the planet runs Linux. AWS EC2 instances are Linux. Docker containers are Linux. Nginx runs on Linux. You don't need to become a Linux expert — but you need to be comfortable enough to connect to a server, inspect what's running, and not feel lost when things break.

💡 JS developer translation

Think of the Linux terminal like Node.js's REPL — a direct interface to the system. Commands are functions. Flags are arguments. Pipes (|) chain them like .then().

SSH — Connecting to a Remote Server

SSH (Secure Shell) lets you run commands on a remote machine as if you were sitting at its keyboard. Every AWS EC2 connection is SSH.

# Basic SSH connection
ssh ubuntu@your-server-ip

# With a specific key file (required for EC2)
ssh -i ~/.ssh/my-key.pem ubuntu@your-server-ip

# Copy files TO server
scp -i ~/.ssh/my-key.pem ./myfile.txt ubuntu@your-server-ip:~/

# Copy files FROM server
scp -i ~/.ssh/my-key.pem ubuntu@your-server-ip:~/logfile.txt ./
⚠️ Key file permissions

AWS will refuse to connect if your .pem file is readable by others. Fix it: chmod 400 ~/.ssh/my-key.pem

SSH Key Pairs — How They Work

SSH uses asymmetric cryptography: you have a private key (never share this) and a public key (put this on the server). AWS generates the key pair for you when you create an EC2 instance. Generate your own for other servers:

# Generate an Ed25519 key pair (modern, secure)
ssh-keygen -t ed25519 -C "your@email.com"

# View your public key (put this on servers)
cat ~/.ssh/id_ed25519.pub

Essential Commands

You need exactly these. Learn them, forget the rest for now.

Navigation & Files

pwd               # Where am I? (print working directory)
ls -la            # List files (long format, show hidden)
cd /var/log       # Change directory
cd ~              # Go home
mkdir -p app/logs # Create directory (and parents)
rm -rf ./dist     # Delete recursively — careful!
cp file.txt backup.txt
mv old.txt new.txt
cat /etc/nginx/nginx.conf    # Print file contents
less /var/log/nginx/error.log  # Read large files (q to quit)
tail -f /var/log/app.log     # Watch live log output (Ctrl+C to stop)

Processes

ps aux            # All running processes
ps aux | grep node  # Find your Node process
kill -9 12345     # Force kill process by PID
htop              # Interactive process viewer (install: apt install htop)

System Services (systemd)

On Ubuntu, apps run as systemd services. This is how Nginx, Docker, and your app start on boot and restart on crash.

sudo systemctl status nginx     # Is it running?
sudo systemctl start nginx      # Start it
sudo systemctl stop nginx       # Stop it
sudo systemctl restart nginx    # Restart
sudo systemctl reload nginx     # Reload config (no downtime)
sudo systemctl enable nginx     # Start on boot
sudo journalctl -u nginx -f     # Live logs for a service

Networking

curl http://localhost:3000/health   # Test if your app responds
curl -I https://your-domain.com     # Check response headers
netstat -tlnp                       # What's listening on which port?
ss -tlnp                            # Modern alternative to netstat

Package Management (apt)

sudo apt update              # Update package index
sudo apt upgrade -y          # Upgrade installed packages
sudo apt install -y nginx    # Install a package
sudo apt remove nginx        # Remove a package
which nginx                  # Where is this binary?
nginx -v                     # Check version

File Permissions

chmod 644 file.txt    # Owner: read+write. Others: read only
chmod 755 script.sh   # Owner: full. Others: read+execute
chmod 400 key.pem     # Owner: read only (required for SSH keys)
chown ubuntu:ubuntu file.txt  # Change owner

Environment Variables & Config Files

Never hardcode secrets. On Linux, environment variables are set per-session or in system files:

# Temporary (current session only)
export DATABASE_URL="postgres://..."

# Permanent for a user (add to ~/.bashrc or ~/.profile)
echo 'export NODE_ENV=production' >> ~/.bashrc
source ~/.bashrc

# For a systemd service (edit the service file)
sudo systemctl edit myapp
# Add under [Service]:
# Environment="NODE_ENV=production"
# EnvironmentFile=/etc/myapp/env
💡 Production best practice

In production, use AWS Secrets Manager or a .env file that is never committed to git. We cover this in Lesson 16 (RDS & Secrets Manager).

Your First Server Setup Checklist

Every new server gets this treatment:

  1. Update packages: sudo apt update && sudo apt upgrade -y
  2. Create a non-root user: adduser deploy, add to sudo: usermod -aG sudo deploy
  3. Copy SSH key to new user: rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy
  4. Disable root SSH login: edit /etc/ssh/sshd_configPermitRootLogin no
  5. Set up a firewall (UFW): sudo ufw allow OpenSSH && sudo ufw allow 'Nginx Full' && sudo ufw enable
  6. Install your tools: sudo apt install -y nginx git curl

Check Your Understanding

1. You SSH into a new EC2 instance and get "Permission denied (publickey)". What's the most likely cause?
2. You want to watch your app's logs in real time as requests come in. Which command does this?
3. You deployed a new Nginx config. You want to apply the changes without any downtime. Which command?
4. You need Nginx to automatically start when the server reboots after a crash. Which command ensures this?