Comment résoudre l'erreur «Manquant` secret_key_base` pour l'environnement de 'production' »(Rails 4.1)

169

J'ai créé une application Rails, en utilisant Rails 4.1, à partir de zéro et je suis confronté à un problème étrange que je ne parviens pas à résoudre.

Chaque fois que j'essaye de déployer mon application sur Heroku, j'obtiens une erreur 500:

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

Le secret.ymlfichier contient la configuration suivante:

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

Sur Heroku, j'ai configuré la SECRET_KEY_BASEvariable d'environnement " " avec le résultat de la rake secretcommande. Si je lance heroku config, je peux voir la variable avec le nom et la valeur corrects.

Pourquoi est-ce que j'obtiens toujours cette erreur?

Paolo Laurenti
la source
1
J'ai exactement le même problème et j'aimerais savoir pourquoi cela se produit aussi. Si je comprends pourquoi, je posterai ma solution.
danielricecodes
Votre fichier de configuration est-il appelé secret.ymlou secrets.yml?
James
2
J'ai configuré à nouveau le fichier .gitignore avec celui généré par les rails et maintenant tout fonctionne bien
Paolo Laurenti
Nous avons également eu ce problème lors de la mise à niveau vers Rails 4. Dans notre cas, c'était parce que nous avions un nom d'environnement personnalisé, et cela ne se reflétait pas dans secrets.yml. Je devais juste ajouter une ligne au fichier avec le nom non standard, commettre et redéployer.
whognu
Pour les futurs lecteurs: cette réponse est probablement la plus simple et la plus précise: stackoverflow.com/a/26541742/4880924
BKSpurgeon

Réponses:

208

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 créé un mini-guide des étapes pour le configurer:

J'utilisais Rails 4.1 avec Unicorn v4.8.2 et lorsque j'ai essayé de déployer mon application, cela n'a pas démarré correctement et dans le unicorn.logfichier, 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 le secret_key, donc si vous lisez le secrets.ymlfichier situé sur, exampleRailsProject/config/secrets.ymlvous 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 le secret_key_basedans votre serveur de production. Afin de 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:

    $ RAILS_ENV=production rake secret

    Cela renvoie une grande chaîne avec des lettres et des chiffres. Copiez cela, que nous appellerons ce code 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

      Allez au bas du fichier en utilisant Shift+ G(«G» majuscule) dans vi.

      Écrivez votre variable d'environnement avec le GENERATED_CODE, en appuyant sur ipour insérer 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 en utilisant Escet puis " :x" et Enterpour enregistrer et quitter dans vi.

    • Mais si vous vous connectez en tant qu'utilisateur normal, appelons-le " example_user" pour l'essentiel, vous devrez trouver l'un de ces autres fichiers:

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

      Ces fichiers sont classés par ordre d'importance, ce qui signifie que si vous avez le premier fichier, vous n'avez pas besoin de modifier les autres. Si vous avez trouvé ces deux fichiers dans votre répertoire ~/.bash_profileet que ~/.profilevous n'aurez à écrire que dans le premier ~/.bash_profile, car Linux ne lira que celui-ci et l'autre sera ignoré.

      Ensuite, nous allons au bas du fichier en utilisant à nouveau Shift+ Get écrivons à nouveau la variable d'environnement avec notre GENERATED_CODEutilisation i, et assurez-vous d'ajouter une nouvelle ligne à la fin du fichier:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Après avoir écrit le code, enregistrez les modifications et fermez le fichier en utilisant à Escnouveau et " :x" et Enterpour enregistrer et quitter.

  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é, elle vous montrera le GENERATED_CODEprécédent. Enfin, une fois la configuration terminée, vous devriez pouvoir déployer sans problème votre application Rails avec Unicorn ou un autre outil.

Lorsque vous fermez votre shell et que vous vous connectez à nouveau au serveur de production, cette variable d'environnement est définie et prête à l'utiliser.

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

Avertissement: Je ne suis pas un gourou de Linux ou de Rails, donc si vous trouvez quelque chose de mal ou une erreur, je serai heureux de le réparer.

Demi Magus
la source
11
Il semble que Rails ne voit pas la variable d'environnement SECRET_KEY_BASE. printenv le montre, les rails c production l'affiche également, si j'inspecte ENV. Mais, je n'ai aucun effet, lorsque je redémarre Unicorn. Le seul moyen, qui fonctionne maintenant, est de le coller directement dans
secrets.yml
1
Cela a fonctionné pour moi. Merci pour votre explication complète. Je viens d'apprendre qu'il existe des gemmes pour gérer les variables d'environnement d'une application. «Dotenv» en est un et «contremaître» pour heroku. Même s'il était éducatif de corriger l'erreur manuellement de cette façon, peut-être que l'utilisation de l'un de ces joyaux rationalisera le processus?
Nick Res
Je suis heureux que ma réponse ait été utile, merci pour les options de gemmes @ ninja08, elles facilitent définitivement le processus, principalement pour ceux qui utilisent capistrano ou un autre outil incrémental pour gérer le serveur :)
Demi Magus
En suivant les excellentes instructions de Demi Magus, j'ai fait quelque chose comme ceci: cd / var / www / rails; rvm utilise ext-rbx-2.5.2@rails; SKB_FILE = / var / www / .secret_key_base; echo "export SECRET_KEY_BASE = $ (RAILS_ENV = rake secret de production)"> $ SKB_FILE; . $ SKB_FILE; echo ". $ SKB_FILE" | tee -a ~ / .bashrc ~ / .bash_profile; chmod o-rwx $ SKB_FILE;
David Winiecki
Bonne réponse!! Je ne sais pas pourquoi ce n'est pas résolu pour moi, je crée une question stackoverflow.com/questions/33117318/...
Adriano Resende
84

Je vais supposer que vous n'avez pas archivé votre secrets.ymlcontrôle de code source (c'est-à-dire qu'il est dans le .gitignorefichier). Même si ce n'est pas votre situation, c'est ce que beaucoup d'autres personnes qui consultent cette question ont fait parce qu'elles ont leur code exposé sur Github et ne veulent pas que leur clé secrète flotte.

S'il n'est pas sous contrôle de code source, Heroku ne le sait pas. Donc Rails cherche Rails.application.secrets.secret_key_baseet il n'a pas été défini car Rails le définit en vérifiant le secrets.ymlfichier qui n'existe pas. La solution de contournement simple consiste à accéder à votre config/environments/production.rbfichier et à ajouter 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 fait gagner beaucoup de temps pour le savoir dès le départ.

Erik Trautman
la source
15
C'est la meilleure réponse. Figaroet heroku_secretsne faites rien à moins que Rails sache que cela SECRET_KEY_BASEvit ENV. J'ai eu du mal à penser que si la variable de configuration existait sur Heroku, Rails la ramasserait simplement en raison de son existence, mais maintenant, il semble aveuglément évident que Rails aurait besoin de savoir où chercher. Je me suis demandé comment je pouvais avoir du code sur Github sans avoir à me soucier de la base de clé secrète; maintenant je sais.
flanger001
1
D'accord, je pense que le secret.yml est superflu avec de grandes gemmes comme Figaro.
Joe
2
Cela semble être la meilleure option si vous utilisez github et heroku pour votre projet.
flexus
1
Quel est le problème avec la validation de vos secrets.yml avec production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Cela ne signifie pas également que la clé secrète réelle n'est pas exposée. Existe-t-il un risque d'exposer les clés de développement et de test dans les secrets.yml validés s'il ne s'agit que de données de départ et de test?
Jay Killeen
Cela fonctionne même dans Rails 6.0.2, quand il n'y a plus de secrets.yml.
Ken Tsoi le
54

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

J'ai eu exactement le même problème et il s'est avéré que le passe-partout .gitignorecréé par Github pour mon application Rails était inclus config/secrets.yml.

danielricecodes
la source
140
config / secrets.yml ne devrait JAMAIS être dans le dépôt que vous pouvez faire.yml.sample et le remplir avec de fausses données mais pour la sécurité, ne jamais faire de .yml dans les
dépôts
9
@ user3379926, dans le contexte d'une application Rails sur Heroku, vous ne pouvez pas choisir les fichiers inclus dans le contrôle de version et ceux qui ne le sont pas. Rails 4.1 s'attend à ce que la configuration secrète existe, sinon l'application ne fonctionnera pas. Si vous avez un moyen de résoudre le problème posé dans la question ci-dessus sans recourir à la validation du fichier secrets.yml dans Git, veuillez aider à améliorer ce fil en fournissant ces conseils.
danielricecodes
9
@danielricecodes vous pouvez définir manuellement la valeur dans un initialiseur. Quelque chose comme Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]cela fonctionnerait et supprimerait l'erreur sans ajouter secrets.ymlà la source.
joshhepworth
11
@ user3379926: Lorsque je génère une nouvelle application Rails avec rails new(produisant, dans ce cas, un Gemfile dont le railsgem a la version 4.2.4), le fichier config/secrets.ymlest généré. Il comprend des clés secrètes prégénérés pour les environnements de développement et de test, et lit le SecretKey pour l'environnement de production d'une variable d'environnement: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Il me semble qu'il est parfaitement sûr, et en effet utile, de conserver ce secrets.ymlfichier en contrôle de version, à condition que l'on n'y définisse jamais réellement la clé secrète.
Teemu Leisti
2
@jasonleonhard pourquoi? si vous lisez de toute façon la clé secrète de env vars, quel est le problème? il n'y a pas de secrets exposés.
horseyguy
13

Cela a fonctionné pour moi.

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

Maintenant, cours sudo nano /etc/environment.

Coller au bas du fichier

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

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

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

sumitsv21
la source
3

Bien que vous puissiez utiliser des initialiseurs comme les autres réponses, la méthode conventionnelle de Rails 4.1+ consiste à utiliser le config/secrets.yml. La raison pour laquelle l'équipe Rails d'introduire cela dépasse le cadre de cette réponse, mais le TL; DR est que cela secret_token.rbconfond la configuration et le code ainsi qu'un risque de sécurité puisque le jeton est archivé dans l'historique de contrôle de source et le seul système qui doit sachez que le jeton secret de production est l'infrastructure de production.

Vous devriez ajouter ce fichier à .gitignorepeu près comme vous n'ajouteriez pas non plus config/database.ymlau contrôle de code source.

En référençant le propre code de Heroku pour la configuration à config/database.ymlpartir DATABASE_URLde leur Buildpack pour Ruby , j'ai fini par forger leur dépôt et je l'ai modifié pour créer à config/secrets.ymlpartir deSECRETS_KEY_BASE la variable d'environnement.

Depuis que cette fonctionnalité a été introduite dans Rails 4.1, j'ai pensé qu'il était approprié de modifier ./lib/language_pack/rails41.rbet d'ajouter cette fonctionnalité.

Ce qui suit est l' extrait du buildpack modifié que j'ai créé dans mon entreprise:

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 ajouter d'autres secrets (par exemple des clés 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) à votre application Heroku (voir la documentation de Heroku ) et redéployez votre application.

Le buildpack créera automatiquement votre config/secrets.ymlvariable d'environnement à partir de votre variable d'environnement dans le cadre du processus de construction dyno chaque fois que vous vous git pushrendrez à Heroku.

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

empilement
la source
Bien que les gemmes .dotenv et .foreman résolvent ce problème: "J'ai des secrets codés en dur pour les environnements de développement et de test", l'utilisation de ces gemmes signifie que vous n'avez pas besoin du buildpack car vous pouvez utiliser ENV_VAR dans votre fichier secrets pour dev et tester aussi
rmcsharry
Notez que les variables d'environnement sont consignées par la plupart des infrastructures, ce qui signifie que les variables d'environnement non chiffrées seront en texte brut dans les journaux. Je n'utilise pas Heroku pour mes applications Rails, je n'ai donc aucune recommandation à ce sujet, mais avec AWS, nous extrayons les valeurs chiffrées du Parameter Store pendant la construction depuis l'intérieur du conteneur de construction et les déchiffrons pour alimenter ces types d'actifs sécurisés.
Daniel Nalbach
1

Vous pouvez exporter les clés secrètes en tant que variables d'environnement sur le ~/.bashrcou ~/.bash_profilede votre serveur:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

Et puis, vous pouvez vous procurer votre .bashrcou .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Ne confiez jamais vos secrets.yml

alessandrocb
la source
1

Dans mon cas, le problème était que ce config/master.keyn'était pas dans le contrôle de version, et j'avais créé le projet sur un autre ordinateur.

Le .gitignore par défaut créé par Rails exclut ce fichier. Comme il est impossible de déployer sans avoir ce fichier, il doit être en contrôle de version, afin de pouvoir être déployé à partir de l'ordinateur de n'importe quel membre de l'équipe.

Solution: supprimez la config/master.keyligne de .gitignore, validez le fichier de l'ordinateur sur lequel le projet a été créé, et maintenant vous pouvez git pullsur l'autre ordinateur et déployer à partir de celui-ci.

Les gens disent de ne pas confier certains de ces fichiers au contrôle de version, sans offrir une solution alternative. Tant que vous ne travaillez pas sur un projet open source, je ne vois aucune raison de ne pas valider tout ce qui est nécessaire pour exécuter le projet, y compris les informations d'identification.

Andrew Koster
la source
Ne validez jamais votre fichier de clé principale dans git. Il s'agit d'une vulnérabilité de sécurité géante pour votre application. Pour l'open source, c'est difficile, mais la création d'un coffre-fort de mots de passe avec votre gestionnaire de mots de passe préféré est une meilleure option.
wsizoo
Pourquoi serait-ce une faille de sécurité, si le repo est privé? Si une personne non autorisée a accès à mon dépôt privé, j'ai de plus gros problèmes que de simples fuites de clés API. Tous les projets ne sont pas open source.
Andrew Koster
J'ai l'impression que tout le monde ne fait que répéter cela parce qu'ils l'ont vu dans un tutoriel pour un projet open source.
Andrew Koster
Tout cela est encore plus déroutant car il y a tellement de documentation obsolète sur l'ancien secrets.yml fichier, qui a été obsolète pour les dernières versions de Rails. Cette question Stack Overflow elle-même a une tonne de réponses, et ils utilisent presque tous cette ancienne API.
Andrew Koster
1

Pour rails6, j'étais confronté au même problème, car il me manquait les fichiers suivants, une fois que je les ai ajoutés, le problème est résolu:

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

Assurez-vous d'avoir ces fichiers. !!!

Tushar H
la source
0

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

Travaillez comme un charme et alors 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.

Géraud Puechaldou
la source
1
pouvez-vous expliquer pourquoi / comment cela fonctionne? La question était pour heroku. Le mince est-il une alternative ou est-il compatible avec heroku?
ahnbizcad
-1

J'ai un correctif que j'ai utilisé dans une application Rails 4.1 pour me permettre de continuer à utiliser le générateur de clés hérité (et donc la compatibilité de session en amont avec Rails 3), en permettant à secret_key_base 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

J'ai depuis reformaté le correctif et je l'ai soumis à Rails en tant que demande de tirage

BF4
la source
-1

J'ai créé le config/initializers/secret_key.rbfichier et je n'ai écrit que la ligne de code suivante:

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

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

Edit: Oh, et enfin j'ai trouvé ce conseil sur Heroku: https://devcenter.heroku.com/changelog-items/426 :)

Prendre plaisir!

fadehelix
la source
-1

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

$ /etc/profile

mais si vous n'êtes pas root, mettez le code de génération dans ce qui suit

$ ~/.bash_profile

$ ~/.bash_login

$ ~/.profile
bung_firman
la source
-3

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

la source
1
Comme cela se répète partout, la validation de secrets.yml ou secret_token.rb dans git n'est PAS recommandée.
cofiem