DEV Community

Peiwen Li
Peiwen Li

Posted on

Configure A Fresh VPS To Host A Website

Got a new VPS (Ubuntu 20.04) on Namecheap. It seems that the basic VPS tier on Namecheap offers double CPU, RAM and storage than that of my old basic tier on AWS lightsail.

This journal concisely notes: How to configurate a fresh VPS to host my new website peiwen.me.

Reminder:

Just run these commands once ssh into remote server

apt update
apt install curl
Enter fullscreen mode Exit fullscreen mode

Notes:

  • apt is a Linux package management system
  • 'fun' fact: apt cmd was introduced in 2014, partly replaced apt-get after the release of Ubuntu 16.04, for being faster, friendlier, easier to use

Firstly! SSH

  • mosh is a good mobile shell - highly responsive, gotta be installed both locally and remotely.
  • local ssh config for convenience:
  # add info to local file: ~/.ssh/config
  Host <name_your_remote>
    HostName <static_IP>
    User <remote_username>
    IdentityFile <path_to_local_id_rsa>
    IdentitiesOnly yes
Enter fullscreen mode Exit fullscreen mode
  • remote ssh config:
  # local shell
  ssh <user>@<static_IP>

  # remote shell
  mkdir .ssh
  touch authorized_keys
  apt-get install nano # just in case
  apt-get install mosh # just in case
  nano authorized_keys
  # paste the content of the local file 'id_rsa.pub' to this file, save and exit
Enter fullscreen mode Exit fullscreen mode
  • NOW! YOU CAN~
  # local shell
  mosh <name_your_remote>
  ssh <name_your_remote>
Enter fullscreen mode Exit fullscreen mode

NodeJS

nvm

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
# might need to reconnect remote for `nvm` command to work properly
Enter fullscreen mode Exit fullscreen mode

Note: check the latest nvm installation script here

node

nvm list-remote
nvm install stable # or pick one from the list
nvm list
node -v
npm -v
npm install --global yarn # recommended
Enter fullscreen mode Exit fullscreen mode

Note: if "nvm 'command' not found" - check 'Troubleshooting on Linux Section'


MongoDB

Problems with installing v5.0

🔥 This exact problem encountered when I installed v5.0 - mongod service won't start. The reason might be:

> the VM’s CPU does not support instructions required by MongoDB 5.0 (such as AVX and SSE) which should be listed in the CPU flags:
> flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr

Similar issues found:

You might need to install apt install procinfo to run cat /proc/cpuinfo to checkout your CPU type.

Install MongoDB v4.4 Community Edition

wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list

sudo apt-get update

sudo apt-get install -y mongodb-org=4.4.15 mongodb-org-server=4.4.15 mongodb-org-shell=4.4.15 mongodb-org-mongos=4.4.15 mongodb-org-tools=4.4.15
Enter fullscreen mode Exit fullscreen mode

Start and config

sudo systemctl start mongod
sudo systemctl status mongod
sudo systemctl enable mongod
mongo
mongosh
Enter fullscreen mode Exit fullscreen mode

Note: sudo can be omitted if you are the root superuser

Uninstall MongoDB

sudo service mongod stop
sudo apt-get purge mongodb-org*
sudo rm -fr /var/log/mongodb
sudo rm -fr /var/lib/mongodb
Enter fullscreen mode Exit fullscreen mode

Security Checklist

MongoDB Guide

IP Binding to create a replica backup

Mongo


Git

Installation

apt update
apt install git
git --version
Enter fullscreen mode Exit fullscreen mode

Setup

To setup username if push to source is needed

git config --global user.name <username>
git config --global user.email <email>
git config --list # or ↓ directly check gitconfig file
nano ~/.gitconfig
Enter fullscreen mode Exit fullscreen mode

This is NOT enough anyway if you were to edit code and push to source, for only SSH communication is allowed with github repos since 2021.

Clone repo

Clone web repo to ~/web/, install the deps

git clone <repo_address>
cd <project>

yarn
# OR
npm i
Enter fullscreen mode Exit fullscreen mode

Configure .env.local

touch .env.local
nano .env.local
Enter fullscreen mode Exit fullscreen mode

.env.local content ↓

MONGODB_URI=<get_this by typing mongosh>
MONGODB_DB=journal

