Skip to content
cayhorstmann edited this page Mar 31, 2020 · 3 revisions

Local Development

It is most comfortable to develop locally.

Since the server is running Linux, you want to develop with Linux. On Windows or Mac OS X, install a Linux virtual machine following these steps:

  1. Download and install http://virtualbox.org/

  2. Download the Lubuntu 16.04 LTS 64 bit ISO from http://lubuntu.me/downloads/

  3. Start VirtualBox. New -> Name: Lubuntu, Version: Ubuntu (64 bit), then follow the wizard with all defaults.

  4. Select Settings -> Storage -> Click on the first + at IDE controller (with tooltip Add CD/DVD drive) -> Choose disk -> Choose the downloaded ISO file -> Ok.

  5. Start your new VM.

  6. Install Lubuntu. Accept all defaults. Remember the password that you chose! (I just choose secret—nobody can log into your VM without first logging into your computer.) A couple of screens in the installer are cut off, but just hitting Enter got me past them.

  7. Restart the virtual machine. From the VirtualBox menu, select Devices -> Shared Clipboard -> Bidirectional and then Devices -> Insert Guest Additions CD Image. A dialog will pop up offering to show a folder of the CD image. Accept that.

  8. Open a terminal (Ctrl+Alt+T). Type these commands (and type secret when prompted for a password):

    cd /media/*/VBOX*
    sudo ./VBoxLinuxAdditions.run
    
  9. Restart the virtual machine. You should now be able to resize the window.

You need to install the following software:

  • Java JDK 8
  • Eclipse
  • SBT
  • Git

Here are the installation instructions:

echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
sudo apt-get update
sudo apt-get install openjdk-11-jdk git sbt sysstat

Point your browser (in Linux) to http://www.eclipse.org/downloads/eclipse-packages/ and select "Eclipse IDE for Java EE Developers". When the download is complete, run

cd
tar xvf ~/Downloads/eclipse*.tar.gz

Build instructions

Run these commands to install the CodeCheck checker:

cd ~/Downloads
wget horstmann.com/codecheck/server/codecheck.tar.gz
sudo mkdir -p /opt/codecheck
sudo chown `whoami` /opt/codecheck
cd /opt/codecheck
tar xvf ~/Downloads/codecheck.tar.gz
echo "JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/" > codecheck.env 

Now build the server:

cd
git clone https://github.com/cayhorstmann/play-codecheck
cd play-codecheck
sbt run

This may take a very long time. Once it's finished, point your browser to http://localhost:9000/health. You should be getting a screen saying "CodeCheck" together with the amount of free space on your machine.

Hit Ctrl+C when you are done.

For development, use Eclipse. Run

cd ~/play-codecheck
sbt eclipse

Start Eclipse by running

~/eclipse/eclipse

Then import the project into Eclipse. (File -> Import -> Existing Project into Workspace)

Note that you use Eclipse only for editing. To compile and run, you run sbt run as before. Whenever you save a file in Eclipse, sbt automatically compiles the file and updates the web application.

Instructions for running the debugger are at https://www.playframework.com/documentation/2.5.x/IDE.

Server instructions

Create a new Ubuntu 18.04 instance (Google Compute Engine: Follow the quickstart at https://cloud.google.com/compute/docs/quickstart-linux, but choose Ubuntu 18.04 LTS instead of Debian.)

Install the gcloud command-line tools as described in https://cloud.google.com/sdk/docs/quickstart-debian-ubuntu

Then run

gcloud compute ssh instanceName --zone zoneName

to log into the instance.

Run these commands:

sudo su ubuntu
sudo mkdir /opt/codecheck
sudo chown ubuntu /opt/codecheck

echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
sudo apt-get update
sudo apt -y -q install openjdk-11-jdk-headless unzip git sbt libxi6 libxtst6 libxrender1 apparmor-utils g++ python3 python3-pillow

wget -q $CODECHECK_URL/codecheck.tar.gz
tar xf codecheck.tar.gz -C /opt/codecheck 
rm codecheck.tar.gz
chmod +x /opt/codecheck/{codecheck,comprog,runprog,killold}

cd
git clone https://github.com/cayhorstmann/play-codecheck

Copy your s3.properties to /opt/codecheck, for example like this:

cat > /opt/codecheck/s3.properties << "EOF"

Now paste in the two lines of your file. On a new line, type

EOF

Each time you want to stop, rebuild, and start the server, run these commands:

pkill -9 java
cd /home/ubuntu/play-codecheck
git pull
sbt run

Static IP Address

Gnerate a new address

gcloud compute addresses create $SERVICE-address --global
gcloud compute addresses describe $SERVICE-address --global

Keep a note of the assigned address.

SSL Certificate

Reserve a domain with your favorite domain name provider.

Install certbot as per https://certbot.eff.org/docs/install.html on your laptop.

Run

export DOMAIN=... # the domain that you reserved, e.g. codecheck.mycompany.com
wget https://dl.eff.org/certbot-auto
chmod a+x ./certbot-auto
sudo ./certbot-auto certonly --agree-tos --manual \
  --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory \
  -d $DOMAIN

Follow the instructions to make a TXT record in the DNS control panel of your favorite domain name provider. When your certificate has been issued, run

sudo mv /etc/letsencrypt/live/$DOMAIN/{fullchain,privkey}.pem .
sudo $(whoami) {fullchain,privkey}.pem .
export CERTIFICATE=${DOMAIN//./-}-$(date +%Y-%m-%d)
gcloud compute ssl-certificates create $CERTIFICATE --certificate fullchain.pem --private-key privkey.pem
rm {fullchain,privkey}.pem

Note: You need to renew the certificate every 3 months, following the same instructions. These steps show you the initial install. When you renew, also run

gcloud compute target-https-proxies update $SERVICE-https-proxy --ssl-certificate $CERTIFICATE

Load balancing and SSL

Define the following environment variables

export INSTANCE=...
export ADDRESS=... # the static IP address that you produced before
export REGION=... # e.g. us-central1
export ZONE=... # e.g. us-central1-a
export PREFIX=lti-codecheck
export SERVICE=${PREFIX}-service
export CHECK=${PREFIX}-check
export GROUP=${PREFIX}-group
export MAP=${PREFIX}-map

Configure firewall

gcloud compute firewall-rules create default-allow-http-9000 \
  --allow tcp:9000 \
  --source-ranges 0.0.0.0/0 \
  --description "Allow port 9000 access for all instances" 

gcloud compute firewall-rules create default-allow-http-443 \
  --allow tcp:443 \
  --source-ranges 0.0.0.0/0 \
  --description "Allow port 443 access"

Configure instance group

gcloud compute instance-groups unmanaged create $GROUP --zone $ZONE
gcloud compute instance-groups unmanaged add-instances $GROUP --instances $INSTANCE --zone $ZONE
gcloud compute instance-groups managed set-named-ports $GROUP --named-ports http:9000 --zone $ZONE

Configure backends

gcloud compute http-health-checks create $CHECK \
  --port 9000 \
  --request-path /health \
  --healthy-threshold 2 \
  --unhealthy-threshold 3 \
  --check-interval 10s

gcloud compute backend-services create $SERVICE \
  --http-health-checks $CHECK \
  --global \
  --timeout 300s

gcloud compute backend-services add-backend $SERVICE \
  --instance-group $GROUP \
  --instance-group-zone $ZONE \
  --global

Configure load balancer

gcloud compute url-maps create $SERVICE-map \
  --default-service $SERVICE

gcloud compute target-http-proxies create $SERVICE-http-proxy \
  --url-map $SERVICE-map

gcloud compute target-https-proxies create $SERVICE-https-proxy \
  --url-map $SERVICE-map \
  --ssl-certificates $CERTIFICATE

Configure frontend

gcloud compute forwarding-rules create $SERVICE-http-rule \
  --global \
  --address $ADDRESS \
  --target-http-proxy $SERVICE-http-proxy \
  --ports 80 

gcloud compute forwarding-rules create $SERVICE-https-rule \
  --global \
  --address $ADDRESS \
  --target-https-proxy $SERVICE-https-proxy \
  --ports 443

At this point, you should be able to point your browser to https://(frontent IP address)/health and and get the health check page without any SSL warning