Skip to content

Instantly share code, notes, and snippets.

@jfcampos1
Last active July 7, 2020 17:16
Show Gist options
  • Save jfcampos1/769acf77c08e8e210a4d875dddcc75ab to your computer and use it in GitHub Desktop.
Save jfcampos1/769acf77c08e8e210a4d875dddcc75ab to your computer and use it in GitHub Desktop.
Rails server setup with passenger, Nginx, SSL

Indice

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

username 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 manendra 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 RVM, Ruby y Rails

Encontraras casi mismo en esta guia goRails

Actualiza lo paquetes:

sudo apt-get update
sudo apt-get upgrade

Instala curl y yarn con:

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

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 RVM:

sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable

Despues corre el comando que dice rvm al final de su instalación, al menos para mi fue este:

source /home/deploy/.rvm/scripts/rvm

Conviene relogear despues de esto.

Instalación de Ruby:

rvm install 2.7.0
rvm use 2.7.0 --default
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

PASO 5 - Instalación de Passenger y Nginx

Passenger configurara Nginx y lo conectara a tu proyecto, permitiendo que este parta automaticamente.

Instala passenger

gem install passenger

Instala Nginx a travez de passenger

rvmsudo passenger-install-nginx-module

Aqui tendras que decirle que quieres que instale Nginx automaticamente y en el path recomendado. (Basicamente apreta enter hasta el final)

Esto tomara facil 10 minutos, puedes ir a hacerte un cafe y comer algo si quieres.

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

Descarga, mueve y haz ejecutable el script de inicio de Nginx:

wget -O init-deb.sh https://www.linode.com/docs/assets/660-init-deb.sh
sudo mv init-deb.sh /etc/init.d/nginx
sudo chmod +x /etc/init.d/nginx
sudo /usr/sbin/update-rc.d -f nginx defaults

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
exit

PASO 8 - Configura tu aplicación

Instala bundler y el resto de las gemas

gem install bundler
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

PASO 9 - Conecta Nginx con tu proyecto

Entra al archivo de configuación de Nginx: sudo vim /opt/nginx/conf/nginx.conf

  • Cambia el server_name por la ip de tu servidor
  • Agrega passenger_enabled on
  • Cambia el root por el path a la carpeta public de tu proyecto
server { 
listen 80; 
server_name example.com; 
passenger_enabled on; 
root /home/deploy/my_awesome_rails_app/public; 
}

Guarda y reinicia Nginx con sudo service nginx restart

Errores comunes

Error opening '/home/deploy/my_awesome_rails_app/current/Passengerfile.json' for reading: Permission denied (errno=13);

Este error lo puedes encontrar al ver tus log de nginx en: cat /opt/nginx/logs/error.log Para corregirlo tienes que hacer ejecutable tu home directory con el siguiente comando:

chmod o+x $HOME

Si hay error de css, precompila:

Este error lo puedes encontrar al ver tus log de nginx en: cat /tu-aplicacion/logs/production.log RAILS_ENV=production bundle exec rake assets:precompile (asegurate de tener yarn instalado)

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

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 /opt/nginx/conf/nginx.conf, 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

Intalaremos letsencrypt para generar los certificados, pero para que funcione todo, letsencrypt hara un request a una ruta especifica de tu pagina (.well-known/acme-challenge/)y si le respondes correctamente te dara el certificado. Por lo tanto necesitamos primero agregar esa ruta a nuestra aplicación.

Agregar ruta en tu aplicación

En Rails, crearemos la ruta primero en config/routes.rb:

get '/.well-known/acme-challenge/:challenge', to: 'pages#letsencrypt'

pages es mi controlador Page y letsencrypt mi metodo, puedes ocupar el controlador y metodo que prefieras.

Luego en PagesController

class PagesController < ApplicationController
  def letsencrypt
    render plain: params[:challenge], layout: false
  end
end

Si tienes CanCan recuerda agregar los permisos necesarios con: can :letsencrypt, Page

