UNPKG

node-red-contrib-telegrambot

Version:
112 lines (88 loc) 4.92 kB
# Automated / git-managed deployments This document covers what you need to do when your Node-RED flows live in source control (or are otherwise managed by automation) and your bot's token is supposed to flow in from an environment variable or a secrets store rather than being typed into the editor by hand. It is also the answer to issue [#432](https://github.com/windkh/node-red-contrib-telegrambot/issues/432). ## Why this needs special handling The bot's `token` field is declared to Node-RED as a **credential**, not a regular config property. Node-RED treats credentials specially: - It strips them out of `flows.json` on save. - It stores their encrypted form in a separate `flows_cred.json` file. - The encryption key is `credentialSecret` from `settings.js`. If `credentialSecret` isn't pinned in `settings.js`, Node-RED generates one and stores it in `.config.runtime.json`. So if your automated deployment commits `flows.json` and uses a fresh `credentialSecret` on every container start, the token will appear to "vanish" — you'll see the bot abort with `Aborting: Token of <botname> is not set`. The plugin's `{env.get("X")}` / `{flow.get("X")}` / `{global.get("X")}` expressions are evaluated **at runtime, inside the credential resolution path**. They work — but only once the encrypted credential has been re-read from `flows_cred.json`. The expression has to survive the credential-serialisation step first. ## Pattern 1 — pin `credentialSecret` and commit `flows_cred.json` The most robust pattern. Pick a deterministic secret per environment and tell Node-RED to use it via `settings.js`: ```js // settings.js module.exports = { credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET || '<a-strong-fallback>', // ... }; ``` Then commit both `flows.json` **and** `flows_cred.json` to your repo. The token field can be a literal value or a `{env.get("...")}` expression — either survives, because Node-RED re-decrypts `flows_cred.json` with the same secret on every boot. If you want to keep the token out of the encrypted file too, put the `{env.get("TG_TOKEN")}` expression in the token field before committing. The plugin will resolve it at runtime against whatever `TG_TOKEN` the container inherits from its environment. ## Pattern 2 — write `flows_cred.json` at boot If you don't want to commit any credential material, generate `flows_cred.json` from your secrets store as the container starts. A small entrypoint script that reads from Vault / SOPS / Doppler / AWS Secrets Manager / ... and writes the file to `$HOME/.node-red/flows_cred.json` before launching Node-RED works fine. `credentialSecret` still needs to match what was used to encrypt it. ## Pattern 3`userDir` and `flowFile` overrides The `userDir` and `flowFile` settings let you point Node-RED at any directory. A common pattern is to keep `flows.json` in `/etc/node-red/flows.json` (read-only, baked into the image) and have Node-RED write `flows_cred.json` to a writable volume. ## What `{env.get(...)}` does and doesn't fix Once the token expression makes it past Node-RED's credential serialisation, the plugin's expression evaluator (see [ADR 0004](doc/architecture/adr/0004-safe-expression-evaluator.md)) handles the supported forms: ``` {env.get("TG_TOKEN")} {flow.get("token")} {global.get("token")} {context.get("token")} {context.flow.get("token")} {context.global.get("token")} ``` `usernames` and `chatids` use the same syntax. As of V17.3.1 a raw string result from `env.get` / `flow.get` / `global.get` is split on commas — so `CHATIDS=123,456` resolves to `[123, 456]`. Anything outside that grammar (function calls, statement chains, prototype walks, `require`, `eval`, etc.) evaluates to `undefined` — see [ADR 0004](doc/architecture/adr/0004-safe-expression-evaluator.md) for the exact whitelist. ## Common pitfalls - **`credentialSecret` is not set in `settings.js`.** Node-RED generates a random one on first start and writes it to `.config.runtime.json`. Subsequent container restarts that lose that file will be unable to decrypt the existing `flows_cred.json`. The bot will then abort with "token is not set". - **`credentialSecret` is rotated.** Same effect — old `flows_cred.json` can no longer be decrypted. Re-enter the token via the editor (or delete `flows_cred.json` and let Node-RED re-create it on save). - **`flows.json` is regenerated by a flow-export step.** Make sure your export pipeline preserves the credential references (it normally just strips the values, which is correct), and doesn't accidentally write back the bot config node with `credentials: {}` cleared. - **Multiple bot config nodes share the same token.** The plugin's `botsByToken` registry aborts the second one with "Token of <botname> is already in use by ...". Use one config node per token and reference it from multiple runtime nodes.