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

135

Я создал приложение 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
    У меня точно такая же проблема, и я хотел бы знать, почему это происходит тоже. Если я выясню почему, я отправлю ответ с моим решением.
  • 0
    Ваш конфигурационный файл называется secret.yml или secrets.yml ?
Показать ещё 4 комментария
Теги:
heroku
ruby-on-rails-4

12 ответов

166
Лучший ответ

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

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, поэтому, если вы найдете что-то неправильно или какую-либо ошибку, я буду рад его исправить!

  • 9
    Похоже, что Rails не видит переменную окружения SECRET_KEY_BASE. printenv показывает это, rails c production также показывает это, если я проверяю ENV. Но я не имею никакого эффекта, когда перезагружаю Единорога. Единственный способ, который работает сейчас, это вставить его непосредственно в secretts.yml
  • 1
    Это сработало для меня. Спасибо за ваше полное объяснение. Я только что узнал, что существуют драгоценные камни, которые существуют для управления переменными среды приложения. «Dotenv» один и «бригадир» для героку. Хотя это было обучение, чтобы исправить ошибку вручную таким образом, возможно, использование одного из этих драгоценных камней упростит процесс?
Показать ещё 12 комментариев
69

Я предполагаю, что ваш 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. Это бы сэкономило мне много времени, чтобы знать это заранее.

  • 14
    Это лучший ответ. Figaro и heroku_secrets ничего не делают, если Rails не знает, что SECRET_KEY_BASE живет в ENV . Я боролся с этим мнением, что если бы существовала переменная конфигурации на Heroku, Rails подхватил бы ее только благодаря ее существованию, но теперь кажется очевидным, что Rails нужно знать, где искать. Мне было интересно, как я могу иметь код на Github, не беспокоясь о секретной базе ключей; теперь я знаю.
  • 1
    Согласен, я думаю, что secretts.yml излишен с такими драгоценными камнями, как Фигаро.
Показать ещё 2 комментария
56

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

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

  • 0
    должно ли это быть новым значением по умолчанию для gitignore? Я просто считаю, что текущая версия должна быть принята, а настройки предыдущих версий описаны в gitignore.
  • 0
    До тех пор, пока вы никогда не передадите информацию о конфигурации производства в систему управления версиями, вы в порядке. Используйте свое собственное суждение. AFAIK, шаблон config/secrets.yml безопасен.
Показать ещё 9 комментариев
9

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

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.

  • 0
    Это решение работает отлично.
4

Хотя вы можете использовать инициализаторы, как и другие ответы, обычным способом 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

Перед повторным развертыванием приложения обязательно установите переменную среды: Изображение 4169

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

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

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

  • 0
    Отличное решение - гемы .dotenv и .foreman решают эту проблему: «У меня есть жестко закодированные секреты для сред разработки и тестирования», поэтому использование этих гемов означает, что вам не нужен пакет сборки, так как вы можете использовать ENV_VAR в файле секретов для dev и проверить также
2

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

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

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

source ~/.bashrc 
source ~/.bash_profile

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

1

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

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

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

thin start -C /whereeveristhefieonprod/configthin.yml

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

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

  • 1
    Вы можете объяснить, почему / как это работает? Вопрос был к героку. Тонкая альтернатива, или она совместима с герою?
0

В Nginx/Passenger/Ruby (2.4)/Rails (5.1.1) ничего не работает, кроме:

passenger_env_var в /etc/nginx/sites-available/default в блоке сервера.

Источник: https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_env_var

0

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

$ /etc/profile

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

$ ~/.bash_profile

$ ~/.bash_login

$ ~/.profile
0

Я создал файл 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:)

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

0

У меня есть патч, который я использовал в приложении 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

-4

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

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

config/initializers/secret_token.rb
config/secrets.yml
  • 1
    Как везде повторяется, фиксация секретов.yml или secret_token.rb в git НЕ рекомендуется.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню