How to use environment variables and dotenv for credentials in WP in WordPress

Contents

Why use environment variables and dotenv for credentials in WordPress

Using environment variables (env vars) or a dotenv (.env) file to store credentials and configuration for WordPress separates secrets from code, reduces the risk of accidentally committing passwords to a VCS, allows different values per environment (development, staging, production), and simplifies automated deployments. Environment-based configuration is a best practice for 12-factor apps and applies to WordPress as well.

High-level approaches

  • System environment variables: Set variables at the OS, web server, PHP-FPM, container, or hosting provider level and read them from PHP using getenv(), _ENV or _SERVER.
  • .env files with a loader (dotenv): Keep a local .env file (ignored by Git) and load into the process environment at runtime with a library (commonly vlucas/phpdotenv) before WP uses the values.
  • Secret managers: Use cloud secret managers (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager) and inject secrets into env vars at deploy time or fetch them at runtime.

Security and operational considerations

  • Never commit .env files to your repository. Add .env to .gitignore and maintain a .env.example with keys but no secrets.
  • Place .env outside the webroot when possible (for example, if WordPress is in /var/www/html, place .env in /var/www and load it from wp-config.php). If it must be in the webroot, protect it with server config (.htaccess deny or nginx rules) so it cannot be served.
  • Restrict file permissions and ownership. Typical permissions: 640 or 600 for .env and ownership by the deploy user or the PHP user as appropriate.
  • Do not echo secrets to logs or error screens. Use safe logging and only show debug info in development.
  • Rotate credentials periodically and have a mechanism to update env vars in hosted environments (CI/CD, deploy scripts, secret manager integration).
  • Use HTTPS for external secret fetching and authenticated access for secret stores.

Which WordPress items to put in environment variables

Typical items stored in environment variables include:

  • Database credentials: DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_CHARSET, DB_COLLATE
  • Authentication unique keys and salts
  • WP_DEBUG, WP_ENV or WP_STAGE, WP_HOME, WP_SITEURL
  • API keys (payment gateways, third-party services)
  • File storage credentials (S3 keys), SMTP credentials, etc.

Installing and using vlucas/phpdotenv (recommended loader)

vlucas/phpdotenv is a widely used package for loading .env files into the process environment. Use Composer to add it to your project and load the autoloader early in wp-config.php before WordPress constants are defined.

Install with Composer

composer require vlucas/phpdotenv

Example .env file (store outside VCS)

# .env (do NOT commit)
DB_NAME=wordpress_db
DB_USER=wp_user
DB_PASSWORD=S3cur3P@ssw0rd
DB_HOST=127.0.0.1
WP_ENV=development
WP_DEBUG=true
WP_HOME=https://example.local
WP_SITEURL=https://example.local/wp
AUTH_KEY=put-your-long-random-string-here
SECURE_AUTH_KEY=...
LOGGED_IN_KEY=...
NONCE_KEY=...
# other secrets such as API keys
STRIPE_KEY=sk_live_...

Basic wp-config.php bootstrap to load .env with vlucas/phpdotenv

Place this at the top of wp-config.php as early as possible (before defining DB constants and before requiring wp-settings.php).

safeLoad() // or dotenv->load() to require the file
    } catch (Exception e) {
        // Optionally handle the exception in deployment environments
        // For production you might prefer not to display errors
    }
}

// Helper to get env var with fallback
function env(key, default = null) {
    value = getenv(key)
    if (value === false) {
        if (isset(_SERVER[key])) {
            value = _SERVER[key]
        } elseif (isset(_ENV[key])) {
            value = _ENV[key]
        } else {
            value = default
        }
    }
    return value
}

// Define database constants from environment variables with fallbacks
define(DB_NAME, env(DB_NAME, database_name_here))
define(DB_USER, env(DB_USER, username_here))
define(DB_PASSWORD, env(DB_PASSWORD, password_here))
define(DB_HOST, env(DB_HOST, localhost))
define(DB_CHARSET, env(DB_CHARSET, utf8))
define(DB_COLLATE, env(DB_COLLATE, ))

// Authentication unique keys and salts
define(AUTH_KEY, env(AUTH_KEY, put your unique phrase here))
define(SECURE_AUTH_KEY, env(SECURE_AUTH_KEY, put your unique phrase here))
define(LOGGED_IN_KEY, env(LOGGED_IN_KEY, put your unique phrase here))
define(NONCE_KEY, env(NONCE_KEY, put your unique phrase here))
define(AUTH_SALT, env(AUTH_SALT, put your unique phrase here))
define(SECURE_AUTH_SALT, env(SECURE_AUTH_SALT, put your unique phrase here))
define(LOGGED_IN_SALT, env(LOGGED_IN_SALT, put your unique phrase here))
define(NONCE_SALT, env(NONCE_SALT, put your unique phrase here))

// Site URLs and environment
define(WP_HOME, env(WP_HOME, http://example.com))
define(WP_SITEURL, env(WP_SITEURL, http://example.com/wp))
define(WP_ENV, env(WP_ENV, production))
define(WP_DEBUG, filter_var(env(WP_DEBUG, false), FILTER_VALIDATE_BOOLEAN))

// Proceed with the rest of wp-config.php...

Advanced dotenv usage and multiple environment files

Common pattern: keep a .env.example in source control with keys but without secrets have per-environment files like .env.development or .env.production. Load files conditionally:

safeLoad()

Where to place .env (practical tips)

  • Outside webroot, e.g. if site is at /var/www/html, place .env in /var/www and create code in wp-config.php to load it via Dotenv::createImmutable(/var/www).
  • If hosting provider (e.g., managed WordPress) supports defining environment variables in the dashboard, prefer that over a .env file.
  • In containers, use Docker secrets or pass env vars via docker-compose or Kubernetes secrets (see examples below).

Examples for different hosting/deployment environments

Docker / docker-compose example

docker-compose with .env file or environment: use an env_file or environment section and ensure wp-config.php loads env vars.

version: 3.8
services:
  wordpress:
    image: wordpress:php8.1-fpm
    env_file:
      - .env
    volumes:
      - ./html:/var/www/html
    depends_on:
      - db
  db:
    image: mariadb:10.6
    environment:
      MYSQL_DATABASE: {DB_NAME}
      MYSQL_USER: {DB_USER}
      MYSQL_PASSWORD: {DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: {MYSQL_ROOT_PASSWORD}
# Dockerfile snippet (example)
FROM php:8.1-fpm
WORKDIR /var/www/html
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
COPY . /var/www/html
RUN composer install --no-dev --prefer-dist --no-interaction

PHP-FPM / systemd: ensure PHP sees environment variables

By default, PHP-FPM clears the environment for security (clear_env = yes). To pass environment variables to PHP-FPM, add env[] entries in the pool config (www.conf) or set clear_env = no and ensure the required variables are exported in the system environment (e.g., via systemd service drop-in).

 /etc/php/8.1/fpm/pool.d/www.conf
clear_env = no
env[DB_NAME] = wordpress_db
env[DB_USER] = wp_user
env[DB_PASSWORD] = S3cur3P@ssw0rd

Or in systemd, create an override file to set environment variables for php-fpm:

# /etc/systemd/system/php8.1-fpm.service.d/env.conf
[Service]
Environment=DB_NAME=wordpress_db DB_USER=wp_user DB_PASSWORD=S3cur3P@ssw0rd
# Then reload and restart: systemctl daemon-reload  systemctl restart php8.1-fpm

Apache example

Use SetEnv in your VirtualHost (not in .htaccess by default) so PHPs getenv() can read it when mod_php is used or when PHP-FPM picks it up via mod_proxy_fcgi depending on configuration.


    ServerName example.com
    DocumentRoot /var/www/html

    SetEnv DB_NAME wordpress_db
    SetEnv DB_USER wp_user
    SetEnv DB_PASSWORD S3cur3P@ssw0rd

Nginx PHP-FPM (fastcgi) example

When using php-fpm behind nginx, you typically set env vars in php-fpm pool config or systemd as shown above. You can also pass custom fastcgi_param values to the PHP process, but fastcgi_param only sets FastCGI variables, not environment variables by default. In php-fpm config, ensure clear_env is set properly.

server {
    listen 80
    server_name example.com
    root /var/www/html

    location ~ .php {
        fastcgi_pass unix:/run/php/php8.1-fpm.sock
        include fastcgi_params
        fastcgi_param SCRIPT_FILENAME document_rootfastcgi_script_name
        # fastcgi_param can add values to _SERVER but not always to getenv()
        fastcgi_param WP_ENV production
    }
}

Using system secret managers and CI/CD

  • In CI/CD pipelines, inject env vars from your secret store into the build/deploy environment (GitHub Actions secrets, GitLab CI variables, CircleCI env vars). Do not write secrets to logs or files that may be archived.
  • On cloud hosts, use platform-specific methods to set env vars (Heroku config vars, AWS ECS task definitions environment variables or secrets, Kubernetes secrets mounted as env or files).
  • If using Kubernetes, mount secrets as environment variables or files and ensure your wp-config.php loads from the correct path. Prefer mounting secrets as files with restrictive permissions or use tools like External Secrets to sync secrets from a manager.

WP-CLI and environment variables

WP-CLI inherits environment variables from the shell that runs it. For local development, you can run:

export DB_NAME=wordpress_db
export DB_USER=wp_user
export DB_PASSWORD=S3cur3P@ssw0rd
wp core install --url=https://example.local --title=Example --admin_user=admin --admin_password=adminpass --admin_email=you@example.com

Alternatively, set a .wp-cli/config.yml file for non-secret settings and rely on env vars for secrets.

Generating and storing WP salts securely

WordPress salts should be long random strings. You can generate them using the WordPress secret-key service and place them in .env or set them as environment variables in your host/CI:

# Generate keys (example: curl to the WP secret-key service)
curl -s https://api.wordpress.org/secret-key/1.1/salt/

Store the returned constants as environment variables on your server or in .env, then reference them in wp-config.php as shown earlier. Avoid exposing salts publicly.

Troubleshooting and common pitfalls

  • Autoload path wrong: If vendor/autoload.php isnt found, Composer may be installed in a parent directory or not run. Ensure Composer install is executed in the correct path and require is correct in wp-config.php.
  • Loading dotenv too late: WordPress bootstraps after wp-config.php. If you load env vars after constants are already defined, changes wont apply. Load dotenv at the top of wp-config.php before any define() calls for DB constant values.
  • clear_env in PHP-FPM: If environment variables arent visible in PHP, check php-fpm pool config clear_env setting and ensure env[] or systemd Environment is configured for the PHP-FPM process.
  • variables_order and _ENV: PHPs variables_order configuration affects whether _ENV is populated. getenv() tends to be more reliable for env vars, but phpdotenv also populates _ENV and _SERVER if configured.
  • Defining constants twice: WordPress will throw notices or ignore redefinitions. Use defined(DB_NAME) checks or load envs before any definitions.
  • Accidentally committed .env: If you commit secrets, rotate them immediately and remove the file from history (use git filter-repo or BFG) and update .gitignore.

Step-by-step implementation checklist

  1. Add vlucas/phpdotenv via Composer and run composer install.
  2. Create a .env.example file with the keys but not real secrets add .env to .gitignore.
  3. Create your .env (local development) with secret values or configure environment variables on the server/platform.
  4. Load the Composer autoloader and dotenv at the top of wp-config.php before defining constants.
  5. Define DB and other WP constants using getenv() or a small env() helper with fallbacks and validation where appropriate.
  6. Protect .env files with file permissions and server rules. Consider placing .env outside the webroot.
  7. Test locally, then test in staging and production. Verify that WP sees the correct values (e.g., via WP-CLI or a secure debug page) and that no secrets are exposed.
  8. Implement rotation and deployment processes to update environment variables or secrets via your CI/CD or hosting provider.

Examples of safer patterns and validation

Its wise to fail fast in non-production environments if required env vars are missing. Example: throw an error in development, but in production you may want to log and fail gracefully. Also validate types for booleans and integers.


Examples: Using cloud secret managers (conceptual)

Instead of .env files, you can fetch secrets from a cloud provider at deploy time and inject them into environment variables. Example pattern:

  • At deploy time, the CI/CD pipeline calls AWS Secrets Manager to fetch DB credentials, then injects them into the container environment or sets env vars on the server.
  • On Kubernetes, use a Kubernetes secret created from the secret manager and mount it as environment variables or files. Ensure RBAC and encryption of secrets at rest and in transit.

Reference table: typical env var names and WP constants

Environment variable WP constant / usage
DB_NAME DB_NAME (database name)
DB_USER DB_USER (database user)
DB_PASSWORD DB_PASSWORD (database password)
DB_HOST DB_HOST (database host:port/unix socket)
WP_ENV Custom environment indicator (development/staging/production)
WP_DEBUG Controls WP_DEBUG boolean
WP_HOME / WP_SITEURL WP_HOME and WP_SITEURL constants
AUTH_KEY, SECURE_AUTH_KEY, etc. WordPress salts and authentication keys
Third-party API keys Plugin and integration credentials

Final best practices (short list)

  • Load secrets before WordPress constants are defined (top of wp-config.php).
  • Keep secrets out of VCS use .env in development and platform/CI-managed env vars in production.
  • Restrict access and permissions to secret files place .env outside webroot when possible.
  • Prefer secret managers for production use env vars as the runtime mechanism.
  • Validate presence of required variables and be conservative about debug output in production.

Quick implementation recipe

  1. composer require vlucas/phpdotenv
  2. Create .env (or configure platform env vars)
  3. Load composer autoload and Dotenv at the top of wp-config.php and map env vars to WP constants
  4. Protect and rotate secrets test the site and deployment pipeline

Useful patterns you can adopt immediately

  • Keep a .env.example in repo, but not .env
  • Use safeLoad() in production so missing local .env does not break automated deployments when you rely on platform env vars
  • Use WP_ENV to switch behavior (caching, debugging, error display) between environments
  • Use secret managers where available and inject into env vars at deploy time

This article contains practical examples, server and container snippets, and deployment guidance so you can adopt environment variables and dotenv in WordPress safely and consistently. Implement the patterns that match your hosting and operational model, validate on staging, and ensure secrets are rotated and protected.



Acepto donaciones de BAT's mediante el navegador Brave :)



Leave a Reply

Your email address will not be published. Required fields are marked *