Ich verwende einen Unix-Socket zwischen Caddy und Discourse statt TCP, aber ab und zu erhalte ich einen „unix:“-Fehler

Die Protokolle zeigen Folgendes:

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

Wenn dies passiert, wird eine „Oops - Error 500“-Seite angezeigt. Zuerst dachte ich, Caddy wäre der Schuldige, weil er die IP-Adresse des Clients nicht an Discourse weiterleitete. Ich versuchte daher verschiedene Konfigurationen, aber keine davon löste das Problem.

Es ist erwähnenswert, dass dies nicht sehr häufig vorkommt. Es tritt nur gelegentlich auf, und wenn es passiert, wird die Seite durch einfaches Aktualisieren sofort wiederhergestellt. Anschließend funktioniert sie für eine ziemlich lange Zeit normal, bevor der Fehler erneut zufällig auftritt.

Ich bin kein Experte und habe Caddy nicht verwendet, sondern Nginx für meine selbst gehostete Instanz, aber kann ich dich nach deiner aktuellen Caddy- und Discourse-Vorlagenkonfiguration in ./app/containers.yml fragen?

Kannst du dich daran erinnern, was du normalerweise getan hast, bevor der Fehler aufgetreten ist? Ich meine, Admin-Einstellungen geändert, Beiträge erstellt oder ein Plugin verwendet?

Es tut mir leid, keine spezifische Hilfe für dein Problem zu bieten, aber ich denke, deine Antworten können deinen Frage mehr Klarheit verleihen und eine schnelle Antwort von der Community ermöglichen.

Das bedeutet, dass eine Anfrage / ein Benutzer eine Remote-IP hat, die auf deinen Socket zeigt, was darauf hindeutet, dass etwas in deiner Proxy-Kette falsch konfiguriert ist.

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


## Welche TCP/IP-Ports soll dieser Container exponieren?
## Wenn du möchtest, dass Discourse einen Port mit einem anderen Webserver wie Apache oder nginx teilt,
## siehe https://meta.discourse.org/t/17247 für Details
expose:
  # - "66:80"   # http
  # - "66:443" # https

params:
  ## Welche Git-Revision soll dieser Container verwenden? (Standard: latest)
  version: latest
  ## Maximale Upload-Größe (Standard: 10m)
  upload_size: 150m
  
  db_default_text_search_config: "pg_catalog.english"

  ## Setze db_shared_buffers auf maximal 25 % des gesamten Speichers.
  ## Wird automatisch vom Bootstrap-Skript basierend auf dem erkannten RAM festgelegt, oder du kannst es überschreiben
  db_shared_buffers: "2048MB"

  ## Kann die Sortierleistung verbessern, erhöht aber den Speicherverbrauch pro Verbindung
  #db_work_mem: "40MB"

  ## Welche Git-Revision soll dieser Container verwenden? (Standard: 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
  ## Wie viele gleichzeitige Webanfragen werden unterstützt? Hängt vom Speicher und den CPU-Kernen ab.
  ## Wird automatisch vom Bootstrap-Skript basierend auf den erkannten CPUs festgelegt, oder du kannst es überschreiben
  UNICORN_WORKERS: 8

  ## TODO: Der Domainname, auf den diese Discourse-Instanz reagieren soll
  ## Erforderlich. Discourse funktioniert nicht mit einer nackten IP-Adresse.
  DISCOURSE_HOSTNAME: example.com

  ## Kommentiere auf, wenn du möchtest, dass der Container mit demselben
  ## Hostnamen (-h-Option) gestartet wird, wie oben angegeben (Standard "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: Liste durch Kommas getrennter E-Mails, die bei der ersten Anmeldung als Admin und Entwickler festgelegt werden
  ## Beispiel 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin+discourse@example.com'

  ## TODO: Der SMTP-Mailserver, der zur Validierung neuer Konten und zum Senden von Benachrichtigungen verwendet wird
  # SMTP-ADRESSE ist erforderlich
  # WARNUNG: SMTP-Passwort sollte in Anführungszeichen gesetzt werden, um Probleme zu vermeiden
  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           # (optional, Standard: true)
  DISCOURSE_SMTP_DOMAIN: example.com # (von einigen Anbietern erforderlich)
  DISCOURSE_NOTIFICATION_EMAIL: noreply@example.com
  #DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: peer        # (optional, Standard: peer, gültige Werte: none, peer, client_once, fail_if_no_peer_cert)
  #DISCOURSE_SMTP_AUTHENTICATION: plain            # (Standard: plain, gültige Werte: plain, login, cram_md5)

  ## Wenn du das Lets Encrypt-Template hinzugefügt hast, kommentiere unten auf, um ein kostenloses SSL-Zertifikat zu erhalten
  # LETSENCRYPT_ACCOUNT_EMAIL: admin+letsencrypt@example.com

  ## Die http- oder https-CDN-Adresse für diese Discourse-Instanz (konfiguriert zum Pullen)
  ## siehe https://meta.discourse.org/t/14857 für Details
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

  ## Die MaxMind-Geolokalisierung IP-Konto-ID und Lizenzschlüssel für IP-Adressnachschläge
  ## siehe https://meta.discourse.org/t/-/173941 für Details
  #DISCOURSE_MAXMIND_ACCOUNT_ID: 123456
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

  # HTTPS erzwingen
  DISCOURSE_FORCE_HTTPS: true
  
  # Anfragereschränkungen
  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

## Der Docker-Container ist zustandslos; alle Daten werden in /shared gespeichert
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

## Plugins gehören hierher
## siehe https://meta.discourse.org/t/19157 für Details
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - cp -a /var/plugins/. $home/plugins/

## Alle benutzerdefinierten Befehle, die nach dem Build ausgeführt werden sollen
run:
  - exec: echo "Beginn der benutzerdefinierten Befehle"
  ## Wenn du die 'Von'-E-Mail-Adresse für deine erste Registrierung festlegen möchtest, kommentiere auf und ändere:
  ## Nach Erhalt der ersten Anmelde-E-Mail die Zeile wieder auskommentieren. Sie muss nur einmal ausgeführt werden.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "Ende der benutzerdefinierten Befehle"

Caddyfile

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

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

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

# Um eine A+-Bewertung in der SSL-Sicherheit zu erreichen
(hsts) {
	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
	}
}

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

#---------------------------------------------------------------------------------
# Forum (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
	#-------------------------------------------------------------------------------
}

#---------------------------------------------------------------------------------
# Subdomains
#---------------------------------------------------------------------------------

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

	# Erzwingen der Nicht-www-Version der Domain
	@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

			# Kritische Dateien
			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
	}
  
  #-------------------------------------------------------------------------------
  # Mehrere eigenständige HTML-Dateien
  #-------------------------------------------------------------------------------

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

  #-------------------------------------------------------------------------------
  # Keine Matcher
  #-------------------------------------------------------------------------------

	handle {
		respond 404
	}

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

Um genauer zu sein, tritt dieser Fehler mehrere Stunden nach dem vorherigen auf, er passiert nicht sehr oft. Ich sehe in app.yml oder der Caddyfile nichts Ungewöhnliches.

Wenn die Socket-Verbindung bis zum Abbruch korrekt ist, können Sie meiner Meinung nach explizite Timeouts und Transportoptionen hinzufügen.

Ich denke, du kannst explizite Timeouts und Transportoptionen hinzufügen

Wie?

Nun, wie ich bereits gesagt habe, habe ich Caddy nicht verwendet, aber du kannst sich ihre offizielle Dokumentation ansehen.

Ich glaube, ich habe das Problem gefunden. Wenn ich einen Neuaufbau durchführe, starte ich Caddy nie neu. Ab jetzt werde ich folgendes tun:

./launcher rebuild app && systemctl reload caddy

Ich vermute, dass Caddy nach einem Neuaufbau den Socket-Cache oder etwas Ähnliches verwendet. Aber das passiert normalerweise nicht sofort nach einem Neuaufbau. Wir werden sehen.