Як вирішити помилку "Відсутня" секретна_відна_база` для середовища "виробництва" (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 4. У нашому випадку це було тому, що у нас була власна назва середовища, і це не відображалось у secrets.yml. Мені просто довелося додати рядок до файлу з нестандартним іменем, фіксацією та повторним розгортанням.
whognu

Для майбутніх читачів: ця відповідь, мабуть, найпростіша та найточніша:
stackoverflow.com/a/26541742/4880924

Відповіді:


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") in 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 показує це, рейки c виробництво також відображає його, якщо я перевіряю ENV. Але я не маю ефекту, коли я перезапускаю Єдиноріг. Єдиний спосіб, який працює зараз, - це вставлення його безпосередньо до
secrets.yml

1
Це працювало для мене. Дякую за ваше повне пояснення. Я щойно дізнався, що існують дорогоцінні камені, які існують для керування змінними середовища середовища програми. 'Dotenv' - це один і 'бригадир' для heroku. Хоча таким чином виправити помилку вручну можна, можливо, використання одного з цих дорогоцінних каменів спростить процес?
Nick Res

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

Дотримуючись чудових інструкцій Демі Магу, я зробив щось подібне: cd / var / www / rails; rvm використовувати ext-rbx-2.5.2@rails; SKB_FILE = / var / www / .secret_key_base; ехо "експорт SECRET_KEY_BASE = $ (RAILS_ENV = виробничий рейк секрет)"> $ SKB_FILE; . $ SKB_FILE; відлуння ". $ SKB_FILE" | tee -a ~ / .bashrc ~ / .bash_profile; chmod o-rwx $ SKB_FILE;
David Winiecki

Приємна відповідь !! Я не знаю, чому це не вирішено для мене, я створюю питання stackoverflow.com/questions/33117318/…
Adriano Resende

84

Я припускаю, що у вас немає 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. Це врятувало б мені багато часу, щоб знати це наперед.


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

1
Погоджено, я вважаю, що Secrets.yml зайвий з чудовими дорогоцінними каменями, як Figaro.
Джо

2
Здається, найкращий варіант, якщо ви використовуєте github та heroku для свого проекту.
флексус

1
Що не так у вчиненні ваших secrets.yml production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>. Не буде це також означати, що фактичний секретний ключ не викритий. Чи є ризик викрити ключі розробника та тесту у скоєному secrets.yml, якщо це лише дані про насіння та тести?
Джей Кілін

Це працює навіть у Rails 6.0.2, коли більше немає Secrets.yml.
Кен Цой

54

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

У мене був такий самий випуск, і якраз виявилося, що котловарка .gitignoreGithub, створена для моєї програми Rails, включена config/secrets.yml.


140
config / secrets.yml НІКОЛИ не повинен знаходитись у репо, ви можете зробити.yml.sample та заповнити його підробленими даними, але для безпеки ніколи не робіть .yml у
репост

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до джерела.
joshhepworth

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

2
@jasonleonhard чому? якщо ви все одно читаєте секретний ключ від env vars, у чому головна справа? немає ніяких таємниць, що піддаються впливу
horseyguy

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та додати цю функціональність.

Нижче наведено фрагмент модифікованого 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

Перш ніж перерозподілити додаток, не забудьте спочатку встановити змінну середовища: Налаштування SECRET_KEY_BASE на інформаційній панелі Heroku

Потім додайте модифікований пакунок збірки (або ви більше ніж ласкаво просимо зв’язатись з моїм) у свій додаток Heroku (див. Документацію Heroku ) та переустановіть свою програму.

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

EDIT: Власна документація Heroku пропонує створити config/secrets.ymlдля читання з змінної середовища, але це означає, що ви повинні перевірити цей файл у контролі джерела. У моєму випадку це не працює добре, оскільки у мене є жорсткі секрети для розробки та тестування середовищ, які я краще не перевіряю.


У той час як чудове рішення дорогоцінні камені .dotenv та .foreman вирішують цю проблему: "У мене жорсткі коди секретів для середовищ розробки та тестування" - тому використання цих дорогоцінних каменів означає, що вам не потрібен buildpack, оскільки ви можете використовувати ENV_VAR у вашому файлі секретів для розробників та тест також
rmcsharry

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

1

Ви можете експортувати секретні ключі як змінні середовища на ~/.bashrcабо ~/.bash_profileна вашому сервері:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

І потім, ви можете вихідний код свого .bashrcабо .bash_profile:

source ~/.bashrc 
source ~/.bash_profile

Ніколи не вчиняйте свої секрети.yml


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

Працюйте як шарм, і тоді не потрібно мати секретний ключ для контролю версій

Сподіваюся, це могло б допомогти, але я впевнений, що те саме можна було б зробити і з Єдинорогом та іншими.


1
Ви можете пояснити, чому / як це працює? Питання було до героїки. Тонка альтернатива, чи вона сумісна з герою?
ahnbizcad

-1

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

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 як запит на витягнення


-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 :)

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




-1

Відповідь Демі Магус працювала на мене до Рейки 5.

На Apache2 / Пасажир / Рубін (2.4) / Рейки (5.1.6) мені довелося покласти

export SECRET_KEY_BASE=GENERATED_CODE

відповідь Демі Магуса в / etc / apache2 / envvars, здається, що причина / etc / profile ігнорується.

Джерело: https://www.phusionpassenger.com/library/indepth/environment_variables.html#apache


-3

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

Все склалося добре після того, як я прокоментував наступні рядки у файлі .gitignore.

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

1
Як це повторюється скрізь, здійснювати tajit.yml або secret_token.rb для git НЕ рекомендується.
cofiem
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.