Skip to content

Instantly share code, notes, and snippets.

@sebackend
Last active December 9, 2021 20:22
Show Gist options
  • Save sebackend/894765f3bb6896254bf2c1857d98f92c to your computer and use it in GitHub Desktop.
Save sebackend/894765f3bb6896254bf2c1857d98f92c to your computer and use it in GitHub Desktop.

1.- Crear nuevo usuario

Para evitar entrar como usuario root, crear otro usuario y darle permisos de sudo

$ sudo adduser deploy

2.- Otorgar permisos de sudo

$ sudo gpasswd -a deploy sudo

3.- Agregar Public Key Authentication (SSH)

Generarla en la máquina local

local$ ssh-keygen
local$ cat ~/.ssh/id_rsa.pub

Pegarla en el servidor, dentro de authorized_keys

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

Luego dar permisos nuevamente

$ chmod 600 .ssh/authorized_keys

4.- Deshabilitar login como root (OPCIONAL)

Entrar a la cuenta root

# nano /etc/ssh/sshd_config

PermitRootLogin yes -> no

Reiniciar el servicio SSH

$ sudo service ssh restart

Salir del servidor e intentar entrar nuevamente para probar que el acceso root quedó deshabilitado.

Correr comandos sudo sin la clave

$ sudo visudo

#Pegar al final de todo
deploy ALL=(ALL) NOPASSWD:ALL

6.- Configurar Timezones y Synch NTP

Timezone

$ sudo dpkg-reconfigure tzdata

NTP

$ sudo apt-get update
$ sudo apt-get install ntp

7.- Agregar memoria Swap

Comprobar si existe swap

$ free -h

Verificar cuanto espacio disponemos de Disco

$ df -h

Agregar 1G de memoria SWAP

$ sudo fallocate -l 1G /swapfile

Verificar

$ ls -lh /swapfile

Habilitar espacio SWAP

$ sudo chmod 600 /swapfile

Verificar los permisos:

$ ls -lh /swapfile

Marcar el espacio como espacio swap

$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ sudo swapon --show
$ free -h

Make the Swap File Permanent

$ sudo cp /etc/fstab /etc/fstab.bak
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Tweak your Swap Settings

$ cat /proc/sys/vm/swappiness

Output
60

For a Desktop, a swappiness setting of 60 is not a bad value. For a server, you might want to move it closer to 0.

We can set the swappiness to a different value by using the sysctl command. For instance, to set the swappiness to 10, we could type:

$ sudo sysctl vm.swappiness=10

This setting will persist until the next reboot. We can set this value automatically at restart by adding the line to our /etc/sysctl.conf file:

$ sudo nano /etc/sysctl.conf

At the bottom, you can add:

vm.swappiness=10
Adjusting the Cache Pressure Setting
$ cat /proc/sys/vm/vfs_cache_pressure

Output
100

As it is currently configured, our system removes inode information from the cache too quickly. We can set this to a more conservative setting like 50 by typing:

sudo sysctl vm.vfs_cache_pressure=50

Output
vm.vfs_cache_pressure = 50

Again, this is only valid for our current session. We can change that by adding it to our configuration file like we did with our swappiness setting:

$ sudo nano /etc/sysctl.conf

At the bottom, add the line that specifies your new value

vm.vfs_cache_pressure=50

8.- Instalar Node

Agregar dependencias

sudo apt update
sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -

Instalar node en su versión 12

sudo apt -y install nodejs

9.- Instalar Ruby (con RVM)

Instalar algunas dependencias base

$ 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

$ sudo apt-get update
$ 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 yarn

Instalar gnupg2

sudo apt install gnupg2

Instalar RVM y Ruby

$ cd /tmp
$ sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
$ curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -
$ curl -sSL https://rvm.io/pkuczynski.asc | gpg2 --import -
$ curl -sSL https://get.rvm.io | bash -s stable
$ source ~/.rvm/scripts/rvm
$ rvm install x.x.x
$ rvm use x.x.x --default
$ ruby -v

Instalar la version de Rails que corresponda

$ gem install rails -v x.x.x --no-document

Instalar Bundler:

$ gem install bundler

10.- Configurar GIT y clave ssh

$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
$ ssh-keygen
$ cat /home/deploy/.ssh/id_rsa.pub
$ ssh -T [email protected]
$ ssh -T [email protected]

11.- Instalar Postgres

