diff --git a/docker-compose.yml b/docker-compose.yml
index e68ba8cc11e504af1411bf3aa95f4684e445656d..d997a5dca8139e8dc9310823b7a8b975afee966a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,14 +11,11 @@ services:
     build:
       context: .
     ports:
-      - ${port:-8080}:${port:-8080}
+      - ${REPDAV_PORT:-8080}:${REPDAV_PORT:-8080}
     environment:
-      host: ${host:-0.0.0.0}
-      port: ${port:-8080}
-      sentry_dsn: ${sentry_dsn}
-      tg_auth_wsdl: "https://textgridlab.org/1.0/tgauth/wsdl/tgextra.wsdl"
-      tg_auth_address: "https://textgridlab.org/1.0/tgauth/tgextra.php"
-      tg_nav_address: "https://textgridlab.org/1.0/tgsearch/navigation/"
-      tg_host: "https://textgridlab.org/"
+      REPDAV_HOST: ${REPDAV_HOST:-0.0.0.0}
+      REPDAV_PORT: ${REPDAV_PORT:-8080}
+      SENTRY_DSN: ${SENTRY_DSN}
+      TEXTGRID_HOST: ${TEXTGRID_HOST}
     volumes:
       - $PWD/src:/app
diff --git a/src/main.py b/src/main.py
index 1bd0276e17ec7206b897ea9d8e3a589317adc3ad..3bf7cd8d74c5afa3e07b2c6c66d06eb864a3b7c6 100644
--- a/src/main.py
+++ b/src/main.py
@@ -4,8 +4,6 @@
 
 """Configure and start the WSGI DAV Server."""
 import logging
-import os
-
 import sentry_sdk
 from cheroot import wsgi
 from wsgidav.wsgidav_app import WsgiDAVApp
@@ -14,13 +12,11 @@ from repdav.config import AppConfig
 app_config = AppConfig()
 
 if app_config.dsn:
-    sentry_sdk.init(
-        app_config.dsn,
-        traces_sample_rate=1.0
-    )
+    sentry_sdk.init(app_config.dsn, traces_sample_rate=1.0)
 
-logging.basicConfig(level=logging.DEBUG,
-                    format='%(name)s %(levelname)s %(asctime)s %(message)s')
+logging.basicConfig(
+    level=logging.DEBUG, format="%(name)s %(levelname)s %(asctime)s %(message)s"
+)
 _logger = logging.getLogger(__name__)
 _logger.propagate = True
 
@@ -31,12 +27,13 @@ tmp_logger.setLevel(logging.DEBUG)
 
 # Configuration of the WsgiDAVApp.
 # https://wsgidav.readthedocs.io/en/latest/user_guide_configure.html
-# TODO: move to config.py
 config = {
-    "host": os.getenv("host") or "localhost",
-    "port": int(os.getenv("port") or "8080"),
+    "host": app_config.host,
+    "port": app_config.port,
     "provider_mapping": {
-        "/": {"class": "repdav.textgrid_named_dav_provider.TextgridNamedResourceProvider"},
+        "/": {
+            "class": "repdav.textgrid_named_dav_provider.TextgridNamedResourceProvider"
+        },
     },
     "verbose": 4,
     "http_authenticator": {
@@ -47,7 +44,8 @@ config = {
         "default_to_digest": False,
         # Name of a header field that will be accepted as authorized user
         "trusted_auth_header": None,
-    }
+    },
+    "tg_host": app_config.tg_host,
 }
 
 app = WsgiDAVApp(config)
diff --git a/src/repdav/config.py b/src/repdav/config.py
index 1d5553fae4789f091489e0b3ea022e2c15d22ab4..b3329bff835776b27920ecf623db28404ef786c4 100644
--- a/src/repdav/config.py
+++ b/src/repdav/config.py
@@ -3,63 +3,51 @@
 # SPDX-License-Identifier: CC0-1.0
 
 import os
+from typing import Optional
+from urllib.parse import urlparse
 
-from .errors import EnvNotSetError
 
-# TODO: remove "tg_auth_wsdl", "tg_auth_address", "tg_nav_address"
+def check_url(url):
+    """Check if `url` can be parsed."""
+    if url:
+        result = urlparse(url)
+        if result.scheme and result.netloc:
+            return url
+        raise ValueError(f"{url} is not a valid URL.")
 
 
-def lookup_env_name(internal_name: str) -> str:
-    mapping = {
-        "_auth_wsdl": "tg_auth_wsdl",
-        "_auth_address": "tg_auth_address",
-        "_dsn": "sentry_dsn",
-        "_host": "tg_host",
-        "_nav_address": "tg_nav_address",
-    }
-    return mapping[internal_name]
+def check_port(port):
+    """Check if port is set correctly to a non-privileged value."""
+    if 1000 <= port <= 65535:
+        return port
+    raise ValueError(f"{port} is not a valid Port.")
 
 
-# TODO check for trailing "/", add if missing!
-# TODO check URLs for validity
-
 class AppConfig:
-    # TODO: configure the app according to the set environment (i.e. prod or dev)
-    def __init__(self) -> None:
-        self._dsn = os.getenv(lookup_env_name("_dsn"))
-
-    @property
-    def dsn(self) -> str:
-        return self._dsn
+    """Settings that can be be configured from the environment."""
 
-
-class TextgridConfig:
     def __init__(self) -> None:
-        self._auth_wsdl = os.getenv(lookup_env_name("_auth_wsdl"))
-        self._auth_address = os.getenv(lookup_env_name("_auth_address"))
-        self._nav_address = os.getenv(lookup_env_name("_nav_address"))
-        self._host = os.getenv(lookup_env_name("_host"))
+        self._dsn = check_url(os.getenv("SENTRY_DSN"))
+        self._host = os.getenv("REPDAV_HOST") or "localhost"
+        self._port = check_port(int(os.getenv("REPDAV_PORT") or 8080))
+        self._tg_host = check_url(os.getenv("TEXTGRID_HOST"))
 
     @property
-    def auth_wsdl(self) -> str:
-        if self._auth_wsdl:
-            return self._auth_wsdl
-        raise EnvNotSetError(lookup_env_name("_auth_wsdl"))
+    def dsn(self) -> Optional[str]:
+        """Sentry DSN."""
+        return self._dsn
 
     @property
-    def auth_address(self) -> str:
-        if self._auth_address:
-            return self._auth_address
-        raise EnvNotSetError(lookup_env_name("_auth_address"))
+    def host(self) -> str:
+        """Service hostname."""
+        return self._host
 
     @property
-    def nav_address(self) -> str:
-        if self._nav_address:
-            return self._nav_address
-        raise EnvNotSetError(lookup_env_name("_nav_address"))
+    def port(self) -> int:
+        """Service port."""
+        return self._port
 
     @property
-    def host(self) -> str:
-        if self._host:
-            return self._host
-        raise EnvNotSetError(lookup_env_name("_host"))
+    def tg_host(self) -> Optional[str]:
+        """Textgrid host URL."""
+        return self._tg_host
diff --git a/src/repdav/textgrid_dav_provider.py b/src/repdav/textgrid_dav_provider.py
index cbdf7861d23316598dff54860ed1a5e6f6e05e6e..cc8a89a58b2048a558f8ef15d895624a865a446a 100644
--- a/src/repdav/textgrid_dav_provider.py
+++ b/src/repdav/textgrid_dav_provider.py
@@ -21,6 +21,16 @@ from repdav.stream_tools import FileLikeQueue
 _logger = logging.getLogger(__name__)
 
 
+def tg_config(environ):
+    """Initialize Textgrid configuration either with or without host setting. This
+    works around an [issue with tgclients](https://gitlab.gwdg.de/dariah-de/textgridrep/textgrid-python-clients/-/issues/59).
+    """
+    tg_host = environ["wsgidav.config"]["tg_host"]
+    if tg_host:
+        return TextgridConfig(tg_host)
+    return TextgridConfig()
+
+
 class TextgridRoot(DAVCollection):
     """Top level collection that incorporates Textgrid projects.
 
@@ -30,8 +40,9 @@ class TextgridRoot(DAVCollection):
     def __init__(self, path, environ):
         DAVCollection.__init__(self, path, environ)
         self._sid = environ["wsgidav.auth.user_name"]
-        config = TextgridConfig()
+        config = tg_config(environ)
         self._auth = TextgridAuth(config)
+        self.projects = ()
 
     def get_display_info(self):
         return {"type": "Textgrid root collection"}
@@ -83,7 +94,7 @@ class TextgridProject(DAVCollection):
         _logger.debug("Called TextgridProject.__init__(self, %s, environ).", path)
         DAVCollection.__init__(self, path, environ)
         self._sid = environ["wsgidav.auth.user_name"]
-        config = TextgridConfig()
+        config = tg_config(environ)
         self._tgsearch = TextgridSearch(config.search)
         self._project_id = self.path.split("/")[-1]
 
@@ -175,7 +186,7 @@ class TextgridAggregation(DAVCollection):
         DAVCollection.__init__(self, path, environ)
         self._sid = environ["wsgidav.auth.user_name"]
         self._info = info
-        config = TextgridConfig()
+        config = tg_config(environ)
         self._tgsearch = TextgridSearch(config.search)
         self._tguri = self.path.split("/")[-1]
 
@@ -261,7 +272,7 @@ class TextgridResource(DAVNonCollection):
         self._tguri = self.path.split("/")[-1]
         self._info = info
         self.upload_thread = None
-        config = TextgridConfig()
+        config = tg_config(environ)
         self._crud = TextgridCRUD(config.crud)
 
     def get_content_length(self):
@@ -273,7 +284,9 @@ class TextgridResource(DAVNonCollection):
         return self._info[self.name]["format"]
 
     def get_content(self):
-        _logger.debug("Called TextgridResource.get_content(self) with path: %s", self.path)
+        _logger.debug(
+            "Called TextgridResource.get_content(self) with path: %s", self.path
+        )
         return io.BytesIO(self._crud.read_data(self._tguri, self._sid).content)
 
     def get_content_title(self):