DevOps & CI/CD Pipelines

Environment Variables & Secrets Management for Web Apps

By Domain India Team · DomainIndia SupportPublished 8 min read
Knowledge base article
Contents (10 sections)

Most leaked API keys are not stolen by clever attacks. They are committed to a Git repository by accident, copied into a screenshot, or left in a web-readable file. This guide shows how to keep database passwords, payment gateway keys and other secrets out of your code with environment variables and .env files, for PHP and Node.js, and where to put them on shared hosting, a VPS and the App Platform.

Key takeaways

Keep every secret out of your code: read it from an environment variable, keep local values in a .env file that is listed in .gitignore, and commit only a .env.example with empty values. On the server, keep the real .env outside the web root with permissions 600, or use the platform's own environment variable settings. If a secret is ever committed or exposed, revoke it at the provider first, then deploy a new one.

1. Why configuration belongs in the environment

The idea comes from the Twelve-Factor App: anything that changes between your laptop, staging and production, such as database details, API keys and URLs, lives in the environment, not in the code. The same code then runs everywhere, and a copy of the repository reveals nothing.

Automated scanners search public repositories constantly for strings that look like cloud, payment and email API keys. A key pushed to a public repository can be found and abused within minutes, and deleting the commit later does not undo the exposure.

2. The .env file pattern

A .env file is plain text with one KEY=value per line:

bash
APP_ENV=production
APP_URL=https://yourbusiness.in
DB_HOST=localhost
DB_NAME=shop_prod
DB_USER=shop_user
DB_PASSWORD=change-me
RAZORPAY_KEY_SECRET=change-me

Two rules make it safe:

  1. Never commit the real file. Add these lines to .gitignore before your first commit:
text
.env
.env.*
!.env.example
  1. Commit a .env.example instead, with the same keys and empty or dummy values, so a new developer knows what to set.

Check that Git really ignores it with git check-ignore -v .env. If it prints nothing, the file is not ignored.

3. Reading variables in PHP

The common library is vlucas/phpdotenv:

bash
composer require vlucas/phpdotenv
php
<?php
require __DIR__ . '/vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASSWORD']);

$dbPassword = $_ENV['DB_PASSWORD'];

required() stops the app with a clear error if a variable is missing, instead of failing later in a confusing way. Read values from $_ENV; the default loader does not fill getenv().

Laravel loads .env for you. Call env() only inside the files in config/, and read values elsewhere with config(). After php artisan config:cache, env() calls outside config/ return null.

4. Reading variables in Node.js

Node.js 20.6 and later can load a .env file itself:

bash
node --env-file=.env server.js

On any version, the dotenv package does the same:

javascript
import 'dotenv/config';            // or: require('dotenv').config();

const required = ['DB_PASSWORD', 'RAZORPAY_KEY_SECRET'];
const missing = required.filter((k) => !process.env[k]);
if (missing.length) {
  console.error(`Missing environment variables: ${missing.join(', ')}`);
  process.exit(1);
}

Frameworks such as Next.js read .env files on their own. In Next.js, only variables prefixed NEXT_PUBLIC_ reach the browser, so never give a secret that prefix. The same applies to any front-end build: a value bundled into browser JavaScript is public.

5. Where production secrets live

Where your app runsPut secrets inNotes
Shared hosting, PHP siteA .env file one level above public_htmlPermissions 600; see the note below on Composer
Shared hosting, Node.js or Python appThe app's Environment variables section in the panelSave, then restart the app
Your own VPS, systemd serviceAn EnvironmentFile= owned by root, mode 600systemctl daemon-reload and restart after changes
Your own VPS, Docker--env-file or env_file: in ComposeNever bake secrets into the image
Domain India App PlatformThe app's Env Vars tabValues are encrypted at rest and masked

Keep .env out of the web root. If a .env sits inside public_html, anyone may be able to download it by typing its address. Put it one level up and point your loader there, for example Dotenv::createImmutable(dirname(__DIR__)). If your framework must live inside public_html, block the file in .htaccess:

apache
<Files ".env">
    Require all denied
</Files>

Then set permissions to 600 in File Manager or with chmod 600 .env, and open https://yourbusiness.in/.env in a browser to confirm it is refused.

On a VPS with systemd:

ini
# /etc/systemd/system/myapp.service
[Service]
EnvironmentFile=/etc/myapp/myapp.env
ExecStart=/usr/bin/node /srv/myapp/server.js

