Problem
Managing more than one client key on a deployment currently means hand-editing two files in sync: profiles.json (add/remove a profile, keep names and secrets unique) and, since the stock mtproxy.service unit passes exactly one secret through -S ${MTPROXY_SECRET} and systemd always expands ${VAR} to a single argument, some way of getting a second -S to official MTProxy. The relay also doesn't reload profiles.json — every change needs systemctl restart tproxy-server, dropping live carrier sessions regardless of which key actually changed.
None of that is hard, but it's easy to get the two files out of sync, and there's no dry-run before it's live.
What we built
tproxy-keys — a small CLI and loopback-only web UI that treats "add/revoke/rotate a key" as one operation:
- Validates the candidate profile set with the relay's own
-config ... -check before writing anything.
- Writes
profiles.json and regenerates official MTProxy's secret list (via a systemd drop-in that switches mtproxy.service to a whitespace-splitting $MTPROXY_SECRET_ARGS, read from an env file it maintains).
- Restarts
mtproxy + tproxy-server, waits for /readyz.
- Rolls back to the previous
profiles.json (and resyncs MTProxy from it) if the restart doesn't come back healthy.
It's a separate Go module (go build ./... / go test ./... at the repo root don't descend into it) with its own systemd unit, bound to 127.0.0.1 only — reachable through an SSH tunnel, gated by a token plus CSRF, nothing on the public hostname. Full writeup and the code: https://github.com/sandamond/tproxy-server/tree/master/keys-panel
Question
Before turning this into a PR against this repo: is a key-management panel something you'd want to carry as part of the reference implementation, or would you rather it stay a separate/companion tool? I ask because the project reads as deliberately minimal elsewhere (no shipped public-site template, to avoid a shared probeable fingerprint; a narrow, hardened admin surface) — a second Go module with its own web server is a bigger, more opinionated addition than that pattern, even bound to loopback, and might not be what you want owning space in the core repo. Happy to open the PR if it's wanted, or leave this as a pointer to the fork if not.
Problem
Managing more than one client key on a deployment currently means hand-editing two files in sync:
profiles.json(add/remove a profile, keep names and secrets unique) and, since the stockmtproxy.serviceunit passes exactly one secret through-S ${MTPROXY_SECRET}and systemd always expands${VAR}to a single argument, some way of getting a second-Sto official MTProxy. The relay also doesn't reloadprofiles.json— every change needssystemctl restart tproxy-server, dropping live carrier sessions regardless of which key actually changed.None of that is hard, but it's easy to get the two files out of sync, and there's no dry-run before it's live.
What we built
tproxy-keys— a small CLI and loopback-only web UI that treats "add/revoke/rotate a key" as one operation:-config ... -checkbefore writing anything.profiles.jsonand regenerates official MTProxy's secret list (via a systemd drop-in that switchesmtproxy.serviceto a whitespace-splitting$MTPROXY_SECRET_ARGS, read from an env file it maintains).mtproxy+tproxy-server, waits for/readyz.profiles.json(and resyncs MTProxy from it) if the restart doesn't come back healthy.It's a separate Go module (
go build ./.../go test ./...at the repo root don't descend into it) with its own systemd unit, bound to127.0.0.1only — reachable through an SSH tunnel, gated by a token plus CSRF, nothing on the public hostname. Full writeup and the code: https://github.com/sandamond/tproxy-server/tree/master/keys-panelQuestion
Before turning this into a PR against this repo: is a key-management panel something you'd want to carry as part of the reference implementation, or would you rather it stay a separate/companion tool? I ask because the project reads as deliberately minimal elsewhere (no shipped public-site template, to avoid a shared probeable fingerprint; a narrow, hardened admin surface) — a second Go module with its own web server is a bigger, more opinionated addition than that pattern, even bound to loopback, and might not be what you want owning space in the core repo. Happy to open the PR if it's wanted, or leave this as a pointer to the fork if not.