Guides to set up NUSMods on production servers.
Most of NUSMods is able to run in Docker containers, but some parts of NUSMods (most notably the scraper, analytics.nusmods.com, and the URL shortener) are not. These steps set up a production server to host the Dockerized section of NUSMods, which currently includes the website and export server.
- Set up DigitalOcean droplet:
- Create a new DigitalOcean droplet. We recommend this configuration, which will cost $20 a month:
- Ubuntu 18.04 LTS x64
- 2 CPUs
- 4GB RAM
- Datacenter region: Singapore 1. Anywhere in Singapore minimizes distance to most of our users, and all existing NUSMods servers are in this datacenter.
- Open droplet page, and enable Floating IP.
- For security, configure a firewall to only expose ports 22, 80, and 443. Within the NUSMods organization, we have one already configured called the
everything-firewall
– just use that.
- Create a new DigitalOcean droplet. We recommend this configuration, which will cost $20 a month:
- Set up DNS records (we use Cloudflare)
- Configure OS:
- Create user account:
- SSH into the
root
account on the new server. - Add a user account. We'll name ours
mods
:adduser mods
- Grant the new account sudo privileges:
usermod -aG sudo mods
- Log in as the new user:
su - mods
- cd to new home directory:
cd
- Optionally create an SSH key to allow the new server to SSH into other servers to copy configs/secrets/data:
ssh-keygen -t ed25519 -a 100
- IF you didn't create a key, create
.ssh
directory; use this hack to make SSH do the work for you:ssh-keygen; rm .ssh/*
cd .ssh
- Create
authorized_keys
file in.ssh
containing all the public keys which you want to allow, or copy it from another server.
- SSH into the
- Install dependencies:
sudo apt update
sudo apt upgrade
- Install Docker, following instructions at https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04.
- Allow
mods
account to run Docker without sudo:sudo usermod -aG docker
- Install Docker Compose, following the instructions on https://docs.docker.com/compose/install/.
- Ensure that
docker run hello-world
works.
- Secure SSH:
- Open /etc/ssh/sshd_config
- Uncomment
PubkeyAuthentication yes
- Comment out
PermitRootLogin yes
- Ensure that
PasswordAuthentication no
is present and not commented out. - Run
service sshd restart
- End the SSH session.
- Create user account:
- Configure NUSMods services:
- SSH into the
mods
account on the new server. - In the user's home directory,
git clone https://github.com/nusmodifications/nusmods.git
cd nusmods
- Inject secrets by creating all the appropriate .env files. If on an official NUSMods server, simply copy the secrets directory over and run
link-secrets.sh ../nusmods
- SSH into the
Dockerized Production Server Setup (NUS Student Development Platform)
The instructions below will set up our dockerized services on CentOS 7, which is used by NUS's new student development platform.
- Follow these instructions to spin up a new EC2 instance using the AWS Service Catalog.
- Wait for instance to be provisioned.
- Through email, request for ports 80 and 443 to be exposed to the public Internet.
- Using the AWS console's jump server, SSH into the instance:
ssh -o ServerAliveInterval=180 <NUSNET ID Exxxxxxx>@<instance IP address>
- Configure OS:
- Install dependencies:
sudo yum update
- Install git:
yum install -y git
. - Install Docker. Because we don't have permission to run
sudo sh
(orsudo su
), the Docker installation script will fail. Instead, run the commands manually:- Generate Docker installation commands:
curl -fsSL https://get.docker.com/ | DRY_RUN=1 sh
- Run all commands with
sudo
. - Start the Docker daemon:
sudo systemctl start docker
- Ensure Docker daemon starts on reboot:
sudo systemctl enable docker
- Generate Docker installation commands:
- Allow your user account to run Docker without sudo:
sudo usermod -aG docker <NUSNET ID>
, then log out and log back in. - Ensure that
docker run hello-world
works. - Install Docker Compose:
- At https://github.com/docker/compose/releases, copy the link to the latest
docker-compose-Linux-x86-64
release asset. - Download Docker Compose:
curl --create-dirs -L "<the link you copied>" -o ~/bin/docker-compose
- Make it executable:
sudo chmod +x ~/bin/docker-compose
- Fix permission error when starting
docker-compose
:mkdir $HOME/tmp
export TMPDIR=$HOME/tmp
echo "export TMPDIR=$HOME/tmp" >> ~/.bashrc
- At https://github.com/docker/compose/releases, copy the link to the latest
- Ensure that
docker-compose version
works.
- Install dependencies:
- Set up DNS records (we use Cloudflare).
- Configure NUSMods services:
git clone https://github.com/nusmodifications/nusmods.git
cd nusmods
- Create and populate
export/env
- Fix Chromium startup crash:
sysctl -w user.max_user_namespaces=1000
. - Start up the NUSMods services:
CF_API_KEY=<Cloudflare Global API Token> ./prod-up.sh
To deploy future updates, run ./prod-deploy.sh
. To spin down all services, run ./prod-down.sh
.
NUS’s new student development platform runs CentOS 7 instead of the Ubuntu that we normally run. The instructions below will set up the scraper and API server on CentOS 7.
- Install software (run the commands below as root – log in as root by running
sudo su -
)- Install git:
yum install -y git
. - Install Nginx and enable its systemctl service by following https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-centos-7.
- Install Node.js.
- Install Yarn.
- Install and enable PM2:
yarn global add pm2 && pm2 startup systemd
- As a regular user, ensure that you can run PM2 by running
pm2
. Ifpm2
can't be executed, check the permissions of the /usr/local/lib/npm folder and the /usr/local/share/.config/yarn/global folders. Try running (untested!)chmod u+rx -R /usr/local/lib/npm/bin /usr/local/share/.config/yarn/global
.
- Install git:
- Configure scraper
- Clone the NUSMods repository:
git clone https//github.com/nusmodifications/nusmods.git
. cd nusmods/scrapers/nus-v2
- Follow the getting started instructions in the scraper README.md to set up the scraper. If you have SSH access to existing scraper servers, you can use
scp
to copy their env.json for convenience. - Test that the scraper will work by running
yarn dev test | yarn bunyan
. If you see an error, it may actually just be a transient issue with the NUS APIs that the test script pings; they throw many random errors all the time. - Enable scraper service by running
pm2 start ecosystem.config.js
.
- Clone the NUSMods repository:
- Configure file server
- (Optional) Copy production API data from existing data servers to a
/home/<username>/api.nusmods.com
folder: on the data server, runscp -r api.nusmods.com <target server>:~
. - Configure Nginx (run below commands as root)
cd /etc/nginx
- Edit
nginx.conf
: comment out the defaultserver
block. - Copy this gist to a new
conf.d/api.nusmods.com.conf
file. Be sure to correct the path to the API data folder. systemctl enable nginx
systemctl restart nginx
- Visit the IP address of the server in your browser. If you see a 403 Forbidden error:
- Configure folder permissions.
- Obtain the directory permissions of the data folder and all its parent directories:
namei -om /home/<username>/api.nusmods.com
. - All folders in the list require read and execute permissions. If some folders do not have them, run
chmod a+rx <folder>
.
- Obtain the directory permissions of the data folder and all its parent directories:
- Configure SELinux to allow the data folder to be served:
chcon -Rt httpd_sys_content_t /home/<username>/api.nusmods.com
. - Change existing file permissions if necessary:
chmod a+r -R api.nusmods.com
.
- Configure folder permissions.
- Set ACL policies on the data directory to ensure that all future directories and files can be served by Nginx:
setfacl -R -d --set u::rwx,g::rx,o::rx api.nusmods.com
.
- (Optional) Copy production API data from existing data servers to a
- Add a DNS record to point to the server's public address.
- Set up HTTPS.