|
|
@@ -0,0 +1,679 @@ |
|
|
#DigitalOcean Rails/Ubuntu/NGINX (16.04) Setup |
|
|
|
|
|
1. Setup |
|
|
2. Swapfile |
|
|
3. NGINX |
|
|
4. ElasticSearch |
|
|
5. RVM |
|
|
6. Rails |
|
|
7. Postgres |
|
|
8. Capistrano |
|
|
9. Let's Encrypt |
|
|
10. Firewall |
|
|
|
|
|
|
|
|
## Droplet |
|
|
Create a new, start with the smallest droplet. Use **Ubuntu 16.04**, log in as **root**. |
|
|
|
|
|
##1. Create non-root user 'rails' |
|
|
[Initial Server Setup with Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04) |
|
|
|
|
|
create user 'rails' |
|
|
|
|
|
``` |
|
|
adduser rails |
|
|
``` |
|
|
|
|
|
Add to sudoers group |
|
|
|
|
|
``` |
|
|
usermod -aG sudo rails |
|
|
``` |
|
|
|
|
|
Switch user to 'rails' |
|
|
|
|
|
``` |
|
|
su - rails |
|
|
``` |
|
|
|
|
|
Create ssh key |
|
|
|
|
|
``` |
|
|
ssh-keygen |
|
|
``` |
|
|
|
|
|
Create sym link for webroot |
|
|
|
|
|
``` |
|
|
cd ~ |
|
|
ln -s /var/www/html html |
|
|
``` |
|
|
|
|
|
|
|
|
##2. Swapfile |
|
|
[How To Add Swap Space on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-16-04) |
|
|
|
|
|
Check swapfile |
|
|
|
|
|
``` |
|
|
free -h |
|
|
``` |
|
|
|
|
|
Check freespace |
|
|
|
|
|
``` |
|
|
df -h |
|
|
``` |
|
|
|
|
|
Create a 4gb Swap File |
|
|
|
|
|
``` |
|
|
sudo fallocate -l 4G /swapfile |
|
|
``` |
|
|
|
|
|
Verify |
|
|
|
|
|
``` |
|
|
ls -lh /swapfile |
|
|
``` |
|
|
|
|
|
Lock it down |
|
|
|
|
|
``` |
|
|
sudo chmod 600 /swapfile |
|
|
``` |
|
|
|
|
|
Make it swap |
|
|
|
|
|
``` |
|
|
sudo mkswap /swapfile |
|
|
``` |
|
|
|
|
|
Enable it |
|
|
|
|
|
``` |
|
|
sudo swapon /swapfile |
|
|
``` |
|
|
|
|
|
Verify |
|
|
|
|
|
``` |
|
|
sudo swapon --show |
|
|
``` |
|
|
|
|
|
Check swapfile |
|
|
|
|
|
``` |
|
|
free -h |
|
|
``` |
|
|
|
|
|
Make it permanent |
|
|
|
|
|
``` |
|
|
sudo cp /etc/fstab /etc/fstab.bak; |
|
|
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab |
|
|
``` |
|
|
|
|
|
##3. NGINX |
|
|
[How To Install Nginx on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04) |
|
|
|
|
|
Install NGINX |
|
|
|
|
|
``` |
|
|
sudo apt-get update |
|
|
sudo apt-get install nginx |
|
|
``` |
|
|
|
|
|
Check status |
|
|
|
|
|
``` |
|
|
systemctl status nginx |
|
|
``` |
|
|
|
|
|
Tweak UFW firewall |
|
|
|
|
|
``` |
|
|
sudo ufw allow 'OpenSSH' |
|
|
sudo ufw allow 'Nginx Full' |
|
|
sudo ufw enable |
|
|
sudo ufw status |
|
|
``` |
|
|
|
|
|
Install CURL, get your IP, and check that you can request a page in your browser! |
|
|
|
|
|
``` |
|
|
sudo apt-get install curl |
|
|
curl -4 icanhazip.com |
|
|
``` |
|
|
|
|
|
**Actions*** |
|
|
|
|
|
``` |
|
|
sudo systemctl start nginx |
|
|
``` |
|
|
|
|
|
``` |
|
|
sudo systemctl stop nginx |
|
|
``` |
|
|
|
|
|
``` |
|
|
sudo systemctl restart nginx |
|
|
``` |
|
|
|
|
|
|
|
|
**Server Configuration** |
|
|
|
|
|
```/etc/nginx``` - The nginx configuration directory. All of the Nginx configuration files reside here. |
|
|
|
|
|
```/etc/nginx/nginx.conf``` The main Nginx configuration file. This can be modified to make changes to the Nginx global configuration. |
|
|
|
|
|
```/etc/nginx/sites-available/``` The directory where per-site "server blocks" can be stored. Nginx will not use the configuration files found in this directory unless they are linked to the sites-enabled directory (see below). Typically, all server block configuration is done in this directory, and then enabled by linking to the other directory. |
|
|
|
|
|
```/etc/nginx/sites-enabled/``` The directory where enabled per-site "server blocks" are stored. Typically, these are created by linking to configuration files found in the sites-available directory. |
|
|
|
|
|
```/etc/nginx/snippets``` This directory contains configuration fragments that can be included elsewhere in the Nginx configuration. Potentially repeatable configuration segments are good candidates for refactoring into snippets. |
|
|
|
|
|
**Server Logs** |
|
|
|
|
|
```/var/log/nginx/access.log``` Every request to your web server is recorded in this log file unless Nginx is configured to do otherwise. |
|
|
|
|
|
```/var/log/nginx/error.log``` Any Nginx errors will be recorded in this log. |
|
|
|
|
|
|
|
|
##4. ElasticSearch |
|
|
[How To Install and Configure Elasticsearch on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-elasticsearch-on-ubuntu-16-04) |
|
|
Elastic search requires at least 2GB of ram to work for some reason. |
|
|
|
|
|
Install JAVA |
|
|
|
|
|
``` |
|
|
sudo add-apt-repository ppa:webupd8team/java |
|
|
sudo apt-get install oracle-java8-installer |
|
|
``` |
|
|
|
|
|
Get ElasticSearch |
|
|
|
|
|
``` |
|
|
sudo apt-get update |
|
|
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.0.deb |
|
|
``` |
|
|
|
|
|
Install |
|
|
|
|
|
``` |
|
|
sudo dpkg -i elasticsearch-5.4.0.deb |
|
|
``` |
|
|
|
|
|
Remove DEB file |
|
|
|
|
|
``` |
|
|
rm elasticsearch-5.4.0.deb |
|
|
``` |
|
|
|
|
|
Enable |
|
|
|
|
|
``` |
|
|
sudo systemctl enable elasticsearch.service |
|
|
``` |
|
|
|
|
|
Configure |
|
|
|
|
|
``` |
|
|
sudo nano /etc/elasticsearch/elasticsearch.yml |
|
|
``` |
|
|
|
|
|
Edit Config File |
|
|
|
|
|
``` |
|
|
... |
|
|
cluster.name: mycluster1 |
|
|
node.name: "My First Node" |
|
|
... |
|
|
``` |
|
|
|
|
|
Restart |
|
|
|
|
|
``` |
|
|
sudo systemctl start elasticsearch.service |
|
|
``` |
|
|
|
|
|
Tweak UFW firewall |
|
|
|
|
|
``` |
|
|
sudo ufw allow from 127.0.0.1 to any port 9200 |
|
|
sudo ufw status |
|
|
``` |
|
|
|
|
|
Test |
|
|
|
|
|
``` |
|
|
curl -X GET 'http://localhost:9200' |
|
|
``` |
|
|
|
|
|
Status |
|
|
|
|
|
``` |
|
|
sudo systemctl status elasticsearch.service |
|
|
``` |
|
|
|
|
|
##5. RVM |
|
|
|
|
|
[How To Install Ruby on Rails with RVM on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rvm-on-ubuntu-16-04) |
|
|
|
|
|
Add key |
|
|
|
|
|
``` |
|
|
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 |
|
|
``` |
|
|
|
|
|
Move to a writeable directory |
|
|
|
|
|
``` |
|
|
cd /tmp |
|
|
``` |
|
|
|
|
|
Get latest Ruby |
|
|
|
|
|
``` |
|
|
curl -sSL https://get.rvm.io -o rvm.sh |
|
|
``` |
|
|
|
|
|
Compile |
|
|
|
|
|
``` |
|
|
cat /tmp/rvm.sh | bash -s stable --rails |
|
|
``` |
|
|
|
|
|
Reload your source file |
|
|
|
|
|
``` |
|
|
source /etc/profile.d/rvm.sh |
|
|
``` |
|
|
|
|
|
Install your Ruby VERSION |
|
|
|
|
|
``` |
|
|
rvm install VERSION --default |
|
|
``` |
|
|
|
|
|
##6. Rails |
|
|
[Deploying a Rails App on Ubuntu 14.04 with Capistrano, Nginx, and Puma](https://www.digitalocean.com/community/tutorials/deploying-a-rails-app-on-ubuntu-14-04-with-capistrano-nginx-and-puma) |
|
|
|
|
|
Install Rails and bundler |
|
|
|
|
|
``` |
|
|
gem install rails -v '5.0.1' -V --no-ri --no-rdoc |
|
|
gem install bundler -V --no-ri --no-rdoc |
|
|
``` |
|
|
|
|
|
Authorize your server to read from your repo, you'll have to add a deployment key to your repo. To do this you must copy your ```~/.ssh/id_rsa.pub``` file to your repo (make sure this is your deployment user, eg. ```rails```) |
|
|
|
|
|
``` |
|
|
ssh -T [email protected] |
|
|
ssh -T [email protected] |
|
|
ssh -T [email protected] |
|
|
``` |
|
|
|
|
|
Change Permissions on html directory |
|
|
|
|
|
``` |
|
|
sudo chown rails:rails /var/www/html/ |
|
|
``` |
|
|
|
|
|
Clone repo |
|
|
|
|
|
``` |
|
|
git clone [email protected]:gituser/example.git |
|
|
``` |
|
|
|
|
|
Add your local key to the server, if this doesn't work just add your local public key (id_rsa.pub) to ```/home/rails/.ssh/authorized_keys``` |
|
|
|
|
|
``` |
|
|
ssh-copy-id [email protected] |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
##7. Postgres |
|
|
[How To Install and Use PostgreSQL on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-16-04) |
|
|
|
|
|
Install Postgres |
|
|
|
|
|
``` |
|
|
sudo apt-get update |
|
|
sudo apt-get install postgresql postgresql-contrib |
|
|
``` |
|
|
|
|
|
Create 'rails' postgres user |
|
|
|
|
|
``` |
|
|
sudo -i -u postgres |
|
|
createuser --interactive |
|
|
``` |
|
|
|
|
|
Make it look like this: |
|
|
|
|
|
``` |
|
|
Enter name of role to add: rails |
|
|
Shall the new role be a superuser? (y/n) y |
|
|
``` |
|
|
|
|
|
Create the database for rails user |
|
|
|
|
|
``` |
|
|
createdb rails |
|
|
``` |
|
|
|
|
|
libpq has to be installed separately |
|
|
|
|
|
``` |
|
|
sudo apt-get install libpq-dev |
|
|
``` |
|
|
|
|
|
##8. Capistrano |
|
|
|
|
|
Add gems to deployment |
|
|
|
|
|
``` |
|
|
group :development do |
|
|
gem 'capistrano' |
|
|
gem 'capistrano-rails' |
|
|
gem 'capistrano-rvm' |
|
|
gem 'capistrano3-puma', github: 'seuros/capistrano-puma' |
|
|
gem 'capistrano-bundler' |
|
|
gem 'capistrano-rails-console' |
|
|
end |
|
|
``` |
|
|
|
|
|
Install Capistrano |
|
|
|
|
|
``` |
|
|
cap install |
|
|
``` |
|
|
|
|
|
Capfile |
|
|
|
|
|
``` |
|
|
require 'capistrano/setup' |
|
|
require 'capistrano/deploy' |
|
|
require 'capistrano/rails' |
|
|
require 'capistrano/rvm' |
|
|
require 'capistrano/bundler' |
|
|
require 'capistrano/puma' |
|
|
require 'capistrano/scm/git' |
|
|
require 'capistrano/rails/console' |
|
|
|
|
|
set :rvm_type, :user |
|
|
set :rvm_ruby_version, '2.3.1' |
|
|
install_plugin Capistrano::Puma |
|
|
install_plugin Capistrano::SCM::Git |
|
|
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } |
|
|
|
|
|
``` |
|
|
|
|
|
Deploy.rb, replace (APP_NAME) |
|
|
|
|
|
``` |
|
|
lock "3.8.1" |
|
|
|
|
|
set :application, "APP_NAME" |
|
|
set :repo_url, "[email protected]:gituser/example.git" |
|
|
set :deploy_to, "/home/rails/html" |
|
|
set :pty, true |
|
|
set :puma_conf, "#{shared_path}/config/puma.rb" |
|
|
|
|
|
append :linked_files, "config/database.yml", "config/secrets.yml", ".env" |
|
|
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" |
|
|
``` |
|
|
|
|
|
Production.rb, replace SERVER_IP |
|
|
|
|
|
``` |
|
|
server 'SERVER_IP', user: 'rails', roles: %w{app db web} |
|
|
``` |
|
|
|
|
|
Create shared config files |
|
|
|
|
|
``` |
|
|
mkdir -p /var/www/html/shared/config |
|
|
touch /var/www/html/shared/config/database.yml |
|
|
touch /var/www/html/shared/config/secrets.yml |
|
|
touch /var/www/html/shared/config/puma.rb |
|
|
touch /home/rails/html/shared/.env |
|
|
|
|
|
``` |
|
|
|
|
|
Copy config in databse.yml |
|
|
|
|
|
``` |
|
|
production: |
|
|
adapter: postgresql |
|
|
encoding: unicode |
|
|
pool: 5 |
|
|
database: APP_PRODUCTION |
|
|
username: rails |
|
|
url: localhost |
|
|
password: <%= ENV['DATABASE_PASSWORD'] %> |
|
|
``` |
|
|
|
|
|
Copy config into secrets.yml |
|
|
|
|
|
``` |
|
|
production: |
|
|
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> |
|
|
``` |
|
|
|
|
|
Copy config into .env |
|
|
|
|
|
``` |
|
|
SECRET_KEY_BASE=mysupersecretkeybase |
|
|
DATABASE_URL=127.0.0.1 |
|
|
DATABASE_PASSWORD=mysupersecretdatabasepassword |
|
|
``` |
|
|
|
|
|
Copy config in puma.rb |
|
|
|
|
|
``` |
|
|
#!/usr/bin/env puma |
|
|
|
|
|
directory '/home/rails/html/current' |
|
|
rackup "/home/rails/html/current/config.ru" |
|
|
environment 'production' |
|
|
|
|
|
tag '' |
|
|
|
|
|
pidfile "/home/rails/html/shared/tmp/pids/puma.pid" |
|
|
state_path "/home/rails/html/shared/tmp/pids/puma.state" |
|
|
stdout_redirect '/home/rails/html/shared/log/puma_access.log', '/home/rails/html/shared/log/puma_error.log', true |
|
|
|
|
|
threads 0,16 |
|
|
|
|
|
bind 'unix:///home/rails/html/shared/tmp/sockets/puma.sock' |
|
|
|
|
|
workers 0 |
|
|
|
|
|
prune_bundler |
|
|
|
|
|
on_restart do |
|
|
puts 'Refreshing Gemfile' |
|
|
ENV["BUNDLE_GEMFILE"] = "/home/rails/html/current/Gemfile" |
|
|
end |
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
May need Node.js for Javascript Runtime |
|
|
|
|
|
``` |
|
|
sudo apt-get install nodejs |
|
|
``` |
|
|
|
|
|
|
|
|
##9 Let's Encrypt |
|
|
[How To Secure Nginx with Let's Encrypt on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04) |
|
|
|
|
|
Install Certbot |
|
|
|
|
|
``` |
|
|
sudo add-apt-repository ppa:certbot/certbot |
|
|
sudo apt-get update |
|
|
sudo apt-get install certbot |
|
|
``` |
|
|
|
|
|
Edit NGINX |
|
|
|
|
|
``` |
|
|
sudo nano /etc/nginx/sites-available/default |
|
|
``` |
|
|
|
|
|
Inside the server block, add this location block |
|
|
|
|
|
``` |
|
|
location ~ /.well-known { |
|
|
allow all; |
|
|
} |
|
|
``` |
|
|
|
|
|
Check your NGINX config file |
|
|
|
|
|
``` |
|
|
sudo nginx -t |
|
|
``` |
|
|
|
|
|
Restart NGINX |
|
|
|
|
|
``` |
|
|
sudo systemctl restart nginx |
|
|
``` |
|
|
|
|
|
Get your cert (make sure you know your webroot) |
|
|
|
|
|
``` |
|
|
sudo certbot certonly --webroot --webroot-path=/var/www/html -d example.com -d www.example.com |
|
|
``` |
|
|
|
|
|
Generate strong diff |
|
|
|
|
|
``` |
|
|
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 |
|
|
``` |
|
|
|
|
|
Create configuration snippet |
|
|
|
|
|
``` |
|
|
sudo nano /etc/nginx/snippets/ssl-example.com.conf |
|
|
``` |
|
|
|
|
|
Paste in your certificates |
|
|
|
|
|
``` |
|
|
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; |
|
|
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; |
|
|
``` |
|
|
|
|
|
Create strong encryption params |
|
|
|
|
|
``` |
|
|
sudo nano /etc/nginx/snippets/ssl-params.conf |
|
|
``` |
|
|
|
|
|
Paste in params |
|
|
|
|
|
``` |
|
|
# from https://cipherli.st/ |
|
|
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html |
|
|
|
|
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; |
|
|
ssl_prefer_server_ciphers on; |
|
|
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; |
|
|
ssl_ecdh_curve secp384r1; |
|
|
ssl_session_cache shared:SSL:10m; |
|
|
ssl_session_tickets off; |
|
|
ssl_stapling on; |
|
|
ssl_stapling_verify on; |
|
|
resolver 8.8.8.8 8.8.4.4 valid=300s; |
|
|
resolver_timeout 5s; |
|
|
# disable HSTS header for now |
|
|
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; |
|
|
add_header X-Frame-Options DENY; |
|
|
add_header X-Content-Type-Options nosniff; |
|
|
|
|
|
ssl_dhparam /etc/ssl/certs/dhparam.pem; |
|
|
``` |
|
|
|
|
|
##Nginx Server finalization |
|
|
[How To Secure Nginx with Let's Encrypt on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04) |
|
|
|
|
|
create a new Nginx config file |
|
|
|
|
|
``` |
|
|
touch /etc/nginx/sites-available/rails |
|
|
chmod 644 rails |
|
|
``` |
|
|
|
|
|
Update your APPLICATIONSOCKET.sock, server_name, snippet location |
|
|
|
|
|
``` |
|
|
upstream app_server { |
|
|
server unix:///home/rails/html/shared/tmp/sockets/APPLICATIONSOCKET.sock fail_timeout=0; |
|
|
} |
|
|
|
|
|
server { |
|
|
listen 80 default_server; |
|
|
listen [::]:80 default_server; |
|
|
server_name EXAMPLE.COM; |
|
|
return 301 https://$server_name$request_uri; |
|
|
} |
|
|
|
|
|
server { |
|
|
# SSL configuration |
|
|
listen 443 ssl http2 default_server; |
|
|
listen [::]:443 ssl http2 default_server; |
|
|
|
|
|
include snippets/ssl-example.com.conf; |
|
|
include snippets/ssl-params.conf; |
|
|
|
|
|
root /home/rails/html/current/public; |
|
|
|
|
|
index index.htm index.html; |
|
|
|
|
|
location / { |
|
|
try_files $uri/index.html $uri.html $uri @app; |
|
|
} |
|
|
|
|
|
location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ { |
|
|
try_files $uri @app; |
|
|
} |
|
|
|
|
|
location @app { |
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
|
|
proxy_set_header X-Forwarded-Proto $scheme; |
|
|
proxy_set_header Host $http_host; |
|
|
proxy_redirect off; |
|
|
proxy_pass http://app_server; |
|
|
} |
|
|
|
|
|
location ~ /.well-known { |
|
|
allow all; |
|
|
} |
|
|
|
|
|
error_page 500 502 503 504 /500.html; |
|
|
client_max_body_size 4G; |
|
|
keepalive_timeout 10; |
|
|
} |
|
|
``` |
|
|
|
|
|
Update symobolic link |
|
|
|
|
|
``` |
|
|
cd /etc/nginx/sites-enabled |
|
|
rm default |
|
|
ln -s /etc/nginx/sites-available/rails default |
|
|
``` |
|
|
|
|
|
Restart NGINX |
|
|
|
|
|
``` |
|
|
sudo systemctl restart nginx |
|
|
``` |
|
|
|