Ploy
Ploy
Features

Environment Variables

Configure environment variables for your workers with .env file support and dashboard secrets.

Environment Variables

Ploy lets you define environment variables in ploy.yaml and access them in your worker via env.vars. Variables can be hardcoded values or references to .env files and process environment variables.

Configuration

Define environment variables in your ploy.yaml:

ploy.yaml
kind: dynamic
build: pnpm build
out: dist
env:
  APP_NAME: my-app
  SECRET_KEY: $SECRET_KEY
  API_URL: $API_URL
  • Hardcoded values (e.g. APP_NAME: my-app) are used as-is in all environments.
  • $VAR references (e.g. SECRET_KEY: $SECRET_KEY) are resolved from your .env file during local development, or from the Ploy dashboard in production.

All environment variables must be defined in ploy.yaml. Variables not declared in ploy.yaml will not be available in your worker, even if they exist in your .env file or the Ploy dashboard.

Run ploy types to generate TypeScript types:

ploy types

This generates an env.d.ts file with typed access to your variables:

env.d.ts
declare global {
	interface PloyEnv {
		vars: {
			APP_NAME: string;
			SECRET_KEY: string;
			API_URL: string;
		};
	}
}

Basic Example

src/index.ts
export default {
	async fetch(request, env) {
		return Response.json({
			appName: env.vars.APP_NAME,
			apiUrl: env.vars.API_URL,
		});
	},
} satisfies Ploy;

Local Development with .env

Create a .env file in your project root:

.env
SECRET_KEY=my-local-secret
API_URL=http://localhost:3000/api

When you run ploy dev, the emulator loads .env and resolves any $VAR references from it. Hardcoded values in ploy.yaml are always used as-is.

Add .env to your .gitignore file. Never commit secrets to version control.

Resolution Order

For $VAR references, the emulator resolves values in this order:

  1. .env file in your project directory (highest priority)
  2. Process environment variables (e.g. from your shell)

If a $VAR reference cannot be resolved from either source, the variable is omitted from the worker environment.

Production: Dashboard Variables

In production, $VAR references are resolved from environment variables set in the Ploy dashboard.

Setting Variables in the Dashboard

  1. Go to your project settings in the Ploy dashboard
  2. Navigate to the Environment Variables section
  3. Add variables that match the $VAR references in your ploy.yaml

For example, if your ploy.yaml has:

env:
  SECRET_KEY: $SECRET_KEY

You would add a variable with key SECRET_KEY and your production secret value in the dashboard.

You can only add variables in the dashboard that are defined in your ploy.yaml env section. The dashboard will reject variables that are not declared in ploy.yaml.

Secret vs Plaintext

When adding variables in the dashboard, you can choose between:

  • Secret: The value is encrypted and never displayed after creation. Use for API keys, tokens, and passwords.
  • Plaintext: The value is stored and displayed in plain text. Use for non-sensitive configuration.

How It Works

Hardcoded Values

Values without a $ prefix are injected directly into the worker environment:

env:
  APP_NAME: my-app # Always "my-app" in all environments
  NODE_ENV: production # Always "production"

These values cannot be overridden by .env files or dashboard settings.

Variable References

Values starting with $ are references that get resolved at runtime:

env:
  SECRET_KEY: $SECRET_KEY # Resolved from .env (local) or dashboard (production)
  DB_URL: $DATABASE_URL # The reference name can differ from the key

The reference name after $ is looked up in the .env file or dashboard. The key name (left side) is what your worker accesses via env.vars.

Accessing Variables

All variables are available under env.vars in your worker:

export default {
	async fetch(request, env) {
		// Hardcoded values
		const appName = env.vars.APP_NAME;

		// Resolved references
		const secretKey = env.vars.SECRET_KEY;

		return new Response(`${appName}: ${secretKey}`);
	},
} satisfies Ploy;

Full Example

Project Structure

my-worker/
├── .env              # Local secrets (gitignored)
├── ploy.yaml         # Variable definitions
├── env.d.ts          # Generated types
├── package.json
├── tsconfig.json
└── src/
    └── index.ts

ploy.yaml

ploy.yaml
kind: dynamic
build: pnpm build
out: dist
env:
  APP_NAME: my-app
  SECRET_KEY: $SECRET_KEY
  API_URL: $API_URL

.env

.env
SECRET_KEY=dev-secret-key-123
API_URL=https://api.dev.example.com

src/index.ts

src/index.ts
export default {
	async fetch(request, env) {
		const url = new URL(request.url);

		if (url.pathname === "/config") {
			return Response.json({
				appName: env.vars.APP_NAME,
				apiUrl: env.vars.API_URL,
				// Never expose secrets in responses!
			});
		}

		// Use SECRET_KEY for authentication
		const authHeader = request.headers.get("Authorization");
		if (authHeader !== `Bearer ${env.vars.SECRET_KEY}`) {
			return new Response("Unauthorized", { status: 401 });
		}

		return Response.json({ message: "Authenticated" });
	},
} satisfies Ploy;

Next Steps

How is this guide?

Last updated on