Zachary W. Huang

Home Projects Blog Guides Resume

Server Setup and Administration (+ recipes)

Creating a new user with sudo permission

  • Assuming you are logged in with root access
adduser [username]
usermod -aG sudo [username]

Adding ssh keys for a user

  • Assuming the user has run ssh-keygen on their machine
  • Assuming you are logged in with root access
mkdir -p /home/[username]/.ssh
chmod 700 /home/[username]/.ssh
# append contents of public key into /home/[username]/.ssh/authorized_keys on the server
# OR...see below:
# on the user's machine
ssh-copy-id -i [path-to-pub-key] [username]@[server-ip]

Disable ssh password authentication

sudo vi /etc/ssh/sshd_config
# and set the following:
# ChallengeResponseAuthentication no
# PasswordAuthentication no
# UsePAM no
# PermitRootLogin without-password # or "no"




crontab -e # edit crontab for current user
sudo systemctl restart cron # run after updating jobs
sudo systemctl status cron # check cron status
vi /var/log/syslog # checking if cron jobs are being run


# hourly job
SHELL=/bin/bash # set shell to bash (default is 'dash' on Ubuntu)
0 * * * * /usr/bin/echo "hello"

Setting a separate log file for cron (not syslog)

sudo vi /etc/rsyslog.d/50-default.conf
# uncomment line with '#cron.*      /var/log/cron.log'
sudo systemctl restart rsyslog

Installing an MTA for more informative error messages

sudo apt install postfix # select 'local only' on install
sudo systemctl restart cron
tail -f /var/mail/[cron user] # to view MTA messages

Backing up to AWS S3

# install and set up aws cli
curl "" -o ""
sudo ./aws/install

# require access id and secret key, generate at
aws configure
# check if authentication success
aws s3 ls
# syncing a directory into an s3 bucket (or vice versa)
aws s3 sync [local directory] s3://[bucket]/[path-in-bucket]

Using UFW as a firewall

DigitalOcean Intro to UFW

sudo ufw app list
sudo ufw allow OpenSSH # open up ssh
sudo ufw enable
sudo ufw status
# examples
sudo ufw allow from
sudo ufw deny from

Setting up an Nginx

sudo apt update
sudo apt install nginx
sudo ufw allow "Nginx HTTP" # or "Nginx HTTPS" or "Nginx Full" (both HTTP and HTTPS)
systemctl status nginx # check if running
curl -4 # check server IP

Using Nginx with an Express server (JS)

Running a node server with PM2

Assuming node/npm is installed

sudo npm i -g pm2
pm2 start [entrypoint].js --time
pm2 startup systemd # to enable pm2 on server boot
pm2 save
sudo systemctl start pm2-[user] # if you ran the setup script
# extra pm2 commands:
pm2 list
pm2 info [app_name]
pm2 monit
pm2 logs [app_name]

Configuring Nginx:

Assuming Nginx is set up

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/[domain]
vi /etc/nginx/sites-available/[domain] 
# # You should have something like:
# server {
#     listen 80 default_server
#     listen [::]:80 default_server
#     server_name [domain] www.[domain]
#     location / {
#         proxy_pass http://localhost:[port];
#         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;
#     }
# }
sudo ln -s /etc/nginx/sites-available/[domain] /etc/nginx/sites-enabled

sudo nginx -t # check for syntax errors
sudo systemctl restart nginx

Adding HTTPS to Nginx

sudo apt install certbot python3-certbot-nginx
sudo ufw allow "Nginx Full" # or "Nginx HTTPS"
sudo certbot --nginx -d [domain] -d www.[domain]
# checking certbot auto-renewal service
sudo systemctl status certbot.timer

Using Redis


# can also be installed using apt, but likely not most recent version
# downloading/building from source -
tar -xvf redis-6.2.5.tar.gz
cd redis-6.2.5
sudo make install # link commands to /usr/local/bin/

Configure init script:

sudo mkdir /etc/redis
sudo mkdir /var/redis

sudo cp utils/redis_init_script /etc/init.d/redis_6379
sudo vi /etc/init.d/redis_6379 # edit REDISPORT or other options
sudo mkdir /var/redis/6379
sudo cp redis.conf /etc/redis/6379.conf
# edit redis config file:
# set daemonize to yes
# set pidfile to /var/run/
# set port (if not 6379)
# set logfile to /var/log/redis_6379.log
# set dir /var/redis/6379

# add init script to default runlevels
sudo update-rc.d redis_6379 defaults
# run instance:
sudo /etc/init.d/redis_6379 start


  • make sure port is firewalled (if accessible to outside world)
  • ‘bind’ option in config file
  • ‘requirepass’ in config file


  • run redis-cli
    • try ping
    • try save and check /var/redis/6379 for dump.rdb
RSS icon github logo linkedin logo

Zachary W. Huang © 2021-2024