Discourse ohne Docker bereitstellen

Einige Details zu meinen Lösungen:

  1. Nginx-Konfiguration:
    Hinter einem Reverse-Proxy (haproxy) müssen Sie die Datei /var/discourse/config/nginx-config-sample.conf nach /etc/nginx/sites-enabled/discourse.conf oder ein ähnliches Ziel kopieren, dann listen <yourreverseproxyport> (falls erforderlich) und das _ von server_name durch Ihren Hostnamen (subdomain.example.com) ersetzen. Sonst nichts ändern.
  2. Seiten werden nicht angezeigt (“Oops”-Nachricht) und E-Mail-Admin-Registrierung funktioniert nicht:
    Magick war die Ursache dafür, dass nach den Admin-Registrierungsseiten beim ersten Start keine Seiten angezeigt wurden. Ich folgte der im Log angegebenen Datei: /var/www/discourse/lib/letter_avatar.rb:112. In Zeile 112 gab es zwei magick-Befehle, die tatsächlich nicht reagierten. convert reagierte, also ersetzte ich magick in dieser Zeile durch convert. Nach diesen Korrekturen wurde ein weiterer Fehler protokolliert. Wenn ich das gleiche Verfahren mit dem angegebenen Befehl aus der Datei versuchte, funktionierte der magick-Befehl nicht und convert schlug fehl. HINWEIS: magick --version war 7.x und convert --version ergab 6.x. Die Ursache war, dass ich zuerst imagemagick mit apt installiert hatte und dann Magick 7 aus dem Quellcode. Es gab einige Konflikte und Magick sagte dem convert-Befehl, er sei veraltet. Also startete ich mein Skript nur mit Magick 7 neu. Dies löste das Problem sofort und ich konnte die brandneuen Seiten sehen, auf die ich tagelang gewartet hatte, und auch die E-Mail funktionierte! Magick ist wirklich magisch.
  3. Das Problem mit gemischten Inhalten bleibt bestehen, aber die Website funktioniert trotzdem gut.
    HINWEIS: In puma.rb muss die Zeile bind ENV.fetch("PUMA_BIND", "tcp://#{ENV['PUMA_BIND_ALL'] ? '' : '127.0.0.1:'}3000") wie folgt aussehen (Korrektur des ersten Beitrags).
  4. BEARBEITUNG “3.”, bezüglich HTTPS-Erzwingung für Discourse: Ich weiß nicht genau warum, aber meine Browser zeigen keine Warnungen wegen “gemischtem Inhalt” mehr an (vielleicht wegen der Cache-Aktualisierung), also ist jetzt alles in Ordnung. Ich muss nur noch mein Skript fertigstellen.
3 „Gefällt mir“

Funktioniert bestätigt!!!
ImageMagick v7 löst das Ooops-Problem!
Soweit ich getestet habe, funktioniert es einwandfrei.
Ich werde die restlichen Funktionen testen und so schnell wie möglich berichten.

1 „Gefällt mir“

Was ich zum Testen getan habe, war, die Umgebungsvariable PUMA_BIND beim Ausführen von Puma zu setzen.

Bezüglich ImageMagick schlägt Discourse aus irgendeinem Grund fehl, eine Bildkonvertierung in der WebUI auszuführen. Wenn ich ein großes Bild hochlade, weigert es sich freundlicherweise, es zu konvertieren… Ich debugge das Problem immer noch.

Gibt es Fortschritte beim Debugging? Ich arbeite meinerseits an Magick.
Bei einigen Bildern von etwa 50 KB wird im Browser ein Popup angezeigt:
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 und es wird kein Bild geladen
Bei größeren Größen erscheint kein Popup, aber das Laderad dreht sich unendlich lange im Kreis, ohne Ergebnis. Es werden keine Fehler in /var/www/discourse/log protokolliert.

Gleiches Problem für mich :joy::sob:

Die einzige Möglichkeit, wie ich es zum Laufen gebracht habe, war die Verwendung von ImageMagick aus dem Brew-Repository.

ABER es schlägt fehl, wenn das Bild mehr als 3 MB groß war… vielleicht habe ich eine sehr restriktive Policy-Konfiguration eingerichtet.

Probieren Sie es aus!!!

Ich teste die Docker-Installation, aber ich glaube, oder es ist ziemlich dumm, Nginx, Unicorn, Redis, PostgreSQL und den Rest in NUR einem Container bereitzustellen… das ergibt überhaupt keinen Sinn. Und es gibt keine Infrastrukturdokumentation für große Bereitstellungen… Ich arbeite seit mehr als 20 Jahren im IT-Bereich und sehe nur Probleme in naher Zukunft, wenn solche Infrastrukturen genutzt werden.

Ganz zu schweigen von „Docker The Space Eater“ (wie Dormammu) :rofl::rofl:

Dieses Problem ist mit der folgenden Lösung am Ende behoben:

Debug 1: bundle db:create gibt Folgendes aus, auch in den Logs beim ersten Start:


unknown OID 21096: failed to recognize type of ‘embeddings’. It will be treated as String.
pngquant worker: pngquant not found; please provide proper binary or disable this worker (–no-pngquant argument or :pngquant => false through options)
oxipng worker: oxipng not found; please provide proper binary or disable this worker (–no-oxipng argument or :oxipng => false through options)
jhead worker: jhead not found, jpegtran not found; please provide proper binary or disable this worker (–no-jhead argument or :jhead => false through options)
jpegoptim worker: jpegoptim not found; please provide proper binary or disable this worker (–no-jpegoptim argument or :jpegoptim => false through options)

Debug 2: Einige magick-Befehle mit Dateien geben Folgendes aus:

no decode delegate for this image format

Dieses letzte Problem wird hier erwähnt.

Die Lösung finden Sie hier (installiert magick mit Formaten-Plugins):

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

Danach kann meine Upload-Größe bis zu 518KB betragen. Darüber hinaus nicht. Dies gilt nur für Bilder. Alle anderen Dokumente, Audio- und Video-Uploads funktionieren.

Temporäre Lösung für das verbleibende Problem:
Ich habe in den Admin-Einstellungen, discourse.conf, nginx/sites-enables/discourse.conf, im Git-Ordner nachgesehen. Schließlich habe ich im AdminPanel/Parameter/Dateien die Option “Composer media optimization image enabled” deaktiviert, dann funktioniert alles einwandfrei. Ich kann jedes Bild hochladen.

Ja, IMEI ist fast die gleiche Lösung wie die Verwendung von Brew, aber ich bin sicher, dass es nicht ungefähr 2 GB Speicherplatz beanspruchen wird :rofl::rofl::sob::sob::sob::face_with_symbols_on_mouth::face_with_symbols_on_mouth::face_with_symbols_on_mouth:

Ich werde Ihre Lösung für die maximale Dateigröße bei Uploads überprüfen.

Ich kämpfe auch mit einer Lösung, um E-Mails „kostenlos“ zu versenden (ich bin in einem frühen Stadium und möchte keine E-Mail-Dienste wie Mailtrap/Mailgun/etc. abonnieren).

Warum installieren Sie keinen Mailserver? Ich habe meinen eigenen und habe die Installation skriptet. Sagen Sie mir Bescheid, wenn Sie interessiert sind.

Klar! Schick mir die Anweisungen oder das Git-Repository per DM! :grinning_face_with_smiling_eyes:

Ich benutze seit vielen Jahren keine selbst gehosteten Mailserver mehr…

Wenn Sie rake assets:precompile ausführen, wird No such file or directory - brotli angezeigt. Installieren Sie es einfach mit einem Paketmanager.

2 „Gefällt mir“

Ich habe festgestellt, dass der folgende Fehler auftritt:

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>'

Dann startet Puma sich neu. Was kann ich tun, um dies zu verhindern?

Bearbeitet: Dies scheint ein Problem von Puma seit Ruby 3.4.0 zu sein. Gelöst durch Deaktivieren von YJIT.

Verwenden Sie dann 3.3.7. Dies ist meine verwendete Version.

Ich bin zu faul, um Gems neu herunterzuladen, deaktiviere einfach YJIT und verwende weiterhin 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"