Come risolvere l'errore "Miss_key_base` mancante per l'ambiente di" produzione "(Rails 4.1)


169

Ho creato un'applicazione Rails, usando 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 applicazione su Heroku ricevo un errore 500:

Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml`

Il secret.ymlfile contiene la seguente configurazione:

secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

Su Heroku ho configurato la " SECRET_KEY_BASE" variabile d'ambiente con il risultato del rake secretcomando. Se lancio heroku config, posso vedere la variabile con il nome e il valore corretti.

Perché visualizzo ancora questo errore?


1
Sto avendo lo stesso identico problema e mi piacerebbe sapere perché anche questo sta accadendo. Se capisco perché, posterò di nuovo con la mia soluzione.
danielricecodes

Il tuo file di configurazione è chiamato secret.ymlo secrets.yml?
James,

2
Ho configurato di nuovo il file .gitignore con quello generato dalle rotaie e ora tutto funziona bene
Paolo Laurenti

Abbiamo riscontrato questo problema anche quando abbiamo eseguito l'aggiornamento a Rails 4. Nel nostro caso, era perché avevamo un nome di ambiente personalizzato e ciò non si rifletteva in secrets.yml. Ho dovuto solo aggiungere una riga al file con il nome non standard, commit e re-deploy.
Whognu

Per i futuri lettori: questa risposta è probabilmente la più semplice e accurata:
stackoverflow.com/a/26541742/4880924

Risposte:


208

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

Stavo usando Rails 4.1 con Unicorn v4.8.2 e quando ho provato a distribuire la mia applicazione non è stata avviata correttamente e nel unicorn.logfile 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 secrets.ymlfile che trovi in exampleRailsProject/config/secrets.ymltroverai 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 ti consiglia di utilizzare una variabile di ambiente per il secret_key_basetuo server di produzione. Per risolvere questo errore dovresti seguire questi passaggi per creare una variabile d'ambiente per Linux (nel mio caso Ubuntu) nel tuo server di produzione:

  1. Nel terminale del server di produzione eseguire:

    $ RAILS_ENV=production rake secret

    Ciò restituisce una stringa di grandi dimensioni con lettere e numeri. Copia quello, che faremo riferimento 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 usando Shift+ G(maiuscola "G") in vi.

      Scrivi la tua variabile d'ambiente con GENERATED_CODE, premendo iper inserire 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 utilizzando Esce quindi " :x" e Enterper salvare ed uscire in vi.

    • Ma se accedi come utente normale, chiamiamolo " example_user" per questa sintesi, 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 si dispone del primo file, non è necessario modificare gli altri. Se hai trovato questi due file nella tua directory ~/.bash_profilee ~/.profiledovrai solo scrivere nel primo ~/.bash_profile, perché Linux leggerà solo questo e l'altro verrà ignorato.

      Quindi andiamo in fondo al file usando Shift+ di Gnuovo e scriviamo la variabile d'ambiente con il nostro GENERATED_CODEutilizzo di inuovo, e assicurati di aggiungere 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 usando Escnuovamente " :x" e Enterper salvare ed uscire.

  3. Puoi verificare che la nostra variabile d'ambiente sia correttamente impostata 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à la GENERATED_CODEprima. Finalmente con tutta la configurazione fatta dovresti essere in grado di distribuire senza problemi la tua applicazione Rails con Unicorn o qualche altro strumento.

Quando chiudi la shell e accedi nuovamente al server di produzione, avrai questa variabile d'ambiente impostata e pronta per usarla.

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

Disclaimer: non sono un guru di Linux o Rails, quindi se trovi qualcosa di sbagliato o qualche errore, sarò felice di risolverlo.


11
Sembra che Rails non veda la variabile d'ambiente SECRET_KEY_BASE. printenv lo mostra, rails c production lo mostra anche se ispeziono ENV. Ma non ho alcun effetto quando riavvio Unicorn. L'unico modo, che funziona ora, è incollarlo direttamente su secrets.yml
AntonAL

1
Questo ha funzionato per me. Grazie per la tua spiegazione completa. Ho appena imparato che esistono gemme per la gestione delle variabili di ambiente di un'app. 'Dotenv' è uno e 'caposquadra' per heroku. Mentre è stato educativo correggere l'errore manualmente in questo modo, forse usando una di quelle gemme si semplifica il processo?
Nick Res

Sono contento che la mia risposta sia stata utile, grazie per le opzioni gemma @ ninja08, rendono definitivamente più semplice il processo, soprattutto per coloro che usano capistrano o altri strumenti incrementali per gestire il server :)
Demi Magus

Seguendo le eccellenti istruzioni di Demi Magus, ho fatto qualcosa del genere: cd / var / www / rails; rvm usa ext-rbx-2.5.2@rails; SKB_FILE = / var / www / .secret_key_base; echo "export SECRET_KEY_BASE = $ (RAILS_ENV = segreto del rastrello di produzione)"> $ SKB_FILE; . $ SKB_FILE; echo ". $ SKB_FILE" | tee -a ~ / .bashrc ~ / .bash_profile; chmod o-rwx $ SKB_FILE;
David Winiecki,

Bella risposta!! Non so perché questo non sia risolto per me, creo la domanda stackoverflow.com/questions/33117318/…
Adriano Resende,

84

Presumo che tu non abbia il tuo secrets.ymlcontrollo nel controllo del codice sorgente (cioè è nel .gitignorefile). Anche se questa non è la tua situazione, è ciò che molte altre persone che hanno visualizzato questa domanda hanno fatto perché hanno il loro codice esposto su Github e non vogliono che la loro chiave segreta vada in giro.

Se non è nel controllo del codice sorgente, Heroku non lo sa. Quindi Rails sta cercando Rails.application.secrets.secret_key_basee non è stato impostato perché Rails lo imposta controllando il secrets.ymlfile che non esiste. La soluzione semplice è andare nel tuo config/environments/production.rbfile 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 secrets.yml. Mi avrebbe risparmiato un sacco di tempo per saperlo in anticipo.


15
Questa è la risposta migliore Figaroe heroku_secretsnon fare nulla a meno che Rails non sappia che SECRET_KEY_BASEvive dentro ENV. Ho lottato con questo pensiero che se la configurazione fosse presente su Heroku, Rails l'avrebbe rilevato solo in virtù della sua esistenza, ma ora sembra accecantemente ovvio che Rails avrebbe bisogno di sapere dove cercare. Mi chiedevo come posso avere il codice su Github senza doversi preoccupare della cosa segreta della chiave di base; adesso lo so.
flanger001,

1
D'accordo, penso che secrets.yml sia superfluo con grandi gemme come Figaro.
Joe,

2
Sembra l'opzione migliore se usi github e heroku per il tuo progetto.
flexus,

1
Cosa c'è di sbagliato nel commettere your secrets.yml con production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Ciò non significa anche che la chiave segreta effettiva non sia esposta. Esiste il rischio di esporre le chiavi dev e test in commit secrets.yml se si tratta solo di seed e test data?
Jay Killeen,

Funziona anche in Rails 6.0.2, quando non c'è più secrets.yml.
Ken Tsoi il

54

Aggiungi config/secrets.ymlal controllo versione e distribuisci di nuovo. Potrebbe essere necessario rimuovere una riga .gitignoreper poter eseguire il commit del file.

Ho avuto lo stesso identico problema e ho appena scoperto che la piastra .gitignorecaldaia creata da Github per la mia applicazione Rails era inclusa config/secrets.yml.


140
config / secrets.yml non dovrebbe MAI trovarsi nel repository che puoi fare.yml.sample e riempirlo con dati falsi ma per sicurezza, non fare mai .yml nei
repository

9
@ user3379926, nel contesto di un'app Rails su Heroku, non puoi scegliere quali file sono inclusi nel controllo versione e quali no. Rails 4.1 si aspetta che esista la configurazione segreta, altrimenti l'applicazione non verrà eseguita. Se hai un modo per risolvere il problema posto nella domanda precedente senza ricorrere al commit del file secrets.yml in Git, ti preghiamo di aiutare a migliorare questo thread fornendo quel consiglio.
danielricecodes

9
@danielricecodes è possibile impostare manualmente il valore in un inizializzatore. Qualcosa del genere Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]funzionerebbe e rimuoverà l'errore senza aggiungerlo secrets.ymlalla fonte.
joshhepworth,

11
@ user3379926: Quando generi una nuova applicazione Rails con rails new(producendo, in questo caso, un Gemfile la cui railsgemma ha la versione 4.2.4), il file config/secrets.ymlviene generato. Esso comprende pregenerato chiavi segrete per gli ambienti di sviluppo e test, e legge la chiave segreta per l'ambiente di produzione da una variabile di ambiente: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Mi sembra che sia perfettamente sicuro, e davvero utile, mantenere questo secrets.ymlfile nel controllo della versione, a condizione che uno non abbia mai effettivamente definito la chiave segreta lì.
Teemu Leisti,

2
@jasonleonhard perché? se stai leggendo la chiave segreta di env vars comunque, qual è il grosso problema? non ci sono segreti da svelare.
Horseyguy,

13

Questo ha funzionato per me.

SSH nel tuo server di produzione e cdnella tua directory corrente, esegui bundle exec rake secreto rake secret, otterrai una lunga stringa come output, copia quella stringa.

Adesso corri sudo nano /etc/environment.

Incolla 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 quella stringa copiata al posto di rake secret.

Riavviare il server e test eseguendo echo $SECRET_KEY_BASE.


3

Mentre puoi usare gli inizializzatori come le altre risposte, il modo convenzionale di Rails 4.1+ è usare config/secrets.yml. Il motivo per cui il team di Rails ha introdotto questo aspetto va oltre lo scopo di questa risposta, ma TL; DR è che secret_token.rbconfonde configurazione e codice, oltre a costituire un rischio per la sicurezza poiché il token viene verificato nella cronologia del controllo del codice sorgente e l'unico sistema che deve sapere che il token segreto di produzione è l'infrastruttura di produzione.

Dovresti aggiungere questo file in .gitignoremodo simile a come non aggiungeresti nemmeno config/database.ymlal controllo del codice sorgente.

Facendo riferimento al codice di Heroku per la configurazione config/database.ymlda DATABASE_URLnel loro Buildpack per Ruby , ho finito per il fork del loro repository e l'ho modificato per creare config/secrets.ymldalla SECRETS_KEY_BASEvariabile d'ambiente.

Da quando questa funzionalità è stata introdotta in Rails 4.1, ho ritenuto opportuno modificare ./lib/language_pack/rails41.rbe aggiungere questa funzionalità.

Di seguito è riportato 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 dalla 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 l'app, assicurarsi di impostare prima la variabile di ambiente: Impostazione di SECRET_KEY_BASE nella dashboard di Heroku

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

Il buildpack creerà automaticamente il tuo config/secrets.ymldalla tua variabile d'ambiente come parte del processo di compilazione del dyno ogni volta che vai git pushsu Heroku.

EDIT: la stessa documentazione di Heroku suggerisce di creare config/secrets.ymluna lettura dalla variabile d'ambiente ma questo implica che dovresti controllare questo file nel controllo del codice sorgente. Nel mio caso, questo non funziona bene dal momento che ho segreti hardcoded per ambienti di sviluppo e test che preferirei non fare il check-in.


Mentre un'ottima soluzione le gemme .dotenv e .foreman risolvono questo problema: "Ho segreti hardcoded per ambienti di sviluppo e test" - quindi l'uso di queste gemme significa che non è necessario il buildpack in quanto è possibile utilizzare ENV_VAR nel file dei segreti per dev e prova anche
rmcsharry,

Si noti che le variabili di ambiente sono registrate dalla maggior parte dell'infrastruttura, il che significa che le variabili di ambiente non crittografate saranno in testo normale nei registri. Non utilizzo Heroku per le mie app Rails, quindi non ho alcuna raccomandazione, ma con AWS estraiamo i valori crittografati dall'archivio parametri durante la compilazione dall'interno del contenitore di build e li decodifichiamo per popolare questo tipo di risorse sicure.
Daniel Nalbach,

1

Puoi esportare le chiavi segrete come variabili d'ambiente sul ~/.bashrco ~/.bash_profiledel tuo server:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

E poi, puoi procurarti il ​​tuo .bashrco .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Non impegnare mai il tuo secrets.yml


1

Nel mio caso, il problema era che config/master.keynon era nel controllo della versione e che avevo creato il progetto su un altro computer.

Il .gitignore predefinito creato da Rails esclude questo file. Dal momento che è impossibile distribuire senza avere questo file, deve essere in controllo versione, per poterlo distribuire dal computer di qualsiasi membro del team.

Soluzione: rimuovere la config/master.keylinea da .gitignore, eseguire il commit del file dal computer in cui è stato creato il progetto e ora è possibile git pullsull'altro computer e distribuirlo da esso.

La gente dice di non impegnare alcuni di questi file nel controllo versione, senza offrire una soluzione alternativa. Finché non stai lavorando a un progetto open source, non vedo alcun motivo per non impegnare tutto ciò che è necessario per eseguire il progetto, comprese le credenziali.


Non eseguire mai il commit del file della chiave principale su git. Questa è una grande vulnerabilità di sicurezza per la tua app. Per open source è difficile, ma la creazione di un vault password con il tuo gestore password preferito è un'opzione migliore.
wsizoo,

Perché sarebbe una vulnerabilità di sicurezza, se il repository è privato? Se una persona non autorizzata ha accesso al mio repository privato, allora ho problemi più grandi della perdita delle chiavi API. Non tutti i progetti sono open source.
Andrew Koster,

Sento che tutti lo stanno solo ripetendo perché l'hanno visto in un tutorial per un progetto open source.
Andrew Koster,

Tutta questa faccenda è molto più confusa perché c'è così tanta documentazione obsoleta sul vecchio secrets.ymlfile, che è stato deprecato per le precedenti versioni di Rails. Questa domanda Stack Overflow ha una tonnellata di risposte e quasi tutti usano questa antica API.
Andrew Koster,

1

Per rails6, stavo affrontando lo stesso problema, poiché mancavano i seguenti file, una volta aggiunti, il problema è stato risolto:

1. config/master.key
2. config/credentials.yml.enc

Assicurati di avere questo file. !!!


0

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 incantesimo e quindi non è necessario disporre della chiave segreta per il controllo della versione

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


1
puoi spiegare perché / come funziona? La domanda era per Heroku. Thin è un'alternativa o è compatibile con Heroku?
ahnbizcad,

-1

Ho una patch che ho usato in un'app Rails 4.1 per consentirmi 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 allora ho riformattato la patch e l'ho inviata a Rails come richiesta pull






-3

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

1
Come si ripete dappertutto, NON è consigliabile eseguire il commit di secrets.yml o secret_token.rb su git.
cofiem,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.