Bootsnap::CompileCache::PermissionError

Hola a todos. He instalado una nueva versión de Discourse en Docker.

El problema es que, tras reconstruir el contenedor, este se inicia y puedo acceder a la página de la aplicación. Sin embargo, recibo una respuesta 502. En los registros o cuando intento acceder, por ejemplo, mediante rails c (dentro del contenedor), lo único que veo es este error:

`permission_error’: bootsnap no tiene permiso para escribir entradas en caché en ‘tmp/cache/bootsnap/compile-cache’ (o, menos probablemente, no tiene permiso para leer ‘/usr/local/lib/ruby/2.7.0/set.rb’) (Bootsnap::CompileCache::PermissionError)

Para solucionarlo, tengo que ejecutar chown -R discourse:discourse /var/www/discourse/tmp (para ser exactos, es el directorio /var/www/discourse/tmp/cache/bootsnap) dentro del contenedor, y justo después la aplicación funciona correctamente, incluso sin reiniciar. Es bastante molesto tener que hacerlo manualmente tras cada reconstrucción.

Pensé que podría resolverlo usando la sección de comandos personalizados en app.yml con el comando chown -R discourse:discourse /var/www/discourse/tmp mencionado anteriormente, pero desafortunadamente no funciona. Parece que los comandos se ejecutan allí (probé con mkdir solo para verificar), pero los permisos de los archivos no se ven afectados.

¿Cuál podría ser el problema y cómo se puede resolver? ¿Quizás haya alguna manera correcta de cambiar los permisos de los archivos?

Eso es extraño. ¿Siguió la Instalación estándar oficial de Discourse?

Por supuesto. No se realizaron pasos adicionales.

¿Puedes pegar tu archivo container.yml (sin contraseñas)?

Claro. Aquí lo tienes:

## esta es la plantilla de contenedor Docker todo-en-uno y autónoma de Discourse
##
## Después de realizar cambios en este archivo, DEBES reconstruir
## /var/discourse/launcher rebuild app
##
## TEN *MUCHO* CUIDADO AL EDITAR!
## ¡LOS ARCHIVOS YAML SON SUPER SENSIBLES A ERRORES EN LOS ESPACIOS EN BLANCO O LA ALINEACIÓN!
## visita http://www.yamllint.com/ para validar este archivo según sea necesario

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
## Descomenta estas dos líneas si deseas agregar Lets Encrypt (https)
  - "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

## ¿Qué puertos TCP/IP debe exponer este contenedor?
## Si deseas que Discourse comparta un puerto con otro servidor web como Apache o nginx,
## consulta https://meta.discourse.org/t/17247 para más detalles
expose:
  - "80:80"   # http
  - "443:443" # https

params:
  db_default_text_search_config: "pg_catalog.english"

  ## Establece db_shared_buffers a un máximo del 25% de la memoria total.
  ## se establecerá automáticamente durante el arranque según la RAM detectada, o puedes sobrescribirlo
  #db_shared_buffers: "256MB"

  ## puede mejorar el rendimiento de ordenación, pero aumenta el uso de memoria por conexión
  #db_work_mem: "40MB"

  ## ¿Qué revisión de Git debe usar este contenedor? (predeterminado: tests-passed)
  #version: tests-passed

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

  ## ¿Cuántas solicitudes web concurrentes se admiten? Depende de la memoria y los núcleos de CPU.
  ## se establecerá automáticamente durante el arranque según los CPUs detectados, o puedes sobrescribirlo
  #UNICORN_WORKERS: 3

  ## TODO: El nombre de dominio al que responderá esta instancia de Discourse
  ## Obligatorio. Discourse no funcionará con una dirección IP desnuda.
  DISCOURSE_HOSTNAME: 'example.com'

  ## Descomenta si deseas que el contenedor se inicie con el mismo
  ## nombre de host (opción -h) especificado anteriormente (predeterminado "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: Lista de correos electrónicos separados por comas que serán administradores y desarrolladores
  ## en el registro inicial, por ejemplo 'usuario1@example.com,usuario2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'test@mail.com'

  ## TODO: El servidor de correo SMTP utilizado para validar nuevas cuentas y enviar notificaciones
  ## Se requieren la dirección SMTP, el nombre de usuario y la contraseña
  # ADVERTENCIA: el carácter '#' en la contraseña SMTP puede causar problemas!
  DISCOURSE_SMTP_ADDRESS: smtp.mail.io
  #DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: 111
  DISCOURSE_SMTP_PASSWORD: 111
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (opcional, predeterminado true)
  #DISCOURSE_SMTP_DOMAIN: discourse.example.com    # (requerido por algunos proveedores)
  #DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.example.com    # (dirección desde la cual enviar notificaciones)

  ## Si agregaste la plantilla de Lets Encrypt, descomenta a continuación para obtener un certificado SSL gratuito
  #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com

  ## La dirección CDN http o https para esta instancia de Discourse (configurada para extraer)
  ## consulta https://meta.discourse.org/t/14857 para más detalles
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com
  
  ## La clave de dirección IP de geolocalización de Maxmind para la búsqueda de direcciones IP
  ## consulta https://meta.discourse.org/t/-/137387/23 para más detalles
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

## El contenedor Docker es sin estado; todos los datos se almacenan en /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## Los plugins van aquí
## consulta https://meta.discourse.org/t/19157 para más detalles
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

## Cualquier comando personalizado para ejecutar después de la compilación
run:
  - exec: echo "Inicio de comandos personalizados"
  ## Si deseas establecer la dirección de correo electrónico 'De' para tu primer registro, descomenta y cambia:
  ## Después de recibir el primer correo electrónico de registro, vuelve a comentar la línea. Solo necesita ejecutarse una vez.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  #- exec: chown -R discourse:discourse /var/www/discourse/tmp/cache/bootsnap  # ejemplo de comando sobre cómo intenté corregir los permisos de archivo
  - exec: echo "Fin de comandos personalizados"

¿No ejecutaste discourse-setup, verdad? Debería haber definido algunas cosas que has comentado. Acabo de realizar esos cambios y quiero asegurarme de que funcionen como se espera.

¿Hay alguna razón por la que no estás usando Let’s Encrypt?

Sin embargo, no veo una explicación para tu problema.

En primer lugar, la aplicación se construyó usando discourse-setup. Tras varios intentos de reconstruirla sin obtener ningún resultado positivo, pasé a uno de los archivos .yml predefinidos del directorio /samples y luego simplemente lo edité con mis credenciales.
¿Por qué no usar Let’s Encrypt? Se pidió usar los certificados del cliente. Pero, hasta donde entiendo, los certificados no tienen nada que ver con esto, ya que son válidos y no hay ningún problema relacionado con ellos.
Parece que el problema está a nivel del proyecto y está específicamente relacionado con los permisos del archivo de caché de bootsnap (quizás el problema esté del lado de Bootsnap).

Gracias. Estoy de acuerdo en que probablemente no sea ese el problema. Realicé un par de instalaciones ayer que funcionaron perfectamente. No veo ninguna explicación para tu problema.

Estábamos enfrentando el mismo problema y confirmo que ejecutar (dentro del contenedor Docker):

chown -R discourse:discourse /var/www/discourse/tmp

¡Solucionó el problema! No fue necesario reiniciar. Antes del cambio de propietario, los permisos del directorio ‘tmp’ estaban asignados a ‘discourse:www-data’. Espero que esto sea algo que se pueda corregir en el futuro para que no sea necesaria esta acción manual después de cada reconstrucción.

¿Estás ejecutando el lanzador como root?

Sí, @pfaffman, lo soy. ¿Es ese el problema?

No lo creo. Siempre inicio mis instancias autoalojadas como root y nunca he visto un problema así.

¿Quién es el propietario del directorio si no usas chown? En un contenedor recientemente reconstruido, se ve así:

# ls -l /var/www/discourse/tmp
total 36
lrwxrwxrwx 1 root      root         19 Mar  2 14:56 backups -> /shared/tmp/backups
drwxr-xr-x 1 discourse discourse  4096 Mar  2 14:57 cache
drwxr-xr-x 1 discourse discourse  4096 Mar  2 14:57 ember-rails
drwxr-xr-x 1 discourse root       4096 Mar  2 15:04 pids
lrwxrwxrwx 1 root      root         20 Mar  2 14:56 restores -> /shared/tmp/restores
drwxr-xr-x 2 discourse root       4096 Mar  2 14:56 sockets
drwxr-xr-x 2 discourse discourse 12288 Mar  2 15:02 stylesheet-cache

¿Añadiste algún comando o hook personalizado a tu app.yml además de clonar plugins?

El propietario, usuario y grupo del directorio /var/www/discourse/tmp era discourse:www-data después de iniciar el contenedor. Reasignarlo a discourse:discourse resolvió el problema. Esto no me había ocurrido antes, aunque llevo usando Discourse varios meses. De todos modos, fue una solución sencilla y podría haber sido algo aleatorio, así que no quiero molestarte más con esto. ¡Muchas gracias, @gerhard!