Cómo resolver el error “Falta 'secret_key_base` para el entorno de' producción '” (Rails 4.1)

169

Creé una aplicación Rails, usando Rails 4.1, desde cero y me enfrento a un extraño problema que no puedo resolver.

Cada vez que intento implementar mi aplicación en Heroku me sale un error 500:

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

El secret.ymlarchivo contiene la siguiente configuración:

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

En Heroku configuré la " SECRET_KEY_BASE" variable de entorno con el resultado del rake secretcomando. Si inicio heroku config, puedo ver la variable con el nombre y el valor correctos.

¿Por qué sigo recibiendo este error?

Paolo Laurenti
fuente
1
Tengo exactamente el mismo problema y me encantaría saber por qué sucede esto también. Si descubro por qué, volveré a publicar con mi solución.
danielricecodes
¿Se llama a su archivo de configuración secret.ymlo secrets.yml?
James
2
Configuré nuevamente el archivo .gitignore con el generado por los rieles y ahora todo funciona bien
Paolo Laurenti
También tuvimos este problema cuando actualizamos a Rails 4. En nuestro caso, fue porque teníamos un nombre de entorno personalizado, y eso no se reflejó en secrets.yml. Solo tenía que agregar una línea al archivo con el nombre no estándar, confirmar y volver a implementar.
whognu
Para futuros lectores: esta respuesta es probablemente la más fácil y precisa: stackoverflow.com/a/26541742/4880924
BKSpurgeon

Respuestas:

208

Tuve el mismo problema y lo resolví creando una variable de entorno para cargar cada vez que iniciaba sesión en el servidor de producción, e hice una mini guía de los pasos para configurarlo:

Estaba usando Rails 4.1 con Unicorn v4.8.2 y cuando intenté implementar mi aplicación no se inició correctamente y en el unicorn.logarchivo encontré este mensaje de error:

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

Después de investigar un poco, descubrí que Rails 4.1 cambió la forma de administrar secret_keyel secrets.ymlarchivo , así que si lees el archivo ubicado en exampleRailsProject/config/secrets.ymleste, encontrarás algo como esto:

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

Esto significa que Rails le recomienda utilizar una variable de entorno para secret_key_baseen su servidor de producción. Para resolver este error, debe seguir estos pasos para crear una variable de entorno para Linux (en mi caso Ubuntu) en su servidor de producción:

  1. En la terminal de su servidor de producción ejecute:

    $ RAILS_ENV=production rake secret

    Esto devuelve una cadena grande con letras y números. Copie eso, al que nos referiremos como código GENERATED_CODE.

  2. Inicie sesión en su servidor

    • Si inicia sesión como usuario root, busque este archivo y edítelo:

      $ vi /etc/profile

      Vaya al final del archivo usando Shift+ G("G" mayúscula) en vi.

      Escriba su variable de entorno con GENERATED_CODE, presionando ipara insertar en vi. Asegúrese de estar en una nueva línea al final del archivo:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Guarde los cambios y cierre el archivo usando Escy luego " :x" y Enterpara guardar y salir en vi.

    • Pero si inicia sesión como usuario normal, llamémoslo " example_user" por esta esencia, necesitará encontrar uno de estos otros archivos:

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

      Estos archivos están en orden de importancia, lo que significa que si tiene el primer archivo, entonces no necesitaría editar los otros. Si encontró estos dos archivos en su directorio ~/.bash_profiley ~/.profilesolo tendrá que escribir en el primero ~/.bash_profile, porque Linux leerá solo este y el otro será ignorado.

      Luego vamos al final del archivo usando Shift+ Gnuevamente y escribimos la variable de entorno con nuestro GENERATED_CODEuso inuevamente, y asegúrese de agregar una nueva línea al final del archivo:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Después de escribir el código, guarde los cambios y cierre el archivo usando Esc" :x" nuevamente y Enterpara guardar y salir.

  3. Puede verificar que nuestra variable de entorno esté configurada correctamente en Linux con este comando:

    $ printenv | grep SECRET_KEY_BASE

    o con:

    $ echo $SECRET_KEY_BASE

    Cuando ejecutas este comando, si todo salió bien, te mostrará el GENERATED_CODEde antes. Finalmente, con toda la configuración realizada, debería poder implementar sin problemas su aplicación Rails con Unicorn u otra herramienta.