Una vez subido esto a tu servidor, continua con el tutorial.

Instala Letsencrypt y Genera tu certificado

Instala Letsencrypt:

apt-get update
apt-get install -y git
git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
cd /opt/letsencrypt
./letsencrypt-auto

Genera tu certificado:

Ubicate en la carpeta correcta: cd /opt/letsencrypt cd /opt/letsencrypt/ ./letsencrypt-auto certonly -a webroot --webroot-path=/home/deploy/my_awesome_rails_app/public -d pagina.com -d www.pagina.com

Deberia ser un ouput parecido a este:

Checking for new version...
Requesting root privileges to run letsencrypt...
/root/.local/share/letsencrypt/bin/letsencrypt certonly -a webroot --webroot-path=/home/deploy/my_awesome_rails_app/public -d pagina.com -d www.pagina.com

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/pagina.com/fullchain.pem. Your cert will
expire on 2016-07-13. To obtain a new version of the certificate in
the future, simply run Let's Encrypt again.
- If you 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

Configura que se renueve automatico:

Crea el archivo sudo nano /opt/letsencrypt/renew-letsencrypt.sh y copia lo siguiente:

#!/bin/sh

cd /opt/letsencrypt/
./letsencrypt-auto renew

if [ $? -ne 0 ]
then
ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log`
echo -e "The Let's Encrypt cert has not been renewed! \n \n" \
$ERRORLOG
else
nginx -s reload
fi

exit 0

Agrega un crontab para que corra cada dos meses, crontab -e:

0 0 1 JAN,MAR,MAY,JUL,SEP,NOV * /opt/letsencrypt/renew-letsencrypt.sh

Genera tu archivo con los parametros de Diffie-Hellman:

Ejecuta el comando:

openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 2048

PASO 12 - Configuración final de Nginx con SSL

Agrega a Nginx tu certificados

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

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

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

    ssl_certificate /etc/letsencrypt/live/pagina.cl/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pagina.cl/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/pagina.cl/chain.pem;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

Redirecciona los request http a https

Dentro del bloque http agrega los siguientes bloques:

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

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

Agrega el bloque para 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 y reinicia Nginx con sudo service nginx restart.

Deberias poder ingresar a tu pagina y que sea https.

Agrega configuraciones para ssl

Crea un archivo en sudo nano /etc/letsencrypt/options-ssl-nginx.conf

Agrega esto al archivo:

ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";


add_header X-Frame-Options SAMEORIGIN;

Ahora incluye este archivo a tu configuración de Nginx sudo nano /opt/nginx/conf/nginx.conf

En el bloque de http: include /etc/letsencrypt/options-ssl-nginx.conf;

Finalmente tu archivo Nginx.conf deberia quedar asi:

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    passenger_root /home/deploy/.rvm/gems/ruby-2.6.5/gems/passenger-6.0.4;
    passenger_ruby /home/deploy/.rvm/gems/ruby-2.6.5/wrappers/ruby;

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

    ssl_certificate /etc/letsencrypt/live/pagina.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pagina.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/pagina.com/chain.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;


    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;
    client_max_body_size 10m;
    
    #gzip  on;
    gzip on;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_proxied any;
    gzip_types *;
    gzip_buffers 16 8k;
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    server {
        return 404;
    }

    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;
        }
    }

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

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

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

  1. Install Passenger, Nginx
  2. Create Swap
  3. Install RVM, Ruby, Rails, Git
  4. Route Letsencrypt on Rails app
  5. Letsencrypt certificate y Renewal
  6. Diffie-Hellman parameters
  7. Config SSL
  8. SSL Labs to test your SSL configuration

Paths utiles de Nginx

Para entrar a tu archivo de configuración:

sudo nano /opt/nginx/conf/nginx.conf

Para ver los logs:

cat /opt/nginx/logs/error.log

@FJavierOss
Copy link

Esta buenisimo

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