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


169

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

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

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

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

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

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

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


1
У меня точно такая же проблема, и я хотел бы знать, почему это происходит тоже. Если я выясню почему, я отправлю ответ с моим решением.
danielricecodes

Ваш конфигурационный файл называется secret.ymlили secrets.yml?
Джеймс

2
Я снова настроил файл .gitignore с файлом, сгенерированным rails, и теперь все работает нормально
Paolo Laurenti

У нас также была эта проблема при обновлении до Rails 4. В нашем случае это было потому, что у нас было имя пользовательской среды, которое не было отражено в secrets.yml. Мне просто нужно было добавить в файл строку с нестандартным именем, зафиксировать и заново развернуть.
whognu

Для будущих читателей: этот ответ, вероятно, самый простой и точный: stackoverflow.com/a/26541742/4880924
BKSpurgeon

Ответы:


208

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

Я использовал 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) на вашем производственном сервере:

  1. В терминале вашего производственного сервера выполните:

    $ RAILS_ENV=production rake secret

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

  2. Войдите на ваш сервер

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

      $ vi /etc/profile

      Перейти в конец файла с помощью Shift+ G(заглавная "G") в vi.

      Напишите переменную окружения GENERATED_CODE, нажав, iчтобы вставить в vi. Будьте уверены, чтобы быть в новой строке в конце файла:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Сохраните изменения и закройте файл, используя, Escа затем " :x" и Enterдля сохранения и выхода в vi.

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

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

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

      Затем мы снова переходим в конец файла с помощью Shift+ и Gснова записываем переменную окружения, GENERATED_CODEиспользуя наше использование i, и обязательно добавляем новую строку в конце файла:

      $ export SECRET_KEY_BASE=GENERATED_CODE

      Написав код, сохраните изменения и закройте файл, используя Escснова и " :x", Enterчтобы сохранить и выйти.

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

    $ printenv | grep SECRET_KEY_BASE

    или с:

    $ echo $SECRET_KEY_BASE

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

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

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

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


11
Похоже, что Rails не видит переменную окружения SECRET_KEY_BASE. printenv показывает это, rails c production также показывает это, если я проверяю ENV. Но я не имею никакого эффекта, когда перезагружаю Единорога. Единственный способ, который работает сейчас, это вставить его непосредственно в secretts.yml
AntonAL

1
Это сработало для меня. Спасибо за ваше полное объяснение. Я только что узнал, что существуют гемы для управления переменными среды приложения. «Dotenv» один и «бригадир» для героку. Хотя это было обучение, чтобы исправить ошибку вручную таким образом, может быть, использование одного из этих драгоценных камней упростит процесс?
Ник Рез

Я рад, что мой ответ был полезен, спасибо за gem options @ ninja08, они определенно упрощают процесс, в основном для тех, кто использует capistrano или другой инкрементный инструмент для управления сервером :)
Demi Magus

Следуя прекрасным инструкциям Деми Магуса, я сделал что-то вроде этого: cd / var / www / rails; rvm use ext-rbx-2.5.2@rails; SKB_FILE = / вар / WWW / .secret_key_base; echo "export SECRET_KEY_BASE = $ (RAILS_ENV = секрет рабочего грабля)"> $ SKB_FILE; , $ SKB_FILE; echo ". $ SKB_FILE" | tee -a ~ / .bashrc ~ / .bash_profile; chmod o-rwx $ SKB_FILE;
Дэвид Винецки

Хороший ответ!! Я не знаю, почему это не решается для меня, я создаю вопрос stackoverflow.com/questions/33117318/…
Адриано Резенде

84

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

Если это не в системе контроля версий, Heroku не знает об этом. Поэтому 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. Это сэкономило бы мне много времени, чтобы узнать это заранее.


15
Это лучший ответ. Figaroи heroku_secretsничего не делать, если Rails не знает, что SECRET_KEY_BASEживет в ENV. Я боролся с этим мнением, что если бы существовала переменная конфигурации на Heroku, Rails подхватил бы ее только благодаря ее существованию, но теперь кажется очевидным, что Rails нужно знать, где искать. Мне было интересно, как я могу иметь код на Github, не беспокоясь о секретной базе ключей; теперь я знаю.
flanger001

