Como resolver o erro “Faltando 'secret_key_base` para o ambiente de' produção '” (Rails 4.1)


169

Criei um aplicativo Rails, usando o Rails 4.1, do zero e estou enfrentando um problema estranho que não consigo resolver.

Sempre que tento implantar meu aplicativo no Heroku, recebo um erro 500:

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

O secret.ymlarquivo contém a seguinte configuração:

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

No Heroku, configurei a SECRET_KEY_BASEvariável de ambiente " " com o resultado do rake secretcomando. Se eu iniciar heroku config, posso ver a variável com o nome e o valor corretos.

Por que ainda estou recebendo esse erro?


1
Estou tendo exatamente o mesmo problema e gostaria de saber por que isso também está acontecendo. Se eu descobrir o porquê, postarei de volta com a minha solução.
Danielricecodes

O seu arquivo de configuração é chamado secret.ymlou secrets.yml?
James

2
Eu configurei novamente o arquivo .gitignore com aquele gerado por trilhos e agora tudo funciona bem
Paolo Laurenti

Também tivemos esse problema quando atualizamos para o Rails 4. No nosso caso, era porque tínhamos um nome de ambiente personalizado e isso não era refletido em secrets.yml. Eu apenas tive que adicionar uma linha ao arquivo com o nome não padrão, confirmar e reimplementar.
whognu

Para os leitores futuros: esta resposta é provavelmente o mais fácil e mais preciso: stackoverflow.com/a/26541742/4880924
BKSpurgeon

Respostas:


208

Eu tive o mesmo problema e o resolvi criando uma variável de ambiente a ser carregada toda vez que eu fazia login no servidor de produção e fazia um mini-guia das etapas para configurá-lo:

Eu estava usando o Rails 4.1 com Unicorn v4.8.2 e quando tentei implantar meu aplicativo, ele não foi iniciado corretamente e no unicorn.logarquivo encontrei esta mensagem de erro:

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

Após algumas pesquisas, descobri que o Rails 4.1 mudou a maneira de gerenciar o secret_key, portanto, se você ler o secrets.ymlarquivo localizado em, exampleRailsProject/config/secrets.ymlencontrará algo parecido com isto:

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

Isso significa que o Rails recomenda o uso de uma variável de ambiente secret_key_baseno servidor de produção. Para resolver esse erro, você deve seguir estas etapas para criar uma variável de ambiente para Linux (no meu caso, Ubuntu) em seu servidor de produção:

  1. No terminal do seu servidor de produção, execute:

    $ RAILS_ENV=production rake secret

    Isso retorna uma string grande com letras e números. Copie isso, ao qual nos referiremos a esse código como GENERATED_CODE.

  2. Entre no seu servidor

    • Se você fizer login como usuário root, encontre este arquivo e edite-o:

      $ vi /etc/profile

      Vá para a parte inferior do arquivo usando Shift+G (capital "G") no vi.

      Escreva sua variável de ambiente com GENERATED_CODE, pressionando ipara inserir no vi. Certifique-se de estar em uma nova linha no final do arquivo:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Salve as alterações e feche o arquivo usando Esce " :x" e Enterpara salvar e sair no vi.

    • Mas se você logar como usuário normal, vamos chamá-lo " example_user" para esta essência, você precisará encontrar um desses outros arquivos:

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

      Esses arquivos estão em ordem de importância, o que significa que, se você tiver o primeiro arquivo, não precisará editar os outros. Se você encontrou esses dois arquivos em seu diretório ~/.bash_profilee ~/.profilesó precisará escrever no primeiro ~/.bash_profile, porque o Linux lerá apenas este e o outro será ignorado.

      Em seguida, vamos para a parte inferior do arquivo usando Shift+ Gnovamente e escrevemos a variável de ambiente GENERATED_CODEusando inovamente, e certifique-se de adicionar uma nova linha no final do arquivo:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Após escrever o código, salve as alterações e feche o arquivo usando Esc" :x" novamente e Enterpara salvar e sair.

  3. Você pode verificar se nossa variável de ambiente está configurada corretamente no Linux com este comando:

    $ printenv | grep SECRET_KEY_BASE

    ou com:

    $ echo $SECRET_KEY_BASE

    Quando você executa este comando, se tudo der certo, ele mostrará o que foi mostrado GENERATED_CODEantes. Finalmente, com toda a configuração concluída, você poderá implantar, sem problemas, seu aplicativo Rails com o Unicorn ou alguma outra ferramenta.

