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.
Three concrete problems, not just a vague "best practice":
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):
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.
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.
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.