Cuando cierre su shell e inicie sesión nuevamente en el servidor de producción, tendrá esta variable de entorno configurada y lista para usarla.

¡Y eso es! Espero que esta mini-guía te ayude a resolver este error.

Descargo de responsabilidad: no soy un gurú de Linux o Rails, por lo que si encuentra algo mal o algún error, me complacerá solucionarlo.

Demi Magus
fuente
11
Parece que Rails no ve la variable de entorno SECRET_KEY_BASE. printenv lo muestra, rails c production también lo muestra, si inspecciono ENV. Pero no tengo ningún efecto cuando reinicio Unicorn. La única forma, que funciona ahora, es pegarlo directamente en secretos.yml
AntonAL
1
Esto funcionó para mí. Gracias por tu explicación completa. Acabo de enterarme de que existen gemas para administrar las variables de entorno de una aplicación. 'Dotenv' es uno y 'capataz' para heroku. Si bien fue educativo corregir el error manualmente de esta manera, ¿tal vez el uso de una de esas gemas simplificará el proceso?
Nick Res
Me alegra que mi respuesta haya sido útil, gracias por las opciones de gema @ ninja08, definitivamente hacen que el proceso sea más fácil, principalmente para aquellos que usan capistrano u otra herramienta incremental para administrar el servidor :)
Demi Magus
Siguiendo las excelentes instrucciones de Demi Magus, hice algo como esto: 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 = secreto del rastrillo de producción)"> $ SKB_FILE; . $ SKB_FILE; echo ". $ SKB_FILE" | tee -a ~ / .bashrc ~ / .bash_profile; chmod o-rwx $ SKB_FILE;
David Winiecki
¡¡Buena respuesta!! No sé por qué esto no está resuelto para mí, creo una pregunta stackoverflow.com/questions/33117318/…
Adriano Resende
84

Asumiré que no ha secrets.ymlverificado su control de origen (es decir, está en el .gitignorearchivo). Incluso si esta no es su situación, es lo que muchas otras personas que vieron esta pregunta han hecho porque tienen su código expuesto en Github y no quieren que su clave secreta flote.

Si no está en el control de la fuente, Heroku no lo sabe. Así que Rails está buscando Rails.application.secrets.secret_key_basey no se ha configurado porque Rails lo configura al verificar el secrets.ymlarchivo que no existe. La solución simple es ir a su config/environments/production.rbarchivo y agregar la siguiente línea:

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

Esto le dice a su aplicación que establezca la clave secreta utilizando la variable de entorno en lugar de buscarla secrets.yml. Me habría ahorrado mucho tiempo saber esto por adelantado.

Erik Trautman
fuente
15
Esta es la mejor respuesta. Figaroy heroku_secretsno hagas nada a menos que Rails sepa que SECRET_KEY_BASEvive allí ENV. He estado luchando con esto pensando que si la var de configuración existiera en Heroku, Rails la recogería solo en virtud de su existencia, pero ahora parece cegadoramente obvio que Rails necesitaría saber dónde buscar. Me he estado preguntando cómo puedo tener código en Github sin tener que preocuparme por la base secreta; ahora sé.
flanger001
1
De acuerdo, creo que secrets.yml es superfluo con grandes gemas como Figaro.
Joe
2
Parece la mejor opción si usas github y heroku para tu proyecto.
flexus
1
¿Qué hay de malo en cometer tus secretos production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>? ¿No significa eso también que la clave secreta real no está expuesta? ¿Existe el riesgo de exponer claves de desarrollo y prueba en secrets.yml comprometidos si todo es solo semilla y datos de prueba?
Jay Killeen
Esto funciona incluso en Rails 6.0.2, cuando ya no hay secretos.yml.
Ken Tsoi
54

Agregar config/secrets.ymlal control de versiones e implementar nuevamente. Es posible que deba eliminar una línea .gitignorepara poder confirmar el archivo.

Tuve exactamente el mismo problema y resultó que .gitignoreincluía el repetitivo que Github creó para mi aplicación Rails config/secrets.yml.