Ao fechar seu shell e efetuar login novamente no servidor de produção, você terá essa variável de ambiente configurada e pronta para usá-la.

E é isso! Espero que este mini-guia o ajude a resolver esse erro.

Isenção de responsabilidade: Eu não sou um guru do Linux ou Rails, portanto, se você encontrar algo errado ou algum erro, terei o maior prazer em corrigi-lo.


11
Parece que o Rails não vê a variável de ambiente SECRET_KEY_BASE. printenv mostra, a produção de trilhos c também exibe, se eu inspecionar ENV. Mas, não tenho efeito, quando reinicio o Unicorn. A única maneira, que funciona agora, é colá-lo diretamente em segredos.yml
AntonAL 17/11/14

1
Isso funcionou para mim. Obrigado por sua explicação completa. Acabei de aprender que existem gemas para gerenciar variáveis ​​de ambiente de um aplicativo. 'Dotenv' é um e 'capataz' para heroku. Embora tenha sido educado corrigir o erro manualmente dessa maneira, talvez o uso de uma dessas gemas simplifique o processo?
Nick Res

Fico feliz que a minha resposta foi útil, obrigado pelas opções gem @ ninja08, eles definitivamente tornar o processo mais fácil, principalmente para aqueles que usam Capistrano ou outra ferramenta incremental para gerenciar o servidor :)
Demi Magus

Seguindo as excelentes instruções de Demi Magus, eu fiz algo assim: cd / var / www / rails; rvm use ext-rbx-2.5.2@rails; SKB_FILE = / var / www / .secret_key_base; echo "export SECRET_KEY_BASE = $ (RAILS_ENV = segredo de comissão de produção)"> $ SKB_FILE; . $ SKB_FILE; eco ". $ SKB_FILE" | tee -a ~ / .bashrc ~ / .bash_profile; chmod o-rwx $ SKB_FILE;
21815 David Winiecki

Boa resposta!! Eu não sei por que isso não é resolvido para mim, eu criar questão stackoverflow.com/questions/33117318/...
Adriano Resende

84

Eu vou assumir que você não tem seu secrets.ymlcheck-in no controle de origem (ou seja, está no .gitignorearquivo). Mesmo que essa não seja a sua situação, é o que muitas outras pessoas que visualizam essa pergunta fizeram porque têm o código exposto no Github e não querem que sua chave secreta flutue.

Se não estiver no controle de origem, o Heroku não sabe disso. Portanto, o Rails está procurando Rails.application.secrets.secret_key_basee não foi definido porque o Rails o define verificando o secrets.ymlarquivo que não existe. A solução simples é entrar no seu config/environments/production.rbarquivo e adicionar a seguinte linha:

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

Isso diz ao seu aplicativo para definir a chave secreta usando a variável de ambiente em vez de procurá-la secrets.yml. Teria me poupado muito tempo para saber disso com antecedência.


15
Esta é a melhor resposta. Figaroe heroku_secretsnão faça nada a menos que o Rails saiba que SECRET_KEY_BASEvive ENV. Eu tenho lutado com esse pensamento de que, se a var de configuração existisse no Heroku, o Rails iria buscá-lo apenas em virtude de existir, mas agora parece óbvio que o Rails precisaria saber para onde procurar. Fiquei me perguntando como posso ter código no Github sem ter que me preocupar com a coisa básica da chave secreta; agora eu sei.
precisa saber é o seguinte

1
Concordo, acho que os segredos.yml são supérfluos com grandes jóias como o Figaro.
Joe

2
Parece a melhor opção se você usar o github e o heroku para o seu projeto.
Flexus

1
O que há de errado em cometer seus segredos.yml production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>? Isso também não significa que a chave secreta real não está exposta. Existe risco de expor as chaves de desenvolvimento e teste em segredos comprometidos.yml se forem apenas dados de semente e teste?
Jay Killeen

Isso funciona mesmo no Rails 6.0.2, quando não há mais secrets.yml.
Ken Tsoi 22/04

54

