Comment résoudre l’erreur “Missing` secret_key_base` pour l’environnement de production “(Rails 4.1)

J’ai créé une application de rails (rails 4.1) à partir de zéro et je suis confronté à un problème étrange que je ne suis pas en mesure de résoudre.

Chaque fois que j’essaie de déployer mon application sur Heroku, je reçois une erreur 500:

Missing secret_key_base pour l’environnement de production, définissez cette valeur dans config/secrets.yml

Le fichier secret.yml contient la configuration suivante:

 secret_key_base:  

Sur Heroku, j’ai configuré une variable d’environnement “SECRET_KEY_BASE” avec le résultat de la commande “rake secret”. Si je lance “heroku config”, je peux voir la variable avec le nom et la valeur corrects.

Pourquoi est-ce que je reçois toujours cette erreur?

Merci beaucoup

J’ai eu le même problème et je l’ai résolu en créant une variable d’environnement à charger chaque fois que je me suis connecté au serveur de production et j’ai réalisé un mini guide des étapes pour le configurer:

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

J’utilisais Rails 4.1 avec Unicorn v4.8.2, lorsque j’ai essayé de déployer mon application, elle n’a pas démarré correctement et dans le fichier unicorn.log, j’ai trouvé ce message d’erreur:

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

Après quelques recherches, j’ai découvert que Rails 4.1 avait changé la façon de gérer la clé secrète, donc si vous lisez le fichier exampleRailsProject/config/secrets.yml situé à exampleRailsProject/config/secrets.yml vous trouverez quelque chose comme ceci:

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

Cela signifie que Rails vous recommande d’utiliser une variable d’environnement pour secret_key_base dans votre serveur de production. Pour résoudre cette erreur, vous devez suivre ces étapes pour créer une variable d’environnement pour Linux (dans mon cas Ubuntu) sur votre serveur de production:

  1. Dans le terminal de votre serveur de production, exécutez la commande suivante:

     $ RAILS_ENV=production rake secret 

    Cela retourne une grande chaîne avec des lettres et des chiffres, copiez-la (nous ferons référence à ce code comme GENERATED_CODE).

  2. Connectez-vous à votre serveur

    • Si vous vous connectez en tant qu’utilisateur root, recherchez ce fichier et modifiez-le:

       $ vi /etc/profile 

      Aller au bas du fichier (“SHIFT + G” pour la majuscule G dans VI)

      Ecrivez votre variable d’environnement avec le GENERATED_CODE (Appuyez sur la touche “i” pour écrire dans VI), assurez-vous d’être dans une nouvelle ligne à la fin du fichier:

       $ export SECRET_KEY_BASE=GENERATED_CODE 

      Enregistrez les modifications et fermez le fichier (nous appuyons sur la touche “Echap” puis écrivez “: x” et “ENTER” pour enregistrer et quitter dans VI).

    • Mais si vous vous connectez en tant qu’utilisateur normal, appelons-le “exemple_utilisateur” pour cet aperçu, vous devrez trouver l’un de ces autres fichiers:

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

      Ces fichiers sont en ordre d’importance, ce qui signifie que si vous avez le premier fichier, vous n’avez pas besoin d’écrire dans les autres. Donc, si vous avez trouvé ces 2 fichiers dans votre répertoire ~/.bash_profile et ~/.profile vous devrez écrire uniquement le premier ~/.bash_profile , car Linux ne lira que celui-ci et l’autre sera ignoré.

      Ensuite, nous allons au bas du fichier (“SHIFT + G” pour la majuscule G dans VI).

      Et nous allons écrire notre variable d’environnement avec notre GENERATED_CODE (Appuyez sur la touche “i” pour écrire dans VI), assurez-vous d’être dans une nouvelle ligne à la fin du fichier:

       $ export SECRET_KEY_BASE=GENERATED_CODE 

      Après avoir écrit le code, sauvegardez les modifications et fermez le fichier (nous appuyons sur la touche “ESC” puis écrivez “: x” et “ENTER” pour enregistrer et quitter dans VI).

  3. Vous pouvez vérifier que notre variable d’environnement est correctement définie sous Linux avec cette commande:

     $ printenv | grep SECRET_KEY_BASE 

    ou avec:

     $ echo $SECRET_KEY_BASE 

    Lorsque vous exécutez cette commande, si tout s’est bien passé, vous verrez le GENERATED_CODE d’avant. Enfin, avec toute la configuration effectuée, vous devriez pouvoir déployer sans problème votre application Rails avec Unicorn ou autre.

