Para evitar entrar como usuario root, crear otro usuario y darle permisos de sudo
$ sudo adduser deploy
$ sudo gpasswd -a deploy sudo
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
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
Timezone
$ sudo dpkg-reconfigure tzdata
NTP
$ sudo apt-get update
$ sudo apt-get install ntp
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
$ 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
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
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
$ gem install rails -v x.x.x --no-document
Instalar Bundler:
$ gem install bundler
$ 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]
$ 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
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
# 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 }
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
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
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;
}