Below are some more detailed notes to accompany the talk too. If you give any of this a try and need more details at all please drop me a line.
The instructions assume a user will be added to the server that will be used for running the hosted applications. In these notes that user is called
The application installation instructions use an app name of
demoapp which can be replaced as appropriate.
Commands that can be run as the
deploy user are prefixed with a
$ whereas commands that need to be run as
root are prefixed with a
Instructions are based on using Ubuntu 16.04 LTS
Add a separate user that will be used for running the hosted applications:
# useradd deploy
sudo, this sets things up so the
deployuser can run commands via
sudowithout needing to enter a password, this is required for deployments to run without user intervention:
# gpasswd -a deploy sudo
# sudo sh -c 'echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'
$ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev nodejs
$ git clone git://github.com/sstephenson/rbenv.git .rbenv
rbenv/binfolder to the path:
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
rbenvwhen logging in:
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
ruby-buildplugin which can be used to build the desired version of Ruby from source:
$ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
ruby-build/binto the path:
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bash_profile
.bash_profileto avoid needing to log out and log back in again to pick up changes above:
$ source ~/.bash_profile
rbenv-varsplugin to allow a
.rbenv-varsfile in each application folder to be used to set environment variables for that app:
$ git clone https://github.com/rbenv/rbenv-vars.git $(rbenv root)/plugins/rbenv-vars
$ rbenv install -v 2.4.1
$ rbenv global 2.4.1
$ echo "gem: --no-document" > ~/.gemrc
$ gem install bundler
nginx is used as the public facing web server:
$ sudo apt-get install nginx
$ sudo apt-get install postgresql postgresql-contrib libpq-dev
One-time changes that should be made to a Rails app before deploying using these notes:
config/puma.rbfile to include separate settings for development and production:
One-time steps needed on the server to set up a new app:
$ sudo -u postgres createuser -s demoapp
Set password for postgres app user:
$ sudo -u postgres psql
psql (9.5.6, server 9.3.15)
Type “help” for help.
postgres=# \password demoapp
Enter new password:
Enter it again:
$ git clone --bare https://github.com/mikej/demoapp.git ~/demoapp_repo
$ mkdir ~/demoapp
~/demoapp. This file is used by the
rbenv-varsplugin to set any necessary environment variables for the app: RAILS_ENV=production SECRET_KEY_BASE=
post-receiveis readable and executable by
/lib/systemd/systemand symlink it into
$ sudo ln -s /lib/systemd/system/demoapp.service /etc/systemd/system/multi-user.target.wants/demoapp.service
/etc/nginx/sites-availableand symlink into
$ ln -s /etc/nginx/sites-available/demoapp /etc/nginx/sites-enabled/demoapp
$ sudo systemctl start demoapp
$ sudo systemctl restart nginx
This section covers generating and installing a Let’s Encrypt certificate once a basic app is up and running. See also: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04
$ sudo apt-get install letsencrypt
Generate a certificate:
$ sudo letsencrypt certonly -a webroot --webroot-path=/home/mike/demoapp/public -d demoapp.josephson.org
-a webroot indicates to use webroot authentication: a file is placed in the a folder called
.well-known under the web-root path. On running the
letsencrypt command, a copy of this file will be requested by Let’s Encrypt to verify ownership of the domain specified.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Create an nginx config snippet file in
/etc/nginx/snippets that is specific to this certificate e.g.
Create a Configuration Snippet with Strong Encryption Settings. This is a file e.g.
/etc/nginx/snippets/ssl-params.conf that can be shared across all your apps, containing a good set of SSL defaults to use for nginx. This is using the recommendations by Remy van Elst on the Cipherli.stsite. You can read more about his decisions regarding the Nginx choices here.
/etc/nginx/sites-availableto support SSL and to redirect non-https requests to the corresponding https URL e.g. using config like this.
$ sudo systemctl restart nginx
$ sudo letsencrypt renew. This can be automated by setting up a daily
crontask - if there are no certificates due for renewal at the time of running then
letsencryptwill indicate this and exit without making any changes.