Lorsque vous fermez votre terminal shell et vous reconnectez au serveur de production, vous aurez cette variable d’environnement définie et prête à l’utiliser.

Et c’est tout!! J’espère que ce mini guide vous aidera à résoudre cette erreur.

Disclaimer: Je ne suis pas un gourou de Linux ou Rails, donc si vous trouvez quelque chose qui ne va pas ou une erreur, je serai ravi de le réparer!

Je vais supposer que vos fichiers .gitignore ne sont pas entrés dans le contrôle de code source (c.-à-d. .gitignore dans le fichier .gitignore ). Même si ce n’est pas votre cas, c’est ce que de nombreuses autres personnes qui consultent cette question ont fait car elles ont exposé leur code sur Github et ne veulent pas que leur clé secrète flotte.

Si ce n’est pas le cas, Heroku ne le sait pas. Donc Rails recherche Rails.application.secrets.secret_key_base et il n’a pas été défini car Rails le définit en vérifiant le fichier secrets.yml qui n’existe pas. La solution simple consiste à aller dans votre fichier config/environments/production.rb et à append la ligne suivante:

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

Cela indique à votre application de définir la clé secrète à l’aide de la variable d’environnement au lieu de la rechercher dans secrets.yml . Cela m’aurait épargné beaucoup de temps pour le savoir d’avance.

Ajoutez config/secrets.yml au contrôle de version et déployez à nouveau. Vous devrez peut-être supprimer une ligne de .gitignore pour pouvoir valider le fichier.

J’ai eu exactement le même problème et il s’est avéré que le .gitignore Github créé pour mon application Rails comprenait config/secrets.yml .

Cela a fonctionné pour moi.

SSH dans votre serveur de production et cd dans votre répertoire actuel, exécutez un bundle exec rake secret rake secret ou un rake secret , vous obtiendrez une longue chaîne en tant que sortie, copiez cette chaîne.

Maintenant, lancez sudo nano /etc/environment .

Coller en bas du fichier

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

rake secret est la chaîne que vous venez de copier, collez cette chaîne copiée à la place du rake secret .

Redémarrez le serveur et testez en exécutant echo $SECRET_KEY_BASE .

Bien que vous puissiez utiliser les initialiseurs comme les autres réponses, la méthode conventionnelle Rails 4.1+ consiste à utiliser config/secrets.yml . La raison pour laquelle l’équipe Rails a introduit ceci est hors de la scope de cette réponse mais la TL; DR est que secret_token.rb confond la configuration et le code tout en étant un risque de sécurité puisque le jeton est archivé dans l’historique de contrôle source et le seul système qui a besoin de connaître le jeton secret de production est l’infrastructure de production.

Vous devriez append ce fichier à .gitignore même manière que vous n’appendiez pas config/database.yml au contrôle de source.

En référençant le propre code de Heroku pour configurer config/database.yml partir de DATABASE_URL dans leur Buildpack pour Ruby , j’ai fini par falsifier leur repo et l’ai modifié pour créer config/secrets.yml SECRETS_KEY_BASE partir de la variable d’environnement SECRETS_KEY_BASE .

Depuis que cette fonctionnalité a été introduite dans Rails 4.1, j’ai jugé bon d’éditer ./lib/language_pack/rails41.rb et d’append cette fonctionnalité.

Ce qui suit est l’ extrait du buildpack modifié que j’ai créé chez moi:

 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 

Vous pouvez bien sûr étendre ce code pour append d’autres secrets (par exemple, des clés d’API tierces, etc.) à lire dans votre variable d’environnement:

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

De cette façon, vous pouvez accéder à ce secret de manière très standard:

 Rails.application.secrets.third_party_api_key 

Avant de redéployer votre application, assurez-vous de définir d’abord votre variable d’environnement: Définition de SECRET_KEY_BASE dans le tableau de bord Heroku

Ajoutez ensuite votre buildpack modifié (ou vous êtes plus que bienvenu pour créer un lien vers le mien) vers votre application Heroku (voir la documentation de Heroku) et redéployez votre application.

Le buildpack créera automatiquement votre config/secrets.yml partir de votre variable d’environnement dans le cadre du processus de génération de dyno chaque fois que vous lancez une git push vers Heroku.

EDIT: La propre documentation de Heroku suggère de créer config/secrets.yml pour lire la variable d’environnement, mais cela implique que vous devriez vérifier ce fichier dans le contrôle de code source. Dans mon cas, cela ne fonctionne pas bien car j’ai des secrets codés pour les environnements de développement et de test que je préfère ne pas enregistrer.

Vous pouvez exporter les clés secrètes en tant que variables d’environnement sur les ~/.bashrc ou ~/.bash_profile de votre serveur:

 export SECRET_KEY_BASE = "YOUR_SECRET_KEY" 

Et puis, vous pouvez vous .bashrc votre .bash_profile .bashrc ou .bash_profile :

 source ~/.bashrc source ~/.bash_profile 

Ne jamais commettre vos secrets.yml

Ce que j’ai fait: Sur mon serveur de production, je crée un fichier de configuration (confthin.yml) pour Thin (je l’utilise) et j’ajoute les informations suivantes:

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

Je lance ensuite l’application avec

 thin start -C /whereeveristhefieonprod/configthin.yml 

Travailler comme un charme et pas besoin d’avoir la clé secrète sur le contrôle de version

J’espère que cela pourrait aider, mais je suis sûr que la même chose pourrait être faite avec Unicorn et d’autres.

J’ai un patch que j’ai utilisé dans une application Rails 4.1 pour me permettre de continuer à utiliser le générateur de clé hérité (et donc la compatibilité de session en arrière avec Rails 3), en permettant à la base secret_key d’être vide.

 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 

Je l’ai depuis reformaté le patch est soumis à Rails comme une demande de traction

J’ai créé le fichier config/initializers/secret_key.rb et j’ai écrit uniquement la ligne de code suivante:

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

Mais je pense que la solution publiée par @Erik Trautman est plus élégante;)

Edit: Oh, et finalement j’ai trouvé ce conseil sur Heroku: https://devcenter.heroku.com/changelog-items/426 🙂

Prendre plaisir!

cela fonctionne bien https://gist.github.com/pablosalgadom/4d75f30517edc6230a67 pour l’utilisateur root devrait modifier

 $ /etc/profile 

mais si vous n’êtes pas root, vous devez mettre le code généré dans ce qui suit

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

Sur Nginx / Passenger / Ruby (2.4) / Rails (5.1.1), rien n’a fonctionné sauf:

passenger_env_var dans /etc/nginx/sites-available/default dans le bloc serveur.

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

La réponse de Demi Magus a fonctionné pour moi jusqu’à ce que Rails 5.

Sur Apache2 / Passenger / Ruby (2.4) / Rails (5.1.6), j’ai dû mettre

 export SECRET_KEY_BASE=GENERATED_CODE 

de Demi Magus répond dans / etc / apache2 / envvars, car / etc / profile semble être ignoré.

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

J’ai eu le même problème après avoir utilisé le fichier .gitignore de https://github.com/github/gitignore/blob/master/Rails.gitignore

Tout s’est bien passé après avoir commenté les lignes suivantes dans le fichier .gitignore.

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