---
title: Config & Settings
description: How Nibiru loads configuration from environment-specific INI files.
---

Nibiru's config layer is intentionally simple: parse a single `settings.<env>.ini` file at boot, expose it through a singleton, and let modules add their own INIs through the [Registry](/core/registry/).

## Environment selection

The `APPLICATION_ENV` environment variable picks which file to load:

| `APPLICATION_ENV` | File loaded |
|---|---|
| `development` (default) | `application/settings/config/settings.development.ini` |
| `staging` | `application/settings/config/settings.staging.ini` |
| `production` | `application/settings/config/settings.production.ini` |

```bash
export APPLICATION_ENV=production
./nibiru -mi production
```

If `APPLICATION_ENV` is unset, Nibiru defaults to `development`.

## Sections

A typical `settings.<env>.ini`:

```ini
[ENGINE]
templates    = "/../../application/view/templates/"
templates_c  = "/../../application/view/templates_c/"
cache        = "/../../application/view/cache/"
config_dir   = "/../../application/view/configs/"
caching      = false
debug        = true
error.controller = "error"

[AUTOLOADER]
iface.pos[]  = "users"
iface.pos[]  = "cms"
class.pos[]  = "users"
class.pos[]  = "cms"

[SETTINGS]
page.url            = "https://my-app.local"
navigation          = "/../../application/settings/config/navigation/main.json"
modules.path        = "/../../application/module/"
entries.per.page    = 25
smarty.css[]        = "/public/css/app.css"
smarty.js[]         = "/public/js/app.js"
timezone            = "Europe/Vienna"

[DATABASE]
driver    = "pdo"
hostname  = "localhost"
port      = 3306
username  = "nibiru"
password  = "secret"
basename  = "nibiru_dev"
encoding  = "utf8mb4"
is.active = true

[SECURITY]
password_hash = "change-me-at-once"

[GENERATOR]
database          = true
database.overwrite = true

[EMAIL]
host       = "smtp.example.com"
port       = 587
encryption = "tls"
username   = "noreply@example.com"
password   = "smtp-secret"
from       = "Nibiru <noreply@example.com>"

[NIBIRU_ROUTING]
; optional regex routes — see /core/routing/

[NIBIRU_SECURITY]
password_hash = "another-salt-for-AES_DECRYPT"
```

## Reading config

```php
$cfg = \Nibiru\Config::getInstance()->getConfig();
$cfg['DATABASE']['driver'];       // 'pdo'
$cfg['SETTINGS']['page.url'];     // 'https://my-app.local'
```

For deeply-nested configs use the typed constants from the View interface:

```php
$cfg[\Nibiru\View::NIBIRU_SETTINGS]['smarty.css'];   // ['/public/css/app.css']
```

## Module configs

Each module under `application/module/<name>/settings/` can carry its own INI files. The Registry picks them up automatically and exposes them through:

```php
$users = \Nibiru\Registry::getInstance()->loadModuleConfigByName('users');
$users->session_lifetime;        // from [USERS] section in users.ini
```

The Registry prefers `<module>.<env>.ini` over `<module>.ini`, so you get per-environment overrides for free.

## Secrets

INI files are *plain text*. Two production-safe options:

### A. Environment overlay

Keep `settings.production.ini` in version control with placeholders, and inject real values from environment variables at runtime:

```ini
[DATABASE]
password = "${DB_PASSWORD}"
```

Then expand them in your container/CI:

```bash
envsubst < settings.production.ini.tpl > settings.production.ini
```

### B. Out-of-tree config

Keep `settings.production.ini` outside the repo and symlink at deploy time:

```bash
ln -s /etc/nibiru/settings.production.ini \
      application/settings/config/settings.production.ini
```

The framework doesn't care where the file lives as long as `parse_ini_file` can read it.

## Reload semantics

Config is read **once** at boot, into the `Settings` static. Changes to the INI require a request cycle to take effect (or for long-running scripts, an explicit `Settings::setConfig(\Nibiru\Config::getEnv())` call).

## Common pitfalls

- **Path leading `/../../`.** The framework's INI paths are *relative to the framework directory*. They must start with `/../../` to escape into your project root. Yes, this looks weird; yes, it works.
- **Boolean parsing.** `parse_ini_file` is permissive — `true`, `on`, `1` all become `1`; `false`, `off`, `0`, `""` become `0`. Triple-quote strings if you really need a literal `"true"`.
- **Array values.** Use `[]` syntax (`smarty.css[] = …`) — Nibiru relies on these being arrays.