danielricecodes
fuente
140
config / secrets.yml NUNCA debe estar en el repositorio, puede hacer.yml.sample y completarlo con datos falsos, pero por seguridad, nunca haga .yml en repos
user3379926
9
@ user3379926, en el contexto de una aplicación Rails en Heroku, no puede elegir qué archivos están incluidos en el control de versiones y cuáles no. Rails 4.1 espera que exista la configuración secreta; de lo contrario, la aplicación no se ejecutará. Si tiene una manera de resolver el problema planteado en la pregunta anterior sin recurrir a la comisión del archivo secrets.yml en Git, ayude a mejorar este hilo al proporcionar ese consejo.
danielricecodes
9
@danielricecodes puede establecer manualmente el valor en un inicializador. Algo así Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]funcionaría y eliminaría el error sin agregarlo secrets.ymla la fuente.
joshhepworth
11
@ user3379926: Cuando genero una nueva aplicación Rails con rails new(produciendo, en este caso, un Gemfile cuya railsgema tiene la versión 4.2.4), config/secrets.ymlse genera el archivo . Incluye pregenerated claves secretas para los entornos de desarrollo y pruebas, y lee el secretkey para el entorno de producción de una variable de entorno: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Me parece que es perfectamente seguro, y de hecho útil, mantener este secrets.ymlarchivo en control de versiones, siempre que uno nunca defina la clave secreta allí.
Teemu Leisti
2
@jasonleonhard ¿por qué? si de todos modos está leyendo la clave secreta de los env, ¿cuál es el problema? No hay secretos expuestos.
horseyguy
13

Esto funcionó para mí.

SSH en su servidor de producción y cden su directorio actual, ejecute bundle exec rake secreto rake secret, obtendrá una cadena larga como salida, copie esa cadena.

Ahora corre sudo nano /etc/environment.

Pegar al final del archivo

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

¿Dónde rake secretestá la cadena que acaba de copiar? Pegue esa cadena copiada en lugar de rake secret.

Reinicie el servidor y pruebe ejecutando echo $SECRET_KEY_BASE.

sumitsv21
fuente
3

Si bien puede usar inicializadores como las otras respuestas, la forma convencional de Rails 4.1+ es usar el config/secrets.yml. La razón para que el equipo de Rails presente esto está más allá del alcance de esta respuesta, pero el TL; DR es que secret_token.rbcombina la configuración y el código, además de ser un riesgo de seguridad, ya que el token se registra en el historial de control de fuente y el único sistema que necesita Conocer el token secreto de producción es la infraestructura de producción.

Debería agregar este archivo .gitignorecomo tampoco lo haría config/database.ymlcon el control de origen.

Haciendo referencia al propio código de Heroku para configurar config/database.ymldesde DATABASE_URLsu Buildpack para Ruby , terminé bifurcando su repositorio y lo modifiqué para crear config/secrets.ymldesde SECRETS_KEY_BASEla variable de entorno.

Dado que esta característica se introdujo en Rails 4.1, sentí que era apropiado editar ./lib/language_pack/rails41.rby agregar esta funcionalidad.

El siguiente es el fragmento del paquete de compilación modificado que creé en mi 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

Por supuesto, puede extender este código para agregar otros secretos (por ejemplo, claves API de terceros, etc.) para que se lean de su variable de entorno:

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

De esta manera, puede acceder a este secreto de una manera muy estándar:

Rails.application.secrets.third_party_api_key

Antes de volver a implementar su aplicación, asegúrese de configurar primero su variable de entorno: Configuración de SECRET_KEY_BASE en el panel de Heroku

A continuación, agregue su paquete de compilación modificado (o sea más que bienvenido a vincular el mío) a su aplicación Heroku (consulte la documentación de Heroku ) y vuelva a implementar su aplicación.

El paquete de compilación creará automáticamente su config/secrets.ymlvariable de entorno como parte del proceso de compilación de dinamómetro cada vez que vaya git pusha Heroku.

EDITAR: la propia documentación de Heroku sugiere crear config/secrets.ymlpara leer desde la variable de entorno, pero esto implica que debe verificar este archivo en el control de origen. En mi caso, esto no funciona bien ya que tengo secretos codificados para entornos de desarrollo y prueba que prefiero no registrar.

stackunderflow
fuente
Si bien es una gran solución, las gemas .dotenv y .foreman resuelven este problema: "He codificado secretos para entornos de desarrollo y prueba", por lo que usar esas gemas significa que no necesita el paquete de compilación, ya que puede usar ENV_VAR en su archivo de secretos para desarrolladores y prueba también
rmcsharry
Tenga en cuenta que las variables de entorno están registradas por la mayoría de la infraestructura, lo que significa que las variables de entorno sin cifrar estarán en texto plano en los registros. No uso Heroku para mis aplicaciones de Rails, por lo que no lo recomiendo, pero con AWS extraemos valores encriptados de Parameter Store durante la compilación desde el contenedor de compilación y los desencriptamos para poblar este tipo de activos seguros.
Daniel Nalbach
1

Puede exportar las claves secretas como variables de entorno en ~/.bashrco ~/.bash_profilede su servidor:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

Y luego, puede obtener su .bashrco .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Nunca cometas tus secretos.yml

alessandrocb
fuente
1

En mi caso, el problema era que config/master.keyno estaba en el control de versiones, y había creado el proyecto en una computadora diferente.

El .gitignore predeterminado que crea Rails excluye este archivo. Dado que es imposible implementar sin tener este archivo, debe estar en control de versiones, para poder implementar desde la computadora de cualquier miembro del equipo.

Solución: elimine la config/master.keylínea .gitignore, confirme el archivo de la computadora donde se creó el proyecto, y ahora puede git pullhacerlo en la otra computadora e implementarlo.

La gente dice que no debe comprometer algunos de estos archivos al control de versiones, sin ofrecer una solución alternativa. Mientras no esté trabajando en un proyecto de código abierto, no veo ninguna razón para no comprometer todo lo necesario para ejecutar el proyecto, incluidas las credenciales.

Andrew Koster
fuente
Nunca confirme su archivo de clave maestra a git. Esta es una vulnerabilidad de seguridad gigante para su aplicación. Para el código abierto es difícil, pero crear una bóveda de contraseñas con su administrador de contraseñas preferido es una mejor opción.
wsizoo
¿Por qué sería una vulnerabilidad de seguridad si el repositorio es privado? Si una persona no autorizada tiene acceso a mi repositorio privado, entonces tengo mayores problemas que las fugas de claves API. No todos los proyectos son de código abierto.
Andrew Koster
Siento que todos están repitiendo esto porque lo vieron en un tutorial para un proyecto de código abierto.
Andrew Koster
Todo esto es muy confuso porque hay mucha documentación obsoleta sobre el secrets.ymlarchivo antiguo , que ha quedado en desuso en las últimas versiones de Rails. Esta pregunta de Stack Overflow tiene muchas respuestas, y casi todas usan esta antigua API.
Andrew Koster
1

Para rails6, estaba enfrentando el mismo problema, ya que me faltaban los siguientes archivos, una vez que los agregué, el problema se resolvió:

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

Asegúrate de tener estos archivos. !!!

Tushar H
fuente
0

Lo que hice: en mi servidor de producción, creo un archivo de configuración (confthin.yml) para Thin (lo estoy usando) y agrego la siguiente información:

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

Luego inicio la aplicación con

thin start -C /whereeveristhefieonprod/configthin.yml

Trabaja como un encanto y luego no es necesario tener la clave secreta en el control de versiones

Espero que pueda ayudar, pero estoy seguro de que lo mismo podría hacerse con Unicorn y otros.

Geraud Puechaldou
fuente
1
¿Puedes explicar por qué / cómo funciona? La pregunta era para heroku. ¿Es delgado una alternativa, o es compatible con heroku?
ahnbizcad
-1

Tengo un parche que he usado en una aplicación Rails 4.1 para permitirme continuar usando el generador de claves heredado (y, por lo tanto, la compatibilidad de la sesión con Rails 3), permitiendo que secret_key_base esté en blanco.

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 reformateé el parche, lo envié a Rails como una solicitud de extracción

BF4
fuente
-1

Creé el config/initializers/secret_key.rbarchivo y escribí solo la siguiente línea de código:

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

Pero creo que la solución publicada por @Erik Trautman es más elegante;)

Editar: Ah, y finalmente encontré este consejo sobre Heroku: https://devcenter.heroku.com/changelog-items/426 :)

¡Disfrutar!

fadehelix
fuente
-3

Tuve el mismo problema después de usar el archivo .gitignore de https://github.com/github/gitignore/blob/master/Rails.gitignore

Todo salió bien después de comentar las siguientes líneas en el archivo .gitignore.

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

fuente
1
Como se repite en todas partes, NO se recomienda enviar secrets.yml o secret_token.rb a git.
cofiem