Managing Secrets in Config
Load API keys and integration secrets explicitly through environment variables and pluginConfig.
Keep secrets outside committed source, load them into process.env before the config file is evaluated, and pass each value through the config key that actually consumes it. The examples target @open-wa/wa-automate@5.1.0 and use WA_* names for runtime settings.
Load a .env file explicitly
The open-wa config loader reads process.env; it does not make a project .env file appear automatically. Create a local npm project and install the runtime, the webhook plugin referenced below, and a .env loader:
npm init -y
npm install @open-wa/wa-automate@5.1.0 @open-wa/integration-webhook@5.1.0 dotenvCreate .env next to wa.config.mjs and keep it out of version control:
WA_API_KEY=replace-with-a-long-random-key
WA_SESSION_ID=sales
WA_PORT=8080
OPEN_WA_WEBHOOK_SECRET=replace-with-webhook-secret
CHATWOOT_URL=https://chatwoot.example/app/accounts/1/inboxes/2
CHATWOOT_API_ACCESS_TOKEN=replace-with-chatwoot-token
OPEN_WA_PUBLIC_URL=https://openwa-api.exampleLoad the file in wa.config.mjs, then start the supported release with that config:
// wa.config.mjs
import 'dotenv/config';
const required = (name) => {
const value = process.env[name];
if (!value) throw new Error(`${name} is required`);
return value;
};
export default {
apiKey: required('WA_API_KEY'),
sessionId: process.env.WA_SESSION_ID ?? 'sales',
port: Number(process.env.WA_PORT ?? 8080),
plugins: ['@open-wa/integration-webhook'],
pluginConfig: {
webhook: {
url: 'https://your-app.example/webhooks/open-wa',
events: ['message.received'],
headers: {
'X-Webhook-Secret': required('OPEN_WA_WEBHOOK_SECRET'),
},
},
},
};npx wa-automate --config ./wa.config.mjs --session-id sales --host 127.0.0.1 --port 8080The shared config loader reads WA_API_KEY, WA_PORT, and WA_SESSION_ID. The published 5.1.0 CLI applies its own session, host, and port defaults after that loader, so the command supplies those three flags explicitly. OPEN_WA_WEBHOOK_SECRET and CHATWOOT_API_ACCESS_TOKEN are application-level names; the config file maps them to the integration settings that consume them.
Docker secrets and environment variables
For complete, digest-pinned run and Compose commands, see the Docker guide. Compose reads .env values for interpolation but passes only mapped environment values into the container. Set W_A_V=5.1.0 there to pin the package installed at startup.
The container does not read Docker secret files by itself. If your platform mounts a secret under /run/secrets, use an entrypoint that reads that file, exports its value as WA_API_KEY, and then runs the open-wa CLI. Restrict access to both the secret file and the session profile.
Plugin configuration shape
The top-level plugins array contains npm package names or local plugin paths. The pluginConfig object is keyed by each plugin's meta.name; the plugin validates and consumes the value under its own key.
Webhook integration
Webhook delivery uses the @open-wa/integration-webhook plugin. Its supported config is an object under pluginConfig.webhook, with url, optional events, and optional request headers:
export default {
plugins: ['@open-wa/integration-webhook'],
pluginConfig: {
webhook: {
url: 'https://your-app.example/webhooks/open-wa',
events: ['message.received'],
headers: {
'X-Webhook-Secret': process.env.OPEN_WA_WEBHOOK_SECRET,
},
},
},
};The top-level webhook config key is a separate string URL field. The current v5 CLI does not register delivery from --webhook; use the plugin shape above for webhook delivery and see Webhook payloads for the receiver contract.
Chatwoot integration
Chatwoot uses the plugin's documented field names, not instanceUrl:
Install the plugin package into the same npm project that installs the runtime:
npm install @open-wa/integration-chatwoot@5.1.0export default {
plugins: ['@open-wa/integration-chatwoot'],
pluginConfig: {
chatwoot: {
chatwootUrl: process.env.CHATWOOT_URL,
chatwootApiAccessToken: process.env.CHATWOOT_API_ACCESS_TOKEN,
apiHost: process.env.OPEN_WA_PUBLIC_URL,
apiKey: process.env.WA_API_KEY,
forceUpdateCwWebhook: true,
},
},
};chatwootUrl contains the Chatwoot account URL and optional inbox path, chatwootApiAccessToken authenticates API calls, and apiHost is the public origin Chatwoot can reach. See Chatwoot integration for the schema and webhook route.
Illustrative custom plugin
my-plugin is an invented application example. Its fields have no meaning to open-wa unless your plugin defines and reads them:
export default {
plugins: ['./plugins/my-plugin.mjs'],
pluginConfig: {
'my-plugin': {
apiKey: process.env.MY_PLUGIN_API_KEY,
enabled: true,
},
},
};Define and validate those fields in the plugin's own configSchema; do not copy this shape into a real integration without checking that integration's schema.
Security rules
- Use environment variables or a secret manager for API keys, license keys, webhook secrets, and integration tokens.
- Add
.envand local secret directories to.gitignore; never commit session profiles or secret files. - Never log the complete config object. Log only booleans such as
hasKey: Boolean(config.apiKey)and non-sensitive URLs. - Rotate a secret by changing the injected value and restarting the runtime or plugin so it is loaded again.
- Treat the browser profile directory as secret material because it contains WhatsApp authentication state.
Validate at startup
Validate required application secrets before starting the runtime. Zod is one option for an application-owned config layer:
import { z } from 'zod';
const configSchema = z.object({
apiKey: z.string().min(1),
webhookSecret: z.string().min(1),
});
const appConfig = configSchema.parse({
apiKey: process.env.WA_API_KEY,
webhookSecret: process.env.OPEN_WA_WEBHOOK_SECRET,
});The runtime validates its own config and plugin schemas separately. Application validation prevents a missing secret from becoming a partially configured integration.
Related
- Docker: complete port, profile, and secret-loading commands.
- Configuration and CLI: config discovery and
WA_*precedence. - Plugin security model: plugin boundaries.
- Security and deployment: production network and secret controls.
Was this helpful?
Your answer includes the page path and docs version.
