Codes are covered until revealed. A reveal is a server-side, per-session
window (60 s, two periods): POST /api/accounts/{id}/reveal opens it and
returns the code, GET /api/codes only ever returns codes for accounts in
that window, and /hide closes it early. The browser therefore never holds
a code it has not asked for by name, which is what makes the log honest.
Settings -> Log is an audit trail in the style of Daito: one line per
event with who, how long ago and from which address. It records what the
server observed - sign-ins and failed attempts (under the name tried),
reveals, accounts added / renamed / removed, delivery and credential
changes, test messages. Entries are JSON lines in audit.jsonl (owner-only,
newest 5,000 kept, compacted at twice that). The address comes from
X-Forwarded-For / X-Real-IP when parseable, else the TCP peer via
ConnectInfo; in Docker bridge networking that peer is the gateway, which
the README and template now say.
The account list shows each service's mark instead of an initial. The
pack (crates/webui/src/icons.js, generated by scripts/fetch-icons.py) is
~175 marks from Simple Icons (CC0) plus Font Awesome Free brands (CC BY
4.0) for Amazon, AWS, Microsoft, LinkedIn, Slack, Xbox, Salesforce and
Yahoo, which Simple Icons no longer carries. Matching is by issuer name,
then shorter word prefixes, then the label's mail domain; unmatched
accounts keep the initial tile. Marks that would vanish against a theme's
tile fall back to ink for that theme only.
The setup and Delivery platform pickers are plain text; the coloured dots
are gone.
Router tests cover the reveal window, session scoping, 401s, and the
forwarded address landing in the log.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
83 lines
4.2 KiB
XML
83 lines
4.2 KiB
XML
<?xml version="1.0"?>
|
|
<!--
|
|
Unraid Docker template for OpenMFA.
|
|
|
|
Drop this into /boot/config/plugins/dockerMan/templates-user/ on the Unraid
|
|
box, or add the repo as a template repository under Docker → Add Container.
|
|
|
|
Bridge networking is correct: OpenMFA makes outbound HTTPS calls to the chat
|
|
platform you choose and serves one HTTP port.
|
|
|
|
Web UI: http://<unraid-ip>:8720/
|
|
-->
|
|
<Container version="2">
|
|
<Name>OpenMFA</Name>
|
|
<Repository>gitea.milesward.dev/mward4/openmfa:latest</Repository>
|
|
<Registry>https://gitea.milesward.dev/mward4/-/packages/container/openmfa</Registry>
|
|
<Network>bridge</Network>
|
|
<MyIP/>
|
|
<Shell>sh</Shell>
|
|
<Privileged>false</Privileged>
|
|
<Support>https://gitea.milesward.dev/mward4/OpenMFA/issues</Support>
|
|
<Project>https://gitea.milesward.dev/mward4/OpenMFA</Project>
|
|
<Overview>
|
|
Self-hosted TOTP authenticator with live delivery to Discord, Slack or
|
|
Telegram.
|
|
|
|
Add accounts by uploading a QR code, scanning with the camera, pasting an
|
|
otpauth:// link, or importing a Google Authenticator export (one export QR
|
|
carries many accounts; you get a checklist, and duplicates are detected).
|
|
The web UI lists every account behind its service mark, the way Google or
|
|
Microsoft Authenticator does. Codes stay covered until you reveal one, and
|
|
Settings -> Log records every reveal and sign-in with who and from where.
|
|
(In bridge networking the address is Docker's gateway; use a reverse proxy
|
|
or host/br0 networking to see real LAN addresses.)
|
|
|
|
The distinctive part: each account keeps ONE message in your chosen
|
|
channel, rewritten in place every time the code rolls. Three accounts means
|
|
three live tiles that keep themselves current. Codes are posted as copyable
|
|
text; on Discord a rendered WebP tile is attached as well.
|
|
|
|
Pick the platform during first-run setup or later in Settings. Discord
|
|
needs only a webhook URL. Slack needs a bot token (its webhooks can't edit
|
|
messages). Telegram needs a bot token, and the app detects your chat ID for
|
|
you.
|
|
|
|
SECURITY NOTE: anyone who can read that channel can read these codes, which
|
|
is most of the point of a second factor. Use a private channel only you are
|
|
in, and treat the webhook URL or bot token as a secret. TOTP secrets are
|
|
encrypted at rest with XChaCha20-Poly1305.
|
|
</Overview>
|
|
<Category>Tools:Utilities Security:</Category>
|
|
<WebUI>http://[IP]:[PORT:8720]/</WebUI>
|
|
<TemplateURL/>
|
|
<Icon>https://gitea.milesward.dev/mward4/OpenMFA/raw/branch/main/docs/brand/icon-256.png</Icon>
|
|
<ExtraParams/>
|
|
<PostArgs/>
|
|
<CPUset/>
|
|
<DateInstalled/>
|
|
<DonateText/>
|
|
<DonateLink/>
|
|
<Requires>
|
|
One of: a Discord incoming-webhook URL; a Slack app with the chat:write
|
|
bot scope plus a channel ID; or a Telegram bot token from @BotFather. All
|
|
can be added after install from Settings → Delivery.
|
|
</Requires>
|
|
<Config Name="WebUI Port" Target="8720" Default="8720" Mode="tcp"
|
|
Description="Port for the web UI and API."
|
|
Type="Port" Display="always" Required="true" Mask="false">8720</Config>
|
|
<Config Name="Data" Target="/var/lib/openmfa"
|
|
Default="/mnt/user/appdata/openmfa"
|
|
Mode="rw"
|
|
Description="Vault, encryption key, admin account and settings. BACK THIS UP — losing it loses every stored TOTP secret."
|
|
Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/openmfa</Config>
|
|
<Config Name="Master key (optional)" Target="OPENMFA_MASTER_KEY" Default=""
|
|
Mode=""
|
|
Description="Base64 of 32 random bytes. Set this to keep the vault key OFF the appdata share, so a leaked backup of the share is useless on its own. Generate with: openssl rand -base64 32. Leave blank to auto-generate a key file inside the data folder instead. WARNING: if you set this later, existing secrets become unreadable — export them first."
|
|
Type="Variable" Display="advanced" Required="false" Mask="true"></Config>
|
|
<Config Name="Log filter" Target="OPENMFA_LOG" Default="info,openmfa=info"
|
|
Mode=""
|
|
Description="tracing-subscriber EnvFilter expression. Use info,openmfa=debug for more detail."
|
|
Type="Variable" Display="advanced" Required="false" Mask="false">info,openmfa=info</Config>
|
|
</Container>
|