Discourse のインストール中に Bootstrap エラー: ENOENT - /etc/runit/1.d/letsencrypt

こんにちは。標準の ./discourse-setup プロセスを使用して Discourse をインストールしようとしていますが、ブートストラップ中にエラーが発生しています。

FAILED
--------------------
Errno::ENOENT: No such file or directory @ rb_sysopen - /etc/runit/1.d/letsencrypt
Location of failure: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.3.0/lib/pups/replace_command.rb:11:in `read'
replace failed with the params {"filename"=>"/etc/runit/1.d/letsencrypt", "from"=>"/--keylength/", "to"=>"-d forum.mysite.org --keylength"}
bootstrap failed with exit code 1
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.

エラーは、ブートストラップ中にコンテナ内に存在しない /etc/runit/1.d/letsencrypt ファイルに対して replace コマンドを実行しようとしているプラグインによってトリガーされているようです。プラグインの関連行は次のようになっています。

- replace:
    filename: "/etc/runit/1.d/letsencrypt"
    from: "/--keylength/"
    to: "-d forum.mysite.org --keylength"

この問題を修正する方法や、不足しているファイルを適切に再生成する方法について、何かアドバイスはありますか?

よろしくお願いします。

プラグインですか?それはあなたの app.yml からの cups コードですよね?別の証明書を追加しようとしていますか?例えば Set up Let’s Encrypt with multiple domains / redirects のようなものでしょうか?実際のコードと両方の証明書を含めていただけますか?

指摘されているように、その runit はもはや存在せず、現在はその処理がコンテナ内の /usr/local/bin/letsencrypt にあります。

サイトが www.mysite.org で、forum.mysite.org の証明書も取得したい場合、おそらく次のようなものが必要だと思います。

- replace:
    filename: "/usr/local/bin/letsencrypt"
    from: "/-d www.mysite.org/"
    to: "-d www.mysite.org -d forum.mysite.org "
    global: true

私なら(あなたには役に立たないかもしれませんが)、コンテナに入り、apt update;apt install -y vim を実行してから、必要な証明書を取得するように /usr/local/bin/letsencrypt を編集します。

上記の Let’s Encrypt のトピックに、ドメインを入力して app.yml にコピー&ペーストできるコードを取得できるコードを追加しました。

「いいね!」 1

アップデートを試みている際に、同じようなエラーメッセージが表示されました。

証明書に関連する変更は何も試みていません。

私の app.yml ファイルは現在以下のようになっています。

 after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d www.nzarchitecture.net.nz --keylength"

あなたの提案に従って以下を実行しましたが、結果は「vim はすでに最新バージョンです(2:9.1.0016-1ubuntu7.8)。」でした。

 apt update;apt install -y vim

2番目の提案ステップについては、何も変更する意図がなかったため、どの証明書が必要なのか全く分かりません。

OK、数時間格闘した結果、なんとか復旧しました。

古い app.yml ファイルを見つけて、それを置き換えました。Discourse に統合されたプラグインへの古い参照を削除しただけです。

この古い app.yml ファイルには、後から見つけた以下のコードは含まれていませんでした。

 after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d www.nzarchitecture.net.nz --keylength"

自分でそのコードを追加した記憶はありませんが、無料のセキュリティ証明書のために Let’s Encrypt を使用するようにサイトを設定していました。しかし、Set up HTTPS support with Let's Encrypt の指示では、これらの行はまったく必要ないようです。そのため、それらが何のためにあったのかは不明です。

他に app.yml にこれらの行を追加した可能性のあるものはありますか?例えば、ベータ版のアップデート中に追加された可能性はありますか?

少なくとも現時点では、これらの行を削除したことで、私のサイトは再び機能し、最新の状態になっています。

現在の SSL 証明書が期限切れになったら、これらの追加行が何のためにあったのかがわかるかもしれません。

ええ、そうですが、ご自身では覚えていないだけです。:wink:

もし yml ファイルに after_ssl のスタンザがある場合、それは以前に、誰かがドメインの前に www を付けた場合に、その www アドレスにアクセスして、証明書エラーなしで非 www アドレスにリダイレクトされるように設定したことを意味します。

私の提案は、コンテナ内に vim をインストールして、そこでファイルをいじってみるということでしたが、app.yml に追加するコードは機能するはずだと思います。

そうです。そして今、https://www.nzarchitecture.net.nz/ にアクセスすると証明書エラーが表示されます。https://forcewww.com/ を使用できます。

上記のリンクにアクセスして、機能するはずだと思う新しいコードを取得できますが、テストはしていません。なぜなら、アップグレードする必要のあるサイトを見つけていないからです。

nzarchitecture.net.nzと同じletsencrypt証明書でwww.nzarchitecture.net.nzもカバーしたい場合、コードは以下のようになると考えてよいでしょうか?

after_ssl:
    - replace:
        filename: /usr/local/bin/letsencrypt
        from: /-d nzarchitecture.net.nz /
        to: "-d nzarchitecture.net.nz -d www.nzarchitecture.net.nz "
        global: true

このスタンザ(素晴らしい専門用語ですね、ありがとうございます!)をapp.ymlの末尾に追加し、元のafter_ssl:スタンザを置き換えました。Discourseの再構築はエラーなく完了しましたが、これは私には役立たないようです。wwwプレフィックスをメイン/証明書付きドメインnzarchitecture.net.nzの前に付けてアクセスしようとすると、ブラウザは依然として「net::ERR_CERT_COMMON_NAME_INVALID」という応答を返します。

参考になるかもしれないので、私の完全なapp.ymlを以下に示します(パスワードとメールアドレスは伏せてあります)。

## これはオールインワンのスタンドアロンDiscourse Dockerコンテナテンプレートです
##
## このファイルを変更した後は、必ず再構築してください
## /var/discourse/launcher rebuild app
##
## 編集は*非常に*注意してください!
## YAMLファイルは、空白やインデントのミスに非常に敏感です!
## 必要に応じて、http://www.yamllint.com/ でこのファイルを検証してください

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
## HTTPSのLets Encryptを追加したい場合は、これらの2行をコメント解除してください
  - "templates/web.ssl.template.yml"
  - "templates/web.letsencrypt.ssl.template.yml"
  - "templates/import/mysql-dep.template.yml"

## このコンテナはどのTCP/IPポートを公開しますか?
## Apacheやnginxのような他のWebサーバーとポートを共有したい場合は、
## https://meta.discourse.org/t/17247 を参照してください
expose:
  - "80:80"   # http
  - "443:443" # https

params:
  db_default_text_search_config: "pg_catalog.english"

  ## db_shared_buffers を合計メモリの最大25%に設定します。
  ## 検出されたRAMに基づいてブートストラップによって自動的に設定されますが、オーバーライドすることもできます
  db_shared_buffers: "128MB"

  ## ソートパフォーマンスを向上させる可能性がありますが、接続ごとのメモリ使用量が増加します
  #db_work_mem: "40MB"

  ## このコンテナはどのGitリビジョンを使用しますか? (デフォルト: tests-passed)
  #version: tests-passed

env:
  LANG: en_US.UTF-8
  # DISCOURSE_DEFAULT_LOCALE: en

  ## 同時に処理できるWebリクエスト数はいくつですか?メモリとCPUコアに依存します。
  ## 検出されたCPUに基づいてブートストラップによって自動的に設定されますが、オーバーライドすることもできます
  UNICORN_WORKERS: 2

  ## TODO: このDiscourseインスタンスが応答するドメイン名
  ## 必須。DiscourseはIPアドレスのみでは機能しません。
  DISCOURSE_HOSTNAME: nzarchitecture.net.nz

  ## 指定されたホスト名(-hオプション)と同じホスト名でコンテナを起動したい場合は、コメント解除してください(デフォルトは「$hostname-$config」)
  #DOCKER_USE_HOSTNAME: true

  ## TODO: 初期サインアップ時に管理者および開発者になるメールアドレスのカンマ区切りリスト
  ## 例: 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: '****************'

  ## TODO: 新規アカウントの検証と通知の送信に使用されるSMTPメールサーバー
  # SMTPアドレス、ユーザー名、パスワードが必要です
  # 警告:SMTPパスワードの文字 '#' は問題を引き起こす可能性があります!
  DISCOURSE_SMTP_ADDRESS: smtp.mailgun.org
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: ****************
  DISCOURSE_SMTP_PASSWORD: "****************"
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (オプション、デフォルトはtrue)

  ## Lets Encryptテンプレートを追加した場合、無料のSSL証明書を取得するには以下をコメント解除してください
  LETSENCRYPT_ACCOUNT_EMAIL: ******************

  ## このDiscourseインスタンスのHTTPまたはHTTPS CDNアドレス(プル用に設定)
  ## https://meta.discourse.org/t/14857 を参照してください
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

## Dockerコンテナはステートレスです。すべてのデータは/sharedに保存されます
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## プラグインはここに配置します
## https://meta.discourse.org/t/19157 を参照してください
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-bbcode.git
## ビルド後に実行するカスタムコマンド
run:
  - exec: echo "カスタムコマンドの開始"
  ## 初回登録メールの「From」アドレスを設定したい場合は、コメントを解除して変更してください:
  ## 初回サインアップメールを取得した後、行をコメントアウトしてください。一度だけ実行する必要があります。
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "カスタムコマンドの終了"

after_ssl:
    - replace:
        filename: /usr/local/bin/letsencrypt
        from: /-d nzarchitecture.net.nz /
        to: "-d nzarchitecture.net.nz -d www.nzarchitecture.net.nz "
        global: true

/usr/local/bin/にファイルがないことは問題の一部ですか?

もしそうなら、そこに入れるべき正しいletsencryptファイルはどこで見つけられますか?

また、「letsencrypt」がそのパスの末尾のファイル名である場合、このファイル名の拡張子がないのは正常ですか?

私のアイデアは、after_ssl行を削除し、他の行をインデント解除することです。

もし私のSSHキーを以下で追加していただけるなら、

ssh-import-id-gh pfaffman

そして私にメールをいただければ、何ができるか確認します。

ありがとうございます!@pfaffman

今メールをお送りしました

アップデートです。

app.yml の一番下にある run セクションにこれを追加すると、DISCOURSE_HOSTNAMEwww.DISCOURSE_HOSTNAME の証明書をリクエストする /usr/local/bin/letsencrypt の問題が解決します。

- exec: sed -i "s|-d \${DISCOURSE_HOSTNAME}|-d \${DISCOURSE_HOSTNAME} -d www.\${DISCOURSE_HOSTNAME}|g" /usr/local/bin/letsencrypt

これは(なぜか)以前は十分でしたが、現在、http://www.HOSTNAME/.well-known… のリクエストが来ると、本来送信されるべきチャレンジを送信するのではなく、非wwwサイトにリダイレクトされます。以下のようなことを試しました。

server {
  listen 80;
  listen [::]:80;
  server_name nzarchitecture.net.nz www.nzarchitecture.net.nz;

  # ACMEチャレンジ(Let's Encrypt)を処理
  location ^~ /.well-known/acme-challenge/ {
    root /var/www/discourse/public;  # Let's EncryptのWebルートと一致していることを確認してください
    allow all;
  }

  # その他すべてをHTTPSにリダイレクト
  location / {
    return 301 https://$host$request_uri;
  }
}

しかし、うまくいきませんでした。

チームの誰かが聞いていたら、letsencryptフックがあれば、これを after_letsencrypt で呼び出すことができると良いのですが。これらの変更を after_ssl で行うと以前は機能していましたが、現在はSSLの後、letsencryptの前に実行されるようです。

「いいね!」 3

私もこの問題が発生しています。修正できたらお知らせします。

私の DISCOURSE_HOSTNAMEwww.textkit.com です。私は nzarchitecture.net.nz の逆のことを行い、www なしのホスト名を証明書に追加しています。これは私にはうまくいきました。

- exec: sed -i "s|-d \\${DISCOURSE_HOSTNAME}|-d www.textkit.com -d textkit.com|g" /usr/local/bin/letsencrypt

@pfaffmannzarchitecture.net.nz が彼のバージョンで問題を抱えている理由を説明することはできませんが、私のホスト名の順序が関係しているのかもしれません。

これも発生しました。

以下を削除しました(コメントアウトしました):

  after_ssl:
#    - replace:
#        filename: "/etc/runit/1.d/letsencrypt"
#        from: /--keylength/
#        to: "-d example.com --keylength"
#    - replace:
#        filename: "/etc/nginx/conf.d/discourse.conf"
#        from: /return 301 https.+/
#        to: |
#          return 301 https://$host$request_uri;

そして、@pfaffman の指示に従い、下部の run セクションに以下を追加しました。

- exec: sed -i "s|-d \\${DISCOURSE_HOSTNAME}|-d \\${DISCOURSE_HOSTNAME} -d www.\\${DISCOURSE_HOSTNAME}|g" /usr/local/bin/letsencrypt

これで十分だったようです。

  • サイトが再構築され、有効な証明書が付与されているようです。
    *Apex から www へのリダイレクトが機能しています。

@pfaffman さん、ありがとうございます!

「いいね!」 4

おお!すごい。証明書の更新を可能にした変更が、私が直面していた問題を解決したのかもしれません。

PRが承認される前に、この問題が必要となる他のサイトを見つけた場合は、これを覚えておきます。

「いいね!」 1

ここにはいくつかの動く部分があります。その再構築ではうまくいきました。状況が変わった場合は、ここで報告します!

「いいね!」 1

証明書の更新を許可するPRはまだマージされていません。まだ保留中です。

マージされれば、app.ymlが大幅に簡略化されるはずです。

「いいね!」 2

奇妙なことに、そのコードは私のサイトの1つでは機能しますが、古いコード(古いコードのみ)は私の他のサイトで機能します。:person_shrugging:

まあ、とにかくすぐにすべてが無意味になることを願っています!

「いいね!」 1

それは非常に奇妙です。discourse_docker は古いバージョンに固定されていますか?

いいえ、そうではありません。インスタンス間には(類似のテーマ/プラグイン/構成を除いて)あまり違いはありませんが、一方のインスタンスはもう一方よりもかなり古いだけです。

まあ、これは学術的なものであればよいのですが。

「いいね!」 1

これは実装されましたか?

私のLet’s Encrypt証明書は昨日、自動更新されずに期限切れになりました。これが、このスレッドの上で提案したapp.ymlへの変更や、その後のDiscourseのアップデートと関係があるのかどうかはわかりません。

AIの支援(はい、知っています!)のおかげで、ngixとcertbotの使用(最終的には機能しましたが)に関するいくつかの落とし穴をたどった後、それらの変更を元に戻し、Discourseが管理するデフォルトの方法に戻すことで、更新できるようになりました。その過程で数回再構築する必要があったため、それが更新をトリガーしたのかどうかはわかりません。

ご迷惑をおかけして申し訳ありません。念のためお伺いしますが、今回再構築される前、最後に再構築されたのはいつですか?

当方で再度更新プロセスを確認・テストしましたが、再現できませんでした。当方のテストでは正常に更新されるため、当方側で何かが起きていないか、あるいは Let’s Encrypt のステージングと本番環境の更新の動作に何らかの違いがあるかのどちらかです。

他に方法がない場合は、サイトの再構築によって更新プロセスが強制的に実行されることも確認できます。

内部では acme.sh を使用しています(コンテナ内の /opt/acme.sh にあります)。ご興味があれば、稼働中の Docker コンテナに入り、スクリプトを実行してそこから検査/更新を行うことも可能です。

「いいね!」 1