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.
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.
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).
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.
¡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.
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.
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)
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
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!
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…)
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.
Hola a todos,
Aquí está mi script para una instalación completa en tres pasos, sin Docker, en un contenedor Debian 12 (lxc en mi caso).
Usa los bloques if para ejecutar solo las partes que necesitas.
Configura tus parámetros y ejecútalo como root con los argumentos requeridos. Ten cuidado: el script terminará en el punto de salida antes de la parte “### MANUAL”.
Debes ejecutar estos comandos manualmente en la terminal del contenedor. No logré que funcionaran en mi contenedor lxc sin privilegios. (el usuario predeterminado es root)
Luego ejecuta el resto.
Lo he probado muchas veces y funciona, pero puede haber algunas partes con errores después de que lo adapté para su publicación.
install_script
#!/bin/bash
########## SCRIPT PARA INSTALAR DISCOURSE EN DEBIAN 12 SIN DOCKER ##################
#- último testeado en diciembre de 2025
############################## EJECÚTALO COMO ROOT, ¡lo mejor en un contenedor lxc!!!!!!!
#- fuente de discusión: https://meta.discourse.org/t/deploy-discourse-without-docker/351194
##############################################################################
# PARÁMETROS MANUALES
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
# FIN DE PARÁMETROS MANUALES
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
### INSTALAR MAGICK 7 y sus 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
### INSTALACIÓN BÁSICA ###
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 # necesario
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' # necesario después de instalar rvm
su - discourse -c 'rvm install 3.3.7' # instalará node 3.3.7 según la fecha actual
source /home/discourse/.rvm/scripts/rvm
# fi
# configurar POSTGRESQL
apt update && apt upgrade -y
apt autoremove -y
# DEBES ACEPTAR LA ACTUALIZACIÓN
/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"
### INSTALAR DISCOURSE DESDE GITHUB
cd /var/www/
git clone https://github.com/discourse/discourse
git config --global --add safe.directory /var/www/discourse
# exit
### NECESARIO PARA bundle, ruby, etc., no para discourse en sí
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 # ¿es necesario????????????????
# 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 # instalará node 22 según la fecha actual
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" # instalar en 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"
# Cargar logstash logger si está habilitado
if enable_logstash_logger
require_relative "../lib/discourse_logstash_logger"
FileUtils.touch(puma_stderr_path) if !File.exist?(puma_stderr_path)
# Nota: Puede que necesites adaptar la inicialización del logger para 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
# Número de workers (procesos)
workers ENV.fetch("PUMA_WORKERS", 8).to_i
# Establecer el directorio
directory discourse_path
# Vincular a la dirección y puerto especificados
bind ENV.fetch("PUMA_BIND", "tcp://#{ENV['PUMA_BIND_ALL'] ? '' : '127.0.0.1:'}3000")
# Ubicación del archivo PID
FileUtils.mkdir_p("#{discourse_path}/tmp/pids")
pidfile ENV.fetch("PUMA_PID_PATH", "#{discourse_path}/tmp/pids/puma.pid")
# Archivo de estado - utilizado por pumactl
state_path "#{discourse_path}/tmp/pids/puma.state"
# Configuración específica del entorno
if ENV["RAILS_ENV"] == "production"
# Tiempo de espera en producción
worker_timeout 30
else
# Tiempo de espera en desarrollo
worker_timeout ENV.fetch("PUMA_TIMEOUT", 60).to_i
end
# Precargar aplicación
preload_app!
# Manejar el inicio y cierre de workers
before_fork do
Discourse.preload_rails!
Discourse.before_fork
# Verificación del supervisor
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
# Workers de Sidekiq
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
# Retrasar la reapertura del log de Sidekiq
sleep 1
Demon::Sidekiq.kill("USR2")
end
end
end
# Demon de sincronización de correo electrónico
if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true"
puts "starting up EmailSync demon"
Demon::EmailSync.start(1)
end
# Demones de plugins
DiscoursePluginRegistry.demon_processes.each do |demon_class|
puts "starting #{demon_class.prefix} demon"
demon_class.start(1)
end
# Hilo de monitoreo del demon
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
# Cerrar conexión Redis
Discourse.redis.close
end
on_worker_boot do
DiscourseEvent.trigger(:web_fork_started)
Discourse.after_fork
end
# Manejo de tiempo de espera del worker
worker_timeout 30
# Opciones de bajo nivel del worker
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
### SERVICIO SYSTEMD DE INICIO AUTOMÁTICO
sudo tee /etc/systemd/system/discourse.service > /dev/null <<EOT
[Unit]
Description=Discourse con Puma Server
After=network.target postgresql.service
Requires=postgresql.service
[Service]
Type=simple
User=discourse
Group=discourse
WorkingDirectory=/var/www/discourse
# requiere ejecutar `rvm 3.3.7 --default` antes de ejecutar este servicio
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'
# es necesario esta línea abajo
Environment=RAILS_ENV=production
# Configuración de reinicio
Restart=always
RestartSec=5s
# Medidas básicas de seguridad
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=read-only
[Install]
WantedBy=multi-user.target
EOT
systemctl enable discourse
systemctl start discourse
# O INICIO MANUAL
# puma -C config/puma.rb
### CONFIGURACIONES
echo "ÚLTIMAS CONFIGURACIONES MANUALES:"
echo ""
echo "VE a Admin > archivos y agrega las extensiones de archivo deseadas - vídeos, audio y documentos
echo "PARA FORZAR HTTPS: https://domain.com/admin/config/security"