Как решить ошибку "Отсутствует" secret_key_base "для" производственной "среды" (Rails 4.1)

Я создал приложение rails (rails 4.1) с нуля, и у меня возникла странная проблема, которую я не могу решить.

Каждый раз, когда я пытаюсь развернуть свое приложение на Heroku, я получаю сообщение об ошибке 500:

Отсутствует secret_key_base для среды "production", установите это значение в config/secrets.yml

Файл secret.yml содержит следующую конфигурацию:

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

В Heroku я настроил переменную окружения "SECRET_KEY_BASE" с результатом команды "rake secret". Если я запустил "конфигурацию героя", я могу увидеть переменную с правильным именем и значением.

Почему я все еще получаю эту ошибку?

Спасибо большое

Ответ 1

У меня была такая же проблема, и я решил ее, создав переменную среды, которая будет загружаться каждый раз, когда я вошел в систему на рабочий сервер, и сделал мини-руководство по его настройкам:

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

Я использовал Rails 4.1 с Unicorn v4.8.2, когда я пытался развернуть свое приложение, он не запускался должным образом, и в файле unicorn.log я нашел это сообщение об ошибке:

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

После некоторых исследований я узнал, что Rails 4.1 изменил способ управления secret_key, поэтому, если вы читаете файл secrets.yml, расположенный в exampleRailsProject/config/secrets.yml, вы найдете что-то вроде этого:

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

Это означает, что Rails рекомендует использовать переменную среды для secret_key_base на вашем рабочем сервере, чтобы решить эту ошибку, вы должны следовать этим шагам, чтобы создать переменную среды для Linux (в моем случае Ubuntu) в вашем сервер производства:

  • В терминале вашего производственного сервера выполните следующую команду:

    $ RAILS_ENV=production rake secret
    

    Это возвращает большую строку с буквами и цифрами, скопируйте ее (мы будем ссылаться на этот код как GENERATED_CODE).

  • Войдите на свой сервер

    • Если вы входите в систему как пользователь root, найдите этот файл и отредактируйте его:

      $ vi /etc/profile
      

      Перейти к нижней части файла ( "SHIFT + G" для капитала G в VI)

      Напишите переменную среды с GENERATED_CODE (нажмите клавишу "i" для записи в VI), убедитесь, что она находится в новой строке в конце файла:

      $ export SECRET_KEY_BASE=GENERATED_CODE
      

      Сохраните изменения и закройте файл (мы нажимаем клавишу "ESC", а затем записываем клавиши ": x" и "ENTER" для сохранения и выхода в VI).

    • Но если вы входите в систему как обычный пользователь, давайте назовем его "example_user" для этого gist, вам нужно будет найти один из этих других файлов:

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

      Эти файлы в порядке важности, это означает, что если у вас есть первый файл, вам не нужно будет писать в других. Поэтому, если вы нашли эти 2 файла в своем каталоге ~/.bash_profile и ~/.profile, вам нужно будет записать только первый ~/.bash_profile, потому что Linux будет читать только этот, а другой будет проигнорирован.

      Затем мы переходим к нижней части файла ( "SHIFT + G" для капитала G в VI).

      И мы напишем нашу переменную среды с нашим GENERATED_CODE (нажмите "i" для записи в VI), обязательно в новой строке в конце файла:

      $ export SECRET_KEY_BASE=GENERATED_CODE
      

      Записав код, сохраните изменения и закройте файл (мы нажимаем клавишу "ESC", а затем записываем клавиши ": x" и "ENTER" для сохранения и выхода в VI).

  • Вы можете проверить, что наша переменная среды правильно установлена ​​в Linux с помощью этой команды:

    $ printenv | grep SECRET_KEY_BASE
    

    или с помощью:

    $ echo $SECRET_KEY_BASE
    

    Когда вы выполните эту команду, если все будет хорошо, она покажет вам GENERATED_CODE. Наконец, при выполнении всей конфигурации вы сможете без проблем развертывать приложение Rails с Unicorn или другим.

Когда вы закроете свой терминал и снова войдете на рабочий сервер, у вас будет установлен этот набор переменных среды и готов к его использованию.

И вот оно! Я надеюсь, что этот мини-справочник поможет вам решить эту ошибку.

Отказ от ответственности: я не являюсь гуру Linux или Rails, поэтому, если вы найдете что-то неправильно или какую-либо ошибку, я буду рад его исправить!

Ответ 2

Я предполагаю, что ваш secrets.yml не установлен в исходном элементе управления (т.е. в файле .gitignore). Даже если это не ваша ситуация, это то, что многие другие люди рассматривают этот вопрос, потому что они имеют свой код, выставленный на Github, и не хотят, чтобы их секретный ключ плавал вокруг.

Если он не находится в исходном управлении, Героку об этом не знает. Поэтому Rails ищет Rails.application.secrets.secret_key_base, и он не был установлен, потому что Rails устанавливает его, проверяя файл secrets.yml, который не существует. Простым решением является переход в ваш файл config/environments/production.rb и добавление следующей строки:

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

Это говорит вашему приложению, чтобы установить секретный ключ, используя переменную окружения, а не искать ее в secrets.yml. Это бы сэкономило мне много времени, чтобы знать это заранее.

Ответ 3

Добавьте config/secrets.yml в управление версиями и развертывание снова. Возможно, вам потребуется удалить строку из .gitignore, чтобы вы могли зафиксировать файл.

У меня была такая же проблема, и только что оказалось, что шаблонный .gitignore Github, созданный для моего приложения Rails, включал config/secrets.yml.

Ответ 4

Это сработало для меня.

SSH на ваш производственный сервер и cd в ваш текущий каталог, запустите bundle exec rake secret или rake secret, вы получите длинную строку в качестве вывода, скопируйте эту строку.

