Server side SWIFT: Vapor, MySQL, and NGINX with SSL-cert running on Ubuntu instance from DigitalOcean

Todd Shifflett
Apr 11, 2017 · 14 min read
Image for post
Image for post

INTRODUCTION

This is an effort to bring together many of the useful resources that helped me get my Swift Vapor server up and running on a machine instance from DigitalOcean with https and MySQL using the NGINX webserver.

References

I rely heavily on Robert Bojor’s guide for setting up Perfect 2.0, Swift, Ubuntu and Digital Ocean. Other sources I attempt to link to where appropriate.

Versions of Packages used in this tutorial

  • Swift : 3.1
  • MySQL : 14.14
  • Vapor : 1.5
  • Nginx : 1.10.0
  • Ubuntu: 16.04.2 x64

Disclaimer

I believe I have fully tested the process after my edits, but it’s possible I missed something. There are also a couple areas I’d like to expand upon. I suspect people will have suggestions and possibly find bugs in my documentation. I will make every effort to incorporate public response.


Create Server instance on DigitalOcean

DigitalOcean is a great cloud computing platform for spinning up an instance of your internet accessible application. If you don’t already have an account you can signup here.

  1. Distribution: select Ubuntu 16.04.2 x64
  2. Size: Probably select the smallest one ( 512 MB/1 CPU — 20 GB SSD disk — 1000 GB transfer). You’ll be able to change this later after you’re up and running.
  3. We don’t need Block Storage for a basic setup.
  4. Region: Select an option close to you.
  5. No additional options.
  6. SSH Key: Select an SSH key you’ve previously set up on DigitalOcean. If you haven’t done that yet, go ahead and do that now. You can use their tutorial for reference. This may not be entirely required, but this tutorial assumes you have that setup.
  7. You’ll create 1 Droplet and you can use the default hostname it provides you.
  8. Click on Create
Image for post
Image for post

Configure DNS

We’ll need to do this for the last step of getting SSL/HTTPS to work. Hopefully if you start the process now the DNS will refresh by the time you need to reference your domain name.

  • NS2.DIGITALOCEAN.COM
  • NS3.DIGITALOCEAN.COM

Configure the remote server

If your DNS has refreshed and you can ping yourdomain.com then you should be able to ssh into your DigitalOcean remote server. I have stored my DigitalOcean RSA key in the file: ~/.ssh/id_rsa_digitalOcean you may have it saved as something different.

ssh -i ~/.ssh/id_rsa_digitalOcean root@YOUR_DOMAIN.COM -v
ssh -i ~/.ssh/id_rsa_digitalOcean root@YOUR_DROPLET_IP -v
useradd -d /home/USER_NAME -m -s /bin/bash USER_NAME  
echo "USER_NAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
mkdir /home/USER_NAME/.ssh  
cp /root/.ssh/authorized_keys /home/USER_NAME/.ssh
chown -R USER_NAME.USER_NAME /home/USER_NAME/.ssh
ssh -i LOCAL_KEY_PATH USER_NAME@YOUR_DROPLET_IP -v
source ~/.bash_profile
export LC_ALL="en_US.UTF-8"  
export LC_CTYPE="en_US.UTF-8"
sudo dpkg-reconfigure locales
Image for post
Image for post
Image for post
Image for post
sudo apt-get update  
sudo apt-get upgrade -y
sudo apt-get install make clang libicu-dev pkg-config libssl-dev libsasl2-dev libcurl4-openssl-dev uuid-dev git curl wget unzip -y
cd /usr/src
sudo wget https://swift.org/builds/swift-3.1-release/ubuntu1604/swift-3.1-RELEASE/swift-3.1-RELEASE-ubuntu16.04.tar.gz
sudo gunzip < swift-3.1-RELEASE-ubuntu16.04.tar.gz | sudo tar -C / -xv --strip-components 1
swift --version
sudo rm -f swift-3.1-RELEASE-ubuntu16.04.tar.gz
cd ~

ADD SWAP

I’ve had problems compiling release builds on DigtalOcean and adding a swap partition seems to have solved that issue.

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=e2f1e9cf-c0a9-4ed4-b8ab-714b8a7d6944
sudo swapon /swapfile
sudo swapon -s
Filename                Type        Size    Used    Priority
/swapfile file 4194300 0 -1
sudo vi /etc/fstab
/swapfile   none    swap    sw    0   0

SETUP MySQL

This How-To will set up MySQL to host the database on the same server as our app. If you are going to use a database provider as a service you can omit mysql-server from the following line.

sudo apt-get install mysql-client libmysqlclient-dev mysql-server -y
Image for post
Image for post
sudo vi /usr/lib/x86_64-linux-gnu/pkgconfig/mysqlclient.pc
sudo mysql_secure_installation
  1. Validate Password Plugin? This is probably a good idea. but not needed for this tutorial. [y]
  2. Change Root Password? We just created the root password so we probably don’t need to change it. [n]
  3. Remove Anonymous Users? [y]
  4. Disallow root login remotely? [y]
  5. Remove test database and access to it? [y]
  6. Reload privilege tables now? [y]
mysql --version
mysql -u root -p
CREATE USER 'NEW_USER'@'localhost' IDENTIFIED BY 'USER_PASSWORD';
GRANT ALL PRIVILEGES ON * . * TO 'NEW_USER'@'localhost';
FLUSH PRIVILEGES;

CONFIGURE FOR VAPOR

Now we’re going to get the tools needed to insure your ubuntu server is up and running with Vapor. You can reference the Vapor Docs.

