DockerなしでDiscourseをデプロイする

私のソリューションに関する詳細:

  1. Nginx 設定:
    リバースプロキシ (haproxy) の背後では、/var/discourse/config/nginx-config-sample.conf/etc/nginx/sites-enabled/discourse.conf または類似のターゲットにコピーし、listen <yourreverseproxyport> (必要に応じて) と server_name_ をホスト名 (subdmain.example.com) に置き換える必要があります。それ以外は変更しないでください。
  2. ページが表示されない(「おっと」メッセージ)および管理者登録メールが機能しない:
    Magick が、最初の起動時の管理者登録ページ後にページが表示されない原因でした。ログに示されたファイル /var/www/discourse/lib/letter_avatar.rb:112 の 112 行目を調べたところ、応答しない magick コマンドが 2 つありました。convert は応答したので、この行の magickconvert に置き換えました。これらの修正後、別のエラーがログに記録されました。ファイルから提供されたコマンドで同じ手順を試したところ、magick コマンドは機能せず、convert も失敗しました。注:magick --version は 7.x で、convert --version は 6.x でした。原因は、apt で imagemagick を最初にインストールし、次にソースから magick 7 をインストールしたことでした。競合があり、magick は convert コマンドを古いと判断しました。そのため、magick 7 のみでスクリプトを再実行しました。これにより問題はすぐに解決し、数日間待っていたブランドの新しいページが表示され、メールも機能しました!Magick は本当に魔法です。
  3. まだ混合コンテンツの問題が残っていますが、ウェブサイトは正常に動作しています。
    注:puma.rb の行 bind ENV.fetch("PUMA_BIND", "tcp://#{ENV['PUMA_BIND_ALL'] ? '' : '127.0.0.1:'}3000") は、(最初の投稿の修正として) このようにする必要があります。
  4. 「3.」を編集、https強制について Discourse の場合:正確にはわかりませんが、ブラウザに「混合コンテンツ」の警告が表示されなくなりました(キャッシュの更新のためかもしれません)。そのため、すべて順調です。スクリプトを完成させるだけです。
「いいね!」 3

確認できました!
ImageMagick v7 で Ooops 問題が解決しました!
テストした限りでは、完全に動作しています。
残りの機能もテストして、できるだけ早く報告します。

「いいね!」 1

テストのために、puma を実行する際に環境変数 PUMA_BIND を設定しました。

ImageMagick については、何らかの理由で Discourse が webUI での画像変換に失敗しています。大きな画像をアップロードすると、親切にも変換を拒否します…まだ問題をデバッグ中です。

デバッグの進捗はありますか? こちらはmagickに取り組んでいます。
約50KBの画像では、ブラウザに次のようなポップアップが表示されます。
timeout -k 40.0 20 magick gif:/tmp/RackMultipart20250927-23598-xrrp6e.gif -auto-orient -background white -interlace none -flatten -debug all -quality 90 jpg:/tmp/image20250927-23598-9ujq3d.jpg
そして画像は読み込まれません。
サイズが大きい場合は、ポップアップは表示されませんが、ローディングホイールが無限に回転し、結果は得られません。/var/www/discourse/logにはエラーは記録されていません。

私も同じ問題です :joy::sob:
brew リポジトリの imagemagick を使用して実行できるようになりました。

しかし、画像が 3MB を超えると失敗します…おそらく、非常に制限的なポリシー構成を設定したのでしょう。

試してみてください!!!

Docker のインストールをテストしていますが、nginx、unicorn、redis、postgresql、その他すべてを 1 つのコンテナにデプロイするのは非常に愚かだと思います…まったく意味がありません。大規模なデプロイメント用のインフラストラクチャ ドキュメントもありません…IT で 20 年以上働いてきましたが、そのようなインフラストラクチャを使用すると、近い将来問題が発生することしか見えません。

「Docker The Space Eater」(Dormammu のように)については言うまでもありません :rofl::rofl:

この問題は、最後に説明されている以下の解決策で解消されました。

デバッグ 1: bundle db:create の出力、および初回起動時のログ:


unknown OID 21096: ‘embeddings’ の型を認識できませんでした。文字列として扱われます。
pngquant worker: pngquant が見つかりません。適切なバイナリを提供するか、このワーカーを無効にしてください (–no-pngquant 引数またはオプション経由の :pngquant => false)
oxipng worker: oxipng が見つかりません。適切なバイナリを提供するか、このワーカーを無効にしてください (–no-oxipng 引数またはオプション経由の :oxipng => false)
jhead worker: jhead が見つかりません、jpegtran が見つかりません。適切なバイナリを提供するか、このワーカーを無効にしてください (–no-jhead 引数またはオプション経由の :jhead => false)
jpegoptim worker: jpegoptim が見つかりません。適切なバイナリを提供するか、このワーカーを無効にしてください (–no-jpegoptim 引数またはオプション経由の :jpegoptim => false)

デバッグ 2: ファイルを使用した一部のマジックコマンドの出力:

この画像形式のデコードデリゲートがありません

この最後の問題は、こちらで言及されています。

解決策はこちらです(マジックとフォーマットプラグインをインストールします)。

t=$(mktemp) && \
wget 'https://dist.1-2.dev/imei.sh' -qO "$t" && \
bash "$t" && \
rm "$t"

その後、アップロードサイズは最大518KBになります。それ以上はできません。これは画像のみです。他のすべてのドキュメント、オーディオ、ビデオのアップロードは機能します。

残りの問題に対する一時的な解決策:
管理設定、discourse.conf、nginx/sites-enables/discourse.conf、gitフォルダを確認しました。最終的にAdminPanel/Parameters/Filesで「Composer media optimization image enabled」を無効にしたところ、すべて正常に機能するようになりました。任意の画像をアップロードできます。

はい、IMEIはbrewを使用するのとほぼ同じソリューションですが、ディスク容量を約2GBも消費することはないと思います:rofl::rofl::sob::face_with_symbols_on_mouth::face_with_symbols_on_mouth::face_with_symbols_on_mouth:

アップロードの最大ファイルサイズに関するあなたのソリューションを確認します。

また、「無料」でメールを送信するソリューションにも苦労しています(初期段階なので、mailtrap/mailgun/etc…と契約したくありません)。

メールサーバーをインストールしてみてはどうですか?私は自分でメールサーバーを構築し、インストールをスクリプト化しました。興味があれば教えてください。

承知しました!指示またはgitリポジトリをDMで送ってください!:grinning_face_with_smiling_eyes:

私は何年も前にセルフホスト型メールサーバーの使用をやめました…

rake assets:precompile を実行すると、「No such file or directory - brotli」というエラーが表示されました。パッケージマネージャーでインストールしてください。

「いいね!」 2

エラーが発生していることがわかりました。

bundler: failed to load command: puma (/home/mry/.rbenv/versions/3.4.6/bin/puma)
/home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/puma-7.0.4/lib/puma/cluster.rb:472:in 'Puma::Cluster#run': undefined method 'wait_readable' for nil (NoMethodError)

            if read.wait_readable([0, @next_check - Time.now].max)
                   ^^^^^^^^^^^^^^
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/puma-7.0.4/lib/puma/launcher.rb:202:in 'Puma::Launcher#run'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/puma-7.0.4/lib/puma/cli.rb:73:in 'Puma::CLI#run'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/puma-7.0.4/bin/puma:10:in '<top (required)>'
        from /home/mry/.rbenv/versions/3.4.6/bin/puma:25:in 'Kernel#load'
        from /home/mry/.rbenv/versions/3.4.6/bin/puma:25:in '<top (required)>'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/cli/exec.rb:59:in 'Kernel.load'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/cli/exec.rb:59:in 'Bundler::CLI::Exec#kernel_load'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/cli/exec.rb:23:in 'Bundler::CLI::Exec#run'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/cli.rb:452:in 'Bundler::CLI#exec'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/vendor/thor/lib/thor/command.rb:28:in 'Bundler::Thor::Command#run'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in 'Bundler::Thor::Invocation#invoke_command'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/vendor/thor/lib/thor.rb:538:in 'Bundler::Thor.dispatch'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/cli.rb:35:in 'Bundler::CLI.dispatch'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/vendor/thor/lib/thor/base.rb:584:in 'Bundler::Thor::Base::ClassMethods#start'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/cli.rb:29:in 'Bundler::CLI.start'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/exe/bundle:28:in 'block in <top (required)>'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/lib/bundler/friendly_errors.rb:117:in 'Bundler.with_friendly_errors'
        from /home/mry/.rbenv/versions/3.4.6/lib/ruby/gems/3.4.0/gems/bundler-2.6.4/exe/bundle:20:in '<top (required)>'
        from /home/mry/.rbenv/versions/3.4.6/bin/bundle:25:in 'Kernel#load'
        from /home/mry/.rbenv/versions/3.4.6/bin/bundle:25:in '<main>'

Puma が再起動します。これを防ぐにはどうすればよいですか?

編集: これは Ruby 3.4.0 以降の Puma に関連する問題 のようです。YJIT を無効にすることで解決しました。

では、3.3.7を使用してください。これは私が使用しているバージョンです。

Gemsを再ダウンロードするのが面倒なので、YJITを無効にして3.4.6を使い続けます。

Hi all,
Here is my script for a full install in three shots, without docker, on a Debian 12 container (lxc for me).
Use the if blocks to only run the parts you need.

  1. Set your parameter and run it as root with the required arguments. Be careful: the script will exit at the exit point before “### MANUAL” part.
  2. You have to pass these commands manually in the container terminal. I did not succeed to make it work in my lxc unprivileged container. (default user is root)
  3. Then run the rest.
    I tested it many times and it works but there may be some buggy parts after i adapted it to publication.
install_script
#!/bin/bash
########## SCRIPT TO INSTALL DISCOURSE ON DEBIAN 12 WITHOUT DOCKER ##################
#- last tested in december 2025
############################## RUN IT AS ROOT, best in a lxc container!!!!!!!
#- discussion source : https://meta.discourse.org/t/deploy-discourse-without-docker/351194
##############################################################################
# MANUAL PARAMETERS
certbot_contact_email=hello@domain.tld
certbot_renew_port=9785
nginx_discourse_port=8080
DISCOURSE_DEVELOPER_EMAILS='emailaddress'
DISCOURSE_SMTP_ADDRESS=smtp_server_address
DISCOURSE_SMTP_PORT=465
DISCOURSE_SMTP_USER_NAME=xxx
DISCOURSE_SMTP_PASSWORD=xxx
DISCOURSE_SMTP_DOMAIN=xxx
DISCOURSE_NOTIFICATION_EMAIL=no-reply-xxxx
DISCOURSE_MAXMIND_ACCOUNT_ID=50
# END MANUAL PARAMETERS

shopt -s expand_aliases
source /etc/bash.bashrc
container=$1
cont_haproxy=$2
pool=$3
lxc_image=$4
hostname=$5
db_password=$6
maxmind_license_key=$7
DISCOURSE_HOSTNAME=$hostname
DISCOURSE_MAXMIND_LICENSE_KEY=$maxmind_license_key

### INSTALL MAGICK 7 and its plugins
# https://github.com/SoftCreatR/imei/?tab=readme-ov-file
if [ 1 == 1 ]; then
t=$(mktemp) && \
wget 'https://dist.1-2.dev/imei.sh' -qO "$t" && \
bash "$t" && \
rm "$t"
fi

### INSTALL BASICS ###
if [ 1 == 1 ]; then
apt install -y apt-utils postgresql nginx libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static redis
systemctl enable --now postgresql redis-server nginx
useradd -m -s /bin/bash discourse
usermod -aG sudo discourse
passwd -d discourse
# RVM (RUBY)
apt install -y ruby-full # nécessaire
su - discourse -c 'curl -sSL https://get.rvm.io | bash'
su - discourse -c 'source /home/discourse/.bashrc'
su - discourse -c 'source /home/discourse/.rvm/scripts/rvm' # nécessaire après rvm install
su - discourse -c 'rvm install 3.3.7' # will install node 3.3.7 as of today
source /home/discourse/.rvm/scripts/rvm
# fi
# configure POSTGRESQL
apt update && apt upgrade -y
apt autoremove -y

# YOU HAVE TO ACCEPT THE UPGRADE
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
apt install -y postgresql-18-pgvector
fi
alias mydb="sudo -u postgres psql discourse -c "
if [ 1 == 1 ]; then
su - discourse -c 'sudo -u postgres createuser -s discourse'
# fi
su - discourse -c 'sudo -u postgres createdb discourse'
su - discourse -c 'sudo -u postgres psql -c "ALTER USER discourse WITH ENCRYPTED PASSWORD '\''password'\'';"'
alias mydb="sudo -Hiu discourse psql -c "
su - discourse -c 'psql -c "GRANT CONNECT ON DATABASE discourse TO root;"'
su - discourse -c 'psql -c "CREATE EXTENSION pg_trgm;CREATE EXTENSION hstore;"'
su - discourse -c 'psql -c "ALTER DATABASE discourse OWNER TO discourse;"'
su - discourse -c 'psql -c "CREATE EXTENSION unaccent;CREATE EXTENSION plpgsql;"'
su - discourse -c 'psql -c "CREATE EXTENSION vector;"'
echo "OK"

### INSTALL DISCOURSE FROM GITHUB
cd /var/www/
git clone https://github.com/discourse/discourse
git config --global --add safe.directory /var/www/discourse
# exit
### NÉCESSAIRE POUR bundle, ruby, etc. pas pour discourse lui-même
tee -a /home/discourse/.bashrc > /dev/null <<EOT
export RAILS_ENV=production
export UNICORN_SIDEKIQ_MAX_RSS=800
export UNICORN_WORKERS=8
export UNICORN_SIDEKIQS=1
export PUMA_SIDEKIQ_MAX_RSS=800
export PUMA_WORKERS=8
export PUMA_SIDEKIQS=1
export RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000
export RUBY_GC_HEAP_INIT_SLOTS=400000
export RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5

export DISCOURSE_HOSTNAME=$hostname
export DISCOURSE_DEVELOPER_EMAILS=$DISCOURSE_DEVELOPER_EMAILS
export DISCOURSE_SMTP_ADDRESS=$DISCOURSE_SMTP_ADDRESS
export DISCOURSE_SMTP_PORT=$DISCOURSE_SMTP_PORT
export DISCOURSE_SMTP_USER_NAME=$DISCOURSE_SMTP_USER_NAME
export DISCOURSE_SMTP_PASSWORD=$DISCOURSE_SMTP_PASSWORD
export DISCOURSE_SMTP_DOMAIN=$DISCOURSE_SMTP_DOMAIN
export DISCOURSE_NOTIFICATION_EMAIL=$DISCOURSE_NOTIFICATION_EMAIL
export DISCOURSE_MAXMIND_ACCOUNT_ID=$DISCOURSE_MAXMIND_ACCOUNT_ID
export DISCOURSE_MAXMIND_LICENSE_KEY=$maxmind_license_key

export DISCOURSE_ENABLE_CORS=true
export DISCOURSE_MAX_REQS_PER_IP_MODE=none
export DISCOURSE_MAX_REQS_PER_IP_PER_MINUTE=20000
export DISCOURSE_MAX_REQS_PER_IP_PER_10_SECONDS=5000
export DISCOURSE_MAX_ASSET_REQS_PER_IP_PER_10_SECONDS=20000
export DISCOURSE_MAX_REQS_RATE_LIMIT_ON_PRIVATE=false
export DISCOURSE_MAX_USER_API_REQS_PER_MINUTE=200
export DISCOURSE_MAX_USER_API_REQS_PER_DAY=28800
export DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE=600
export DISCOURSE_MAX_DATA_EXPLORER_API_REQ_MODE=none
EOT
cd /var/www/discourse
git stash
git pull
git checkout tests-passed 
cd plugins
for plugin in *
do
echo "ok"
    echo $plugin; cd ${plugin}; git pull; cd ..
done
# fi
chown -R discourse:discourse /var/www/discourse/     
mkdir -p /var/www/discourse/public
chown -R discourse:www-data /var/www/discourse/public
tee -a /var/www/discourse/config/discourse.conf > /dev/null <<EOT
max_data_explorer_api_req_mode = 'none'
max_user_api_reqs_per_day = '28800'
hostname = '$hostname'
redis_host = 'localhost'
smtp_user_name = $$DISCOURSE_SMTP_USER_NAME
db_password = '$db_password'
smtp_address = '$DISCOURSE_SMTP_ADDRESS'
db_socket = ''
max_reqs_per_ip_per_10_seconds = '5000'
max_asset_reqs_per_ip_per_10_seconds = '20000'
max_reqs_rate_limit_on_private = 'false'
developer_emails = '$DISCOURSE_DEVELOPER_EMAILS'
max_user_api_reqs_per_minute = '200'
maxmind_license_key = '$maxmind_license_key'
smtp_port = '$DISCOURSE_SMTP_PORT'
maxmind_account_id = '$DISCOURSE_MAXMIND_ACCOUNT_ID'
smtp_password = '$DISCOURSE_SMTP_PASSWORD'
max_reqs_per_ip_per_minute = '20000'
notification_email = '$DISCOURSE_NOTIFICATION_EMAIL'
db_host = 'localhost'
enable_cors = 'true'
db_port = ''
max_reqs_per_ip_mode = 'none'
smtp_domain = '$DISCOURSE_SMTP_DOMAIN'
#max_admin_api_reqs_per_minute = '600'
smtp_force_tls='true'
EOT

cd /var/www/discourse && sed -i '/gem "rails_multisite"/i gem "rails"' Gemfile
cd /var/www/discourse && sed -i '/gem "image_optim"/i gem "image_optim_pack"' Gemfile
su - discourse -c 'cd /var/www/discourse && bundle install'
# fi

### PNPM (NODEJS)
su - discourse -c 'curl -fsSL https://get.pnpm.io/install.sh' | su - discourse -c 'sh -'
su - discourse -c 'source /home/discourse/.bashrc'
source /home/discourse/.rvm/scripts/rvm
su - discourse -c 'sed -i "s/~> 3.3/3.3.7/" /var/www/discourse/Gemfile'
chown -R discourse:discourse /var/www/discourse/Gemfile Gemfile.lock
apt-get -yqq install brotli # is it needed ????????????????
# fi
su - discourse -c 'cd /var/www/discourse && bin/rails db:create'
# fi
su - discourse -c 'source /home/discourse/.rvm/scripts/rvm'
tee -a .bashrc > /dev/null <<EOT
# pnpm
export PNPM_HOME="/home/discourse/.local/share/pnpm"
case ":\$PATH:" in
  *":\$PNPM_HOME:"*) ;;
  *) export PATH="\$PNPM_HOME:\$PATH" ;;
esac
# pnpm end
EOT
which pnpm
source .bashrc
pnpm env use --global lts # will install node 22 as of today
cd /var/www/discourse && pnpm i
chown -R discourse:discourse .
chown -R discourse:www-data public
exit

#################################
######### MANUAL ################
export PATH="$PATH:/home/discourse/.rvm/bin"
rvm install "ruby-3.3.7" # install in root
cd /var/www/discourse
bundle install
bundle exec rake db:migrate
bundle exec rake themes:update
bundle exec rake assets:precompile
######### MANUAL #################
##################################

fi
### puma.rb
#cd /var/www/discourse
cp /var/www/discourse/config/puma.rb /var/www/discourse/config/puma.rb_original

tee /var/www/discourse/config/puma.rb > /dev/null <<EOT
# frozen_string_literal: true

require "fileutils"

discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")

enable_logstash_logger = ENV["ENABLE_LOGSTASH_LOGGER"] == "1"
puma_stderr_path = "#{discourse_path}/log/puma.stderr.log"
puma_stdout_path = "#{discourse_path}/log/puma.stdout.log"

# Load logstash logger if enabled
if enable_logstash_logger
  require_relative "../lib/discourse_logstash_logger"
  FileUtils.touch(puma_stderr_path) if !File.exist?(puma_stderr_path)
  # Note: You may need to adapt the logger initialization for Puma
  log_formatter = proc do |severity, time, progname, msg|
    event = {
      "@timestamp" => Time.now.utc,
      "message" => msg,
      "severity" => severity,
      "type" => "puma"
    }
    "#{event.to_json}\n"
  end
else
  stdout_redirect puma_stdout_path, puma_stderr_path, true
end

# Number of workers (processes)
workers ENV.fetch("PUMA_WORKERS", 8).to_i

# Set the directory
directory discourse_path

# Bind to the specified address and port
bind ENV.fetch("PUMA_BIND", "tcp://#{ENV['PUMA_BIND_ALL'] ? '' : '127.0.0.1:'}3000")

# PID file location
FileUtils.mkdir_p("#{discourse_path}/tmp/pids")
pidfile ENV.fetch("PUMA_PID_PATH", "#{discourse_path}/tmp/pids/puma.pid")

# State file - used by pumactl
state_path "#{discourse_path}/tmp/pids/puma.state"

# Environment-specific configuration
if ENV["RAILS_ENV"] == "production"
  # Production timeout
  worker_timeout 30
else
  # Development timeout
  worker_timeout ENV.fetch("PUMA_TIMEOUT", 60).to_i
end

# Preload application
preload_app!

# Handle worker boot and shutdown
before_fork do
  Discourse.preload_rails!
  Discourse.before_fork

  # Supervisor check
  supervisor_pid = ENV["PUMA_SUPERVISOR_PID"].to_i
  if supervisor_pid > 0
    Thread.new do
      loop do
        unless File.exist?("/proc/#{supervisor_pid}")
          puts "Kill self supervisor is gone"
          Process.kill "TERM", Process.pid
        end
        sleep 2
      end
    end
  end

  # Sidekiq workers
  sidekiqs = ENV["PUMA_SIDEKIQS"].to_i
  if sidekiqs > 0
    puts "starting #{sidekiqs} supervised sidekiqs"

    require "demon/sidekiq"
    Demon::Sidekiq.after_fork { DiscourseEvent.trigger(:sidekiq_fork_started) }
    Demon::Sidekiq.start(sidekiqs)

    if Discourse.enable_sidekiq_logging?
      Signal.trap("USR1") do
        # Delay Sidekiq log reopening
        sleep 1
        Demon::Sidekiq.kill("USR2")
      end
    end
  end

  # Email sync demon
  if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true"
    puts "starting up EmailSync demon"
    Demon::EmailSync.start(1)
  end

  # Plugin demons
  DiscoursePluginRegistry.demon_processes.each do |demon_class|
    puts "starting #{demon_class.prefix} demon"
    demon_class.start(1)
  end

  # Demon monitoring thread
  Thread.new do
    loop do
      begin
        sleep 60

        if sidekiqs > 0
          Demon::Sidekiq.ensure_running
          Demon::Sidekiq.heartbeat_check
          Demon::Sidekiq.rss_memory_check
        end

        if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true"
          Demon::EmailSync.ensure_running
          Demon::EmailSync.check_email_sync_heartbeat
        end

        DiscoursePluginRegistry.demon_processes.each(&:ensure_running)
      rescue => e
        Rails.logger.warn("Error in demon processes heartbeat check: #{e}\n#{e.backtrace.join("\n")}")
      end
    end
  end

  # Close Redis connection
  Discourse.redis.close
end

on_worker_boot do
  DiscourseEvent.trigger(:web_fork_started)
  Discourse.after_fork
end

# Worker timeout handling
worker_timeout 30

# Low-level worker options
threads 8, 32
EOT

### CERTBOT
apt install -y certbot
certbot certonly --non-interactive --agree-tos --renew-with-new-domains  --standalone --email $certbot_contact_email --rsa-key-size 4096 --http-01-port $certbot_renew_port -d $hostname
# fi

### NGINX
cp /var/www/discourse/config/nginx.sample.conf /etc/nginx/sites-enabled/discourse.conf
sed -i "s/80/$nginx_discourse_port/" /etc/nginx/sites-enabled/discourse.conf
sed -i "s/server_name _/server_name $hostname/" /etc/nginx/sites-enabled/discourse.conf
mkdir -p /var/nginx/cache
systemctl enable nginx
systemctl restart nginx
systemctl status nginx

### SYSTEMD SERVICE AUTOSTART
sudo tee /etc/systemd/system/discourse.service > /dev/null <<EOT
[Unit]
Description=Discourse with Puma Server
After=network.target postgresql.service
Requires=postgresql.service

[Service]
Type=simple
User=discourse
Group=discourse
WorkingDirectory=/var/www/discourse
# requires running `rvm 3.3.7 --default` before this service is run
ExecStart=/usr/bin/bash -lc '/home/discourse/.rvm/gems/ruby-3.3.7/bin/puma -C config/puma.rb'
ExecReload=/usr/bin/bash -lc '/home/discourse/.rvm/gems/ruby-3.3.7/bin/pumactl restart'
# il faut cette ligne dessous
Environment=RAILS_ENV=production
# Restart configuration
Restart=always
RestartSec=5s

# Basic security measures
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=read-only

[Install]
WantedBy=multi-user.target
EOT

systemctl enable discourse
systemctl start discourse

# OR MANUAL START
# puma -C config/puma.rb

### SETTINGS
echo "LAST MANUAL SETTINGS:"
echo ""
echo "GO in Admin>files and add wanted file extensions - vidéos, audio et documents
echo "TO FORCE HTTPS: https://domain.com/admin/config/security"