diff --git a/bin/get-translatable-strings b/bin/get-translatable-strings
index bc4a4f2e9f51cda02149cb4867fd5ed159fd69dc..adbb53c337a86e6964e30f53c895d4c7e8d52ae2 100755
--- a/bin/get-translatable-strings
+++ b/bin/get-translatable-strings
@@ -19,7 +19,7 @@ use SimpleSAML\Utils;
 use Symfony\Component\Filesystem\Filesystem;
 
 // This is the base directory of the SimpleSAMLphp installation
-$baseDir = dirname(dirname(__FILE__));
+$baseDir = dirname(__FILE__, 2);
 
 // Add library autoloader
 require_once($baseDir . '/src/_autoload.php');
diff --git a/bin/importPdoMetadata.php b/bin/importPdoMetadata.php
index 271152a73c7572f65408921c614dbd0eaa40589a..01c87b898899cd4e4a0583ed70dfd1de68139797 100755
--- a/bin/importPdoMetadata.php
+++ b/bin/importPdoMetadata.php
@@ -1,7 +1,7 @@
 #!/usr/bin/env php
 <?php
 
-$baseDir = dirname(dirname(__FILE__));
+$baseDir = dirname(__FILE__, 2);
 
 require_once $baseDir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . '_autoload.php';
 require_once \SimpleSAML\Utils\Config::getConfigDir() . DIRECTORY_SEPARATOR . 'config.php';
diff --git a/bin/initMDSPdo.php b/bin/initMDSPdo.php
index 79af70f12511f70cb1ecec289ccb4e310fa0579d..d8387b437d66556e902ac75b65103b93e2fc12c4 100755
--- a/bin/initMDSPdo.php
+++ b/bin/initMDSPdo.php
@@ -2,7 +2,7 @@
 <?php
 
 // This is the base directory of the SimpleSAMLphp installation
-$baseDir = dirname(dirname(__FILE__));
+$baseDir = dirname(__FILE__, 2);
 
 // Add library autoloader and configuration
 require_once $baseDir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . '_autoload.php';
diff --git a/bin/memcacheSync.php b/bin/memcacheSync.php
index 85bdbacfc2d85940c055f5c5708724a7d6dcc98e..bbdbcf2f6bd184c561be6d2dfe0531dea2bc011a 100755
--- a/bin/memcacheSync.php
+++ b/bin/memcacheSync.php
@@ -18,7 +18,7 @@ if (!class_exists('Memcache') && !class_exists('Memcached')) {
 }
 
 // This is the base directory of the SimpleSAMLphp installation
-$baseDir = dirname(dirname(__FILE__));
+$baseDir = dirname(__FILE__, 2);
 
 // Add library autoloader
 require_once($baseDir . '/src/_autoload.php');
diff --git a/bin/pwgen.php b/bin/pwgen.php
index 5980566bf4e06c1e27dc5261be33f2dcefeaa792..37f6c3482fecd2b3729d1b5fb3cd927f736553e9 100755
--- a/bin/pwgen.php
+++ b/bin/pwgen.php
@@ -7,7 +7,7 @@
  */
 
 // This is the base directory of the SimpleSAMLphp installation
-$baseDir = dirname(dirname(__FILE__));
+$baseDir = dirname(__FILE__, 2);
 
 // Add library autoloader
 require_once($baseDir . '/src/_autoload.php');
diff --git a/docs/simplesamlphp-install.md b/docs/simplesamlphp-install.md
index dcb6106b5082dfddc88b833a700e60729fc09351..9523b5aacacc32f0d4abf679f585aaea6f464b77 100644
--- a/docs/simplesamlphp-install.md
+++ b/docs/simplesamlphp-install.md
@@ -434,13 +434,13 @@ Now, we need to make a few configuration changes. First, let's edit `~/public_ht
 Change the two lines from:
 
 ```php
-require_once(dirname(dirname(__FILE__)) . '/lib/_autoload.php');
+require_once(dirname(_FILE__, 2) . '/lib/_autoload.php');
 ```
 
 to something like:
 
-```bash
-require_once(dirname(dirname(dirname(__FILE__))) . '/lib/_autoload.php');
+```php
+require_once(dirname(__FILE__, 3) . '/lib/_autoload.php');
 ```
 
 **Warning**: note that this will make upgrading SimpleSAMLphp much more difficult, since you will need to move the
diff --git a/modules/core/src/Controller/ErrorReport.php b/modules/core/src/Controller/ErrorReport.php
index b5cee781e886fdbc68ac91641cbd27e708bb3cf9..dabe55df84ed9dd960dff0f8a50eb68f0f5e247b 100644
--- a/modules/core/src/Controller/ErrorReport.php
+++ b/modules/core/src/Controller/ErrorReport.php
@@ -97,7 +97,7 @@ class ErrorReport
         $data['reportId'] = $reportId;
         $data['version'] = $this->config->getVersion();
         $data['hostname'] = php_uname('n');
-        $data['directory'] = dirname(dirname(__FILE__));
+        $data['directory'] = dirname(__FILE__, 2);
 
         if ($this->config->getOptionalBoolean('errorreporting', true)) {
             $mail = new Utils\EMail('SimpleSAMLphp error report from ' . $email);
diff --git a/modules/cron/bin/cron.php b/modules/cron/bin/cron.php
index b68bf8523a090bc670b99573164e4ad49aa19953..4049106d33fc5c6a34dc0a5aca2157b30ae0b372 100755
--- a/modules/cron/bin/cron.php
+++ b/modules/cron/bin/cron.php
@@ -8,7 +8,7 @@
  */
 
 // This is the base directory of the SimpleSAMLphp installation
-$baseDir = dirname(dirname(dirname(dirname(__FILE__))));
+$baseDir = dirname(__FILE__, 4);
 
 // Add library autoloader.
 require_once($baseDir . '/src/_autoload.php');
diff --git a/src/SimpleSAML/Configuration.php b/src/SimpleSAML/Configuration.php
index 83ce66e19e13bd8868fead2720eef85e452e6d52..050a96b2548d389b9b63a79c2cba46c7f2b99f31 100644
--- a/src/SimpleSAML/Configuration.php
+++ b/src/SimpleSAML/Configuration.php
@@ -229,7 +229,7 @@ class Configuration implements Utils\ClearableState
             if ($configSet !== 'simplesaml') {
                 throw new Exception('Configuration set \'' . $configSet . '\' not initialized.');
             } else {
-                self::$configDirs['simplesaml'] = dirname(dirname(dirname(__FILE__))) . '/config';
+                self::$configDirs['simplesaml'] = dirname(__FILE__, 3) . '/config';
             }
         }
 
diff --git a/src/SimpleSAML/Error/ConfigurationError.php b/src/SimpleSAML/Error/ConfigurationError.php
index bc0d9c261c130973c7c2e68ecb28317294e5fe73..531571c0bdd711f793a9416778c9aeb2df4dd639 100644
--- a/src/SimpleSAML/Error/ConfigurationError.php
+++ b/src/SimpleSAML/Error/ConfigurationError.php
@@ -41,7 +41,7 @@ class ConfigurationError extends Error
         $params = ['CONFIG'];
         if ($file !== null) {
             $params['%FILE%'] = $file;
-            $basepath = dirname(dirname(dirname(dirname(__FILE__)))) . '/';
+            $basepath = dirname(__FILE__, 4) . '/';
             $file_str = '(' . str_replace($basepath, '', $file) . ') ';
         }
         if ($reason !== null) {
diff --git a/src/SimpleSAML/Module.php b/src/SimpleSAML/Module.php
index 56130313d13e2156a382d2942ee7dd86b4566398..d3b5dc1950e0a1e437388a3e94654e4df9d0a535 100644
--- a/src/SimpleSAML/Module.php
+++ b/src/SimpleSAML/Module.php
@@ -124,7 +124,7 @@ class Module
      */
     public static function getModuleDir(string $module): string
     {
-        $baseDir = dirname(dirname(dirname(__FILE__))) . '/modules';
+        $baseDir = dirname(__FILE__, 3) . '/modules';
         $moduleDir = $baseDir . '/' . $module;
 
         return $moduleDir;
@@ -505,7 +505,7 @@ class Module
         }
 
         $hooks = [];
-        $hook_dir = Path::canonicalize(dirname(dirname(dirname(__FILE__))) . '/modules/' . $module . '/hooks');
+        $hook_dir = Path::canonicalize(dirname(__FILE__, 3) . '/modules/' . $module . '/hooks');
         if ((new Filesystem())->exists($hook_dir)) {
             $finder = new Finder();
             $finder->files()->in($hook_dir)->depth(0);
diff --git a/src/SimpleSAML/Utils/Config.php b/src/SimpleSAML/Utils/Config.php
index 567ad67de5be52706f4586a69a70484da3837b77..e965340954e0d0dae8e3f18c13fde4e95d1d9954 100644
--- a/src/SimpleSAML/Utils/Config.php
+++ b/src/SimpleSAML/Utils/Config.php
@@ -65,7 +65,7 @@ class Config
      */
     public function getConfigDir(): string
     {
-        $configDir = dirname(dirname(dirname(__DIR__))) . '/config';
+        $configDir = dirname(__DIR__, 3) . '/config';
         $configDirEnv = getenv('SIMPLESAMLPHP_CONFIG_DIR');
 
         if ($configDirEnv === false) {
diff --git a/tests/routers/configLoader.php b/tests/routers/configLoader.php
index 5fa2b8888535c5b0cd03908275f118cc7899187d..d9af3356528b984f728cc11c1204aa9828956314 100644
--- a/tests/routers/configLoader.php
+++ b/tests/routers/configLoader.php
@@ -35,7 +35,7 @@ use SimpleSAML\Configuration;
 include_once(sys_get_temp_dir() . '/' . getmypid() . '.lock');
 
 // load SimpleSAMLphp's autoloader
-require_once(dirname(dirname(dirname(__FILE__))) . '/vendor/autoload.php');
+require_once(dirname(__FILE__, 3) . '/vendor/autoload.php');
 
 // initialize configuration
 if (isset($config)) {
diff --git a/tests/src/SimpleSAML/ConfigurationTest.php b/tests/src/SimpleSAML/ConfigurationTest.php
index 719003bab2bf7dc90a12220fdc3b3c42ea06009b..013e4721eb141d59d30d214c453dddf944a236b1 100644
--- a/tests/src/SimpleSAML/ConfigurationTest.php
+++ b/tests/src/SimpleSAML/ConfigurationTest.php
@@ -234,7 +234,7 @@ class ConfigurationTest extends ClearStateTestCase
     public function testGetBaseDir(): void
     {
         $c = Configuration::loadFromArray([]);
-        $this->assertEquals($c->getBaseDir(), dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR);
+        $this->assertEquals($c->getBaseDir(), dirname(__FILE__, 4) . DIRECTORY_SEPARATOR);
 
         $c = Configuration::loadFromArray([
             'basedir' => DIRECTORY_SEPARATOR . 'basedir',
diff --git a/tests/src/SimpleSAML/ModuleTest.php b/tests/src/SimpleSAML/ModuleTest.php
index c5bb51e3cf96dd47216477e8abf03edddedb9664..19138c8381f1f36406384fd18f506fd00cfdad6b 100644
--- a/tests/src/SimpleSAML/ModuleTest.php
+++ b/tests/src/SimpleSAML/ModuleTest.php
@@ -32,7 +32,7 @@ class ModuleTest extends TestCase
     {
         // test for the most basic functionality
         $this->assertEquals(
-            Path::canonicalize(dirname(dirname(dirname(dirname(__FILE__)))) . '/modules/module'),
+            Path::canonicalize(dirname(__FILE__, 4) . '/modules/module'),
             Path::canonicalize(Module::getModuleDir('module')),
         );
     }
diff --git a/tests/src/SimpleSAML/Utils/ConfigTest.php b/tests/src/SimpleSAML/Utils/ConfigTest.php
index 2e75b09d6117a6d20b44e3aaab278e29590cf7e3..34cefef55e4177a52fd02185f6d572e7500cdb67 100644
--- a/tests/src/SimpleSAML/Utils/ConfigTest.php
+++ b/tests/src/SimpleSAML/Utils/ConfigTest.php
@@ -40,7 +40,7 @@ class ConfigTest extends TestCase
         putenv('SIMPLESAMLPHP_CONFIG_DIR');
         $configDir = $this->configUtils->getConfigDir();
 
-        $this->assertEquals($configDir, dirname(dirname(dirname(dirname(__DIR__)))) . '/config');
+        $this->assertEquals($configDir, dirname(__DIR__, 4) . '/config');
     }
 
 
diff --git a/tests/src/SimpleSAML/XHTML/TemplateTranslationTest.php b/tests/src/SimpleSAML/XHTML/TemplateTranslationTest.php
index 07089206fd36cd9006efb3db77d93ff40376f1fe..9637a3445b8bc13204e242e996b7e238ccb26cae 100644
--- a/tests/src/SimpleSAML/XHTML/TemplateTranslationTest.php
+++ b/tests/src/SimpleSAML/XHTML/TemplateTranslationTest.php
@@ -126,7 +126,7 @@ class TemplateTranslationTest extends TestCase
 
     public function testValidateTwigFiles(): void
     {
-        $root = dirname(dirname((dirname(dirname(__DIR__)))));
+        $root = dirname(__DIR__, 4);
 
         // Setup basic twig environment
         $loader = new FilesystemLoader(['templates', 'modules'], $root);
diff --git a/www/_include.php b/www/_include.php
index cf3f991291bdcdad3a9c01d56886aff9b80534c6..25eeb52a8eb88aaaab7fb6802a80d72b5cb7e43f 100644
--- a/www/_include.php
+++ b/www/_include.php
@@ -3,7 +3,7 @@
 declare(strict_types=1);
 
 // initialize the autoloader
-require_once(dirname(dirname(__FILE__)) . '/src/_autoload.php');
+require_once(dirname(__FILE__, 2) . '/src/_autoload.php');
 
 use SAML2\Compat\ContainerSingleton;
 use SimpleSAML\Compat\SspContainer;