diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py index 6b8875afb4..82a4e18c67 100755 --- a/synapse/app/homeserver.py +++ b/synapse/app/homeserver.py @@ -58,6 +58,7 @@ from twisted.internet import defer, reactor from twisted.web.resource import EncodingResourceWrapper, Resource from twisted.web.server import GzipEncoderFactory from twisted.web.static import File +from twisted.internet import error logger = logging.getLogger("synapse.app.homeserver") @@ -131,29 +132,36 @@ class SynapseHomeServer(HomeServer): if tls: for address in bind_addresses: - reactor.listenSSL( - port, - SynapseSite( - "synapse.access.https.%s" % (site_tag,), - site_tag, - listener_config, - root_resource, - ), - self.tls_server_context_factory, - interface=address - ) + try: + reactor.listenSSL( + port, + SynapseSite( + "synapse.access.https.%s" % (site_tag,), + site_tag, + listener_config, + root_resource, + ), + self.tls_server_context_factory, + interface=address + ) + except error.CannotListenError as e: + check_bind_error(e, address, bind_addresses) + else: for address in bind_addresses: - reactor.listenTCP( - port, - SynapseSite( - "synapse.access.http.%s" % (site_tag,), - site_tag, - listener_config, - root_resource, - ), - interface=address - ) + try: + reactor.listenTCP( + port, + SynapseSite( + "synapse.access.http.%s" % (site_tag,), + site_tag, + listener_config, + root_resource, + ), + interface=address + ) + except error.CannotListenError as e: + check_bind_error(e, address, bind_addresses) logger.info("Synapse now listening on port %d", port) def _configure_named_resource(self, name, compress=False): @@ -232,25 +240,31 @@ class SynapseHomeServer(HomeServer): bind_addresses = listener["bind_addresses"] for address in bind_addresses: - reactor.listenTCP( - listener["port"], - manhole( - username="matrix", - password="rabbithole", - globals={"hs": self}, - ), - interface=address - ) + try: + reactor.listenTCP( + listener["port"], + manhole( + username="matrix", + password="rabbithole", + globals={"hs": self}, + ), + interface=address + ) + except error.CannotListenError as e: + check_bind_error(e, address, bind_addresses) elif listener["type"] == "replication": bind_addresses = listener["bind_addresses"] for address in bind_addresses: - factory = ReplicationStreamProtocolFactory(self) - server_listener = reactor.listenTCP( - listener["port"], factory, interface=address - ) - reactor.addSystemEventTrigger( - "before", "shutdown", server_listener.stopListening, - ) + try: + factory = ReplicationStreamProtocolFactory(self) + server_listener = reactor.listenTCP( + listener["port"], factory, interface=address + ) + reactor.addSystemEventTrigger( + "before", "shutdown", server_listener.stopListening, + ) + except error.CannotListenError as e: + check_bind_error(e, address, bind_addresses) else: logger.warn("Unrecognized listener type: %s", listener["type"]) @@ -284,6 +298,13 @@ class SynapseHomeServer(HomeServer): return db_conn +def check_bind_error(e, address, bind_addresses): + if address == '0.0.0.0' and '::' in bind_addresses: + logger.warn('Failed to listen on 0.0.0.0, continuing because listening on [::]') + else: + raise e + + def setup(config_options): """ Args: diff --git a/synapse/config/server.py b/synapse/config/server.py index 9035fbf22d..436dd8a6fe 100644 --- a/synapse/config/server.py +++ b/synapse/config/server.py @@ -220,14 +220,12 @@ class ServerConfig(Config): port: %(bind_port)s # Local addresses to listen on. - # On Linux and Mac OS, this will listen on all IPv4 and IPv6 + # On Linux and Mac OS, `::` will listen on all IPv4 and IPv6 # addresses by default. For most other OSes, this will only listen # on IPv6. bind_addresses: - '::' - # For systems other than Linux or Mac OS, uncomment the next line - # to also listen on IPv4. - #- '0.0.0.0' + - '0.0.0.0' # This is a 'http' listener, allows us to specify 'resources'. type: http @@ -265,7 +263,7 @@ class ServerConfig(Config): # For when matrix traffic passes through loadbalancer that unwraps TLS. - port: %(unsecure_port)s tls: false - bind_addresses: ['::'] + bind_addresses: ['::', '0.0.0.0'] type: http x_forwarded: false