1
Согласен, я думаю, что secretts.yml излишен с такими драгоценными камнями, как Фигаро.
Джо

2
Похоже, лучший вариант, если вы используете github и heroku для вашего проекта.
Flexus

1
Что не так с совершением ваших секретов production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Разве это не означает, что фактический секретный ключ не раскрывается. Существует ли риск раскрытия ключей dev и test в зафиксированном secretts.yml, если это всего лишь начальные и тестовые данные?
Джей Киллин,

Это работает даже в Rails 6.0.2, когда нет SecretS.yml больше.
Кен Цой

54

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

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


140
config / secrets.yml НИКОГДА не должен находиться в репозитории, который вы можете сделать в .ml.sample и заполнить его поддельными данными, но для безопасности никогда не делайте .yml в репозиториях
user3379926

9
@ user3379926, в контексте приложения Rails на Heroku вы не можете выбирать, какие файлы включены в управление версиями, а какие нет. Rails 4.1 ожидает, что секретная конфигурация существует, иначе приложение не запустится. Если у вас есть способ решить проблему, поставленную в вопросе выше, не прибегая к фиксации файла secrets.yml в Git, помогите улучшить эту ветку, предоставив этот совет.
danielricecodes

9
@danielricecodes вы можете вручную установить значение в инициализаторе. Нечто подобное Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]сработало бы и убрало ошибку, не добавляя secrets.ymlв источник.
Джошепуорт

11
@ user3379926: Когда я генерирую новое приложение Rails с rails new(производящим, в данном случае, Gemfile, у которого в railsгеме есть версия 4.2.4), config/secrets.ymlсоздается файл . Она включает в себя pregenerated секретных ключей для сред разработки и тестирования, и читает SecretKey для производственной среды с переменным окружением: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Мне кажется, что совершенно безопасно и действительно полезно хранить этот secrets.ymlфайл в системе контроля версий при условии, что никто никогда не определит секретный ключ там.
Теему Лейсти

2
@jasonleonhard почему? если вы все равно читаете секретный ключ из env vars, в чем дело? нет никаких секретов разоблачения.
скакун

13

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

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.


3

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

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

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

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

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

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

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


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

Обратите внимание, что переменные среды регистрируются большинством инфраструктур, что означает, что незашифрованные переменные среды будут находиться в виде простого текста в журналах. Я не использую Heroku для своих приложений на Rails, поэтому не рекомендую его, но с помощью AWS мы извлекаем зашифрованные значения из хранилища параметров во время сборки из контейнера сборки и расшифровываем их для заполнения таких видов защищенных ресурсов.
Даниэль

1

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

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

И тогда вы можете получить ваш .bashrcили .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Никогда не передавайте свои секреты.


1

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

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

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

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


Никогда не передавайте свой файл мастер-ключа в git. Это гигантская уязвимость безопасности для вашего приложения. С открытым исходным кодом это сложно, но лучше создать хранилище паролей с помощью предпочитаемого вами менеджера паролей.
wsizoo

Почему это может быть уязвимость безопасности, если репозиторий закрыт? Если неавторизованный человек имеет доступ к моему личному репо, то у меня больше проблем, чем просто утечка ключей API. Не каждый проект с открытым исходным кодом.
Эндрю Костер

Я чувствую, что все просто повторяют это, потому что они видели это в учебнике для проекта с открытым исходным кодом.
Эндрю Костер

Все это очень запутанно, потому что существует слишком много устаревшей документации по старому secrets.ymlфайлу, которая устарела для нескольких последних версий Rails. На этот вопрос о переполнении стека есть масса ответов, и почти все они используют этот древний API.
Андрей Костер

1

Для rails6 я столкнулся с той же проблемой, так как мне не хватало следующих файлов, после того как я их добавил, проблема решена:

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

Убедитесь, что у вас есть эти файлы. !!!


0

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

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

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

thin start -C /whereeveristhefieonprod/configthin.yml

Работайте как шарм и тогда не нужно иметь секретный ключ для контроля версий

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


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

-1

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

С тех пор я переформатировал патч и отправил его в Rails как Pull Request


-1

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

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





-3

У меня была такая же проблема после того, как я использовал файл .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 НЕ рекомендуется.
cofiem
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.