PASS=<some_password>
NEXT_PUBLIC_PASS_TOKEN=<some_JWT_like_token>

NEXT_PUBLIC_REVAL_TOKEN=<some_token_for_revalidation_token>
Enter fullscreen mode Exit fullscreen mode

Build

yarn build
yarn global add pm2
pm2 start yarn --name "peiwen.me" -- start
pm2 ls

# to start on startup
pm2 startup
# to freeze/save the processes
pm2 save
Enter fullscreen mode Exit fullscreen mode

Nginx

1. Install, config firewall and enable nginx

apt install nginx

# firewall
ufw app list

# returns
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
  mosh

# enable firewall
ufw allow 'Nginx Full'
ufw allow OpenSSH # important
ufw allow mosh
ufw enable
ufw status

# returns
Status: active
To                         Action      From
--                         ------      ----
Nginx Full                 ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
mosh                       ALLOW       Anywhere
Nginx Full (v6)            ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)
mosh (v6)                  ALLOW       Anywhere (v6)

# check your nginx server
systemctl status nginx

# get your IP if you don't already know for some reason
curl -4 icanhazip.com
<IP_address>

# enter this <IP_address> into the browser, you should be able to see the landing page of nginx

# lastely, enable it on every boot
systemctl enable nginx
Enter fullscreen mode Exit fullscreen mode

2. Setting Up Server Blocks

An nginx server block is a file inside folder /etc/nginx/sites-available/

cd /etc/nginx/sites-available
touch <new_domain> # optional
nano <new_domain>
Enter fullscreen mode Exit fullscreen mode

Insert content:

server {
  # the name of your domain
  server_name <new_domain> www.<new_domain>;

  location / {
    # this must stay localhost. The port must be the same as your Next.js project
    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;
  }

  # simple headers
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  add_header X-XSS-Protection          "1; mode=block" always;
  add_header X-Frame-Options DENY always;

  # this will serve the project on port 80
  listen 80;
}
Enter fullscreen mode Exit fullscreen mode

3. Verify and reload nginx for it to take effect

# check all working
nginx -t

ln -s /etc/nginx/sites-available/<new_domain> /etc/nginx/sites-enabled/

systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

PS. Do NOT forget

Refs:


SSL

1. Install certbot and some preparation

apt install certbot python3-certbot-nginx

# firewall settings
ufw allow 'Nginx Full'
ufw allow 'Nginx HTTPS'
ufw deny 'Nginx HTTP'
ufw status

# check if the <server_name> is exactly the format "example.com www.example.com"
nano /etc/nginx/sites-available/example.com
Enter fullscreen mode Exit fullscreen mode

2. Obtain the SSL/TLS Certificate

# do not forget the '-d' before www.example.com
certbot --nginx -d example.com -d www.example.com
# enter your email...
Enter fullscreen mode Exit fullscreen mode

Once you configure HTTPS, Certbot completes generating the certificate and reloads Nginx with the new settings.

Finally, the output displays that you have successfully generated a certificate and specifies the location of the certificate on your server. /etc/letsencrypt/live/example.com/fullchain.pem (success)

Ref: How to Secure Nginx with Let's Encrypt On Ubuntu 20.04

If you open your nginx file now nano /etc/nginx/sites-available/example.com, you'll find the extra info has been added:

server {
  server_name <new_domain> www.<new_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;
  }

  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  add_header X-XSS-Protection          "1; mode=block" always;
  add_header X-Frame-Options DENY always;

  # ↓ the following lines are added by Certbot

  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

  server_name example.com www.example.com;
  listen 80;
    return 404; # managed by Certbot
}
} # an extra for some reason...
Enter fullscreen mode Exit fullscreen mode
# check certificate's auto-renewal
certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

3. Setup Cronjob to Enable Automatic Certificate Renewal

# open Crontab
crontab -e
Enter fullscreen mode Exit fullscreen mode

Add a line:

# Schedule it to run daily at a specified time (in this example, it does so at 05:00 a.m.)
0 5 * * * /usr/bin/certbot renew --quiet
Enter fullscreen mode Exit fullscreen mode

Maintain

# in remote <site_folder>
git pull && yarn build && pm2 restart peiwen.me
Enter fullscreen mode Exit fullscreen mode

Useful articles 😄

Top comments (0)