diff --git a/Containers/talk-recording/healthcheck.sh b/Containers/talk-recording/healthcheck.sh index 2750d59e77f..6c715acbb20 100644 --- a/Containers/talk-recording/healthcheck.sh +++ b/Containers/talk-recording/healthcheck.sh @@ -4,4 +4,4 @@ if [ "$AIO_LOG_LEVEL" = 'debug' ]; then set -x fi -nc -z 127.0.0.1 1234 || exit 1 +nc -z 127.0.0.1 1234 || nc -z ::1 1234 || exit 1 diff --git a/Containers/talk-recording/start.sh b/Containers/talk-recording/start.sh index bb7d2ea464b..8b768397564 100644 --- a/Containers/talk-recording/start.sh +++ b/Containers/talk-recording/start.sh @@ -58,13 +58,21 @@ extensionaudio = .m4a extensionvideo = .mp4" fi +# Detect IPv6 availability to choose the right listen address +RECORDING_LISTEN="0.0.0.0:1234" +if ! grep -q "1" /sys/module/ipv6/parameters/disable 2>/dev/null \ +&& ! grep -q "1" /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null \ +&& ! grep -q "1" /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null; then + RECORDING_LISTEN="[::]:1234" +fi + cat << RECORDING_CONF > "/conf/recording.conf" [logs] # 30 means Warning level = ${TALK_RECORDING_LOG_LEVEL} [http] -listen = 0.0.0.0:1234 +listen = ${RECORDING_LISTEN} [backend] allowall = ${ALLOW_ALL} diff --git a/Containers/talk/healthcheck.sh b/Containers/talk/healthcheck.sh index 83022f18972..8f187c04f14 100644 --- a/Containers/talk/healthcheck.sh +++ b/Containers/talk/healthcheck.sh @@ -4,11 +4,13 @@ if [ "$AIO_LOG_LEVEL" = 'debug' ]; then set -x fi -nc -z 127.0.0.1 8081 || exit 1 +nc -z 127.0.0.1 8081 || nc -z ::1 8081 || exit 1 nc -z 127.0.0.1 8188 || exit 1 nc -z 127.0.0.1 4222 || exit 1 -nc -z 127.0.0.1 "$TALK_PORT" || exit 1 +nc -z 127.0.0.1 "$TALK_PORT" || nc -z ::1 "$TALK_PORT" || exit 1 eturnalctl status || exit 1 # Verify that the signaling server is actually serving requests, not just # listening on the TCP port (which nc -z above only tests for open port). -wget -q -O /dev/null http://127.0.0.1:8081/api/v1/stats || exit 1 +# SC2102: [::1] is an IPv6 address literal in a URL, not a character-range glob. +# shellcheck disable=SC2102 +wget -q -O /dev/null http://127.0.0.1:8081/api/v1/stats || wget -q -O /dev/null http://[::1]:8081/api/v1/stats || exit 1 diff --git a/Containers/talk/start.sh b/Containers/talk/start.sh index e5bd251b7a9..6af1dc68f6a 100644 --- a/Containers/talk/start.sh +++ b/Containers/talk/start.sh @@ -75,6 +75,13 @@ if grep -q "1" /sys/module/ipv6/parameters/disable \ || grep -q "1" /proc/sys/net/ipv6/conf/default/disable_ipv6; then IP_BINDING="0.0.0.0" fi +# Build a listen address suitable for the signaling server's "ip:port" format. +# IPv6 needs bracket notation: [::]:8081; IPv4 keeps the plain form: 0.0.0.0:8081 +if [ "$IP_BINDING" = "::" ]; then + SIGNALING_LISTEN="[::]:8081" +else + SIGNALING_LISTEN="$IP_BINDING:8081" +fi if [ "$AIO_LOG_LEVEL" != 'debug' ]; then set +x fi @@ -118,7 +125,7 @@ fi # Signaling cat << SIGNALING_CONF > "/conf/signaling.conf" [http] -listen = 0.0.0.0:8081 +listen = ${SIGNALING_LISTEN} readtimeout = 15 writetimeout = 30 diff --git a/php/src/Data/ConfigurationManager.php b/php/src/Data/ConfigurationManager.php index 108a0f4e9a3..a62fc621e38 100644 --- a/php/src/Data/ConfigurationManager.php +++ b/php/src/Data/ConfigurationManager.php @@ -1111,9 +1111,9 @@ private function getPlaceholderValue(string $placeholder) : string { 'INSTALL_LATEST_MAJOR' => $this->installLatestMajor ? 'yes' : '', 'REMOVE_DISABLED_APPS' => $this->nextcloudKeepDisabledApps ? '' : 'yes', // Allow to get local ip-address of database container which allows to talk to it even in host mode (the container that requires this needs to be started first then) - 'AIO_DATABASE_HOST' => gethostbyname('nextcloud-aio-database'), + 'AIO_DATABASE_HOST' => DataConst::resolveHostname('nextcloud-aio-database'), // Allow to get local ip-address of caddy container and add it to trusted proxies automatically - 'CADDY_IP_ADDRESS' => in_array('caddy', $this->aioCommunityContainers, true) ? gethostbyname('nextcloud-aio-caddy') : '', + 'CADDY_IP_ADDRESS' => in_array('caddy', $this->aioCommunityContainers, true) ? DataConst::resolveHostname('nextcloud-aio-caddy') : '', 'WHITEBOARD_ENABLED' => $this->isWhiteboardEnabled ? 'yes' : '', 'AIO_VERSION' => $this->getAioVersion(), default => $this->getRegisteredSecret($placeholder), diff --git a/php/src/Data/DataConst.php b/php/src/Data/DataConst.php index 10d5342b349..0d4ff9c2843 100644 --- a/php/src/Data/DataConst.php +++ b/php/src/Data/DataConst.php @@ -71,4 +71,21 @@ public static function GetContainersDefinitionPath() : string { public static function GetAioVersionFile() : string { return (string)realpath(__DIR__ . '/../../templates/includes/aio-version.twig'); } + + /** + * Resolve a hostname to its IP address, trying IPv4 first and falling back + * to IPv6 (AAAA record) when no A record is found. Returns the hostname + * unchanged when neither record resolves successfully. + */ + public static function resolveHostname(string $hostname): string { + $ipv4 = gethostbyname($hostname); + if ($ipv4 !== $hostname) { + return $ipv4; + } + $records = dns_get_record($hostname, DNS_AAAA); + if (is_array($records) && isset($records[0]['ipv6']) && $records[0]['ipv6'] !== '') { + return $records[0]['ipv6']; + } + return $hostname; + } } diff --git a/php/src/Docker/DockerActionManager.php b/php/src/Docker/DockerActionManager.php index ca6a4d7206d..a98685b762b 100644 --- a/php/src/Docker/DockerActionManager.php +++ b/php/src/Docker/DockerActionManager.php @@ -449,7 +449,7 @@ public function CreateContainer(Container $container): void { // Special things for the jellyfin community container } elseif ($container->identifier === 'nextcloud-aio-jellyfin') { - $lldapIp = gethostbyname('nextcloud-aio-lldap'); + $lldapIp = DataConst::resolveHostname('nextcloud-aio-lldap'); if ($lldapIp !== 'nextcloud-aio-lldap') { $requestBody['HostConfig']['ExtraHosts'] = ['nextcloud-aio-lldap:' . $lldapIp]; }