Come risolvere l’errore “Manca` secret_key_base` per l’ambiente di ‘produzione’ (Rails 4.1)

Ho creato un’applicazione per rails (rails 4.1) da zero e sto affrontando uno strano problema che non sono in grado di risolvere.

Ogni volta che provo a distribuire la mia app su Heroku ottengo un errore 500:

Manca secret_key_base per l’ secret_key_base di ‘produzione’, imposta questo valore in config/secrets.yml

Il file secret.yml contiene la seguente configurazione:

 secret_key_base:  

Su Heroku ho configurato una variabile di ambiente “SECRET_KEY_BASE” con il risultato del comando “rake secret”. Se lancio “heroku config”, posso vedere la variabile con il nome e il valore corretti.

Perché ricevo ancora questo errore?

molte grazie

Ho avuto lo stesso problema e l’ho risolto creando una variabile di ambiente da caricare ogni volta che ho effettuato l’accesso al server di produzione e ho creato una mini guida dei passaggi per configurarlo:

https://gist.github.com/pablosalgadom/4d75f30517edc6230a67

Stavo usando Rails 4.1 con Unicorn v4.8.2, quando ho provato a distribuire la mia app non è stato avviato correttamente e nel file unicorn.log ho trovato questo messaggio di errore:

app error: Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml` (RuntimeError)

Dopo alcune ricerche ho scoperto che Rails 4.1 ha cambiato il modo di gestire il secret_key, quindi se leggi il file secrets.yml che si trova su exampleRailsProject/config/secrets.yml troverai qualcosa del genere:

 # Do not keep production secrets in the repository, # instead read values from the environment. production: secret_key_base: < %= ENV["SECRET_KEY_BASE"] %> 

Ciò significa che Rails raccomanda di utilizzare una variabile di ambiente per il secret_key_base nel server di produzione, per risolvere questo errore è necessario seguire questa procedura per creare una variabile di ambiente per Linux (nel mio caso Ubuntu) nel server di produzione:

  1. Nel terminale del server di produzione eseguire il comando successivo:

     $ RAILS_ENV=production rake secret 

    Questo restituisce una stringa di grandi dimensioni con lettere e numeri, copia quella (ci riferiremo a quel codice come GENERATED_CODE).

  2. Accedi al tuo server

    • Se accedi come utente root, trova questo file e modificalo:

       $ vi /etc/profile 

      Vai in fondo al file (“MAIUSC + G” per la maiuscola G in VI)

      Scrivi la tua variabile di ambiente con GENERATED_CODE (premi il tasto “i” per scrivere in VI), assicurati di essere in una nuova riga alla fine del file:

       $ export SECRET_KEY_BASE=GENERATED_CODE 

      Salvare le modifiche e chiudere il file (premiamo il tasto “ESC” e quindi scriviamo “: x” e “ENTER” per salvare e uscire in VI).

    • Ma se accedi come utente normale, chiamiamolo “example_user” per questo gist, dovrai trovare uno di questi altri file:

       $ vi ~/.bash_profile $ vi ~/.bash_login $ vi ~/.profile 

      Questi file sono in ordine di importanza, il che significa che se hai il primo file, non avresti bisogno di scrivere negli altri. Quindi, se hai trovato questi 2 file nella tua directory ~/.bash_profile e ~/.profile devi solo scrivere nel primo ~/.bash_profile , perché Linux leggerà solo questo e l’altro sarà ignorato.

      Quindi andiamo in fondo al file (“SHIFT + G” per la maiuscola G in VI).

      E scriveremo la nostra variabile di ambiente con il nostro GENERATED_CODE (premi il tasto “i” per scrivere in VI), assicurati di essere in una nuova riga alla fine del file:

       $ export SECRET_KEY_BASE=GENERATED_CODE 

      Dopo aver scritto il codice, salvare le modifiche e chiudere il file (premiamo il tasto “ESC” e quindi scriviamo “: x” e “ENTER” per salvare e uscire in VI).

  3. Puoi verificare che la nostra variabile d’ambiente sia impostata correttamente in Linux con questo comando:

     $ printenv | grep SECRET_KEY_BASE 

    o con:

     $ echo $SECRET_KEY_BASE 

    Quando esegui questo comando, se tutto è andato bene, ti mostrerà il GENERATED_CODE di prima. Infine, con tutte le configurazioni fatte, dovresti essere in grado di distribuire senza problemi la tua app Rails con Unicorn o altro.

Quando chiudi il tuo terminale di shell e accedi di nuovo al server di produzione, avrai questa variabile d’ambiente impostata e pronta per l’uso.

E questo è tutto !! Spero che questa mini guida ti aiuti a risolvere questo errore.

Disclaimer: non sono un guru di Linux o di Rails, quindi se trovi qualcosa di sbagliato o qualsiasi errore sarò lieto di sistemarlo!

Presumo che tu non abbia i tuoi secrets.yml controllati nel controllo del codice sorgente (cioè nel file .gitignore ). Anche se questa non è la tua situazione, è ciò che hanno fatto molte altre persone che hanno visualizzato questa domanda perché hanno il loro codice esposto su Github e non vogliono che la loro chiave segreta fluttui intorno.

Se non è nel controllo del codice sorgente, Heroku non lo sa. Quindi Rails sta cercando Rails.application.secrets.secret_key_base e non è stato impostato perché Rails lo imposta controllando il file secrets.yml che non esiste. La semplice soluzione è quella di andare nel tuo file config/environments/production.rb e aggiungere la seguente riga:

 Rails.application.configure do ... config.secret_key_base = ENV["SECRET_KEY_BASE"] ... end 

Questo dice alla tua applicazione di impostare la chiave segreta usando la variabile d’ambiente invece di cercarla in secrets.yml . Mi avrebbe risparmiato un sacco di tempo per conoscerlo in anticipo.

Aggiungi config/secrets.yml al controllo della versione e distribuisci di nuovo. Potrebbe essere necessario rimuovere una riga da .gitignore modo da poter eseguire il commit del file.

Ho avuto questo stesso identico problema e ho appena scoperto che il .gitignore config/secrets.yml Github è stato creato per la mia applicazione Rails inclusa config/secrets.yml .

Questo ha funzionato per me.

SSH nel server di produzione e cd nella directory corrente, esegui bundle exec rake secret o rake secret , otterrai una stringa lunga come output, copia quella stringa.

Ora esegui sudo nano /etc/environment .

Incollare nella parte inferiore del file

 export SECRET_KEY_BASE=rake secret ruby -e 'p ENV["SECRET_KEY_BASE"]' 

Dove rake secret è la stringa che hai appena copiato, incolla la stringa copiata al posto del rake secret .

Riavvia il server e prova eseguendo echo $SECRET_KEY_BASE .

Mentre è ansible utilizzare gli inizializzatori come le altre risposte, il modo convenzionale di Rails 4.1+ è quello di usare config/secrets.yml . Il motivo per cui il team di Rails lo ha introdotto va oltre lo scopo di questa risposta, ma il TL; DR è che secret_token.rb confonde configurazione e codice oltre a costituire un rischio per la sicurezza poiché il token è controllato nella cronologia dei controlli sorgente e l’unico sistema che ha bisogno di sapere che il token segreto di produzione è l’infrastruttura di produzione.

Dovresti aggiungere questo file a .gitignore modo simile a quanto non aggiungerebbe config/database.yml al controllo del codice sorgente.

Facendo riferimento al codice di Heroku per configurare config/database.yml da DATABASE_URL nel loro Buildpack per Ruby , ho finito con la forking del repository e l’ho modificato per creare config/secrets.yml dalla variabile d’ambiente SECRETS_KEY_BASE .

Poiché questa funzione è stata introdotta in Rails 4.1, ho ritenuto opportuno modificare ./lib/language_pack/rails41.rb e aggiungere questa funzionalità.

Quello che segue è lo snippet del buildpack modificato che ho creato nella mia azienda:

 class LanguagePack::Rails41 < LanguagePack::Rails4 # ... def compile instrument "rails41.compile" do super allow_git do create_secrets_yml end end end # ... # writes ERB based secrets.yml for Rails 4.1+ def create_secrets_yml instrument 'ruby.create_secrets_yml' do log("create_secrets_yml") do return unless File.directory?("config") topic("Writing config/secrets.yml to read from SECRET_KEY_BASE") File.open("config/secrets.yml", "w") do |file| file.puts <<-SECRETS_YML <% raise "No RACK_ENV or RAILS_ENV found" unless ENV["RAILS_ENV"] || ENV["RACK_ENV"] %> < %= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>: secret_key_base: < %= ENV["SECRET_KEY_BASE"] %> SECRETS_YML end end end end # ... end 

Ovviamente puoi estendere questo codice per aggiungere altri segreti (ad esempio chiavi API di terze parti, ecc.) Da leggere sulla tua variabile di ambiente:

 ... < %= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>: secret_key_base: < %= ENV["SECRET_KEY_BASE"] %> third_party_api_key: < %= ENV["THIRD_PARTY_API"] %> 

In questo modo, puoi accedere a questo segreto in un modo molto standard:

 Rails.application.secrets.third_party_api_key 

Prima di ridistribuire la tua app, assicurati di impostare prima la variabile di ambiente: Impostazione SECRET_KEY_BASE in Heroku Dashboard

Quindi aggiungi il tuo buildpack modificato (o sei più che benvenuto per collegarti al mio) alla tua app di Heroku (vedi la documentazione di Heroku) e ridistribuisci la tua app.

Il buildpack creerà automaticamente il tuo config/secrets.yml dalla tua variabile d’ambiente come parte del processo di build di dyno ogni volta che git push a Heroku.

EDIT: la documentazione di Heroku suggerisce di creare config/secrets.yml per leggere dalla variabile di ambiente, ma questo implica che dovresti controllare questo file nel controllo del codice sorgente. Nel mio caso, questo non funziona bene dato che ho segreti hardcoded per ambienti di sviluppo e test che preferirei non controllare.

Puoi esportare le chiavi segrete come variabili di ambiente su ~/.bashrc o ~/.bash_profile del tuo server:

 export SECRET_KEY_BASE = "YOUR_SECRET_KEY" 

E poi, puoi trovare il tuo .bashrc o .bash_profile :

 source ~/.bashrc source ~/.bash_profile 

Non commettere mai i tuoi segreti.yml

Cosa ho fatto: sul mio server di produzione, creo un file di configurazione (confthin.yml) per Thin (lo sto usando) e aggiungo le seguenti informazioni:

 environment: production user: www-data group: www-data SECRET_KEY_BASE: mysecretkeyproduction 

Quindi avvio l’app con

 thin start -C /whereeveristhefieonprod/configthin.yml 

Funziona come un fascino e quindi non è necessario avere la chiave segreta sul controllo della versione

Spero che possa essere d’aiuto, ma sono sicuro che la stessa cosa potrebbe essere fatta con Unicorn e altri.

Ho una patch che ho usato in un’app Rails 4.1 per permettermi di continuare a utilizzare il generatore di chiavi legacy (e quindi la compatibilità con le versioni precedenti di Rails 3), consentendo a secret_key_base di essere vuoto.

 Rails::Application.class_eval do # the key_generator will then use ActiveSupport::LegacyKeyGenerator.new(config.secret_token) fail "I'm sorry, Dave, there's no :validate_secret_key_config!" unless instance_method(:validate_secret_key_config!) def validate_secret_key_config! #:nodoc: config.secret_token = secrets.secret_token if config.secret_token.blank? raise "Missing `secret_token` for '#{Rails.env}' environment, set this value in `config/secrets.yml`" end end end 

Da quando ho riformattato la patch, l’ho inviato a Rails come richiesta di pull

Ho creato il file config/initializers/secret_key.rb e ho scritto solo la seguente riga di codice:

 Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"] 

Ma penso che la soluzione pubblicata da @Erik Trautman sia più elegante;)

Modifica: Oh, e alla fine ho trovato questo consiglio su Heroku: https://devcenter.heroku.com/changelog-items/426 🙂

Godere!

questo funziona bene https://gist.github.com/pablosalgadom/4d75f30517edc6230a67 per l’utente root dovrebbe modificare

 $ /etc/profile 

ma se non root dovresti inserire il codice di generazione nel modo seguente

 $ ~/.bash_profile $ ~/.bash_login $ ~/.profile 

Su Nginx / Passenger / Ruby (2.4) / Rails (5.1.1) nient’altro ha funzionato tranne:

passenger_env_var in /etc/nginx/sites-available/default nel blocco del server.

Fonte: https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_env_var

La risposta di Demi Magus ha funzionato per me fino a Rails 5.

Su Apache2 / Passenger / Ruby (2.4) / Rails (5.1.6), ho dovuto inserire

 export SECRET_KEY_BASE=GENERATED_CODE 

dalla risposta di Demi Magus in / etc / apache2 / envvars, la causa / etc / profile sembra essere ignorata.

Fonte: https://www.phusionpassenger.com/library/indepth/environment_variables.html#apache

Ho avuto lo stesso problema dopo aver utilizzato il file .gitignore da https://github.com/github/gitignore/blob/master/Rails.gitignore

Tutto ha funzionato bene dopo aver commentato le seguenti righe nel file .gitignore.

 config/initializers/secret_token.rb config/secrets.yml