$ sudo apt install postgresql libpq-dev

Crear el usuario deploy y la base de datos para la aplicación

$ sudo su - postgres
$ createuser --pwprompt deploy # preguntará por password, será la password para acceder a la base de datos
$ createdb -O deploy database_app_name # nombre de la base de datos de la app
$ exit

OJO, los datos ingresados anteriormente, son lo que van en el archivo database.yml más adelante

12.- DEPLOY

[OPCION 1] Capistrano + Passenger

Agregar las dependencias necesarias

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'
echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger focal main" | sudo tee /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

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

Y modificamos sólo la líne que dice passenger_ruby por

passenger_ruby /home/deploy/.rvm/rubies/ruby-2.4.2/bin/ruby; # modificar por la version que corresponda

Iniciamos el servicio de nginx

sudo service nginx start

Next we're going to remove this default NGINX server and add one for our application instead.

$ sudo rm /etc/nginx/sites-enabled/default
$ sudo nano /etc/nginx/sites-enabled/nombre_app
``` console

Y pegar la siguiente configuración
``` console
server {
  listen 80;
  listen [::]:80;

  server_name IP_SERVER;
  root /home/deploy/app_folder_name/current/public;

  passenger_enabled on;
  passenger_app_env production;

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

  location ~ ^/(assets|packs) {
    expires max;
    gzip_static on;
  }
}

Reniciar servicio de nginx

$ sudo service nginx reload

Agregar Capistrano al Gemfile

group :development do
  gem 'capistrano',                 require: false
  gem 'capistrano-rvm',             require: false
  gem 'capistrano-rails',           require: false
  gem 'capistrano-bundler',         require: false
  gem 'capistrano-passenger',       require: false
  gem 'capistrano-ssh-doctor',      require: false
  gem 'capistrano-rails-collection'
end

Instalar gemas

$ bundle install
$ cap install

Capfile

# Load DSL and set up stages
require 'capistrano/setup'

require 'capistrano/deploy'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/passenger'
require 'capistrano/ssh_doctor'
require 'capistrano/rails/collection'
require "capistrano/scm/git"

install_plugin Capistrano::SCM::Git
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

deploy.rb

set :repo_url,        'REPO_URL.git'
set :application,     'APP_NAME'
set :user,            'deploy'

# Don't change these unless you know what you're doing
set :pty, true
set :use_sudo,        false
set :stage,           :production
set :deploy_via,      :remote_cache
set :deploy_to,       "/home/#{fetch(:user)}/#{fetch(:application)}"
set :ssh_options,     { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa) }

set :linked_files, fetch(:linked_files, []).push('.env', 'config/database.yml', 'config/secrets.yml')
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :keep_releases, 5

namespace :deploy do

  # Not needed if using capistrano-passenger gem/recipe
  # desc 'Restart application'
  # task :restart do
  #   on roles(:app), in: :sequence, wait: 5 do
  #     execute :touch, release_path.join('tmp/restart.txt')
  #   end
  # end

  after :publishing, 'deploy:restart'
  after :finishing, 'deploy:cleanup'
end

En el archivo config/deploy/production.rb llenar con los datos de la IP y el usuario del servidor (deploy en este caso).

server 'IP.DEL.SERVIDOR', user: 'deploy', roles: %w{web db app}

Iniciar el primer deploy

$ cap production deploy

Lo cual fallará, porque no encontrará los linked_files, para eso debemos entrar al servidor y crearlos (en carpeta del proyecto, dentro del servidor)

  • Crear archivo .env
  • Crear archivo database.yml en carpeta shared/config
  • Crear archivo secrets.yml en carpeta shared/config

Una vez creados, y llenados con sus respectivos datos volver a intentar el deploy

$ cap production deploy

[OPCION 2] MINA

Instalar Nginx solito

$ sudo apt-get install nginx -y

Instalar Puma en el servidor

$ gem install puma -v 3.7.0

Agregar Puma y Mina al Gemfile

gem 'puma', '3.7'
gem 'mina', require: false
gem 'mina-puma', require: false, github: 'untitledkingdom/mina-puma'

Instalar gemas

$ bundle install
$ mina init

Esto generará el archivo config/deploy.rb y deberá quedar mas o menos así

require 'mina/rails'
require 'mina/git'
require 'mina/rvm'
require 'mina/puma'