Adicione config/secrets.ymlao controle de versão e implante novamente. Pode ser necessário remover uma linha de.gitignore para poder confirmar o arquivo.

Eu tive exatamente o mesmo problema e acabou que o clichê .gitignorecriado pelo Github para o meu aplicativo Rails foi incluído config/secrets.yml.


140
config / secrets.yml nunca deve ser no repo pode do.yml.sample e preenchê-lo com dados falsos, mas para a segurança, nunca faça .yml em repos
user3379926

9
@ user3379926, no contexto de um aplicativo Rails no Heroku, você não pode escolher quais arquivos estão incluídos no controle de versão e quais não. O Rails 4.1 espera que a configuração secreta exista, caso contrário o aplicativo não será executado. Se você tem uma maneira de resolver o problema colocado na pergunta acima, sem precisar comprometer o arquivo secrets.yml no Git, ajude a melhorar esse segmento, fornecendo esse conselho.
Danielricecodes

9
@danielricecodes, você pode definir manualmente o valor em um inicializador. Algo como Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]iria funcionar e remover o erro sem adicionar secrets.ymlà fonte.
joshhepworth

11
@ user3379926: Quando eu gero um novo aplicativo Rails com rails new(produzindo, neste caso, um Gemfile cuja railsgema possui a versão 4.2.4), o arquivo config/secrets.ymlé gerado. Ele inclui pregenerated chaves secretas para os ambientes de desenvolvimento e teste, e lê o secretkey para o ambiente de produção a partir de uma variável de ambiente: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Parece-me que é perfeitamente seguro, e de fato útil, manter esse secrets.ymlarquivo no controle de versão, desde que nunca se defina a chave secreta.
Teemu Leisti 27/08/2015

2
@jasonleonhard why? se você está lendo a chave secreta dos env vars de qualquer maneira, qual é o problema? não há segredos sendo expostos.
Horseyguy 15/09/16

13

Isso funcionou para mim.

SSH no servidor de produção e cdno diretório atual, execute bundle exec rake secretourake secret , você obterá uma sequência longa como saída, copie essa sequência.

Agora corra sudo nano /etc/environment .

Cole na parte inferior do arquivo

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

Onde rake secretestá a sequência que você acabou de copiar, cole essa sequência no lugar derake secret .

Reinicie o servidor e teste executando echo $SECRET_KEY_BASE.


3

Embora você possa usar inicializadores como as outras respostas, a maneira convencional do Rails 4.1+ é usar o config/secrets.yml. A razão para a equipe do Rails introduzir isso está além do escopo desta resposta, mas o TL; DR é quesecret_token.rb confunde configuração e código, além de ser um risco à segurança, pois o token é verificado no histórico de controle de origem e o único sistema que precisa ser implementado. conhecer o token secreto de produção é a infraestrutura de produção.

Você deve adicionar esse arquivo da .gitignoremesma forma que não adicionariaconfig/database.yml ao controle de origem.

Referenciando próprio código de Heroku para configurar config/database.ymla partir DATABASE_URLem sua Buildpack para Ruby , acabei bifurcação sua repo e modificado para criar config/secrets.ymla partir deSECRETS_KEY_BASE variável de ambiente.

Desde que esse recurso foi introduzido no Rails 4.1, achei apropriado editar ./lib/language_pack/rails41.rbe adicionar essa funcionalidade.

A seguir, o snippet do buildpack modificado que criei na minha empresa:

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

Obviamente, você pode estender esse código para adicionar outros segredos (por exemplo, chaves de API de terceiros, etc.) para serem lidos em sua variável de ambiente:

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

Dessa forma, você pode acessar esse segredo de uma maneira muito padrão:

Rails.application.secrets.third_party_api_key

Antes de reimplementar seu aplicativo, defina sua variável de ambiente primeiro: Definindo SECRET_KEY_BASE no painel Heroku

Em seguida, adicione seu pacote de compilação modificado (ou você poderá adicionar um link ao meu) no seu aplicativo Heroku (consulte a documentação do Heroku ) e reimplemente seu aplicativo.

O buildpack criará automaticamente sua config/secrets.ymlvariável de ambiente como parte do processo de construção do dyno toda vez que você git pushacessar o Heroku.