curl -sL check.vapor.sh | bash
eval "$(curl -sL https://apt.vapor.sh)"
sudo apt-get install vapor
vapor --help 

PREPARE USER’s HOME DIRECTORIES and GIT REPOSITORIES

You may want to customize some of these steps and locations to suit your own workflow. My process may not be considered “best practice”, and if you have suggestions on a better workflow I would very much like to incorporate it into this document.

mkdir -p src/APP_NAME/beta/.git src/APP_NAME/production/.git appServer/APP_NAME/production/bin appServer/APP_NAME/production/Public appServer/APP_NAME/beta/bin appServer/APP_NAME/beta/Public

git init ~/src/APP_NAME/beta/.git/. --bare
git init ~/src/APP_NAME/production/.git/. --bare
rm ~/src/APP_NAME/*/.git/hooks/*.sample
cd ~/src/APP_NAME/beta/.git/hooks
chmod +x post-receive
cp ~/src/APP_NAME/beta/.git/hooks/post-receive ~/src/APP_NAME/production/.git/hooks/post-receive

CONFIGURE SUPERVISOR

supervisor is a process that will run on the remote server and insure that your Swift App stays up and running.

sudo apt-get install supervisor -y  
service supervisor restart
cd /etc/supervisor/conf.d
sudo supervisorctl reread

CONFIGURE NGINX

On the remote DigtalOcean server instance… If everything has been set up correctly, you should be able to login by typing…

ssh REMOTE_USER_NAME@YOUR_DOMAIN.COM
sudo apt-get install nginx -y
cd /etc/nginx/sites-available
sudo rm -rf default ../sites-enabled/default
sudo ln -s /etc/nginx/sites-available/APP_NAME.vhost /etc/nginx/sites-enabled/APP_NAME.vhostsudo ln -s /etc/nginx/sites-available/APP_NAME-beta.vhost /etc/nginx/sites-enabled/APP_NAME-beta.vhost
cd /etc/nginx
sudo mv nginx.conf nginx.conf.backup
sudo /etc/init.d/nginx restart

ENABLE SSL/HTTPS

The https protocol is an extra layer of security for internet traffic. I won’t try to describe it any farther than that. It does become extra important if your webApp is serving as an API for iOS applications. It’s my understanding Apple has begun to enforce that calls made from your app will need to connect via https and that regular old http will no longer pass App Store requirements.

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
cd /opt/letsencrypt
./letsencrypt-auto certonly -a webroot --webroot-path=/home/USER_NAME/appServer/APP_NAME/production/Public -d YOUR_DOMAIN.COM
Image for post
Image for post
Image for post
Image for post
Output:
IMPORTANT NOTES:
- If you lose your account credentials, you can recover through
e-mails sent to USER_NAME@MAIL_DOMAIN.com
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/BETA.YOUR_DOMAIN.COM/fullchain.pem. Your
cert will expire on 2016-03-15. To obtain a new version of the
certificate in the future, simply run Let's Encrypt again.
- Your account credentials have been saved in your Let's Encrypt
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Let's
Encrypt so making regular backups of this folder is ideal.
- If like Let's Encrypt, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
./letsencrypt-auto certonly -a webroot --webroot-path=/home/USER_NAME/appServer/APP_NAME/beta/Public -d BETA.YOUR_DOMAIN.COM
sudo ls -aF /etc/letsencrypt/live
./    ../    BETA.YOUR_DOMAIN.COM/    YOUR_DOMAIN.COM/ 
cd /etc/nginx/sites-available
sudo vi YOUR_DOMAIN.vhost
sudo /etc/init.d/nginx restart

LOCAL DEVELOPMENT

Okay, now let’s jump back to your local machine for a bit to setup the app for development if you don’t already have one.

cd ~/Desktop
vapor new APP_NAME
cd APP_NAME
vapor xcode --mysql
APP_NAME/
.build/
.git/
.gitignore
.travis.yml
Config/
Localization/
Package.pins
Package.swift
Procfile
Public/
README.md
Resources/
Sources/
app.json
APP_NAME.xcodeproj/
license
.DS_Store
.build
Packages
*.xcodeproj
xcuserdata
secrets
mysql.json
Config/
app.json
clients.json
crypto.json
droplet.json
servers.json
beta/
mysql.json
production/
mysql.json
secrets/
mysql.json
{
"host": "127.0.0.1",
"user": "MYSQL_USER_NAME",
"password": "MYSQL_PASSWORD",
"database": "APP_DATABASE"
}
{
"host": "127.0.0.1",
"user": "MYSQL_USER_NAME",
"password": "MYSQL_PASSWORD",
"database": "APP_DATABASE_beta"
}
{
"default": {
"port": "$PORT:8181",
"host": "0.0.0.0",
"securityLayer": "none"
}
}
Host YOUR_DOMAIN.COM
Hostname YOUR_DOMAIN.COM
user REMOTE_USER_NAME
IdentityFile=~/.ssh/YOUR_DIGITAL_OCEAN_ID_RSA_FILE
git remote add beta ssh://REMOTE_USER_NAME@YOUR_DOMAIN.COM/home/REMOTE_USER_NAME/src/APP_NAME/beta/.gitgit remote add production ssh://REMOTE_USER_NAME@YOUR_DOMAIN.COM/home/REMOTE_USER_NAME/src/APP_NAME/production/.git
git add .
git commit -m 'First commit to test pushing to beta server`
git push beta master

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store