Uso un socket Unix entre Caddy y Discourse en lugar de TCP, pero de vez en cuando obtengo un error de 'unix:'

Los registros muestran lo siguiente:

PG::InvalidTextRepresentation (ERROR: sintaxis de entrada no válida para el tipo inet: "unix:" LÍNEA 7: client_ip = 'unix:', ^ ) lib/mini_sql_multisite_connection.rb:109:in 'MiniSqlMult

Error del trabajo: ERROR: sintaxis de entrada no válida para el tipo inet: "unix:" LÍNEA 2: SET ip_address = 'unix:' ^  

Cuando ocurre, se muestra una página de «Oops - Error 500». Al principio, pensé que Caddy era el culpable porque no estaba reenviando la dirección IP del cliente a Discourse, así que probé varias configuraciones diferentes, pero ninguna resolvió el problema.

Cabe mencionar que esto no ocurre con mucha frecuencia. Sucede solo ocasionalmente, y cuando lo hace, simplemente actualizar la página recupera el sitio de inmediato. Luego funciona normalmente durante bastante tiempo antes de que el error vuelva a aparecer aleatoriamente.

No soy un experto y no usé Caddy, sino Nginx en mi instancia autoalojada, pero ¿puedo pedirte la configuración actual de tus plantillas de Caddy y Discourse en ./app/containers.yml?

¿Recuerdas qué solías hacer antes de que ocurriera el error? Me refiero a cambiar la configuración de administrador, publicar, usar algún complemento, etc.

Lamento no poder ofrecerte una ayuda específica para tu problema, pero creo que tus respuestas pueden aportar valor a tu pregunta para obtener una respuesta clara y rápida de la comunidad.

Esto significa que una solicitud/usuario tiene una IP remota que apunta a tu socket, lo que indica que algo en tu cadena de proxies está mal configurado.

@satonotdead @Falco

app.yml

templates:
  - "templates/postgres.18.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  
  - "templates/web.socketed.template.yml"
  
  - "templates/enable-ruby-yjit.yml"


## ¿qué puertos TCP/IP debe exponer este contenedor?
## Si quieres 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:
  # - "66:80"   # http
  # - "66:443" # https

params:
  ## ¿Qué revisión de Git debe usar este contenedor? (predeterminado: latest)
  version: latest
  ## Tamaño máximo de subida (predeterminado: 10m)
  upload_size: 150m
  
  db_default_text_search_config: "pg_catalog.english"

  ## Establece db_shared_buffers como máximo al 25% de la memoria total.
  ## se establecerá automáticamente durante el bootstrap según la RAM detectada, o puedes anularlo
  db_shared_buffers: "2048MB"

  ## puede mejorar el rendimiento de las ordenaciones, pero añade 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

  ## https://meta.discourse.org/t/rescaling-the-server-which-configs-need-to-be-changed-unicorn-workers-memory-etc/252788
  ## ¿Cuántas peticiones web concurrentes se soportan? Depende de la memoria y los núcleos de CPU.
  ## se establecerá automáticamente durante el bootstrap según las CPUs detectadas, o puedes anularlo
  UNICORN_WORKERS: 8

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

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

  ## TODO: Lista de correos electrónicos separados por comas que serán admin y developer
  ## en el primer registro, ejemplo 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin+discourse@example.com'

  ## TODO: El servidor de correo SMTP utilizado para validar nuevas cuentas y enviar notificaciones
  # La DIRECCIÓN SMTP es obligatoria
  # ADVERTENCIA: La contraseña SMTP debe ir entre comillas para evitar problemas
  DISCOURSE_SMTP_ADDRESS: smtp.provider.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: noreply@example.com
  DISCOURSE_SMTP_PASSWORD: "***"
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (opcional, predeterminado: true)
  DISCOURSE_SMTP_DOMAIN: example.com # (requerido por algunos proveedores)
  DISCOURSE_NOTIFICATION_EMAIL: noreply@example.com
  #DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: peer        # (opcional, predeterminado: peer, valores válidos: none, peer, client_once, fail_if_no_peer_cert)
  #DISCOURSE_SMTP_AUTHENTICATION: plain            # (predeterminado: plain, valores válidos: plain, login, cram_md5)

  ## Si has añadido la plantilla de Lets Encrypt, descomenta abajo para obtener un certificado SSL gratuito
  # LETSENCRYPT_ACCOUNT_EMAIL: admin+letsencrypt@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

  ## El ID de cuenta y la clave de licencia de geolocalización IP de Maxmind para búsquedas de dirección IP
  ## consulta https://meta.discourse.org/t/-/173941 para más detalles
  #DISCOURSE_MAXMIND_ACCOUNT_ID: 123456
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

  # Forzar HTTPS
  DISCOURSE_FORCE_HTTPS: true
  
  # Límites de peticiones
  DISCOURSE_MAX_REQS_PER_IP_MODE: none
  DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE: 12000
  
  DISCOURSE_MAX_DATA_EXPLORER_API_REQ_MODE: none
  DISCOURSE_MAX_DATA_EXPLORER_API_REQS_PER_10_SECONDS: 1000

  DISCOURSE_YJIT_ENABLED: true

## 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
  - volume:
      host: /var/discourse/plugins
      guest: /var/plugins

## 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
          - cp -a /var/plugins/. $home/plugins/

## Cualquier comando personalizado para ejecutar después de la compilación
run:
  - exec: echo "Inicio de comandos personalizados"
  ## Si quieres establecer la dirección de correo electrónico 'De' para tu primer registro, descomenta y cambia:
  ## Después de recibir el correo de registro, vuelve a comentar la línea. Solo necesita ejecutarse una vez.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "Fin de comandos personalizados"

Caddyfile

#---------------------------------------------------------------------------------

{
	storage file_system {
		root /var/caddy/data
	}
}

#---------------------------------------------------------------------------------

# Para obtener una calificación A+ en seguridad SSL
(hsts) {
	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
	}
}

# credenciales autoalojadas de acme-dns
(tls-challenge) {
	tls admin+letsencrypt@example.com {
		dns acmedns {
			username ***
			password ***
			subdomain ***
			server_url http://acme.example.com:5005
		}
	}
}

#---------------------------------------------------------------------------------
# Foro (Discourse)
#---------------------------------------------------------------------------------
example.com {
	#-------------------------------------------------------------------------------
	import hsts
	import tls-challenge
	#-------------------------------------------------------------------------------
	request_header X-Real-IP {remote_host}
	reverse_proxy unix//var/discourse/shared/standalone/nginx.http.sock
	#-------------------------------------------------------------------------------
}

#---------------------------------------------------------------------------------
# Subdominios
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
*.example.com {
	#-------------------------------------------------------------------------------
	import hsts
	import tls-challenge
	#-------------------------------------------------------------------------------

	# Forzar la versión sin www del dominio
	@www host www.example.com
	redir @www https://example.com{uri} permanent
  
	#-------------------------------------------------------------------------------
  
	@store host store.example.com
	handle @store {
		@wc_private {
			path /license.txt
			path /readme.html

			# Archivos críticos
			path /wp-config.php
			path /xmlrpc.php
			path /wp-settings.php
			path /wp-load.php
			path /wp-blog-header.php

			path /wp-admin.php

			path /wp-admin/install.php

			path /wp-content/uploads/wc-logs/*
			path /wp-content/uploads/nuvei-logs/*

			path /wp-content/uploads/woocommerce_uploads/*
		}

		# protect_php
		@wc_private_php {
			not path /wp-includes/ms-files.php

			path_regexp protect_php ^/(wp-includes|wp-admin/includes|wp-content/uploads)/.*\.php$
		}
		respond @wc_private 403
		respond @wc_private_php 403

		root * /usr/share/wordpress
		php_fastcgi unix//run/php/php8.3-fpm.sock
		file_server
	}
  
  #-------------------------------------------------------------------------------
  # Múltiples archivos HTML independientes
  #-------------------------------------------------------------------------------

  @join host join.example.com
  handle @join {
    root * /var/example/join
    file_server
  }

  #-------------------------------------------------------------------------------
  # Sin matchers
  #-------------------------------------------------------------------------------

	handle {
		respond 404
	}

	#-------------------------------------------------------------------------------
}

Para ser más específico, este error ocurre varias horas después del anterior, no sucede muy a menudo. No veo nada inusual en app.yml o en el Caddyfile.

Si la conexión al socket es correcta hasta que se interrumpe, creo que puedes agregar tiempos de espera y opciones de transporte explícitas.

Creo que puedes añadir tiempos de espera explícitos y opciones de transporte

¿Cómo?

Bueno, como dije antes, no usé Caddy, pero puedes consultar su documentación oficial.

Creo que he encontrado el problema. Si realizo una reconstrucción, nunca reinicio Caddy. A partir de ahora, voy a hacer esto:

./launcher rebuild app && systemctl reload caddy

Sospecho que Caddy utiliza la caché de sockets o algo similar después de una reconstrucción. Pero normalmente no ocurre inmediatamente después de una reconstrucción. Ya veremos.