set :user, 'deploy'
set :application_name, 'nombre_carpeta_proyecto'
set :domain, 'IP.DEL.SERVIDOR'
set :deploy_to, '/home/deploy/nombre_carpeta_proyecto'
set :repository, '[email protected]:repo-git-url'
set :branch, 'master'

set :shared_dirs, fetch(:shared_dirs, []).push('log', 'tmp/pids', 'tmp/sockets')
set :shared_files, fetch(:shared_files, []).push(
  '.env',
  'config/database.yml',
  'config/secrets.yml',
  'tmp',
  'log',
  'config/puma.rb'
)

task :remote_environment do
  invoke :'rvm:use', '2.3.1'
end

task :setup do
  command %[touch "#{fetch(:shared_path)}/config/database.yml"]
  command %[touch "#{fetch(:shared_path)}/config/secrets.yml"]
  comment "Be sure to edit '#{fetch(:shared_path)}/config/database.yml', 'secrets.yml' and puma.rb."
end

task :setup  do
  command %[mkdir -p "/home/deploy/nombre_carpeta_proyecto/shared/log"]
  command %[chmod g+rx,u+rwx "/home/deploy/nombre_carpeta_proyecto/shared/log"]

  command %[mkdir -p "/home/deploy/nombre_carpeta_proyecto/shared/config"]
  command %[chmod g+rx,u+rwx "/home/deploy/nombre_carpeta_proyecto/shared/config"]

  command %[mkdir -p "/home/deploy/nombre_carpeta_proyecto/shared/tmp"]
  command %[chmod g+rx,u+rwx "/home/deploy/nombre_carpeta_proyecto/shared/tmp"]

  command %[touch "/home/deploy/nombre_carpeta_proyecto/shared/.env"]
  command %[touch "/home/deploy/nombre_carpeta_proyecto/shared/config/database.yml"]
  command %[touch "/home/deploy/nombre_carpeta_proyecto/shared/config/secrets.yml"]
  command %[touch "/home/deploy/nombre_carpeta_proyecto/shared/config/puma.rb"]
end

desc "Deploys the current version to the server."
task :deploy do
  deploy do
    comment "Deploying #{fetch(:application_name)} to #{fetch(:domain)}:#{fetch(:deploy_to)}"
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
    invoke :'bundle:install'
    invoke :'rails:db_migrate'
    invoke :'rails:assets_precompile'
    invoke :'deploy:cleanup'

    on :launch do
      invoke :'puma:phased_restart'
    end
  end

  # you can use `run :local` to run tasks on local machine before of after the deploy scripts
  run(:local){ say 'done' }
end

Inicializar Mina desde la máquina local

$ mina setup

By default, Mina will create all folders mentioned in shared_dirs and shared_files. In setup, however, you can add section auto-creation of empty files and fill them later.

Después de esto, hay que entrar al servidor y llenar los datos necesarios en los archivos

  • .env
  • puma.rb
  • database.yml
  • secrets.yml

Llenar el archivo puma.rb

environment "production"

bind "unix:/home/deploy/nombre_carpeta_proyecto/shared/tmp/sockets/puma.sock"
pidfile "/home/deploy/nombre_carpeta_proyecto/shared/tmp/pids/puma.pid"
state_path "/home/deploy/nombre_carpeta_proyecto/shared/tmp/sockets/puma.state"
directory "/home/deploy/nombre_carpeta_proyecto/current"

workers 2
threads 1,4

daemonize true

stdout_redirect "/home/deploy/nombre_carpeta_proyecto/shared/log/puma.stdout.log", "/home/deploy/nombre_carpeta_proyecto/shared/log/puma.stderr.log"

activate_control_app 'unix:/home/deploy/nombre_carpeta_proyecto/shared/tmp/sockets/pumactl.sock'

prune_bundler

Configurar Nginx para puma

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/nombre_app

Modificar archivo /etc/nginx/sites-available/nombre_app con lo siguiente, y reemplazar donde corresponda

upstream puma {
  server unix:///home/deploy/APP_FOLDER/shared/tmp/sockets/APP_NAME-puma.sock;
}

server {
  listen 80;
  listen [::]:80;

  server_name IP.DEL.SERVIDOR;

  root /home/deploy/APP_FOLDER/current/public;
  access_log /home/deploy/APP_FOLDER/current/log/nginx.access.log;
  error_log /home/deploy/APP_FOLDER/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://puma;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 10M;
  keepalive_timeout 10;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment