diff --git a/app/Config/Paths.php b/app/Config/Paths.php index 3dc9c5d93951..61010e10355a 100644 --- a/app/Config/Paths.php +++ b/app/Config/Paths.php @@ -75,4 +75,16 @@ class Paths * is used when no value is provided to `Services::renderer()`. */ public string $viewDirectory = __DIR__ . '/../Views'; + + /** + * --------------------------------------------------------------- + * ENVIRONMENT DIRECTORY NAME + * --------------------------------------------------------------- + * + * This variable must contain the name of the directory where + * the .env file is located. + * Please consider security implications when changing this + * value - the directory should not be publicly accessible. + */ + public string $envDirectory = __DIR__ . '/../../'; } diff --git a/system/Boot.php b/system/Boot.php index ba3675516b16..5b228664146f 100644 --- a/system/Boot.php +++ b/system/Boot.php @@ -170,7 +170,8 @@ public static function preload(Paths $paths): void protected static function loadDotEnv(Paths $paths): void { require_once $paths->systemDirectory . '/Config/DotEnv.php'; - (new DotEnv($paths->appDirectory . '/../'))->load(); + $envDirectory = $paths->envDirectory ?? $paths->appDirectory . '/../'; + (new DotEnv($envDirectory))->load(); } protected static function defineEnvironment(): void diff --git a/system/Commands/Encryption/GenerateKey.php b/system/Commands/Encryption/GenerateKey.php index a3fdbd4393a9..b34b422f7bfe 100644 --- a/system/Commands/Encryption/GenerateKey.php +++ b/system/Commands/Encryption/GenerateKey.php @@ -17,6 +17,7 @@ use CodeIgniter\CLI\CLI; use CodeIgniter\Config\DotEnv; use CodeIgniter\Encryption\Encryption; +use Config\Paths; /** * Generates a new encryption key. @@ -101,7 +102,7 @@ public function run(array $params) // force DotEnv to reload the new env vars putenv('encryption.key'); unset($_ENV['encryption.key'], $_SERVER['encryption.key']); - $dotenv = new DotEnv(ROOTPATH); + $dotenv = new DotEnv((new Paths())->envDirectory ?? ROOTPATH); $dotenv->load(); CLI::write('Application\'s new encryption key was successfully set.', 'green'); @@ -155,7 +156,7 @@ protected function confirmOverwrite(array $params): bool protected function writeNewEncryptionKeyToFile(string $oldKey, string $newKey): bool { $baseEnv = ROOTPATH . 'env'; - $envFile = ROOTPATH . '.env'; + $envFile = ((new Paths())->envDirectory ?? ROOTPATH) . '.env'; if (! is_file($envFile)) { if (! is_file($baseEnv)) { diff --git a/system/Commands/Utilities/Environment.php b/system/Commands/Utilities/Environment.php index 22794fe9d51d..99a90415ceea 100644 --- a/system/Commands/Utilities/Environment.php +++ b/system/Commands/Utilities/Environment.php @@ -16,6 +16,7 @@ use CodeIgniter\CLI\BaseCommand; use CodeIgniter\CLI\CLI; use CodeIgniter\Config\DotEnv; +use Config\Paths; /** * Command to display the current environment, @@ -119,7 +120,7 @@ public function run(array $params) // however we cannot redefine the ENVIRONMENT constant putenv('CI_ENVIRONMENT'); unset($_ENV['CI_ENVIRONMENT'], $_SERVER['CI_ENVIRONMENT']); - (new DotEnv(ROOTPATH))->load(); + (new DotEnv((new Paths())->envDirectory ?? ROOTPATH))->load(); CLI::write(sprintf('Environment is successfully changed to "%s".', $env), 'green'); CLI::write('The ENVIRONMENT constant will be changed in the next script execution.'); @@ -134,7 +135,7 @@ public function run(array $params) private function writeNewEnvironmentToEnvFile(string $newEnv): bool { $baseEnv = ROOTPATH . 'env'; - $envFile = ROOTPATH . '.env'; + $envFile = ((new Paths())->envDirectory ?? ROOTPATH) . '.env'; if (! is_file($envFile)) { if (! is_file($baseEnv)) { diff --git a/user_guide_src/source/changelogs/v4.7.0.rst b/user_guide_src/source/changelogs/v4.7.0.rst index c3d9cd1d5c12..843f1f393533 100644 --- a/user_guide_src/source/changelogs/v4.7.0.rst +++ b/user_guide_src/source/changelogs/v4.7.0.rst @@ -101,6 +101,7 @@ Changes - **Cookie:** The ``CookieInterface::EXPIRES_FORMAT`` has been changed to ``D, d M Y H:i:s \G\M\T`` to follow the recommended format in RFC 7231. - **Format:** Added support for configuring ``json_encode()`` maximum depth via ``Config\Format::$jsonEncodeDepth``. +- **Paths:** Added support for changing the location of the ``.env`` file via the ``Paths::$envDirectory`` property. ************ Deprecations diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index 35a30153d034..5e71840a98bf 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -97,3 +97,25 @@ of those: .. literalinclude:: managing_apps/004.php Only when you change the Application Directory, see :ref:`renaming-app-directory` and modify the paths in the **index.php** and **spark**. + +Changing the Location of the .env File +====================================== + +If necessary, you can change the location of the ``.env`` file by adjusting the ``$envDirectory`` +property in ``app/Config/Paths.php``. + +By default, the framework loads environment settings from a ``.env`` file located one level above +the ``app/`` directory (in the ``ROOTPATH``). This is a safe location when your domain is correctly +pointed to the ``public/`` directory, as recommended. + +In practice, however, some applications are served from a subdirectory (e.g., ``http://example.com/myapp``) +rather than from the main domain. In such cases, placing the ``.env`` file within the ``ROOTPATH`` may expose +sensitive configuration data if ``.htaccess`` or other protections are misconfigured. + +To avoid this risk in such setups, it is recommended that you ensure the ``.env`` file is located outside any web-accessible directories. + +.. warning:: + + If you change the location of the ``.env`` file, make absolutely sure it is not publicly accessible. + Exposure of this file could lead to compromised credentials and access to critical services, such as your + database, mail server, or third-party APIs.