Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Welcome

This is a collection of personal notes by Ilham Aulia Majid.

🧠 VPS Setup Notes

πŸ–₯️ Base Info

  • User: <your_username> (created by provider)
  • Purpose: Base secure setup for future use
  • Access: via SSH key (no password login)

1. πŸ”‘ SSH Setup

Goal: Secure and simplify login.

Steps:

ssh <your_username>@<your_vps_ip>

Local key generated:

ssh-keygen -t ed25519

Key copied to VPS:

ssh-copy-id <your_username>@<your_vps_ip>

SSH config (~/.ssh/config):

Host *
    AddKeysToAgent yes
    IdentitiesOnly yes
    ServerAliveInterval 60
    IdentityFile ~/.ssh/id_ed25519
    # UseKeychain yes  # macOS only

Host github.com
    HostName github.com
    User git

Host my-vps
    HostName <your_vps_ip>
    User <your_username>
    Port 22

Result βœ…

  • Login via: ssh my-vps
  • Root login disabled
  • Key-only authentication

2. πŸ”’ Firewall (UFW)

Installed and allowed SSH only:

sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status

Result βœ…

  • Only port 22 open
  • Ping (ICMP) blocked by default
  • To allow ping:
    sudo ufw allow proto icmp
    

3. 🌍 Timezone Setup

sudo timedatectl set-timezone Asia/Jakarta
timedatectl

Result βœ…

  • Server clock set to local time (WIB)

4. πŸ” Auto Security Updates

Installed and configured:

sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

Config file: /etc/apt/apt.conf.d/50unattended-upgrades

Optional auto-reboot setting:

Unattended-Upgrade::Automatic-Reboot "true";

Logs:

/var/log/unattended-upgrades/unattended-upgrades.log

Result βœ…

  • Daily automatic security updates
  • Kernel and package updates applied quietly

5. πŸ›‘οΈ Fail2Ban

Protects against brute-force attacks by banning IPs with failed login attempts.

Install and enable:

sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check status:

sudo fail2ban-client status
sudo fail2ban-client status sshd

Unban an IP (if needed):

sudo fail2ban-client set sshd unbanip <ip_address>

Optional: Customize settings (only if you want to change defaults)

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo vim /etc/fail2ban/jail.local

Example custom settings:

  • maxretry = 5 – Ban after 5 failed attempts (default)
  • bantime = 600 – Ban duration in seconds (default: 10 min)
  • findtime = 600 – Time window for counting failures (default: 10 min)

Result βœ…

  • SSH jail enabled by default
  • Automatic IP banning for failed logins

🌐 NGINX Setup Notes

Prerequisites

  • Base VPS security setup completed (SSH, UFW, Fail2Ban)
  • Domain name pointed to your VPS IP (optional, for production use)

1. πŸ“¦ Installation

Install NGINX:

sudo apt update
sudo apt install -y nginx

Check version:

nginx -v

Enable and start service:

sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx

2. πŸ”₯ Firewall Rules

Allow HTTP and HTTPS:

sudo ufw allow 'Nginx Full'

Or allow individually:

sudo ufw allow 80/tcp   # HTTP
sudo ufw allow 443/tcp  # HTTPS

Check firewall status:

sudo ufw status

3. πŸ§ͺ Test Installation

Visit your VPS IP in browser:

http://<your_vps_ip>

You should see the default NGINX welcome page.


4. πŸ“ Important Directories

  • Config files: /etc/nginx/
  • Main config: /etc/nginx/nginx.conf
  • Sites available: /etc/nginx/sites-available/
  • Sites enabled: /etc/nginx/sites-enabled/
  • Web root: /var/www/html/
  • Logs: /var/log/nginx/

5. πŸ”§ Basic Server Block (Virtual Host)

Create new site config:

sudo vim /etc/nginx/sites-available/<your_domain>

Basic configuration:

server {
    listen 80;
    listen [::]:80;

    server_name <your_domain>;

    root /var/www/<your_domain>;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/<your_domain>.access.log;
    error_log /var/log/nginx/<your_domain>.error.log;
}

Create web root directory:

sudo mkdir -p /var/www/<your_domain>
sudo chown -R $USER:$USER /var/www/<your_domain>

Create a test page:

echo "<h1>Welcome to <your_domain></h1>" > /var/www/<your_domain>/index.html

Enable the site:

sudo ln -s /etc/nginx/sites-available/<your_domain> /etc/nginx/sites-enabled/

Test configuration:

sudo nginx -t

Reload NGINX:

sudo systemctl reload nginx

6. πŸ”„ Reverse Proxy (Optional)

For apps running on localhost:

server {
    listen 80;
    server_name <your_domain>;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

7. πŸ”’ SSL with Let’s Encrypt

Install Certbot:

sudo apt install -y certbot python3-certbot-nginx

Get SSL certificate for a domain:

sudo certbot --nginx -d <your_domain>

For multiple domains/subdomains at once:

sudo certbot --nginx -d example.com -d www.example.com -d api.example.com

Adding SSL to a new subdomain later:

sudo certbot --nginx -d new-subdomain.example.com

Auto-renewal is enabled by default. Test it:

sudo certbot renew --dry-run

List all certificates:

sudo certbot certificates

8. πŸ› οΈ Common Commands

# Test configuration
sudo nginx -t

# Reload (graceful, no downtime)
sudo systemctl reload nginx

# Restart
sudo systemctl restart nginx

# Stop
sudo systemctl stop nginx

# View access logs
sudo tail -f /var/log/nginx/access.log

# View error logs
sudo tail -f /var/log/nginx/error.log

Result βœ…

  • NGINX installed and running
  • Firewall configured for web traffic
  • Ready to serve websites or act as reverse proxy

πŸ” Headscale Setup Notes

Prerequisites

  • Base VPS security setup completed
  • NGINX installed and configured
  • Domain pointed to VPS IP
  • Port 443 available

1. πŸ“¦ Installation

Download latest release:

cd /tmp
wget https://github.com/juanfont/headscale/releases/latest/download/headscale_<version>_linux_amd64.deb

Install:

sudo apt install ./headscale_*_linux_amd64.deb

Verify installation:

headscale version

2. βš™οΈ Configuration

Copy your config to the correct location:

sudo cp headscale.config.yaml /etc/headscale/config.yaml
sudo chown headscale:headscale /etc/headscale/config.yaml
sudo chmod 644 /etc/headscale/config.yaml

Review and edit config as needed:

sudo vim /etc/headscale/config.yaml

Important: Disable built-in ACME (nginx will handle SSL):

acme_email: ""
tls_letsencrypt_hostname: ""
tls_letsencrypt_listen: ""

Create data directory:

sudo mkdir -p /var/lib/headscale
sudo chown headscale:headscale /var/lib/headscale

3. 🌐 NGINX Reverse Proxy (HTTP Only - Temporary)

Create nginx config:

sudo vim /etc/nginx/sites-available/<your_domain>

Add basic HTTP configuration:

map $http_upgrade $connection_upgrade {
    default      upgrade;
    ''           close;
}

server {
    listen 80;
    listen [::]:80;

    server_name <your_domain>;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $server_name;
        proxy_buffering off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable site:

sudo ln -s /etc/nginx/sites-available/<your_domain> /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

4. πŸ”’ SSL Certificate

Get certificate (certbot will auto-configure HTTPS):

sudo certbot --nginx -d <your_domain>

5. πŸš€ Start Service

Enable and start:

sudo systemctl enable headscale
sudo systemctl start headscale

Check status:

sudo systemctl status headscale
sudo journalctl -u headscale -f

Note: You may see a warning β€œListening without TLS but ServerURL does not start with http://” - this is expected when using nginx as reverse proxy.


6. πŸ‘₯ User Management

Create a user:

sudo headscale users create <username>

List users:

sudo headscale users list

7. πŸ“± Connect Devices

Generate registration key:

sudo headscale preauthkeys create --user <username> --expiration 1h

On client device:

tailscale up --login-server https://<your_domain> --authkey <key>

List connected nodes:

sudo headscale nodes list

8. 🌍 Exit Node Setup (Optional)

Configure the VPS to act as an exit node for routing traffic.

Install Tailscale client on VPS:

curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt update
sudo apt install -y tailscale

Enable IP forwarding:

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Allow forwarding in firewall:

sudo ufw allow in on tailscale0
sudo ufw route allow in on tailscale0

Generate auth key for VPS:

sudo headscale preauthkeys create --user <username> --expiration 1h

Connect VPS to headscale and advertise as exit node:

sudo tailscale up --login-server https://<your_domain> --advertise-exit-node --authkey <key>

9. πŸ› οΈ Common Commands

# List all nodes
sudo headscale nodes list

# List users
sudo headscale users list

# Create preauth key
sudo headscale preauthkeys create --user <username>

# Remove node
sudo headscale nodes delete --identifier <node-id>

# Service management
sudo systemctl status headscale
sudo systemctl restart headscale
sudo journalctl -u headscale -n 50

Result βœ…

  • Headscale running with SSL
  • Ready to accept Tailscale clients
  • Self-hosted VPN control server