EDIT: A própria documentação do Heroku sugere criar config/secrets.ymlpara ler a variável de ambiente, mas isso implica que você deve verificar esse arquivo no controle de origem. No meu caso, isso não funciona bem, pois tenho segredos codificados para ambientes de desenvolvimento e teste que prefiro não fazer check-in.


Enquanto uma ótima solução, as gemas .dotenv e .foreman resolvem este problema: "Eu tenho segredos codificados para ambientes de desenvolvimento e teste" - portanto, usar essas gemas significa que você não precisa do buildpack, pois pode usar ENV_VAR em seu arquivo de segredos para desenvolvedores e desenvolvedores. teste também
rmcsharry

Observe que as variáveis ​​de ambiente são registradas pela maioria da infraestrutura, o que significa que variáveis ​​de ambiente não criptografadas estarão em texto sem formatação nos logs. Eu não uso o Heroku para meus aplicativos Rails, por isso não tenho recomendação, mas com a AWS extraímos valores criptografados do Parameter Store durante a compilação de dentro do contêiner de compilação e os descriptografamos para preencher esses tipos de ativos seguros.
Daniel Nalbach

1

Você pode exportar as chaves secretas para como variáveis ​​de ambiente no ~/.bashrcou ~/.bash_profiledo seu servidor:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

E então, você pode obter seu .bashrcou .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Nunca cometa seus segredos.yml


1

No meu caso, o problema era que config/master.keynão estava no controle de versão e eu havia criado o projeto em um computador diferente.

O .gitignore padrão que o Rails cria exclui esse arquivo. Como é impossível implantar sem ter esse arquivo, ele precisa estar no controle de versão para poder implantar no computador de qualquer membro da equipe.

Solução: remova a config/master.keylinha .gitignore, confirme o arquivo no computador em que o projeto foi criado e agora você pode git pullno outro computador e implantar a partir dele.

As pessoas estão dizendo para não confirmar alguns desses arquivos no controle de versão, sem oferecer uma solução alternativa. Desde que você não esteja trabalhando em um projeto de código aberto, não vejo razão para não comprometer tudo o que é necessário para executar o projeto, incluindo credenciais.


Nunca submeta seu arquivo de chave mestra ao git. Esta é uma vulnerabilidade de segurança gigante para o seu aplicativo. Para código aberto, é difícil, mas criar um cofre de senhas com seu gerenciador de senhas preferido é uma opção melhor.
wsizoo 27/09/19

Por que seria uma vulnerabilidade de segurança, se o repositório for privado? Se uma pessoa não autorizada tiver acesso ao meu repositório particular, eu tenho problemas maiores do que apenas o vazamento de chaves da API. Nem todo projeto é de código aberto.
Andrew Koster

Eu sinto que todo mundo está repetindo isso porque eles viram isso em um tutorial para um projeto de código aberto.
Andrew Koster

Essa coisa toda é extra confusa porque há muita documentação desatualizada sobre o secrets.ymlarquivo antigo , que foi preterida nas últimas versões do Rails. Essa questão do Stack Overflow em si tem muitas respostas, e quase todas elas usam essa API antiga.
Andrew Koster

1

Para o rails6, eu estava enfrentando o mesmo problema, pois estava faltando os seguintes arquivos, depois que os adicionei, o problema foi resolvido:

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

Verifique se você possui esses arquivos. !!!


0

O que fiz: No meu servidor de produção, crio um arquivo de configuração (confthin.yml) para o Thin (estou usando-o) e adiciono as seguintes informações:

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

Em seguida, inicio o aplicativo com

thin start -C /whereeveristhefieonprod/configthin.yml

Funciona como um encanto e não precisa ter a chave secreta no controle de versão

Espero que ajude, mas tenho certeza de que o mesmo pode ser feito com o Unicorn e outros.


1
você pode explicar por que / como isso está funcionando? A pergunta era para heroku. O thin é uma alternativa ou é compatível com o heroku?
ahnbizcad

-1

Eu tenho um patch que usei em um aplicativo Rails 4.1 para permitir que eu continue usando o gerador de chaves herdado (e, portanto, a compatibilidade de sessões com o Rails 3), permitindo que a secret_key_base fique em branco.

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

Desde que reformatei o patch, o enviei ao Rails como uma solicitação de recebimento






Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.