Skip to content

Instantly share code, notes, and snippets.

@dorukozerr
Last active December 1, 2024 21:08
Show Gist options
  • Save dorukozerr/b47d6d0c7af369052f7ae50dec4076b9 to your computer and use it in GitHub Desktop.
Save dorukozerr/b47d6d0c7af369052f7ae50dec4076b9 to your computer and use it in GitHub Desktop.

VPS Setup

How to setup a secure VPS and configure it for app deployment

  1. First update and upgrade your system with
    1. To update your system run sudo apt update
    2. To upgrade your system run sudo apt upgrade you don't need sudo if you are logged in as root
  2. Security setup
    1. First change the root password with passwd command
    2. Create a non-root user
      • Run this command to add a new user adduser <username>
      • Set a password then enter the user details
      • Change user group with usermod -aG sudo <username>
      • Verify the user group with groups <username>
      • Exit and try to login with ssh <username>@<ipaddress>
    3. Configure a ssh key to login
      • Create a ssh directory in /home/<username>/.ssh
      • Copy and paste your public ssh key into /home/<username>/.ssh/authorized_keys
      • Now you can connect to your VPS without password with ssh <username>@<ipaddress>
    4. Disable password login
      • Edit /etc/ssh/sshd_config file
      • Make sure PubkeyAuthentication yes so you can login with public key
      • Set PasswordAuthentication no
      • Edit /etc/ssh/sshd_config.d/*.conf file and make sure PasswordAuthentication no is set
    5. Disable root login
      • Edit /etc/ssh/sshd_config file and set PermitRootLogin no
      • To restart ssh service run sudo service ssh restart
      • Try running ssh root@<ipaddress> command to make sure changes applied
    6. Network and firewall policy
      • Enable this from vps service provider dashboard
    7. Close unused ports
      • Must look into this further
    8. Change default ssh port
      • Must look into this further
    9. Restrict port access to a specific ip
      • Must look into this further
    10. Enable and configure automatic updates
      • Run sudo apt install unattended-upgrades
      • Check automatic updates with sudo systemctl status unattended-upgrades
  3. Custom domain configuration
    1. Setup up dns records on your provider I use cloudflare on this guide
    2. Create a dns record with Type A and name @ then with content ip address and TTL 1min max
    3. Try to access it with dig domainname A this should output
      ANSWER SECTION
      domainname TTL IN A ipadress
      
    4. www subdomain record CNAME records and TEXT records
      • Type A, Name www, content ipaddress, Proxy status DNS only, TTL 1min
      • TYPE CNAME, name banana, target domainname, proxy status DNS only, TTL 1min
        • CNAME is a record points to target domain name
      • TYPE TXT, name @, content anyhting, TTL 1 min
  4. Caddy setup
    1. Installation
    2. Directory Structure Setup
      • Create the following folders:
        • /etc/caddy/sites-available
        • /etc/caddy/sites-enabled
    3. Configure Main Caddyfile
      • Update /etc/caddy/Caddyfile with the example configuration below
    4. Create HTTP Redirects
      • Create a file /etc/caddy/sites-available/http-redirects example configuration below:
      • Create symbolic link ln -s /etc/caddy/sites-available/http-redirects /etc/caddy/sites-enabled/http-redirects
    5. Subdomain Configuration (Optional)
      • Create separate files for each subdomain in /etc/caddy/sites-available/ with the example below
      • For each configuration file, create a symbolic link ln -s /etc/caddy/sites-available/your-config /etc/caddy/sites-enabled/your-config
    6. Apply Changes
      • After any configuration changes sudo service caddy reload
  5. PM2 setup
    1. Install pm2 with npm i -g pm2
    2. Run your apps with pm2 start --name <processname> <pathtoindex> or pm2 start --name <processname> npm -- start
    3. Run pm2 startup to make pm2 run your apps when server reboots
    4. Run pm2 save to save all running apps so they can start again after reboot
  • Main CaddyFile content

    <domainname> {
        # For reverse proxying dynamic apps
        # reverse_proxy :3000
    
        # For serving static files:
        # root * /www/var/<pathtoindex>
        # file_server {
        #     hide .git
        # }
    
        handle_errors {
            respond "{err.status_code} {err.status_text}"
        }
    }
    
    import sites-enabled/*
    
  • http-redirects content

    <ipaddress>:80, www.<domainname> {
        redir https://<domainname>{uri}
    }
    
  • Subdomain Configuration

    <subdomain>.<domainname> {
        # Configuration similar to main domain
        # reverse_proxy :3000
    
        handle_errors {
            respond "{err.status_code} {err.status_text}"
        }
    }
    
    www.<subdomain>.<domainname> {
        redir https://{subdomain}.{domainname}{uri}
    }
    
  • SSH Deploy key setup

    ssh-keygen -t ed25519 -C
    eval "$(ssh-agent -s)"
    ssh-add id_ed25519_deploykeyname
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment