Estou usando um soquete Unix entre Caddy e Discourse em vez de TCP, mas de vez em quando recebo um erro 'unix:'

Os logs mostram o seguinte:

PG::InvalidTextRepresentation (ERROR: invalid input syntax for type inet: "unix:" LINE 7: client_ip = 'unix:', ^ ) lib/mini_sql_multisite_connection.rb:109:in 'MiniSqlMult

Job exception: ERROR: invalid input syntax for type inet: "unix:" LINE 2: SET ip_address = 'unix:' ^  

Quando isso acontece, uma página de “Oops - Erro 500” é exibida. A princípio, achei que o Caddy fosse o culpado, pois ele não estava repassando o endereço IP do cliente ao Discourse, então tentei várias configurações diferentes, mas nenhuma resolveu o problema.

Vale mencionar que isso não acontece com frequência. Ocorre apenas ocasionalmente, e quando ocorre, basta atualizar a página para que o site volte a funcionar normalmente. Ele então opera sem problemas por um bom tempo, até que o erro ocorra aleatoriamente novamente.

Não sou especialista e não usei Caddy, mas sim Nginx na minha instância auto-hospedada, mas posso pedir sua configuração atual de modelos Caddy e Discourse em ./app/containers.yml?

Você consegue lembrar o que costumava fazer antes do erro acontecer? Quero dizer, alterar configurações de administrador, postar, usar algum plugin?

Sinto muito por não poder ajudar especificamente com seu problema, mas acho que suas respostas podem agregar valor à sua pergunta para obter uma resposta clara e rápida da comunidade.

Isso significa que uma solicitação/usuário tem um IP remoto apontando para seu socket, o que indica que algo na sua cadeia de proxies está configurado incorretamente.

@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"


## quais portas TCP/IP este contêiner deve expor?
## Se você quiser que o Discourse compartilhe uma porta com outro servidor web como Apache ou nginx,
## consulte https://meta.discourse.org/t/17247 para mais detalhes
expose:
  # - "66:80"   # http
  # - "66:443" # https

params:
  ## Qual revisão do Git este contêiner deve usar? (padrão: latest)
  version: latest
  ## Tamanho máximo de upload (padrão: 10m)
  upload_size: 150m
  
  db_default_text_search_config: "pg_catalog.english"

  ## Defina db_shared_buffers para no máximo 25% da memória total.
  ## será definido automaticamente pelo bootstrap com base na RAM detectada, ou você pode substituir
  db_shared_buffers: "2048MB"

  ## pode melhorar o desempenho de ordenação, mas aumenta o uso de memória por conexão
  #db_work_mem: "40MB"

  ## Qual revisão do Git este contêiner deve usar? (padrão: 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
  ## Quantas solicitações web simultâneas são suportadas? Depende da memória e dos núcleos de CPU.
  ## será definido automaticamente pelo bootstrap com base nas CPUs detectadas, ou você pode substituir
  UNICORN_WORKERS: 8

  ## TODO: O nome de domínio ao qual esta instância do Discourse responderá
  ## Obrigatório. O Discourse não funcionará com um número IP puro.
  DISCOURSE_HOSTNAME: example.com

  ## Descomente se quiser que o contêiner seja iniciado com o mesmo
  ## nome de host (opção -h) especificado acima (padrão "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: Lista de e-mails separados por vírgula que serão feitos admin e developer
  ## no cadastro inicial exemplo 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin+discourse@example.com'

  ## TODO: O servidor de e-mail SMTP usado para validar novas contas e enviar notificações
  # O ENDEREÇO SMTP é obrigatório
  # AVISO: a senha SMTP deve estar entre aspas 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, padrão: true)
  DISCOURSE_SMTP_DOMAIN: example.com # (obrigatório por alguns provedores)
  DISCOURSE_NOTIFICATION_EMAIL: noreply@example.com
  #DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: peer        # (opcional, padrão: peer, valores válidos: none, peer, client_once, fail_if_no_peer_cert)
  #DISCOURSE_SMTP_AUTHENTICATION: plain            # (padrão: plain, valores válidos: plain, login, cram_md5)

  ## Se você adicionou o template do Lets Encrypt, descomente abaixo para obter um certificado SSL gratuito
  # LETSENCRYPT_ACCOUNT_EMAIL: admin+letsencrypt@example.com

  ## O endereço do CDN http ou https para esta instância do Discourse (configurado para pull)
  ## consulte https://meta.discourse.org/t/14857 para mais detalhes
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

  ## O ID da conta e a chave de licença do Maxmind geolocation IP para consultas de endereço IP
  ## consulte https://meta.discourse.org/t/-/173941 para mais detalhes
  #DISCOURSE_MAXMIND_ACCOUNT_ID: 123456
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

  # Forçar HTTPS
  DISCOURSE_FORCE_HTTPS: true
  
  # Limites de Solicitação
  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

## O contêiner Docker é stateless; todos os dados são armazenados em /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

## Os plugins vão aqui
## consulte https://meta.discourse.org/t/19157 para mais detalhes
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - cp -a /var/plugins/. $home/plugins/

## Quaisquer comandos personalizados para executar após a construção
run:
  - exec: echo "Início dos comandos personalizados"
  ## Se você quiser definir o endereço de e-mail 'De' para seu primeiro cadastro, descomente e altere:
  ## Após receber o e-mail de primeiro cadastro, re-comente a linha. Ela só precisa ser executada uma vez.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "Fim dos comandos personalizados"

Caddyfile

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

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

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

# Para obter uma classificação A+ em segurança SSL
(hsts) {
	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
	}
}

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

#---------------------------------------------------------------------------------
# Fórum (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
	#-------------------------------------------------------------------------------
}

#---------------------------------------------------------------------------------
# Subdomínios
#---------------------------------------------------------------------------------

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

	# Forçar a versão não-www do domínio
	@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

			# Arquivos 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/*
		}

		# proteger_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últiplos arquivos HTML independentes
  #-------------------------------------------------------------------------------

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

  #-------------------------------------------------------------------------------
  # Sem matchers
  #-------------------------------------------------------------------------------

	handle {
		respond 404
	}

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

Para ser mais específico, esse erro ocorre várias horas após o anterior, não acontece com muita frequência. Não vejo nada de incomum no app.yml ou no Caddyfile.

Se a conexão com o socket estiver correta até ser interrompida, acho que você pode adicionar tempos limite e opções de transporte explícitos.

Acho que você pode adicionar tempos limite e opções de transporte explícitos

Como?

Bem, como eu disse antes, não usei o Caddy, mas você pode consultar a documentação oficial deles.

Acho que encontrei o problema. Quando faço uma reconstrução, nunca reinicio o Caddy. A partir de agora, vou fazer isso:

./launcher rebuild app && systemctl reload caddy

Suspeito que o Caddy use o cache de soquetes ou algo semelhante após uma reconstrução. Mas isso geralmente não acontece imediatamente após a reconstrução. Vamos ver.