6. Secrets in CI/CD

Never write a secret into a workflow file. In GitHub, add it under Settings › Secrets and variables › Actions and reference it by name:

yaml
- name: Deploy
  env:
    SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
  run: ./deploy.sh

GitHub masks secret values in logs, but a script that prints or transforms them can still leak them, so don't echo secrets in build steps. For a full pipeline to a server you manage, see GitHub Actions CI/CD to a VPS.

7. What is a secret, and what is just config

Kind of valueWhere it belongsExample
Passwords, API keys, tokens, signing keysEnvironment variable or secret storeDB_PASSWORD, RAZORPAY_KEY_SECRET
Per-environment settingsEnvironment variableAPP_URL, APP_ENV
Feature switchesEnvironment variable or a config fileFEATURE_NEW_CHECKOUT=true
Non-sensitive constantsA committed config filepage size, default language

A useful test: if you would be uncomfortable seeing the value in a public screenshot, it is a secret.

8. Rotating secrets and handling a leak

Rotate a secret when someone who knew it leaves, when a device or laptop is lost, and whenever you suspect exposure. Rotate without downtime in this order: create the new value at the provider, deploy it, confirm the app works, and only then revoke the old one.

Committed a secret by mistake? Revoke it first

1. Revoke or rotate the secret at the provider immediately, before anything else. The damage is the live key, not the Git history.
2. Check the provider's logs for use you don't recognise since the commit.
3. Deploy the new value.
4. Clean the history with git filter-repo if you want, but assume anyone who cloned or saw the repository already has the old value.

To catch mistakes early, run a scanner such as gitleaks as a pre-commit hook or in CI, and use trufflehog to audit a repository's full history. On GitHub, secret scanning and push protection block many known key formats before they are pushed.

9. Running this on Domain India

  • Shared hosting (cPanel, DirectAdmin): Composer cannot run on our shared servers, so run composer install on your own computer or in CI and upload the project with its vendor/ folder. Keep .env above public_html. For Node.js and Python apps, use the panel's app page: see deploying a Node.js app and deploying a Python app. Jailed SSH is available on every shared plan; it is off by default, so ask support to enable it.
  • App Platform: set secrets in the app's Env Vars tab; see App Platform environment variables.
  • VPS: you manage the server, so use systemd EnvironmentFile, Docker env files or a secret manager as above.
App Starter
₹100/mo + GST
  • 512 MB RAM per app
  • 1 vCPU
  • 5 GB NVMe SSD
  • PostgreSQL Database
See plan details

Prices on the cards exclude 18% GST.

Frequently asked questions

Is a .env file encrypted?

No. A .env file is plain text. It is protected only by keeping it out of Git, out of the web root and readable by your own user alone, with permissions 600. For encryption at rest, use a platform's secret settings or a dedicated secret manager.

Should I commit .env.example?

Yes. Commit .env.example with the same keys and empty or dummy values, so others know what to set. Never commit .env, .env.production or any file with real values.

Where should I put the .env file on shared hosting?

One level above public_html, so it can't be downloaded over the web, with permissions 600. If it must be inside public_html, deny access to it in .htaccess and test that https://yourdomain/.env is refused.

Can I use Composer to install phpdotenv on Domain India shared hosting?

Not on the server. Composer cannot run on Domain India shared hosting, so run composer install on your own computer or in CI and upload the project together with its vendor folder.

How do I set environment variables for a Node.js app on cPanel?

Open your app in the panel's Node.js app page and add them in the Environment variables section, then save and restart the app. Read them in your code with process.env.

I pushed an API key to GitHub. What do I do first?

Revoke or rotate the key at the provider immediately, then check the provider's logs for misuse and deploy the new key. Rewriting Git history is optional and does not help if anyone already copied the repository.

Is it safe to log environment variables while debugging?

Not all of them. Never print the whole environment, because logs are often kept and read by more people and tools than you expect. Log only the specific non-sensitive values you need.

Ready to deploy with your secrets kept safe? Look at the App Platform for apps with built-in environment variables, cPanel hosting for PHP sites, or a VPS for full control.

Deploy your app on Domain India

Set your app's secrets in the dashboard, encrypted at rest and masked on screen, and deploy without putting keys in your code.

See the App Platform

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app