Skip to content

Instantly share code, notes, and snippets.

@jfcampos1
Last active June 25, 2020 00:04
Show Gist options
  • Save jfcampos1/04e73948d9073be7a6a7403154504135 to your computer and use it in GitHub Desktop.
Save jfcampos1/04e73948d9073be7a6a7403154504135 to your computer and use it in GitHub Desktop.
Rails server setup with passenger, Nginx via apt, SSL

Indice

Esta guía toma menor tiempo de instalación que esta otra, además de evitar tener que agregar una ruta a tu proyecto para obtener los certificados https

PASO 1 - Usuario deploy y deshabilitar root login

Este paso es muy importante para que no tengas problemas de permisos despues con passenger.

Creando el usuario deploy y darle privilegios de sudo

sudo adduser deploy
sudo adduser deploy sudo
su - deploy

HABILITAR ssh para el user deploy:

su - deploy
mkdir .ssh
chmod 700 .ssh
nano .ssh/authorized_keys

Pegar clave ssh de tu computador en el nuevo archivo .ssh/authorized_keys

Guardar y cambiar el permiso de lectura del archivo con:

chmod 600 .ssh/authorized_keys

Salir y entrar ahora como deploy@IPMAQUINA debería funcionar sin problemas.

Correr comandos sudo sin la clave:

sudo visudo

Pegar al final de todo

deploy ALL=(ALL) NOPASSWD:ALL y reemplaza username por tu usuario

Desabilitar el usuario root:

Es un paso para no permitir el acceso facilmente a tu servidor.

Deshabilitando el login ssh para el usuario Root, tienes que estar conectado con el usuario deploy:

Cambiar en el archivo sshd_config, yes a no: sudo nano /etc/ssh/sshd_config

PermitRootLogin yes
PermitRootLogin no

Reiniciar el servicio de ssh: sudo service ssh restart

PASO 2 - Configurar TimeZone

sudo dpkg-reconfigure tzdata Selecciona la zona horaria en a que quieres que el servidor este.

Configura NTP Synchronization

NTP sirve para mantener tu horario actualizado en el tiempo, permitiendo que se ajuste a los cambios en tu zona horaria.

sudo apt-get update
sudo apt-get install ntp

Eso es todo, NTP mantendra actualizada tu hora.

PASO 3 - Agregar swap space (Opcional)

Agregar swap para servidores con poca RAM Encontraras lo mismo en esta guia Add swap

Para ver si existe swap actualmente: sudo swapon --show

Creando un swap file

Reemplaza 1G por la cantidad de espacio que quieras asignar(ej: 2G, 3G, 4G):

sudo fallocate -l 1G /swapfile

Setea los permisos, crea el espacio y activalo con:

sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Has el cambio permanente agregando al final de /etc/fstab con:

sudo nano /etc/fstab

esta linea: /swapfile swap swap defaults 0 0

Listo ahora puedes ver que quedo creado el espacio con:

sudo swapon --show
sudo free -h

PASO 4 - Instalación de Rbenv, Ruby y Rails

Encontraras casi mismo en esta guia goRails

Primero instalaremos curl, yarn y node.js para que funcione correctamente rails:

sudo apt install curl
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

Actualiza lo paquetes:

sudo apt-get update
sudo apt-get upgrade

Instala las dependencias necesarias:

sudo apt-get install git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev nodejs yarn

Instalación de Rbenv:

cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL

Instalación de Ruby:

rbenv install 2.6.5
rbenv global 2.6.5
ruby -v

Antes de instalar gemas setear para que no se instale la documentación: echo "gem: --no-rdoc --no-ri" >> .gemrc

Instalación de Rails:

gem install rails -v 5.1.7
rails -v

Instala Bundler:

gem install bundler

Despues de instalar bundler y rails:

rbenv rehash

PASO 5 - Instalación de Passenger y Nginx

En esta guia instalaremos passenger y Nginx via apt.

Preparación

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update

Instala Passenger y Nginx

sudo apt-get install -y nginx-extras libnginx-mod-http-passenger

Al finalizar la instalación tienes que configurar algunas cosas de Nginx

Crea un symlink al modulo de passenger en Nginx:

if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi

sudo ls /etc/nginx/conf.d/mod-http-passenger.conf

Ahora necesitamos que passenger apunte a la correcta version de ruby.

Editamos el siguiente archivo:

sudo nano /etc/nginx/conf.d/mod-http-passenger.conf

cambiando la linea de passenger_ruby por:

passenger_ruby /home/deploy/.rbenv/shims/ruby;

Inicia Nginx sudo service nginx start

PASO 6 - Configura git y clona tu proyecto

Agrega tu nombre, email y crea un sshkey para tu email

ssh-keygen -t rsa -b 4096

