5.1 Configuration and data locations
The current source workflow runs Teloa and DSH in local Node.js processes, with only PostgreSQL in Docker by default. Compose runs all three in containers. Both existing workflows use standard Docker; OrbStack is not required. Native npm installation is described below; keep data directories separate between installation methods.
Where files and programs are used
Native mode uses a local working directory and integrated, authorized tools. Compose uses programs and a working directory inside the container. The default Compose configuration does not mount your computer's entire filesystem and cannot directly invoke native desktop applications.
To expose a directory on your computer to a container, configure an explicit mount and its read/write permissions. The path belongs to the machine running the Docker engine; a remote engine does not automatically receive files from your computer. See Docker bind mounts.
Who manages each setting
| Setting | Managed in | What to check |
|---|---|---|
| Business areas, employees, tasks and grants | Teloa pages and database | Use the supported actions; direct database edits bypass validation |
| Models, keys, MCP and run configurations | The DSH configuration reached from Settings | Verify a real call after saving |
| Extension composition | Source configuration and setup:dsh | Prepare and build again after changes |
| Browser authentication | A new authentication link from the launcher | The link changes after restart; do not publish it |
Compose data locations
| Named volume | Container path | Contents |
|---|---|---|
app-data | /data in the app | DSH conversations, model configuration, Teloa working files and knowledge |
postgres-data | /var/lib/postgresql/data in the database | PostgreSQL business data |
database-secret | /run/teloa-secrets in the app and database | The generated database password |
credentials-secret | /run/teloa-credentials in the app only (read-only) | The generated key storage master key, kept apart from app-data |
Actual volume names include the Compose project prefix, such as teloa_app-data. Using -p changes that prefix. Do not confuse these volumes with the fixed container used for source development.
DSH configuration lives in /data/dsh, Teloa data in /data/teloa, and the working directory in /data/teloa/workspace. The database is reachable through the internal Compose service db; no database port is published on the device running Teloa.
Source development data locations
When you run Node.js directly from source, the database volume is teloa-postgres-data, the Teloa data directory is .runtime/teloa, and the DSH directory is .runtime/dsh. The adapter log is harness.log inside the data directory. Redact it before sharing.
For either installation, back up both the database and the working files. Copying source code or connection settings alone is not a complete backup.
Read-only dashboard database role
Business dashboard queries run over a dedicated login role, teloa_business_reader. The role can read only the table holding copies of business records and the safe helper functions, both in the schema that holds the Teloa tables (public by default). It has no superuser, create-database, create-role, replication or row-level-security bypass attributes, and it is not a member of any other role. Teloa checks these conditions at startup; if they do not hold, dashboard queries are disabled and the reason is written only to the server log.
The role password is generated randomly and kept in a password file inside the Teloa data directory (mode 0600, owned by the system user running Teloa); the database stores only a SCRAM verifier. To rotate the password, stop Teloa, delete the password file and start Teloa again. Startup generates a new password and updates the database role. Do not edit the file by hand or include it in shared backups.
npm data layout
GitHub Releases provides the native 0.2.10 package; see installation for native installation. The installer keeps program versions, application data, and working files separate: ~/.teloa/releases/ stores programs, instances/default/ stores sessions and configuration, and workspaces/default/ stores working files. Updating the npm package does not automatically migrate data or restart the service. Docker PostgreSQL is the default; an existing dedicated local database is an alternative. Do not mix these paths with a source or Compose installation.
Keys and environment variables
Model keys and connection grants share the DSH key storage, which prefers encryption with a master key in the system keychain or a master key file outside the DSH folder. Auto mode falls back to plaintext only on first initialization when neither is available, with a persistent warning in Settings. An existing encrypted store is locked if its key cannot be retrieved; it does not downgrade.
- The source and container launchers drop key-like variables from the environment they start in: names that, split on
_, contain a whole segment such asKEY,TOKEN,SECRET,PASSWORDorAUTH, and values that are URLs with a password (such aspostgres://user:password@…). Only the dropped names are printed, never the values. The npmteloacommand already passes a fixed short list of variables. - URLs with a password in proxy variables (such as
HTTPS_PROXY=http://user:password@…) are dropped as well, and proxy variables have no_FILEform; with the source or container launcher, use a local proxy forwarder that needs no password. The npmteloacommand passes proxy variables through unchanged under its allowlist. - Enter model keys in Settings. To inject one from a file, point
<NAME>_FILEat a file only you can read (for exampleDEEPSEEK_API_KEY_FILE). The security action token likewise moves toTELOA_SECURITY_ACTION_TOKEN_FILE. - IM channel keys (
FEISHU_APP_SECRET,FEISHU_ENCRYPT_KEY,LARK_APP_SECRET,LARK_ENCRYPT_KEY,TELEGRAM_BOT_TOKEN,SLACK_BOT_TOKEN,SLACK_APP_TOKEN) can only be saved under Settings > IM channels; environment variables and_FILEhave no effect. When the launcher drops them, the startup log shows one extra notice. - With Teloa stopped you can maintain the key storage:
teloa credentials --action export-plaintext --confirmwrites an owner-only (0600) plaintext file before you roll back to the previous version;teloa credentials --action reset --confirmresets the store when the master key cannot be recovered and keeps the old files renamed to.bak-<time>. Reset deletes only the keychain entries this installation registered and never enumerates the keychain; if macOS still shows a keychain prompt, declining it does not stop the reset. The entry for the previous master key is kept so the.bak-*files can still be opened; delete it by hand in the system keychain (serviceTeloa Credentials) once you no longer need it. - An npm installation needs network access to fetch the system keychain component for the current platform. If you install offline (
npm install --offline) and the local cache lacks that component, or the platform is not supported, the program still installs, but first initialization quietly uses a master key file instead, and it never switches back to the system keychain on its own. To move to the keychain: reinstall with network access, stop Teloa, optionally runteloa credentials --action export-plaintext --confirmfirst to keep a plain-text copy for re-entry, then runteloa credentials --action reset --confirm, start Teloa (setTELOA_CREDENTIALS_STORE=keyringto require the keychain), enter your keys again in Settings, and check the current method under Settings > Key storage. teloa backupincludes neither keys, authorizations nor the.envfile in the DSH folder (it may hold plain-text keys). If you need it, save it yourself somewhere protected and, after a restore, put it back asinstances/default/dsh/.envin the new installation (mode0600); the backup and restore commands both print this reminder.- Security-related
TELOA_*switches (the OAuth callback address, the security action address and token, usage statistics and online market switches, the data folder, acceptance switches and so on) are read only from the environment Teloa inherits at launch; setting them in a.envfile in your project folder or the DSH folder has no effect. Upgrade note: such variables that you previously kept in either.envfile stop working after the upgrade; Teloa prints one warning at startup listing only their names. Set them in the environment that launches Teloa instead (the npm-installedteloadoes not pass them; put the OAuth callback inoauth.publicCallbackUrlinconfig.jsonin the data directory). - Known forms of AI tool calls that read key storage files, master keys, the DSH folder's
.env, database password files or backup folders are blocked. Content matching saved keys in tool output or group posts is replaced with[已隐藏]. This raises the bar but does not cover arbitrary encodings or every outbound path; it is not a security boundary. - Settings > Key storage shows how keys are encrypted and keeps a warning on screen while the store is locked or can only save plain text. It also lists plain-text key copies left from before encryption: copies in old backups and upgrade backup folders, and
.credentials.yaml.quarantine-*files set aside at startup. Nothing is deleted until you select the copies (one by one or all at once) and confirm again; each file is overwritten with zeros in place before it is removed. Files that share their contents with another path (hard links) are marked for manual handling in the list and cannot be selected; links, files that cannot be overwritten and files replaced after the list was built are not deleted either. SSDs, APFS and system backups (such as Time Machine) may still hold old data; overwriting with zeros does not guarantee physical erasure. Backups written elsewhere withteloa backup --outputare not scanned; clean those up yourself.
Skill API keys
Skill key configuration does not enable unsupported resources. X Search, Finance Search, Macro Data, CellCog and CellCog Image Generation remain unsupported and cannot be enabled by entering keys.
The following workflow applies only to a supported, installed marketplace skill that lists its required keys:
- Open the skill under Resources > Apps and choose Keys. Review each key's purpose, required status, destination domain and path prefix, and injection location (Bearer, header or query parameter). Do not send keys in chat, write them into skill content or put them in environment variables.
- Enter the key in the password field and save. Fields are write-only, never prefilled with stored values, and cleared on submission; the page shows only saved or missing status. Teloa saves third-party API keys in the encrypted key storage described above, using the same storage tiers and initial fallback rules. Check the actual status under Settings > Key storage.
- If the catalog's key-use description changes, saving from an old page is rejected. The page refreshes the description; you must review it, enter the keys and submit again. Old input is not retried automatically. Reconfirmation clears old keys that you do not re-enter. Changes to destinations, methods, injection locations, variable names, labels and required status all require you to review again.
- A locked or read-only store prevents saving and deletion; unknown status is not shown as missing. Resolve it under Settings > Key storage first. To remove keys, choose delete and confirm again: this deletes all stored keys for that skill. It does not revoke them at the third-party provider; revoke them with the provider separately.
Teloa makes the request and injects keys only for the HTTPS origins listed by the skill, path prefixes and HTTP methods. At every hop it checks that all DNS results are public addresses, locks the connection addresses and verifies the destination hostname's TLS certificate. Only same-origin redirects that stay within what the skill lists are allowed. The web search and reading master switch and domain blocklist still apply. Binding follows the currently installed, active marketplace skill; a workspace skill overriding it by name receives no injected keys. The model cannot retrieve raw values through key interfaces and does not receive these keys through environment variables.
Limits: the authorized third-party service receives the keys. Response bodies are redacted by the values used and common encodings; this does not cover arbitrary transformations or control a provider's echoing or forwarding, and is not a general exfiltration boundary. Skill requests follow the official DSH proxy settings (HTTP_PROXY / HTTPS_PROXY / NO_PROXY). Direct connections check for public addresses and lock the connection address; through a proxy, the proxy resolves the destination, so address locking does not apply and protection comes from verifying the destination hostname's TLS certificate. Proxy addresses and accounts never appear in logs, errors or responses.
Write confirmation and employee grants: every request that changes data (POST, PUT, PATCH, DELETE) shows a confirmation card that you decide on the workbench; IM can only reject it. After a rejection or no answer, the same skill calling the same address with the same method does not show another card for 60 seconds. An AI employee's task session can use a skill's keys only if you tick that skill under Employees > Capabilities; skills added later are not granted by default, and sub-task and group-routed sessions can never use them.
Extra headers, call guides and shared keys: the catalog may allow a few extra request headers for a skill (up to 8); authentication, routing and forwarding headers are never allowed. The catalog may also include reviewer-written call guidance, which explains how to call the service but never widens the allowed addresses, methods or headers. Several skills can share one key: the key page lists the skills that share it, and saving or deleting applies to all of them at once.
IM channels
IM channels (Feishu, Lark (Feishu international), Telegram, Slack) ships with the app and is loaded by default; nothing needs to be installed from the marketplace. A channel starts running as soon as you enable it in Settings > IM channels (no restart needed); it needs Node.js 22.19 or later (the verified 0.2.10 baseline is 24.22.1, or 22.23.4 or later in the 22.x line). Teloa connects out to each platform from your machine: Telegram uses long polling, Slack uses Socket Mode, and Feishu and Lark use a long-lived event connection (to open.feishu.cn and open.larksuite.com respectively), so no public address or inbound port is needed, but the machine running Teloa must be able to reach the platform.
- Channel keys are stored only in the DSH key storage. The
im-gateway/folder in the data directory holds channel switches, bindings and audit records (folder0700, files0600) and never contains key values or pairing codes. - The Feishu SDK is not shipped with Teloa: the first time a Feishu or Lark channel is saved, Teloa downloads a locked version from npm, verifies its integrity, skips install scripts and places it in the data directory; both channels share this copy. Feishu and Lark channels cannot be added offline.
- Only one process per data directory may connect IM channels (
im-gateway/instance.lock). A second Teloa shows "Another Teloa is connected to this channel" for its channels, and its settings page is read-only. - Enabling or disabling only changes the DSH profile's bundle list; disabling keeps
im-gateway/and the keys. Source, container and npm upgrades re-register the bundled extension at startup and check that it comes from this program's own directory, so you do not need to re-runpnpm setup:dsh; if the source does not match, Teloa refuses to start. If you had configured channels before upgrading, IM channels is enabled once automatically (recorded inteloa-官方扩展.jsonin the profile directory). teloa backupdoes not include keys: after a restore, save the channel keys again in Settings; bindings are kept inim-gateway/.- When moving Teloa, keep the bindings in
im-gateway/and re-enter keys in Settings on the new installation. Do not copy ciphertext as a substitute for re-entering them: its master key belongs to the original installation.
See Chat with employees from IM for usage.
OAuth callback address
App connections on Apps that need OAuth authorization with the service (such as Supabase remote, GitLab and Slack) send the authorization result back to Teloa's /oauth/callback:
- Local deployments (Teloa listens only on
127.0.0.1) need no configuration; the callback ishttp://127.0.0.1:<port>/oauth/callback. - Inside the Compose container Teloa always listens on
127.0.0.1:3100, so the callback and the authorization entry are fixed athttp://127.0.0.1:3100/oauth/…. If you changeTELOA_PORTto another port, the browser is sent back to 3100 after authorization and never reaches Teloa. When you use OAuth connections, keepTELOA_PORT=3100, or setoauth.publicCallbackUrlbelow behind an HTTPS reverse proxy so the callback matches the address you actually use. - Server deployments (Teloa listens on
0.0.0.0or another external address) must set a public HTTPS callback inconfig.jsonin the data directory. Otherwise starting authorization is refused with "Server deployments must set oauth.publicCallbackUrl in the configuration file to use OAuth authorization."
{
"oauth": {
"publicCallbackUrl": "https://teloa.example.com/oauth/callback"
}
}- The address must use
https://and must not contain a user name, password or#fragment. Your reverse proxy must forward that path unchanged to Teloa's/oauth/callback, and forward the siblingstartpath (such ashttps://teloa.example.com/oauth/start) to Teloa's/oauth/start. Authorization opens through that entry: it first writes a one-time cookie to the browser and then redirects to the authorization server, so the callback must come back to the same browser. The authorization entry link is returned only to the person who started authorization; do not forward it. The first browser to open it is bound, and other browsers cannot complete authorization. config.jsonlives in the data directory (.runtime/teloa/config.jsonwhen running from source,/data/teloa/config.jsonin Compose). It must be owned by the system user running Teloa and must not be writable by other users; otherwise the setting is ignored and a warning is logged.- Teloa reads it once at startup; restart after changing it. Only when the file has no such setting does Teloa fall back to the
TELOA_OAUTH_PUBLIC_CALLBACK_URLenvironment variable. - The npm-installed
teloacommand passes only a fixed set of environment variables to Teloa, soTELOA_OAUTH_PUBLIC_CALLBACK_URLhas no effect there. Setoauth.publicCallbackUrlinconfig.jsonin its data directory instead (by default~/.teloa/instances/default/runtime/config.json). - Authorization tokens are also kept in the key storage and are no longer written to separate plaintext files under
mcp/credentials/. Encryption and first-initialization fallback follow the rules above. Token values do not appear in connection configuration, pages or logs.
After changing configuration
Check that the change was saved, that it applies to the intended employee or task, and that an actual call succeeds. Extension code or composition changes may require a build and service restart in development. Refreshing the browser does not reload server code.
See Commands and configuration for environment variables and Backup, restore and upgrades for maintenance.