Xanadu for Xojo Tech Info | CampSoftware
CampSoftware is made up of a fantastic team of people who loves developing Apps to solve problems.
Phone: 407-282-5585
Our blog posts in your email:






Xanadu Flow

We have Xanadu configured as shown below to show how how to scale. Again, you don't need to do any of this if your Web App has a light load.

It helps to think of the Flow Chart below split into half. NGINIX request routing is the top half and the Web App Instance + External resources as the bottom half. We would need the second half to run our app no matter what, so we're just adding NGINX for Web Request routing and Let's Encrypt for SSL Certs.
 
Xanadu Flow Chart
NGINX portion of the flow:

  • User's Browser visits https://foo.com with sends a Web Request to the server running NGINX.
  • NGINX looks at the request.
  • If the Web Request begins with http://foo.com/, NGINX redirects the user to https://foo.com/
  • If the Web Request begins with http://foo.com/.well-known/acme-challenge, NGINX serves the request file so Let's Encrypt can verify the ownership of foo.com.
  • If the Web Request begins with https://foo.com/, NGINX provides the Let's Encrypt SSL Certificate Key and PrivateKey and then send the request to the IP address and port of our Web App which is on the same server, for instance 127.0.0.1:8080

That's what we're doing now. We're not actually scaling yet since NGINX and the Web App are on the same server. The first step in scaling would be to move the Web App to a different Amazon Lightsail server and change the IP address of the Web App to the new server. Next would be to run the same Web App on the new Amazon Lightsail server two more times and update NGINX to automatically distribute the Web Requests to each of the three Web App instances.

Xanadu's Flow starts when NGINX sends the request to one of our Web App instances.

  • Xojo's HandleURL event fires which calls Aloe's .
  • Aloe's AppRequestProcess method runs and examines the Request Path.
  • If the Request is handled by our Web App, we return HTML and access external or embed resources like the MySQL database on Amazon Aurora, URLs to Amazon S3 files, and other API calls.
  • If the Request is not handled by our Web App, Aloe checks to see if the Request Path matches a file in htdocs and returns the file.
  • If our Web App isn't handled and there isn't a file, a 404 error is returned.
  • Returned data is sent back to the the User's Web Browser.



Amazon Lightsail

Amazon makes a great choice to host your Web Apps and is very affordable.
Stacks Image 3960
Server Setup

Choose the Lightsail Instance name carefully as it doesn't seem possible to rename it later.

Static IP —> Server Instance

Once created, the Server Instance will have an internal IP address and will not be exposed to the internet. Add a Static IP to your account and assign it to the Server Instance which will make it accessible via the internal IP or the external IP. Below you can see how the Server Instance is paired with a Static IP.

If you use NGINX, you'll only need one IP address that is assigned to the Server Instance that is running NGINX routing web requests to the same or different Server Instances using their internal IP addresses.
Stacks Image 3962
Amazon Private Key

Download your Amazon private key for use with other SSH apps by clicking on the Instance and follow the link to download the key.

Terminal

Lightsail makes it simple to connect to the Server Instance shell. Just click the terminal / shell icon.

We use this AppleScript saved an application to use the Mac Terminal to access the Server Instance shell via SSH. Just open the Mac Script Editor app, paste in this script, update the path to the downloaded Amazon private key, replace 33.199.x.x with the Amazon Lightsail Static IP, and then save the AppleScript as an application. When opening the script, a new terminal window will open that connects to the Lightsail Instance.

tell application "Terminal"
     do script "ssh -i /Users/hal/Documents/LightsailPrivateKey.pem ec2-user@33.199.x.x"
     
activate
end tell

File Transfers

Just like the SSH shell connection, you need the downloaded Amazon private key. In Coda, a Mac development app that supports SFTP, just add a new site, enter the Amazon Lightsail Static IP, username 'ec2-user', and instead of typing a password, select the Amazon private key. When you connect you'll be able to look around at the file structure of the Server Instance as well as upload and download files.

We've been uploading our Xojo Web Apps in /home/ec2-user/.

NGINX

You can install NGINX on your Amazon Lightsail Instance with the following commands:

apt-get install yum
sudo yum update
sudo yum install nginx


Next step is to edit the /etc/nginx/nginx.conf file. Below you can see our nginx.conf file that implements the Xanadu Flow chart near the top of this page.

We use Coda via SFTP to edit nginx.conf. If you can't seem to edit the file you might need to change the permission in order to edit. Here's how to set the permissions so the user can edit, world can read and everyone can read:

sudo chmod 644 /etc/nginx/nginx.conf

After modifying the nginx.conf, use this commend to start or restart NGINX.

Start: sudo nginx

Restart: sudo nginx -s reload

Let's Encrypt

Install Let's Encrypt with these commands:

sudo yum install -y git
cd /opt
sudo git clone https://github.com/certbot/certbot
cd certbot
./certbot-auto -h


Then make a web root folder to share the Let's Encrypt challenge files, if it doesn't already exist:

cd /var
mkdir www
cd www
mkdir html
cd html


Now you can create certificates assuming that you have NGINX configured so that Let's Encrypt can verify the challenge files. For Xanadu, I used the following command:

sudo /opt/certbot/./certbot-auto certonly --webroot -w /var/www/html -d xanadu.campsoftware.com --non-interactive --agree-tos --email hal@campsoftware.com --debug

That commend will create a certificate for xanadu.campsoftware.com and save the challenge files in the /var/www/html/.well-known/acme-challenge directory. Once the challenge files are accepted, they are automatically deleted. Let's Encrypt will automatically email you when the certificate gets close to the 90 day expiration date.

To update the certificate, you can use the same command or you can run this command to update all the certificates in need of an update:

sudo /opt/certbot/./certbot-auto renew

After the certificate is created or renewed, you may need to restart NGINX and your Xojo Web App.



nginix.conf

Here's what the NGNIX settings file looks like:

# NGINX config file located in /etc/nginx/nginx.conf
# To Eeload: sudo nginx -s reload

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {

# ######################################################

# Loads the default mime types to serve files with the correct Content-Type
include /etc/nginx/mime.types;

# ######################################################

# Disables the default host.
# See: http://serverfault.com/questions/420351/best-way-to-prevent-default-server
server {
listen 80 default_server;
server_name _;
return 444;
}

# ######################################################

server {
listen 80;
server_name xanadu.campsoftware.com;
location '/.well-known/acme-challenge' { default_type "text/plain"; root /var/www/html; }
location / { return 301 https://$server_name$request_uri; }
}

server {
listen 443 ssl;
server_name xanadu.campsoftware.com;
ssl_certificate /etc/letsencrypt/live/xanadu.campsoftware.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xanadu.campsoftware.com/privkey.pem;
location ~ ^/(static|other)/ { root /var/www/html/xanadu; add_header Cache-Control "public, max-age=172800"; }
location / {
proxy_pass http://127.0.0.1:2112;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass_request_headers on;
client_max_body_size 5m;
}
}

# ######################################################

}