← Back to Wiki
Self-Hosting / Security

Give Every Automation Its Own Account, Not Yours

The lazy path when you want a script to post a deploy notification, a status update, or a moderation action into some self-hosted app is to just reuse your own login — it already works, and it's one less thing to set up. It's also the wrong call the moment that script's credential ends up in a config file, a cron job, or a CI pipeline. Here's the pattern that avoids it, using a real self-hosted chat app's bot-account feature as the concrete example, plus the general lessons that apply regardless of what app you're automating.

Share on X

Why not just reuse your own login

Three concrete problems, not just a vague "best practice":

The pattern: a real account, not a special auth mode

The self-hosted apps that get this right (well-designed ones, anyway) don't invent a separate bolt-on auth system for automation — they give it a real account in the existing user/permission model, just authenticated differently. Outpost, a self-hosted Discord alternative, is a clean concrete example: its API bot accounts are real members with real roles, the only difference from a human member being that they authenticate with a long-lived token instead of a password, over the exact same REST/gateway API any client uses. No parallel bot-only API surface to maintain, and no special-cased permission model to reason about separately from the normal one.

That's the shape to look for (or build, if you're the one adding automation support to something):

  1. A real account row in the existing user table, flagged as a service/bot account rather than modeled as something entirely separate.
  2. Normal role/permission assignment — the same system a human account uses, so a script can be scoped down to exactly what it needs (post in one channel, not manage the whole instance) without a second permission system to audit.
  3. A token issued once, shown once — not a reusable password. If the app can't show you the credential again after creation, that's usually a sign it isn't storing it anywhere retrievable either, which is the property you actually want.
  4. Independent revoke/delete — killing the automation's access shouldn't require touching any human account's credentials.

Grant the narrowest role, not the convenient one

It's tempting to hand a new automation account an admin/owner-equivalent role so you never have to think about it again. Don't — the same logic as the blast-radius point above applies to the role you grant, not just the account you grant it to. A deploy-notification bot needs permission to post in one channel, full stop. Work out the actual minimum before wiring in the credential, not after something goes wrong.

A real gotcha this surfaced when setting up a self-hosted password manager to store one of these tokens: Vaultwarden's CLI (bw create item, item type 1 / login) silently drops the password field if the created item lands in a shared organization collection — it saves the username and everything else, just not the secret you actually needed stored. The same call works correctly as a personal (non-org) item. If a freshly created login item in your vault is missing its password with no error anywhere, check whether it landed in a shared collection before assuming the credential itself is bad — it's very easy to lose ten minutes suspecting the wrong thing. See the password manager guide for the base Vaultwarden setup this applies to.

Where the token actually lives

Once you have a scoped, independently-revocable credential, treat it like any other secret: a password manager entry (as a personal item, per the gotcha above) or your CI system's own secret store — never committed to a repo, never pasted into a chat message or an issue thread to "share it with the team." If the automation runs somewhere with standing SSH access already set up, a plain environment file readable only by the service's own user is a reasonable fallback, but a real secret store beats that whenever one's already available.

The checklist

  1. Does the app support a real dedicated account type for automation, distinct from your own login? If not, that's a real gap worth weighing against alternatives.
  2. Grant it the narrowest role/permission set the automation actually needs — work that out before wiring in the credential.
  3. Store the resulting token in a real secret store, as its own entry — not bundled into a shared/org collection where a tool's own quirks (see the Vaultwarden gotcha above) can silently drop part of it.
  4. Confirm you can revoke just this credential later without touching any human account.