Copia el ssh key, lo encontraras asi: cat ~/.ssh/id_rsa.pub

Agregalo en github, lo deberias encontrar en configuraciones > SSH and GPT keys.

Clona tu proyecto.

PASO 7 - Instala postgres y crea un usuario

Instala Postgres

sudo apt install postgresql libpq-dev

Crear el usuario deploy y la DB de la aplicación

sudo su - postgres
createuser --interactive --pwprompt

PASO 8 - Configura tu aplicación

Instala bundler y el resto de las gemas

Entra a tu proyecto y instala todo lo necesario con bundle:

cd my_awesome_rails_app
bundle config set without 'development test'
bundle install

Genera y Agrega el secret_key

Genera un secret key para tu aplicación: RAILS_ENV=production rake secret

Agrega un .env con el secret_key: SECRET_KEY_BASE=sdslksjdjdls

Agrega la configuración de postgres:

En config/database.yml:

default: &default
  adapter: postgresql
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  host: localhost
  encoding: utf-8
  username: <%= ENV["MYAPP_DATABASE_USERNAME"] %>
  password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>

production:
  <<: *default
  database: my_awesome_rails_app_server

Crea y migra la base de datos

RAILS_ENV=production rails db:create
RAILS_ENV=production rails db:migrate

Precompila tus assets:

Importante

Si por alguna razon tus assets no cargan como esperas, bloked Cors o simplemente no se muestran. Revisa que tu asset_path en config/enviroments/production.rb sea el correcto y despues precompilar tus assets: config.action_controller.asset_host = 'https://pagina.cl/' # o lo que pusiste en tu server_name

RAILS_ENV=production bundle exec rake assets:precompile (asegurate de tener yarn instalado)

PASO 9 - Conecta Nginx con tu proyecto

Para esto primero eliminamos la configuración default.

sudo rm /etc/nginx/sites-enabled/default

Ahora creamos la nueva configuación en:

sudo nano /etc/nginx/sites-available/myapp

Rellenando con:

  • Cambia el server_name por la ip de tu servidor
  • Cambia el root por el path a la carpeta public de tu proyecto
server {
  listen 80 default_server;
  listen [::]:80 default_server;

  server_name ip;
  passenger_enabled on;
  passenger_app_env production;

  root /home/deploy/my_awesome_rails_app/public;
  
  # location /cable {
  #   passenger_app_group_name myapp_websocket;
  #   passenger_force_max_concurrent_requests_per_process 0;
  # }
}

Creamos un symlink para este archivo:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp

Con esto ya tienes listo toda la configuración de Nginx por el momento.

Reinicia Nginx y deberias poder ver tu pagina en el server_name que indicaste

sudo service nginx restart

Con esto ya deberias tener tu aplicación funcionando en la ip de tu servidor con http y deberia funcionar como normalmente.

Ahora setearemos el Dominio(pagina.com o www.pagina.com) de tu pagina y los certificados SSL para que quede con https.

PASO 10 - Configura tu dominio

Existen multiples maneras de registrar tu dominio y de guardarlo en un DNS. En mi caso ocupe el servicio de DigitalOcean.

En Networking agrega tu dominio

alt text

Tienes que crear dos dominios:

  1. pagina.com
  2. www.pagina.com

Seleccionalo y direcciona tu dominio a tu servidor

Para ambos dominios tienes que hacer lo siguiente: Selecciona la pestaña "A": alt text

Donde dice "HOSTNAME" ingresa un @ y en "WILL DIRECT TO" selecciona tu servidor o la ip de este.

En el caso de tu dominio www., tambien tienes que agregar un cname. Selecciona la pestaña "CNAME":

Donde dice "HOSTNAME" ingresa un tu dominio completo(www.pagina.com), si se vera como duplicado pero esta bien.

En "IS AN ALIAS OF" ingresa un @.

Agrega los servidores de Digital Ocean a la pagina donde conseguiste tu dominio

En mi caso fue nicChile

Los servidores a agregar de digitalOcean son tres:

  • ns1.digitalocean.com
  • ns2.digitalocean.com
  • ns3.digitalocean.com

Agrega tu dominio a Nginx

En sudo nano /etc/nginx/sites-available/myapp, cambia el server_name ip;.

Por tus dominios:

server_name pagina.com www.pagina.com;

Ahora deberias poder ingresar a tu pagina con solo ingresar tu dominio.

PASO 11 - Genera tus certificados https

Para generar tus certificados, utilizaremos la opción de generar e instalar los certificados de cerbot.

Instala Cerbot y Genera tu certificado

Instala Cerbot:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update

sudo apt-get install certbot python-certbot-nginx

Genera tu certificado:

sudo certbot --nginx

Deberia preguntar un par de cosas, la primera deberia ser esta:

