Installa prima Ruby, poi il resto: la scelta che evita metà dei problemi
Su Linux e UNIX, Rails non si installa bene “a pacchetti sparsi” senza una strategia. La sequenza corretta è semplice: definisci la versione di Ruby, scegli come gestirla, prepara le librerie native, installa Bundler e solo dopo crea l’app. Se inverti l’ordine, finisci quasi sempre con gemme compilate male, dipendenze incoerenti o permessi sballati nella home dell’utente.
La decisione architetturale da fare all’inizio è questa: vuoi un ambiente per sviluppo locale, un server di test o una macchina destinata a ospitare applicazioni in produzione? La risposta cambia poco la sintassi dei comandi, ma cambia molto il livello di controllo. In pratica: per sviluppo usa un version manager, per un server usa un utente dedicato e una versione Ruby esplicita, mai il Ruby di sistema se puoi evitarlo.
Prerequisiti reali: compilatori, librerie e tool di base
Rails si appoggia a Ruby, ma molte gemme richiedono estensioni native. Quindi servono compilatore, tool di build e alcune librerie di sistema. I nomi cambiano un po’ tra distribuzioni, ma il concetto resta lo stesso: se manca una libreria di sviluppo, l’installazione si ferma al primo gem install che prova a compilare qualcosa.
Su Debian, Ubuntu e derivate, il set minimo tipico è questo:
sudo apt update
sudo apt install -y git curl build-essential libssl-dev libreadline-dev zlib1g-dev libyaml-dev libgdbm-dev libncurses5-dev libffi-dev
Su RHEL, Rocky, AlmaLinux o Fedora la logica è identica, cambiano i nomi dei pacchetti:
sudo dnf install -y git curl gcc gcc-c++ make openssl-devel readline-devel zlib-devel libyaml-devel gdbm-devel ncurses-devel libffi-devel
Se lavori su Solaris, FreeBSD o altri UNIX meno comuni, controlla prima il package manager locale e la disponibilità di OpenSSL, readline e tool di compilazione. Il gap qui non è teorico: senza queste dipendenze Rails parte male o non parte proprio. Se non sai quali librerie ti mancano, la prova più rapida è tentare l’installazione e leggere l’errore della gemma nativa; di solito indica il file header assente o il pacchetto di sviluppo mancante.
Scegliere il gestore di Ruby: rbenv, asdf o pacchetto di sistema
Per la maggior parte dei casi, rbenv è la scelta più lineare. È semplice, non invade il sistema e ti consente di fissare una versione Ruby per utente o per progetto. asdf è più generale e utile se gestisci anche Node.js, Python o altri runtime. Il Ruby di sistema va bene solo se hai un ambiente controllato e sai esattamente perché lo stai usando.
Il punto non è la moda del tool, ma la reversibilità. Se un progetto richiede Ruby 3.2 e un altro Ruby 3.3, un version manager ti evita conflitti. Se invece installi tutto con i pacchetti della distro, la versione disponibile può essere vecchia o patchata in modo diverso dalla compatibilità attesa da Rails.
Installazione rapida con rbenv
Su una shell bash o zsh, la procedura tipica è questa. I comandi qui sotto non toccano il sistema in modo distruttivo e restano confinati all’utente corrente.
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
mkdir -p ~/.rbenv/plugins
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init - bash)"' >> ~/.bashrc
source ~/.bashrc
Verifica subito che il comando sia risolto dal tuo shell environment e non da un binario di sistema:
which rbenv
rbenv --version
Se il path non compare, il problema non è Ruby: è la shell che non sta caricando l’inizializzazione. In quel caso controlla il file corretto per il tuo login shell, per esempio ~/.profile, ~/.bash_profile o ~/.zshrc.
Installare Ruby con una versione esplicita
La regola pratica è non inseguire l’ultima release solo perché è l’ultima. Rails ha una matrice di compatibilità con Ruby e alcune gemme fanno lo stesso. Scegli una versione supportata dal tuo target applicativo e fissala nel progetto. Per un’installazione moderna, Ruby 3.2 o 3.3 è spesso una base sensata, ma va verificata con la versione di Rails che userai.
rbenv install 3.3.0
rbenv global 3.3.0
ruby -v
Il controllo da fare dopo è banale ma decisivo: ruby -v deve restituire la versione attesa e non quella di sistema. Se vedi una release diversa, il PATH non è stato sistemato o la shell ha cache di comandi vecchi. In quel caso usa hash -r oppure riapri la sessione.
Su ambienti server, evita di installare Ruby come root nella home di root. È una scorciatoia che complica manutenzione, backup e aggiornamenti. Meglio un utente applicativo dedicato, per esempio deploy o rails, con permessi limitati e ownership coerente della directory del progetto.
Bundler e gemme: il confine tra progetto e sistema
Bundler è il pezzo che trasforma una collezione di gemme in un ambiente ripetibile. Senza Bundler, ogni macchina finisce con una combinazione leggermente diversa di dipendenze. Con Bundler, il progetto dichiara ciò che serve e il lockfile fissa la risoluzione effettiva.
gem update --system
gem install bundler
bundle -v
Se usi rbenv, le gemme restano isolate per versione Ruby. Questo riduce gli effetti collaterali. Quando installi gemme globalmente fuori da un version manager, invece, il rischio è ritrovarti con dipendenze che cambiano tra utenti o con aggiornamenti di sistema che rompono applicazioni già funzionanti.
Per un progetto Rails, il file centrale è Gemfile. Un esempio minimale ma realistico è questo:
source 'https://rubygems.org'
ruby '3.3.0'
gem 'rails', '~> 7.1.0'
gem 'puma', '>= 5.0'
gem 'sqlite3', '>= 1.4'
Se il progetto userà PostgreSQL o MySQL, sostituisci sqlite3 con il driver adeguato. Non lasciare il database “temporaneo” per inerzia: è una scelta che spesso sopravvive troppo a lungo e poi crea differenze di comportamento tra sviluppo e produzione.
Creare una nuova app Rails e verificare che il bootstrap sia sano
Una volta pronta la base Ruby, la creazione del progetto è veloce. Qui la verifica importante non è che il comando funzioni, ma che il bundle iniziale chiuda senza errori di compilazione o di rete. Se il download delle gemme fallisce, hai già un indizio su proxy, DNS, certificati CA o connettività verso RubyGems.
rails new myapp
cd myapp
bin/rails server
Apri poi un secondo terminale e controlla la risposta HTTP sul loopback:
curl -I http://127.0.0.1:3000
Atteso: un codice 200 o comunque una risposta coerente con il server in ascolto. Se ottieni Connection refused, il server non è partito o ha scelto un’altra interfaccia. Se ricevi un errore di gemme mancanti, torna al bundle e leggi il primo messaggio utile, non l’ultimo: la causa vera quasi sempre sta più in alto nello stack del log.
Database: scegliere subito il motore giusto
Rails supporta bene SQLite per sviluppo rapido, ma per un server serio PostgreSQL è la scelta più comune. MySQL/MariaDB resta valido se lo standard del tuo ambiente lo richiede, ma la decisione va presa prima di scrivere codice applicativo significativo. Cambiare motore dopo significa toccare migrazioni, tipi di dato e in certi casi anche query e indici.
Con PostgreSQL, il pacchetto client e gli header di sviluppo devono essere presenti prima di installare la gemma pg:
sudo apt install -y postgresql-client libpq-dev
bundle add pg
bundle install
Su server con PostgreSQL locale, verifica che il servizio risponda e che l’utente applicativo abbia i privilegi minimi necessari. Non usare superuser del database per l’app Rails: è una superficie d’attacco inutile e rende più difficile l’audit.
Un file config/database.yml tipico deve restare semplice e leggibile. Un esempio minimale:
default: &default
adapter: postgresql
encoding: unicode
pool: 5
username: myapp
password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>
production:
<<: *default
database: myapp_production
Qui il punto importante è l’uso della variabile d’ambiente. La password non va scritta in chiaro nel repository. Se serve un segreto persistente, gestiscilo con un secret manager, con un file fuori dal VCS o con un meccanismo del pannello/servizio già in uso, ma sempre fuori dal codice versionato.
Web server e processo applicativo: Puma dietro Nginx
Rails in produzione non va esposto direttamente su Internet nella maggior parte dei casi. La configurazione classica è Puma come application server e Nginx come reverse proxy. Questa separazione ti dà controllo su TLS, compressione, buffering, header e limiti di connessione.
Con Puma puoi partire in modo semplice e poi raffinare. Per un controllo rapido:
bundle exec puma -C config/puma.rb
Nel file config/puma.rb puoi tenere una configurazione essenziale:
workers Integer(ENV.fetch('WEB_CONCURRENCY', 2))
threads_count = Integer(ENV.fetch('RAILS_MAX_THREADS', 5))
threads threads_count, threads_count
port ENV.fetch('PORT', 3000)
environment ENV.fetch('RAILS_ENV', 'production')
Per Nginx, un blocco server base può instradare verso Puma su socket o porta locale. Se usi socket Unix, riduci un po’ l’overhead e semplifichi i permessi sul loopback. Un esempio concettuale, da adattare al tuo host:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Se abiliti TLS, la parte critica non è solo il certificato ma anche la catena completa e il rinnovo automatico. Controlla il risultato con curl -Iv https://example.com e verifica che il certificato presentato sia quello atteso e che la catena non produca warning di trust.
Servizio systemd: avvio pulito e riavvio controllato
Su Linux moderno, un’unità systemd per Puma o per il processo Rails evita avvii manuali e migliora il controllo operativo. L’idea è standard: directory di lavoro nota, utente dedicato, variabili d’ambiente minime e restart policy ragionevole. Non serve complicarla oltre misura.
[Unit]
Description=MyApp Rails
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/srv/myapp
Environment=RAILS_ENV=production
ExecStart=/home/deploy/.rbenv/shims/bundle exec puma -C /srv/myapp/config/puma.rb
Restart=on-failure
[Install]
WantedBy=multi-user.target
Salva il file, ricarica systemd e verifica lo stato:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp
Se il servizio fallisce, il primo posto da guardare è il journal:
journalctl -u myapp -n 100 --no-pager
Questo ti dice subito se il problema è un path errato, una gemma non trovata, un permesso negato o una variabile d’ambiente mancante. In pratica, ti evita di perdere tempo in ipotesi astratte.
Permessi, directory e ownership: il dettaglio che rompe più installazioni di quanto sembri
Molte installazioni falliscono non per Rails ma per una ownership incoerente nella directory del progetto o nelle cache delle gemme. Se l’utente che avvia il servizio non può scrivere su tmp/, log/ o storage/, il boot può fallire o l’app può funzionare solo a metà.
Controllo rapido:
ls -ld /srv/myapp /srv/myapp/tmp /srv/myapp/log /srv/myapp/storage
Se serve correggere, fallo in modo mirato e solo sulla directory applicativa, non sul resto del filesystem:
sudo chown -R deploy:deploy /srv/myapp
Qui il blast radius è limitato alla directory dell’app, ma il rollback va comunque considerato: se hai cambiato ownership in modo errato, ripristina il proprietario precedente dalla documentazione operativa o dall’ultimo snapshot noto.
Verifiche finali: non fermarti al “bundle install” riuscito
Una installazione Rails è davvero a posto solo quando chiude il ciclo completo: Ruby corretto, bundle risolto, database accessibile, server avviato e HTTP rispondente. Il test minimo è questo:
- Controlla la versione Ruby con
ruby -v. - Controlla Bundler con
bundle -v. - Esegui
bundle installe verifica che non ci siano gemme native fallite. - Avvia l’app con
bin/rails servero con systemd. - Testa la risposta HTTP con
curl -I http://127.0.0.1:3000oppure con il dominio pubblico se il proxy è già attivo.
Se uno di questi passi non torna, non passare subito al refactor. Fai prima una verifica osservabile: log applicativi, journal, stato del database, spazio disco e connessioni in ascolto. Le cause più banali sono spesso quelle giuste: una variabile d’ambiente mancante, un certificato scaduto, un path sbagliato o una gemma nativa compilata contro header non presenti.
Per un controllo rapido delle porte in ascolto:
ss -lntp | grep -E ':3000|:80|:443'
Se il server non ascolta sulla porta prevista, la soluzione non è aprire firewall a caso: prima identifica quale processo deve stare in ascolto e perché non è partito. Il firewall si tocca solo dopo aver confermato che l’app è viva localmente.
Scelta pratica finale: installazione ripetibile, non eroica
Il modo più pulito per installare Rails su Linux e UNIX è mantenere separati tre livelli: runtime Ruby, dipendenze di sistema e configurazione dell’app. Se tratti questi tre strati come entità distinte, gli aggiornamenti diventano prevedibili e il troubleshooting si accorcia parecchio.
In sintesi operativa: usa un version manager, fissa la versione di Ruby, installa le librerie native prima delle gemme, tieni il database fuori dal codice, fai girare l’app con un utente dedicato e metti un reverse proxy davanti. È una sequenza semplice, ma proprio per questo è la più robusta quando devi passare da un notebook a un server vero.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.