---
title: The .env File Explained
description: "`.env` lives at `/var/www/rackhelm/.env` and holds the settings that have to exist before RackHelm can boot: how to reach the database, where the application lives, and your licence key. Everything else — company details, mail, payment gateways, integrations — is…"
url: "https://rackhelm.com/documentation/env-file-reference/"
updated: "2026-09-24"
category: "Installation & Server Setup"
---

# The .env File Explained

`.env` lives at `/var/www/rackhelm/.env` and holds the settings that have to exist before RackHelm can boot: how to reach the database, where the application lives, and your licence key. Everything else — company details, mail, payment gateways, integrations — is configured inside the admin area and stored in the database. This article explains the keys that matter and why a few of them are pinned to fixed values.

## Before you start

`.env` is owned `root:<web user>` with mode `640`, so you need root to edit it. That is deliberate: the file holds the application encryption key and the database password, and the PHP runtime user must not be able to rewrite its own configuration.

> **Warning:** Not every key below is present in `.env` to begin with. Adding a value by editing an existing line only works if that line is there — if it is not, append the key instead. And where a key appears twice, the **first** occurrence wins, so delete duplicates rather than adding another line at the bottom.

## Application

| Key | What it does |
| --- | --- |
| `APP_NAME` | Display name used by the framework. Largely cosmetic in RackHelm, because the admin's **Company Name** setting overrides `app.name` at runtime. See the warning about Redis prefixes below before changing it. |
| `APP_ENV` | `production` on any live install. It selects the Horizon worker profile (up to 10 processes in `production`, 3 in `local`). |
| `APP_KEY` | The application encryption key, in the form `base64:…`. Payment gateway configuration, server integration credentials, notification channel settings, e-mail route passwords and several stored settings are all encrypted with it. **Losing or rotating it makes those unrecoverable.** |
| `APP_DEBUG` | Must be `false` in production. `true` exposes the application key, database credentials and decrypted configuration on any unhandled exception. |
| `APP_URL` | The full public URL including scheme, for example `https://portal.example.com`. Three things depend on it: the host RackHelm will accept requests for, the root URL used to build links in e-mails, and whether links are generated as HTTPS. Get it wrong and every request returns `400 Bad Request`. |
| `ASSET_URL` | Base URL for compiled front-end assets. The installer sets it to the same value as `APP_URL` when the site is on HTTPS. |
| `APP_USE_HTTPS` | Written to `.env` by the installer on an HTTPS install, but nothing in the application reads it. What actually drives the behaviour is the scheme in `APP_URL` — if that starts with `https://`, generated URLs are forced to HTTPS. |
| `APP_LOCALE`, `APP_FALLBACK_LOCALE` | Language used for framework strings. Defaults to `en`. |
| `BCRYPT_ROUNDS` | Password hashing cost. `12` is the shipped value; raising it slows every login. |

> **Note:** The **Company URL** field under **Platform Settings → General & System** overrides `APP_URL` once the application has booted. If you change your portal's address, change it in both places or the two will disagree about which host is trusted.

## Database

| Key | What it does |
| --- | --- |
| `DB_CONNECTION` | `mysql` on any installer-built deployment. |
| `DB_HOST` | `127.0.0.1` for a local database, or the remote server's address. |
| `DB_PORT` | `3306` unless your database listens elsewhere. |
| `DB_DATABASE` | Database name. The installer creates `rackhelm`. |
| `DB_USERNAME` | Database user. The installer creates `rackhelm_user`. |
| `DB_PASSWORD` | That user's password. The installer generates 32 random characters and also writes it to `/root/.rackhelm-credentials`. |

## Cache, queue and session

| Key | What it does |
| --- | --- |
| `CACHE_STORE` | `redis` on an installer-built deployment. |
| `QUEUE_CONNECTION` | `redis`. Horizon only manages Redis queues, so changing this to `database` or `sync` stops background provisioning, invoicing and e-mail from running the way the platform expects. |
| `SESSION_DRIVER` | `redis`. Sessions are always encrypted and the cookie is always marked Secure, regardless of driver. |
| `SESSION_LIFETIME` | Idle minutes before a session expires. Default `120`. |
| `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`, `REDIS_CLIENT` | How to reach Redis. Defaults are `127.0.0.1`, `6379`, no password, `phpredis`. |
| `REDIS_QUEUE_RETRY_AFTER` | Seconds before a queued job is considered stalled and re-dispatched. Default `90`. It must be larger than the longest job timeout, or long-running provisioning jobs run twice. |

### Why REDIS_PREFIX and HORIZON_PREFIX are pinned

Laravel derives both Redis namespaces from `APP_NAME`: the cache and queue prefix defaults to a slug of the app name followed by `-database-`, and Horizon's prefix defaults to a slug followed by `_horizon:`. That means **renaming the application silently moves every Redis key**. Jobs already queued under the old prefix are never picked up again, cached data disappears, active sessions are invalidated, and Horizon loses sight of its own workers — with no error anywhere.

The installer therefore writes both prefixes literally:

```ini
REDIS_PREFIX=rackhelm-database-
HORIZON_PREFIX=rackhelm_horizon:
```

Once they are pinned, `APP_NAME` becomes a purely cosmetic value you can change freely.

> **Warning:** Do not change `REDIS_PREFIX` or `HORIZON_PREFIX` on a live install. If you must, drain the queue first — check the Horizon dashboard shows nothing pending — then change the value and restart the worker.

## Licensing

| Key | What it does |
| --- | --- |
| `RACKHELM_LICENSE_KEY` | Your licence key. Read from `.env` at runtime on every request that needs a fresh verdict, which is why configuration caching is not used on this platform. |
| `ORBI_LICENSE_KEY` | The pre-rename variable. Installs that predate the RackHelm rebrand still have it, and it is read as a fallback when `RACKHELM_LICENSE_KEY` is absent. New installs should use the new name; do not set both. |

See [Licensing and activation](/docs/licensing-and-activation/) for what the heartbeat sends and how offline grace behaves.

## Mail

The installer **deletes every `MAIL_` line** from `.env`, because RackHelm configures outgoing mail in the admin area instead: **Platform Settings → Mail Settings** stores `mail_type` (`smtp` or `sendmail`), host, port, encryption, username, password and the from address in the database, and those values override the framework's mail configuration on every boot. Editing `MAIL_HOST` in `.env` has no effect on a seeded install.

One related setting is worth knowing about: to trust an internal or self-signed SMTP relay, set the **CA bundle** path in the mail settings rather than disabling TLS verification. Disabling verification turns off both chain and hostname checks, and outgoing mail carries password-reset links.

## Logging

| Key | What it does |
| --- | --- |
| `LOG_CHANNEL` | `stack`, which fans out to the channels named in `LOG_STACK`. |
| `LOG_STACK` | `single` writes everything to `storage/logs/laravel.log`. Set it to `daily` for rotated files. |
| `LOG_LEVEL` | Minimum severity recorded. `debug` captures everything; `warning` or `error` is quieter on a busy install. |
| `LOG_DAILY_DAYS` | Retention for the `daily` channel. Default `14`. |

## Optional keys

| Key | What it does |
| --- | --- |
| `HORIZON_PATH` | URI path for the Horizon dashboard. Default `horizon`. |
| `HORIZON_DOMAIN` | Serve Horizon from a separate subdomain instead of the portal's own. |
| `CSP_CONNECT_SRC`, `CSP_SCRIPT_SRC`, `CSP_STYLE_SRC`, `CSP_IMG_SRC`, `CSP_FRAME_SRC`, `CSP_DEFAULT_SRC` | Extra sources merged into the Content Security Policy, space- or comma-separated. Use these when your install fronts a host the portal cannot discover on its own, for example `CSP_CONNECT_SRC="wss://node1.example.com:8080 https://node1.example.com:8080"`. |
| `FILESYSTEM_DISK` | `local` stores private files under `storage/app/private`; the `public` disk under `storage/app/public` is what `storage:link` exposes. |
| `IMPORT_CLIENTEXEC_ALLOW_PRIVATE` | Allows the ClientExec importer to connect to private or internal database hosts. Off by default as an SSRF guard; turn it on only for the duration of an import. |
| `QUEUE_FAILED_DRIVER` | Where failed jobs are recorded. Default `database-uuids`, which populates the `failed_jobs` table. |

## Applying a change

RackHelm does not use a cached configuration file, so an edit to `.env` takes effect on the next web request. Background workers are long-lived, though, and hold the values they booted with — restart them after any change:

```bash
cd /var/www/rackhelm
sudo -u www-data php artisan horizon:terminate
```

> **Warning:** Never run `php artisan config:cache` on this platform. It freezes the licence key at the moment of caching, and a key set or changed afterwards is then ignored.

## Troubleshooting

| Symptom | Cause and fix |
| --- | --- |
| `400 Bad Request` on every page, nothing in the log | `APP_URL`'s host does not match the hostname being requested. Only that host is trusted. |
| Queued jobs pile up and never run after a rename | `APP_NAME` was changed while the Redis prefixes were not pinned, so the workers are now watching different keys. Restore the old prefix, let the queue drain, then pin both values. |
| Payment gateways and integrations report bad credentials after a restore | `APP_KEY` does not match the one those rows were encrypted with. Restore the original key from your backup. |
| Changing `MAIL_HOST` in `.env` does nothing | Mail is configured in **Platform Settings → Mail Settings** and the database values win. |
| A change to `.env` applies to the site but not to queued work | Horizon is still running with the old environment. Run `php artisan horizon:terminate`. |
