Validate your .env files with Ghostable | Ghostable                           On this page

- [What you'll build](#what-youll-build)
- [Prerequisites](#prerequisites)
- [1. Define your validation schema](#define-schema)
- [2. Add rules for your framework](#framework-rules)
- [3. Validate locally before merging](#validate-locally)
- [4. Gate deploys in CI/CD](#ci-cd)
- [What not to do](#anti-patterns)
- [Why validation protects deploys](#deployment-benefits)
- [Next steps](#next-steps)

 Ghostable's validation keeps bad environment variables out of your deployments without ever uploading plaintext values or schema details. In this tutorial you'll define validation rules, run them locally, wire them into CI, and learn patterns that keep Laravel, Node/Next.js, Rails, and Django apps from shipping broken config.

What you'll build
-----------------

- A project-level schema in `.ghostable/schema.yaml` with sensible defaults.
- Environment overrides (e.g., production-only rules) in `.ghostable/schemas/.yaml`.
- A repeatable command: `ghostable env validate --env ` that fails fast when config drifts.
- A CI job that blocks merges/deploys when validation fails.

Prerequisites
-------------

- Ghostable CLI installed and authenticated (`ghostable login --token $GHOSTABLE_TOKEN`).
- A project initialized with `.ghostable/ghostable.yaml` so the CLI knows which project/environment to target.
- Local `.env` files for the environments you want to validate.
- Node.js available if you're running the CLI in CI (see GitHub Actions example below).

1. Define your validation schema
--------------------------------

All validation lives locally inside `.ghostable` (see the [validation docs](https://docs.ghostable.dev/v2/digging-deeper/validation)). Start with a global schema file and add per-environment overrides only when needed.

```yaml
.ghostable/
  ghostable.yaml
  schema.yaml           # global rules
  schemas/
    production.yaml     # env-specific overrides
    staging.yaml

```

Create `.ghostable/schema.yaml` with baseline rules that apply everywhere:

```yaml
APP_NAME:
  - required
  - string
  - max:64

APP_ENV:
  - required
  - in:local,staging,production

APP_DEBUG:
  - required
  - boolean

APP_URL:
  - required
  - url

LOG_CHANNEL:
  - required
  - in:stack,stdout

```

Add overrides for stricter environments (e.g., production):

```yaml
# .ghostable/schemas/production.yaml
APP_DEBUG:
  - required
  - boolean
  - in:false

APP_KEY:
  - required
  - starts_with:base64:
  - min:44

QUEUE_CONNECTION:
  - required
  - in:redis,sqs

```

Ghostable merges the global schema with the matching override file before validating your `.env`.

2. Add rules for your framework
-------------------------------

Here are practical rule sets you can drop into `schema.yaml`. Tweak names and allowed values to match your stack.

### Laravel

```yaml
APP_KEY:
  - required
  - starts_with:base64:
  - min:44

SESSION_DRIVER:
  - required
  - in:file,database,redis

CACHE_DRIVER:
  - required
  - in:file,redis,memcached,dynamodb

MAIL_MAILER:
  - required
  - in:smtp,log,mailgun,postmark,sendmail

DB_CONNECTION:
  - required
  - in:mysql,pgsql,sqlsrv,sqlite

```

### Next.js / Node

```yaml
NODE_ENV:
  - required
  - in:development,staging,production

NEXT_PUBLIC_API_URL:
  - required
  - url

DATABASE_URL:
  - required
  - regex:^postgres://

JWT_SECRET:
  - required
  - min:32
  - starts_with:sk_

```

### Django / Rails

```yaml
SECRET_KEY:
  - required
  - min:50

DJANGO_SETTINGS_MODULE:
  - required
  - ends_with:.settings

RAILS_ENV:
  - required
  - in:development,test,production

DATABASE_URL:
  - required
  - regex:^postgres://

ALLOWED_HOSTS:
  - required
  - string

```

Prefer `in:` for controlled enums, `starts_with`/`regex` for keys and URLs, and `required` everywhere you expect the app to boot.

3. Validate locally before merging
----------------------------------

Run validation against any environment. The CLI loads `schema.yaml`, merges the matching override, and compares against your resolved `.env` (you can pass `--file` for non-standard names).

```bash
ghostable env validate --env production
# or validate a custom file:
ghostable env validate --env staging --file .env.staging
```

Failures are human-readable and the command exits non-zero:

```bash
X APP_KEY must start with "base64:"
X APP_DEBUG must be "false"
! QUEUE_CONNECTION is set to sync (recommended: redis)
```

Fix values locally, rerun, and only push or deploy once validation passes.

4. Gate deploys in CI/CD
------------------------

Because validation happens locally ([zero-knowledge](https://ghostable.dev/learn/zero-knowledge-encryption)), it fits neatly into your pipeline. Here is a GitHub Actions job that blocks merges when validation fails:

```yaml
name: Validate env

on:
  pull_request:
  workflow_dispatch:

jobs:
  validate-env:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install @ghostable/cli@latest
      - name: Validate production schema
        env:
          GHOSTABLE_TOKEN: ${{ secrets.GHOSTABLE_TOKEN }}
        run: |
          ghostable login --token "$GHOSTABLE_TOKEN"
          ghostable env validate --env production

```

Apply the same pattern to deploy jobs so release pipelines fail fast when config drifts.

What not to do
--------------

- Don't copy real secrets into schema files or checked-in `.env` examples - keep schemas as contracts, not storage.
- Don't treat warnings as optional in production. Tighten `in:` lists or add overrides so prod rules are explicit.
- Don't skip validation for "small" changes. A single mistyped queue driver or URL can break deploys.
- Don't maintain divergent schemas per developer. Keep one shared `.ghostable` folder in version control.

Why validation protects deploys
-------------------------------

- **Prevents broken releases:** schema violations fail pipelines before code hits servers.
- **Codifies expectations:** rules document required keys and safe values across every environment.
- **Stops config drift:** pairing validation with `ghostable env push|pull` keeps remote and local envs aligned.
- **Safer rotations:** regex and `starts_with` checks catch half-rotated keys or wrong providers.

Next steps
----------

- Expand schemas with optional keys marked `nullable` to reduce noise while staying explicit.
- Add staging/preview overrides that mirror production (minus the strictest checks) to surface drift earlier.
- Continue with the [validation deep-dive](https://docs.ghostable.dev/v2/digging-deeper/validation) for full rule syntax and tips.

 Tags

 [  validation  ](https://ghostable.dev/learn/tag/validation) [  env-files  ](https://ghostable.dev/learn/tag/env-files) [  ci-cd  ](https://ghostable.dev/learn/tag/ci-cd) [  configuration  ](https://ghostable.dev/learn/tag/configuration)

 On this page

- [What you'll build](#what-youll-build)
- [Prerequisites](#prerequisites)
- [1. Define your validation schema](#define-schema)
- [2. Add rules for your framework](#framework-rules)
- [3. Validate locally before merging](#validate-locally)
- [4. Gate deploys in CI/CD](#ci-cd)
- [What not to do](#anti-patterns)
- [Why validation protects deploys](#deployment-benefits)
- [Next steps](#next-steps)

 [   Back to Learn ](https://ghostable.dev/learn) [ View validation docs ](https://docs.ghostable.dev/v2/digging-deeper/validation)

  Want product news and updates?
--------------------------------

 Sign up for our newsletter.

   Email Address

  Subscribe →    Subscribing...

We care about your data. Read our [privacy policy](https://ghostable.dev/privacy).
