- Rust 78.2%
- HTML 21.3%
- Dockerfile 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
docker / build (push) Successful in 3m31s
New mytsaccount check (needs MYTS_EMAIL/MYTS_PASSWORD, skipped without): log in with a session, validate it, read the settings sync (requestServerItems), the badge service (getBadges) and the chat backend (getActiveIdentifierList), then log out with deleteSession. A green check means those backends served a real account, not just that login answers. Every run opens and closes one session on the account. All calls were verified against the live API: session validation answers ErrorCommon 102, the sync status 300/301/302 all mean the service works, getBadges lists badges with no error field on success, and the tschat error_handling must carry ChatRequestReturnCode 1 (SUCCESS). The password hash question is settled too: the client's binary salts PBKDF2 with lower(email)+"ts3Login"+password for 10000 rounds, exactly like the web app. Matrix credentials stay unreadable: the sync items are end-to-end encrypted, so the chat check ends at the tschat backend. |
||
| .forgejo/workflows | ||
| src | ||
| static | ||
| .dockerignore | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| config.toml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
TeamSpeak online status
Small self-hosted status page for TeamSpeak's online services. Unofficial.
Checked by default (see config.toml):
| Group | Check |
|---|---|
| Website | https://teamspeak.com/ answers 2xx and contains "TeamSpeak" |
| myTeamSpeak | web app, API index, products and addons from the database (plus one addon file), login, account round trip (sync, badges, chat backend) |
| Chat (Matrix) | chat.teamspeak.com plus every chat-<n>.tmspk.net found via DNS, and federation between them |
| Downloads | every server and client release in the versions JSON exists; one server release's checksum |
| Other | community forum, chat push gateway (Sygnal /health), badge list (plus one badge image), license server |
Matrix homeservers are up when /_matrix/client/versions answers, and degraded
when /_matrix/federation/v1/version does not, or when they cannot federate:
each homeserver is asked for the next one's signing key (in a ring, plus any
peers, by default matrix.org for chat.teamspeak.com), newer than it can
have cached, so it has to fetch it over federation right then. These requests use the TS chat
client's User-Agent (matrix_user_agent), because TeamSpeak's proxy answers 503
to other clients on most homeservers.
The login check uses the protobuf API the TeamSpeak client uses
(POST https://clientapi.myteamspeak.com/authentication, content type
application/ts3cloud), because the web app's /api/login is behind a
Cloudflare bot check that plain HTTP clients fail. The body is the RPC method
name with a one byte length prefix followed by the serialized request message;
the answer is the serialized reply. The check sends login with
LoginData { email, password, skipSession }, the password hashed like the
client does, every 15 minutes:
- With
MYTS_EMAILandMYTS_PASSWORDset, the account must log in (code 200).skipSessionkeeps this from creating a session. Use a separate account without 2FA. If the credentials are rejected or need 2FA, the check says so, shows as unknown and falls back to the made-up account until the next restart, so a wrong password is not retried until the account locks. - Without them, a made-up account must be rejected (code 202,
ERROR_LOGIN_FAILED). That shows the gateway and login backend answer, but not that a real login works. Failed logins from one address might one day trip TeamSpeak's abuse protection, another reason to prefer an account.
The account check (mytsaccount, same environment variables, also every 15
minutes) walks one session through the services behind login: log in with a
session, validate it (session), read the settings sync
(requestServerItems), the badge service (getBadges) and the chat backend
(getActiveIdentifierList), then log out (deleteSession). A green result
means those backends served a real account; each run opens and closes one
session, which may show in the account's session list. It is skipped without
the environment variables. All calls are read-only except for the session
lifecycle itself; write calls (bookmarks, contacts, voice servers) are never
made. The chat backend hands out Matrix identifiers, but the synced data that
would contain Matrix credentials is end-to-end encrypted, so a scripted
end-to-end chat login is not possible through this API.
Checks with every run less often than the others and repeat their last
result in between. Any check slower than slow_ms
is degraded. A check that is not up is retried once, 5 seconds later, and only
the retry counts, so a single slow or failed request does not become an incident.
The monitor also checks its own internet connection against a few unrelated hosts
([connectivity]). If none answer, every service is shown as unknown for that
time instead of down, and unknown periods are left out of uptime numbers.
Individual check results (retention_days, default 7) feed the 24 hour bars
and the 24h/7d uptime. Daily summaries and incidents (summary_days, default
400) feed the 30 day uptime and the month by month overview; days and months are
UTC. Everything is kept in data/state.json.
Bot protection
Requests from outside the local network go through
Anubis (shipped in the Docker image), a
proof-of-work check that browsers pass automatically. Local clients
([anubis] local_networks, private ranges by default) get the page directly.
client ─▶ :8080 ─┬─ local ───────────────────────────▶ app
└─ other ─▶ Anubis 127.0.0.1:8923 ─▶ app 127.0.0.1:8081
Behind a reverse proxy the client address comes from X-Forwarded-For (or
X-Real-IP if there is no X-Forwarded-For), but only when the connection
comes from trusted_proxies (private ranges by default, or TRUSTED_PROXIES). The header is read
from the right, so addresses a client puts in front itself are ignored.
This relies on the proxy appending to or replacing X-Forwarded-For (nginx
$proxy_add_x_forwarded_for, Traefik and Caddy do); a proxy that passes the
client's header through unchanged lets clients claim a local address. If the
proxy is not trusted, every visitor looks like the proxy, which is local.
- Set
REDIRECT_DOMAINSin[anubis.env]to your public hostname. - Anubis cookies are
Secure, so outside access needs HTTPS (or setCOOKIE_SECURE = "false"). - Publish the port only to your reverse proxy or LAN. Some Docker setups (userland proxy) make every client appear as a local address.
- The signing key lives in
data/anubis.key, so passed checks survive restarts. - Remove the
[anubis]section to serve everyone directly.
Run
cargo run --release
# or
docker compose up -d --build
Then open http://localhost:8080.
Environment:
CONFIG: config path, defaultconfig.toml; the built-in copy is used if the file is missing.TRUSTED_PROXIES: comma separated networks or addresses whoseX-Forwarded-For/X-Real-IPare believed, e.g.172.16.0.0/12,192.168.0.10. Replaces[anubis] trusted_proxies; an empty value trusts no proxy.MYTS_EMAIL,MYTS_PASSWORD: myTeamSpeak account for the login check (optional, see above). Only the password hash is sent.RUST_LOG: log filter, defaultinfo.
Endpoints
/status page/api/statuscurrent status and the last 24 hours, as JSON/api/historydaily summaries per check and all incidents, as JSON/healthzliveness; 503 when no check round finished for 3 intervals