Linux Server Essentials: What Every Developer Should Know (2026)
You don't need to be a sysadmin. But knowing these commands and concepts will save you hours when things go wrong.
Connecting to a Server
# SSH basics
ssh user@server-ip # Password auth
ssh -i ~/.ssh/mykey.pem user@server # Key-based auth
ssh -p 2222 user@server # Custom port
# SSH config (add to ~/.ssh/config)
Host myserver
HostName 43.135.172.134
User root
Port 22
IdentityFile ~/.ssh/mykey.pem
ServerAliveInterval 60 # Keep connection alive
# Now just: ssh myserver
# Copy files
scp file.txt user@server:/path/ # Upload
scp user@server:/path/file.txt ./ # Download
scp -r folder/ user@server:/path/ # Upload directory
rsync -avz ./local/ user@server:/remote/ # Sync (faster for updates)
Navigation & Files
# Navigation
pwd # Where am I?
cd /path/to/dir # Go to directory
cd ~ # Home directory
cd - # Previous directory
# Listing
ls # List files
ls -la # List ALL with details (permissions, size, owner)
ls -lh # Human-readable sizes (KB, MB, GB)
ls -lt # Sort by modification time (newest first)
ls -R # Recursive listing
# File operations
touch newfile.txt # Create empty file
mkdir newdir # Create directory
mkdir -p a/b/c # Create nested directories
cp file.txt backup/ # Copy file
cp -r folder backup/ # Copy directory
mv old.txt new.txt # Move/rename
rm file.txt # Delete file
rm -r folder/ # Delete directory (recursive!)
# NEVER: rm -rf / # Destroys everything!
# File info
file mystery-file # Detect file type
wc -l file.txt # Count lines
du -sh directory/ # Directory size (human-readable)
df -h # Disk space (human-readable)
stat file.txt # Detailed file metadata
# Finding files
find / -name "*.log" 2>/dev/null # Find by name
find . -type f -mtime -1 # Files modified in last 24h
find . -size +100M # Files larger than 100MB
find . -name "node_modules" -type d -prune -exec rm -rf {} + # Delete all node_modules!
grep -r "password" --include="*.js" . # Search inside files
# Quick tip: locate is faster but uses a database
sudo updatedb # Update the database first
locate nginx.conf # Instant lookup
Viewing & Editing Files
# Quick viewing
cat file.txt # Print entire file
head -20 file.txt # First 20 lines
tail -20 file.txt # Last 20 lines
tail -f /var/log/app.log # Follow log in real-time!
less file.txt # Pager (scroll, search, quit with q)
# Searching inside files
grep "error" log.txt # Find lines containing "error"
grep -i "error" log.txt # Case insensitive
grep -n "error" log.txt # With line numbers
grep -A 5 "error" log.txt # 5 lines after match
grep -B 5 "error" log.txt # 5 lines before match
grep -r "TODO" src/ # Recursive search
grep -r --include="*.ts" "import" . # Search only TypeScript files
# Inline editing with sed
sed -i 's/old/new/g' config.txt # Replace all occurrences
sed -i 's/old/new/2' config.txt # Replace 2nd occurrence only
sed -i '3d' config.txt # Delete line 3
# AWK for column processing
awk '{print $1, $3}' data.csv # Print columns 1 and 3
awk -F',' '{sum += $2} END {print sum}' data.csv # Sum column 2
# Editor choices:
# nano - Simple, always available
# vim - Powerful, worth learning basics
# For remote editing: use your local IDE with SFTP/SSH
Permissions & Users
# Permission model: owner | group | others
# rwxr-xr-- = owner(rwx) group(r-x) others(r--)
# r = read (4), w = write (2), x = execute (1)
# View permissions
ls -la
# drwxr-xr-x 2 root root 4096 May 29 14:00 dir/
# -rw-r--r-- 1 root root 123 May 29 14:00 file.txt
# Change permissions
chmod 755 script.sh # rwxr-xr-x (executable by all)
chmod 644 file.txt # rw-r--r-- (readable by all, writable by owner)
chmod +x script.sh # Add execute permission
chmod -w file.txt # Remove write permission
# Change ownership
chown user:group file.txt
chown -R www-data:www-data /var/www # Recursive
# Sudo (run as root)
sudo command # Run as root
sudo -u www-data whoami # Run as specific user
sudo visudo # Safely edit sudoers file
Processes & System Monitoring
# Process management
ps aux # All running processes
ps aux | grep node # Find Node.js processes
top # Interactive process viewer
htop # Better top (if installed)
# System resources
free -h # Memory usage
uptime # Uptime and load average
cat /proc/cpuinfo # CPU info
nproc # Number of CPU cores
lscpu # Detailed CPU info
# Disk
df -h # Disk space by filesystem
du -sh /var/log/* # Size of log files
du -sh * | sort -rh | head -10 # Top 10 largest items
# Network
ip addr # IP addresses
ss -tlnp # Listening ports (replaces netstat)
curl -I https://example.com # HTTP headers
wget -qO- https://example.com # Fetch URL content
# Killing processes
kill 12345 # Graceful kill (SIGTERM)
kill -9 12345 # Force kill (SIGKILL)
killall node # Kill all processes named "node"
pkill -f "node server" # Kill by command pattern
# Background processes
nohup node server.js & # Run in background, survives logout
disown # Detach from current shell
# Or use: npm run start &>> output.log &
Package Management
# apt (Debian/Ubuntu)
sudo apt update # Update package lists
sudo apt upgrade # Upgrade all packages
sudo apt install nginx # Install package
sudo apt remove package # Remove package
sudo apt autoremove # Remove unused dependencies
apt search keyword # Search packages
apt show package # Package info
# Snap (alternative)
snap install package
snap list # Installed snaps
# Node.js version management
curl -fsSL https://fnm.vercel.app/install | bash
fnm install 20 # Install Node 20
fnm use 20 # Use Node 20
fnm default 20 # Set default
# npm global packages
npm list -g --depth=0 # List global packages
npm install -g pnpm # Install globally
Service Management (systemd)
# Service commands (replace "nginx" with your service name)
sudo systemctl start nginx # Start service
sudo systemctl stop nginx # Stop service
sudo systemctl restart nginx # Restart
sudo systemctl reload nginx # Reload config (no downtime)
sudo systemctl status nginx # Check status
sudo systemctl enable nginx # Start on boot
sudo systemctl disable nginx # Don't start on boot
# Journal logs
sudo journalctl -u nginx # Service-specific logs
sudo journalctl -u nginx -f # Follow logs
sudo journalctl --since "1 hour ago" # Recent logs
sudo journalctl --since today # Today's logs
# Creating a custom service
# /etc/systemd/system/myapp.service
# [Unit]
# Description=My Node.js App
# After=network.target
#
# [Service]
# Type=simple
# User=root
# WorkingDirectory=/root/myapp
# ExecStart=/root/.nvm/versions/node/v20/bin/node server.js
# Restart=always
# RestartSec=5
# Environment=NODE_ENV=production
#
# [Install]
# WantedBy=multi-user.target
#
# Then: sudo systemctl enable myapp && sudo systemctl start myapp
Firewall & Security
# UFW (Ubuntu Firewall)
sudo ufw status # Check firewall status
sudo ufw enable # Enable firewall
sudo ufw allow 22/tcp # Allow SSH
sudo ufw allow 80/tcp # Allow HTTP
sudo ufw allow 443/tcp # Allow HTTPS
sudo ufw allow 3000/tcp # Allow custom port
sudo ufw delete allow 3000/tcp # Remove rule
sudo ufw deny from 1.2.3.4 # Block specific IP
# Fail2ban (auto-ban attackers)
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status # Check banned IPs
sudo fail2ban-client status sshd # SSH-specific bans
# SSH hardening
# Edit /etc/ssh/sshd_config:
# Port 22 # Or change to non-standard
# PermitRootLogin no # Disable root login
# PasswordAuthentication no # Key-only auth
# MaxAuthTries 3 # Limit login attempts
# AllowUsers deploy # Only specific users
Cron & Scheduled Tasks
# Edit crontab
crontab -e # Edit your crontab
crontab -l # List scheduled tasks
# Cron format: MIN HOUR DOM MON DOW COMMAND
# * * * * * = every minute
# */5 * * * * = every 5 minutes
# 0 * * * * = every hour
# 0 0 * * * = midnight daily
# 0 9 * * 1 = Monday 9 AM
# Examples:
*/5 * * * * /root/scripts/health-check.sh >> /var/log/health.log 2>&1
0 3 * * * /root/scripts/backup.sh # Daily at 3 AM
0 */6 * * * /root/scripts/sync.sh # Every 6 hours
# System-wide crontab: /etc/crontab
# User-specific: crontab -e
# Cron logs: grep CRON /var/log/syslog
Quick Troubleshooting
# Port already in use?
ss -tlnp | grep :3000 # What's on port 3000?
lsof -i :3000 # Same thing
# Can't connect to a service?
curl -v http://localhost:3000 # Verbose connection test
nc -zv localhost 3000 # Port check
# Out of disk space?
df -h # Check filesystems
du -sh /var/log # Log file sizes
journalctl --disk-usage # Journal size
sudo journalctl --vacuum-size=100M # Trim journal to 100MB
sudo apt autoremove # Remove unused packages
# High memory?
free -h # Overview
ps aux --sort=-%mem | head -10 # Top memory consumers
pmap 12345 # Process memory map
# High CPU?
ps aux --sort=-%cpu | head -10 # Top CPU consumers
top -o %CPU # Interactive view
# Can't bind to port 80/443?
sudo netstat -tlnp | grep ':80' # Check what's using it
sudo fuser -k 80/tcp # Kill process on port 80
# SSH connection issues?
ssh -vvv user@server # Debug connection
systemctl status sshd # Check SSH service
tail -f /var/log/auth.log # SSH auth logs
# Node.js won't start?
node --version # Check Node is installed
which node # Check PATH
npm ls --depth=0 # Check dependencies
NODE_DEBUG=request node app.js # Debug mode
What Linux command took you longest to learn? What's your must-have server tool?
Follow @armorbreak for more practical developer guides.
Top comments (0)