Apreta enter solamente, para que genere el certificado para ambos.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: pagina.cl
2: www.pagina.cl
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

Despues preguntara esto:

En este caso prefiero seleccionar la primera opción y configurar el resto personalmente.
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1

Finalmente deberias obtener un ouput parecido a este:

Congratulations! You have successfully enabled https://pagina.cl and
https://www.pagina.cl

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=pagina.cl
https://www.ssllabs.com/ssltest/analyze.html?d=www.pagina.cl
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/pagina.cl/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/pagina.cl/privkey.pem
   Your cert will expire on 2020-05-08. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Revisa que se renueve automaticamente:

sudo certbot renew --dry-run

Puedes revisar el cron creado en alguno de estos tres path:

/etc/crontab/
/etc/cron.*/*
systemctl list-timers

En mi caso esta en el tercero 👀

Ahora deberias revisar que puede acceder a tu sitio por https 🙌🙌🙌

PASO 12 - Configuración final de Nginx con SSL

Cerbot instalo los certificados en /etc/nginx/sites-available/myapp, pero los moveremos a /etc/nginx/nginx.conf.

Aprovecharemos de configurar correctamente la redirección de http a https:

Redirecciona los request http a https

Entra a sudo nano /etc/nginx/sites-available/myapp.

Vamos a redireccionar todo los request a un solo server_name para evitar tener problemas con los assets despues.

Cambia tu bloque del server 80 por este:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name pagina.com www.pagina.com;
    return 301 https://pagina.com$request_uri;
}

y agrega este:

server {
    listen 443 ssl;
    server_name www.pagina.com;
    return 301 https://pagina.com$request_uri;
}

Agrega el bloque para https

Ahora en el mismo archivo agrega un bloque para el server 443(https):

server {
    listen [::]:443 ssl ipv6only=on;
    listen 443 ssl;
    server_name pagina.com;

    passenger_enabled on; 
    root /home/deploy/my_awesome_rails_app/public; 
       
    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

Guarda el archivo.

Agrega a Nginx tu certificados

Ahora cambiaremos el archivo /etc/nginx/nginx.conf para agregar tus certificados.

Entra a sudo nano /etc/nginx/nginx.conf

Dentro del bloque de http, agrega las 5 lineas que dicen ssl_*:

    include       mime.types;
    default_type  application/octet-stream;
    
    ##
    # SSL Settings
    ##

    ssl_certificate /etc/letsencrypt/live/pagina.cl/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/pagina.cl/privkey.pem; # managed by Certbot
    ssl_trusted_certificate /etc/letsencrypt/live/pagina.cl/chain.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

Borra las lineas que exitian previamente con ssl_*:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

Guarda y reinicia Nginx con sudo service nginx restart.

Deberias poder ingresar a tu pagina y que sea https.

Finalmente tu archivos Nginx deberian quedar asi:

nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

        ssl_certificate /etc/letsencrypt/live/pagina.cl/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/pagina.cl/privkey.pem; # managed by Certbot
        ssl_trusted_certificate /etc/letsencrypt/live/pagina.cl/chain.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##
	
	gzip on;
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 16 8k;
        gzip_http_version 1.1;    
        gzip_types *;
        gzip_disable "MSIE [1-6].(?!.*SV1)";

	##
	# Virtual Host Configs
	##

        # Allow uploads up to 100MB in size
        client_max_body_size 100m;

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

sites-available/myapp
server {
    listen [::]:443 ssl ipv6only=on;
    listen 443 ssl;
    server_name pagina.cl;

    passenger_enabled on; 
    root /home/deploy/my_awesome_rails_app/public;
       
    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name pagina.cl www.pagina.cl;
    return 301 https://pagina.cl$request_uri;
}

server {
    listen 443 ssl;
    server_name www.pagina.cl;
    return 301 https://pagina.cl$request_uri;
}

Para este tutorial, segui indicaciónes de los siguientes tutoriales:

  1. Create Swap
  2. Install Rbenv, Ruby, Rails, Git, Passenger, Nginx
  3. Cerbot
  4. Config SSL
  5. SSL Labs to test your SSL configuration

Paths utiles de Nginx

Para entrar a tu archivo de configuración:

sudo nano /etc/nginx/nginx.conf

sudo nano /etc/nginx/sites-available/myapp

Para ver los logs:

sudo cat /var/log/nginx/error.log

sudo cat /var/log/nginx/access.log

Errores comunes

Si por alguna razon tus assets no cargan como esperas, bloked Cors o simplemente no se muestran. Revisa que tu asset_path en config/enviroments/production.rb sea el correcto y despues precompilar tus assets: config.action_controller.asset_host = 'https://pagina.cl/' # o lo que pusiste en tu server_name

RAILS_ENV=production bundle exec rake assets:precompile (asegurate de tener yarn instalado)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment