Desplegar Discourse sin Docker

Algunos detalles sobre mis soluciones:

  1. Configuración de Nginx:
    Detrás de un proxy inverso (haproxy), necesitas copiar /var/discourse/config/nginx-config-sample.conf a /etc/nginx/sites-enabled/discourse.conf o un destino similar, luego reemplazar listen <tu_puerto_del_proxy_inverso> (si es necesario) y el _ de server_name por tu nombre de host (subdominio.ejemplo.com). No se debe cambiar nada más.
  2. Páginas no mostradas (mensaje “Oops”) y registro de administrador por correo electrónico no funcionando:
    Magick fue la causa de que las páginas no se mostraran después de las páginas de registro de administrador al arrancar por primera vez. Seguí el archivo indicado en el registro: /var/www/discourse/lib/letter_avatar.rb:112. En la línea 112, había dos comandos magick que efectivamente no respondían. convert respondía, así que reemplacé magick en esta línea por convert. Después de estas correcciones, se registró otro error. Intentando el mismo procedimiento con el comando dado del archivo, el comando magick no funcionó y convert fallaba. Nota: magick --version era 7.x y convert --version daba 6.x. La causa fue que primero instalé imagemagick con apt, y luego magick 7 desde el código fuente. Hubo algunos conflictos y magick indicó que el comando convert estaba desactualizado. Así que volví a ejecutar mi script solo con magick 7. Esto resolvió inmediatamente el problema y pude ver las nuevas páginas esperadas durante días, ¡y el correo electrónico también funcionó! Magick es realmente mágico.
  3. Todavía queda el problema del contenido mixto, pero el sitio web funciona bien.
    Nota: en puma.rb, la línea bind ENV.fetch("PUMA_BIND", "tcp://#{ENV['PUMA_BIND_ALL'] ? '' : '127.0.0.1:'}3000") debe ser así (corrección de la primera publicación).
  4. EDITAR “3.”, sobre la fuerza de https para discourse: No sé por qué exactamente, pero mis navegadores ya no muestran advertencias de ‘contenido mixto’ (quizás debido a la actualización de la caché), así que todo está bien ahora. Solo necesito terminar mi script.
3 Me gusta

¡Funciona confirmado!
¡ImageMagick v7 soluciona el problema Ooops!
Hasta donde he probado, funciona perfectamente.
Probaré el resto de las funciones y os informaré lo antes posible.

1 me gusta

Lo que hice para probar fue establecer la variable de entorno PUMA_BIND al ejecutar puma.

Con respecto a ImageMagick, por alguna razón Discourse no está logrando ejecutar una conversión de imagen en la interfaz web, cuando subo una imagen grande amablemente se niega a convertirla… Todavía estoy depurando el problema.

¿Algún avance en la depuración? Por mi parte, estoy trabajando en magick.
En algunas imágenes de alrededor de 50 ko, en el navegador aparece una ventana emergente:
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 y no se carga ninguna imagen.
Si el tamaño es mayor, no hay ventana emergente, pero la rueda de carga gira en un bucle infinito sin resultado. No se registran errores en /var/www/discourse/log.

Mismo problema para mí :joy::sob:

La única forma en que pude hacerlo funcionar fue usando imagemagick del repositorio de brew.

PERO falla cuando la imagen es de más de 3 MB… tal vez configuré una política muy restrictiva.

¡¡¡Pruébalo!!!

Estoy probando la instalación de docker, pero creo que es bastante estúpido desplegar nginx, unicorn, redis, postgresql y el resto en UN solo contenedor… no tiene ningún sentido. Y no hay documentación de infraestructura para grandes implementaciones… He trabajado en TI durante más de 20 años y solo veo problemas en el futuro cercano usando tal infraestructura.

Sin hablar de “docker El Devorador de Espacio” (como Dormammu) :rofl::rofl:

Este problema ha desaparecido con la siguiente solución descrita al final:

Depuración 1: bundle db:create muestra, también en los registros al primer arranque:


OID desconocido 21096: no se puede reconocer el tipo de ‘embeddings’. Se tratará como String.
pngquant worker: no se encuentra pngquant; proporcione un binario adecuado o deshabilite este worker (argumento --no-pngquant o :pngquant => false a través de las opciones)
oxipng worker: no se encuentra oxipng; proporcione un binario adecuado o deshabilite este worker (argumento --no-oxipng o :oxipng => false a través de las opciones)
jhead worker: no se encuentra jhead, no se encuentra jpegtran; proporcione un binario adecuado o deshabilite este worker (argumento --no-jhead o :jhead => false a través de las opciones)
jpegoptim worker: no se encuentra jpegoptim; proporcione un binario adecuado o deshabilite este worker (argumento --no-jpegoptim o :jpegoptim => false a través de las opciones)

Depuración 2: Algunos comandos magick con archivos muestran:

no hay delegado de decodificación para este formato de imagen

Este último problema se menciona aquí.

La solución está aquí (instala magick con plugins de formatos):

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

Después de esto, mi tamaño de carga puede ser de hasta 518 KB. Antes no. Esto es solo para imágenes. Todas las demás cargas de documentos, audio y video funcionan.

Solución temporal para el problema restante:
He buscado en la configuración de administrador, discourse.conf, nginx/sites-enables/discourse.conf, en la carpeta git. Finalmente, en AdminPanel/Parameters/Files, deshabilité “Composer media optimization image enabled”, entonces todo funciona bien. Puedo cargar cualquier imagen.

Sí, IMEI es casi la misma solución que usar brew, ¡pero estoy seguro de que no ocupará alrededor de 2 GB de disco! :rofl::rofl::sob::face_with_symbols_on_mouth::face_with_symbols_on_mouth::face_with_symbols_on_mouth:

Revisaré tu solución para el tamaño máximo de archivo en las cargas.

También estoy luchando con una solución para enviar correos electrónicos “gratis” (estoy en una etapa temprana y no quiero contratar mailtrap/mailgun/etc…)

¿Por qué no instalas un servidor de correo? Yo tengo el mío y escribí un script para la instalación. Dime si te interesa.

¡Claro! ¡Envíame las instrucciones o el repositorio de Git por mensaje directo! :grinning_face_with_smiling_eyes:

Dejé de usar servidores de correo autoalojados hace muchos años…

Al ejecutar rake assets:precompile, apareció el mensaje No such file or directory - brotli, simplemente instálalo con un gestor de paquetes.

2 Me gusta

Encontré que está arrojando este error:

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

luego Puma se reinicia solo. ¿Qué debo hacer para evitar esto?

Editado: Esto parece ser un problema de Puma desde Ruby 3.4.0. Se solucionó deshabilitando YJIT.

Entonces usa 3.3.7. Esta es la versión que uso.

Soy demasiado perezoso para volver a descargar gemas, solo deshabilitaré YJIT y seguiré usando 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"