Теперь запустите sudo nano /etc/environment.

Вставить в нижней части файла

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

Где rake secret - только что скопированная строка, вставьте эту скопированную строку вместо rake secret.

Перезагрузите сервер и протестируйте, запустив echo $SECRET_KEY_BASE.

Ответ 5

Хотя вы можете использовать инициализаторы, как и другие ответы, обычным способом Rails 4.1+ является использование config/secrets.yml. Причина, по которой команда Rails представить это, выходит за рамки этого ответа, но TL; DR - это то, что secret_token.rb объединяет конфигурацию и код, а также представляет угрозу безопасности, поскольку токен проверяется в истории управления версиями и единственная система который должен знать маркер производства, является производственной инфраструктурой.

Вы должны добавить этот файл в .gitignore так же, как вы бы не добавляли config/database.yml в исходный элемент управления.

Ссылка на собственный код Heroku для настройки config/database.yml от DATABASE_URL в Buildpack для Ruby, я закончил разблокировать свое репо и изменить его, чтобы создать переменную среды config/secrets.yml из SECRETS_KEY_BASE.

Поскольку эта функция была введена в Rails 4.1, я счел нужным отредактировать ./lib/language_pack/rails41.rb и добавить эту функциональность.

Ниже представлен фрагмент из измененного buildpack, который я создал в моей компании:

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

Вы можете, конечно, расширить этот код, чтобы добавить другие секреты (например, сторонние ключи API и т.д.), которые будут считаться с вашей переменной среды:

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

Таким образом, вы можете получить доступ к этому секрету стандартным образом:

Rails.application.secrets.third_party_api_key

Перед повторным развертыванием приложения обязательно установите переменную среды: Setting SECRET_KEY_BASE in Heroku Dashboard

Затем добавьте модифицированный buildpack (или вы более чем можете подключиться к моему) в свое приложение Heroku (см. документацию Heroku ) и повторное развертывание вашего приложения.

buildpack автоматически создаст ваш config/secrets.yml из вашей переменной окружения как часть процесса построения динамической системы каждый раз, когда вы git push до Heroku.

РЕДАКТИРОВАТЬ: документация > предлагает создать config/secrets.yml для чтения из переменной среды, но это означает, что вы должны проверить этот файл на исходный элемент управления, В моем случае это не сработает, так как у меня есть жестко запрограммированные секреты для сред разработки и тестирования, которые я бы не захотел проверить.

Ответ 6

Вы можете экспортировать секретные ключи в качестве переменных среды на ~/.bashrc или ~/.bash_profile вашего сервера:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

И затем вы можете указать свой .bashrc или .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Никогда не совершайте свои secrets.yml

Ответ 7

Что я сделал: На моем рабочем сервере я создаю файл конфигурации (confthin.yml) для Thin (я использую его) и добавляю следующую информацию:

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

Затем я запускаю приложение с помощью

thin start -C /whereeveristhefieonprod/configthin.yml

Работайте как шарм, а затем нет необходимости иметь секретный ключ в управлении версиями

Надеюсь, это может помочь, но я уверен, что то же самое можно было бы сделать с Unicorn и другими.

Ответ 8

В моем случае проблема заключалась в том, что config/master.key не был в управлении версиями, и я создал проект на другом компьютере.

По умолчанию .gitignore, который создает Rails, исключает этот файл. Поскольку невозможно развернуть без этого файла, он должен быть в управлении версиями, чтобы иметь возможность развертывания с любого компьютера члена группы.

Решение: удалите строку config/master.key из .gitignore, зафиксируйте файл с компьютера, на котором был создан проект, и теперь вы можете git pull на другом компьютере и выполнить развертывание с него.

Люди говорят не передавать некоторые из этих файлов для контроля версий, не предлагая альтернативного решения. Пока вы не работаете над проектом с открытым исходным кодом, я не вижу причин не фиксировать все, что требуется для запуска проекта, включая учетные данные.

Ответ 9

У меня есть патч, который я использовал в приложении Rails 4.1, чтобы позволить мне продолжать использовать устаревший генератор ключей (и, следовательно, совместимость с предыдущим сеансом с Rails 3), позволяя secret_key_base быть пустым.

Rails::Application.class_eval do
  # the key_generator will then use ActiveSupport::LegacyKeyGenerator.new(config.secret_token)
  fail "I'm sorry, Dave, there 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

Я с тех пор переформатировал патч отправил его Rails в качестве запроса Pull

Ответ 10

Я создал файл config/initializers/secret_key.rb, и я написал только следующую строку кода:

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

Но я думаю, что решение, отправленное @Erik Trautman, более изящно;)

Изменить: О, и, наконец, я нашел этот совет по Heroku: https://devcenter.heroku.com/changelog-items/426:)

Наслаждайтесь!

Ответ 11

это хорошо работает https://gist.github.com/pablosalgadom/4d75f30517edc6230a67 для пользователя root следует отредактировать

$ /etc/profile

но если вы не root должны поместить код генерации в следующий

$ ~/.bash_profile

$ ~/.bash_login

$ ~/.profile

Ответ 13

Ответ деми Магуса работал на меня до Rails 5.

На Apache2/Passenger/Ruby (2.4)/Rails (5.1.6) мне пришлось поставить

export SECRET_KEY_BASE=GENERATED_CODE

из ответа Деми Магуса в /etc/apache2/envvars, причина /etc/profile, похоже, игнорируется.

Источник: https://www.phusionpassenger.com/library/indepth/environment_variables.html#apache

Ответ 14

У меня была такая же проблема после того, как я использовал файл .gitignore из https://github.com/github/gitignore/blob/master/Rails.gitignore

Все прошло отлично после того, как я прокомментировал следующие строки в файле .gitignore.

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