- TypeScript 98.4%
- HTML 1.1%
- JavaScript 0.2%
- Just 0.1%
| .github | ||
| docker | ||
| docs | ||
| LICENSES | ||
| public | ||
| src | ||
| .dockerignore | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .prettierignore | ||
| .watchmanconfig | ||
| eslint.config.js | ||
| justfile | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| REUSE.toml | ||
| tsconfig.json | ||
| vite.config.ts | ||
| yarn.lock | ||
Ketesa
The evolution of Synapse Admin. Manage users, rooms, media, and federation across your Matrix homeserver from one web interface. Formerly Synapse Admin.
About
Ketesa began as a fork of Awesome-Technologies/synapse-admin and quietly grew into its own thing. The interface got a full redesign, it now covers far more of the Synapse and MAS admin APIs than the original ever did, it speaks ten languages, and it's picked up a pile of management tools the original never had.
Already running synapse-admin? Switching over is genuinely nothing. Ketesa is a drop-in replacement with no config changes, so take your pick:
| Method | How |
|---|---|
| Hosted (CDN) | Open admin.etke.cc and point it at your homeserver, nothing to install |
| Docker | Swap your image tag to ghcr.io/etkecc/ketesa:latest |
| Static files | Drop the Ketesa release tarball where your current dist directory lives |
One private server or a federated community with thousands of users, it's the same tool either way.
Questions? Come say hi in the community room or open an issue.
Features
User management
Everything you'd do to an account lives on one page. Suspend someone, shadow-ban them, deactivate or erase the account outright. Set rate limits, flip on experimental features, dig into account data. Third-party IDs, devices (create, rename, delete), room memberships, and cross-signing keys are all right there too. Got a whole batch to onboard? Hand CSV import a file and it registers everyone at once, third-party IDs and all. Passwords generate on demand or you set them by hand, and every avatar wears a role badge (admin, bot, support, federated, system-managed) so you know what you're dealing with before you click in.
Running Matrix Authentication Service (MAS)? Ketesa grows a whole MAS-native side: browse and revoke active sessions (compat, OAuth2, personal), manage linked email addresses, check upstream OAuth provider links, and create users straight through MAS.
Room management
See every room on your server, then act on any of them: block or unblock, purge history, or delete a room outright. The messages viewer walks room history with filters and jump-to-date, and spaces get their own hierarchy tab. You can hand out room-admin rights and pull users into rooms straight from the UI, and media can be quarantined, protected, or deleted by file, by user, or by whole room.
Room management guide · Media management guide
Authentication
Log in however your server expects: username and password, a raw access token, or OIDC/SSO. Ketesa speaks Matrix Authentication Service (MAS) natively, session management and registration tokens included, and when Synapse hands authentication off to an external provider, a dedicated external auth provider mode reshapes the interface to match.
Customization
Every data table is built on react-admin's Configurable component, so you can show, hide, and reorder columns to taste, no code required.
And there's a deployment-level layer on top of those per-user preferences. A config.json
file (or your homeserver's /.well-known/matrix/client) lets you
restrict which homeservers people can connect to,
add your own navigation items,
pre-fill the login form,
tune CORS credentials,
and shield appservice-managed users (bridge puppets) from accidental edits.
Server statistics
Wondering what's eating your disk? Built-in stats break down per-user media usage and database room size. The federation overview tells you which remote destinations are healthy and which have gone unreachable, and reported events land in a list you can review and act on without leaving the page.
Server statistics guide · Federation guide · Event reports guide
Ten languages
Ketesa is fully translated into ten languages: English, German, French, Japanese, Russian, Persian, Ukrainian, Chinese, Italian, and Portuguese. Fully meaning fully, every string, with no half-translated screens or stray English left sitting in the other locales.
Mobile support
The whole interface is responsive, so running your server from a phone or tablet actually works. Tables fold down into readable lists on a small screen, long identifiers wrap instead of running off the edge, and every action you'd reach for on desktop is still there.
Built and maintained by etke.cc
Ketesa is built and maintained by etke.cc, a managed Matrix hosting provider. Everything you've read about so far is open source and free for anyone to use, developed in the open at github.com/etkecc.
And if you happen to host your server with etke.cc, that same admin interface doubles as the control panel for the platform itself. These are the same screens you already use for users and rooms; they just light up when there's an etke.cc platform behind them to talk to:
| Feature | What it does |
|---|---|
| Server health | A live status badge in the toolbar and a dashboard covering every server component, with color-coded indicators, error details, and suggested actions. |
| Notifications | Server events appear as an in-app feed with an unread badge. |
| Server actions | Run management commands on demand, schedule them for a specific time, or set up recurring weekly jobs. |
| Components | Browse, add, and remove server add-ons (bridges, bots, apps) from a self-service catalogue, with the cost impact shown before you commit. |
| Billing | View payment history and transaction details, and download invoices, without leaving the admin panel. |
| Support | Open support requests, track their progress, and exchange messages with etke.cc support from the same interface. |
| White-labelling | Custom name, logo, favicon, and background, applied automatically from the platform with no extra configuration. |
Learn more about etke.cc managed Matrix hosting.
Availability
| Where | Details |
|---|---|
| etke.cc | Managed hosting with Ketesa built in |
| admin.etke.cc | Hosted instance, always on the latest development version |
| GitHub Releases | Official prebuilt tarballs for root-path and /admin deployments |
| GHCR / Docker Hub | Official container images |
| Source | Build from source or track main directly |
Official static builds:
ketesa.tar.gzfor root path deployment, such ashttps://admin.example.comketesa-subpath-admin.tar.gzfor/admindeployments, such ashttps://example.com/admin
For nightly builds, distro packages, Ansible integrations, and IPFS, see the full availability guide.
Configuration
There are two ways to configure Ketesa. The straightforward one is a config.json file in the
deployment root. The convenient one is your homeserver's /.well-known/matrix/client file: drop
Ketesa's settings under the cc.etke.ketesa key and every instance pointed at that homeserver picks
them up on its own, so you never have to touch each deployment by hand. When both are present,
/.well-known/matrix/client wins.
Note: The legacy key
cc.etke.synapse-adminis still supported for backward compatibility, but is deprecated. Please migrate tocc.etke.ketesaat your convenience.
If you use spantaleev/matrix-docker-ansible-deploy or
etkecc/ansible,
configuration is automatically written to /.well-known/matrix/client for you.
To inject a config.json into a Docker container, use a bind mount:
services:
ketesa:
...
volumes:
- ./config.json:/var/public/config.json:ro
...
Prefilling the login form
Every field on the login page can be pre-filled via URL query parameters, which is handy for sharing direct-access links with your users.
Restricting available homeservers
Lock down the homeserver selection so users can only connect to servers you approve. Useful for managed deployments where the homeserver should never change.
Configuring CORS credentials
Fine-tune the CORS credentials mode for your Ketesa deployment to match your server's cross-origin policies.
Protecting appservice-managed users
Bridge puppets and other appservice-managed accounts can be shielded from accidental edits. Specify a list of MXID patterns (as regular expressions) to be restricted to display name and avatar changes only.
Adding custom menu items
Extend the navigation menu with links to your own tools or documentation, no rebuild required.
External auth provider mode
When Synapse delegates authentication to an external provider (OIDC, LDAP, and similar), enable this mode to adjust Ketesa's behavior accordingly and avoid confusing UI elements that don't apply in your setup.
Matrix Authentication Service (MAS)
MAS requires a small amount of additional configuration to enable its admin API. See the designated MAS section for the details.
Usage
Supported APIs
See Supported APIs for a full list of API endpoints used by Ketesa.
Supported Synapse versions
Ketesa needs Synapse v1.150.0 or newer for everything to work as intended.
Not sure what you're running? Call /_synapse/admin/v1/server_version, or just glance at the version
indicator that shows up under the homeserver URL field on the login page.
See also: Synapse version API
Prerequisites
Your browser needs access to the following endpoints on your homeserver:
/_matrix/_synapse/admin
See also: Synapse administration endpoints
Use without installing anything
The hosted build at admin.etke.cc is always current and needs no installation. Open it, type in your homeserver URL, and log in with your admin account. That's the whole setup.
Your browser must be able to reach
/_synapse/adminon your homeserver. The endpoints do not need to be exposed to the public internet; access from your local network is enough.
Step-by-step installation
Choose a method:
| Method | Best for |
|---|---|
| Tarball + webserver | Any static hosting, full control |
| Source + Node.js | Development or custom builds |
| Docker | Containerized deployments |
Steps for 1)
- Make sure you have a webserver installed that can serve static files (nginx, Apache, Caddy, or anything else will work)
- Configure a virtual host for Ketesa on your webserver
- Download the appropriate
.tar.gzfrom the latest release:ketesa.tar.gzfor root path deployment (e.g.,https://admin.example.com)ketesa-subpath-admin.tar.gzfor/adminsubpath deployment (e.g.,https://example.com/admin)
- Unpack the archive and place the contents in your virtual host's document root
- Open the URL in your browser
Reverse proxy configuration examples
Steps for 2)
- Make sure you have git, yarn, and Node.js installed
- Clone the repository:
git clone https://github.com/etkecc/ketesa.git - Enter the directory:
cd ketesa - Install dependencies:
yarn install - Start the development server:
yarn start
Steps for 3)
-
Run the Docker container:
docker run -p 8080:8080 ghcr.io/etkecc/ketesaOr use the provided docker-compose.yml:
docker-compose -f docker/docker-compose.yml up -dNote: If you're building on a non-amd64 architecture (e.g., Raspberry Pi), set a Node.js memory cap to prevent OOM failures during the build:
NODE_OPTIONS="--max_old_space_size=1024".Note: On IPv4-only systems, set
SERVER_HOST=0.0.0.0so Ketesa binds correctly.To build your own image from source:
services: ketesa: container_name: ketesa hostname: ketesa build: context: https://github.com/etkecc/ketesa.git dockerfile: docker/Dockerfile.build args: - BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 # - NODE_OPTIONS="--max_old_space_size=1024" # - BASE_PATH="/ketesa" ports: - "8080:8080" restart: unless-stopped -
Open http://localhost:8080 in your browser
Serving Ketesa under a custom path
The base path is baked in at build time and cannot be changed at runtime.
- For
/adminspecifically: use the prebuiltketesa-subpath-admintarball from GitHub Releases or thedist-subpath-adminartifact from GitHub Actions, or the*-subpath-adminDocker image tag. - For root path: use
ketesa.tar.gzor thedist-rootartifact. - For any other prefix: build from source with
yarn build --base=/my-prefix, or pass theBASE_PATHbuild argument to Docker.
If you need a reverse proxy to expose Ketesa under a different base path without rebuilding, here is a Traefik example:
docker-compose.yml
services:
traefik:
image: traefik:v3
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ketesa:
image: ghcr.io/etkecc/ketesa:latest
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.admin.rule=Host(`example.com`) && PathPrefix(`/admin`)"
- "traefik.http.services.admin.loadbalancer.server.port=8080"
- "traefik.http.middlewares.admin-slashless-redirect.redirectregex.regex=(/admin)$$"
- "traefik.http.middlewares.admin-slashless-redirect.redirectregex.replacement=$${1}/"
- "traefik.http.middlewares.admin-strip-prefix.stripprefix.prefixes=/admin"
- "traefik.http.routers.admin.middlewares=admin-slashless-redirect,admin-strip-prefix"
Development
- See https://yarnpkg.com/getting-started/editor-sdks for IDE setup instructions
| Command | What it does |
|---|---|
yarn lint |
Run all style and linter checks |
yarn test |
Run all unit tests |
yarn fix |
Auto-fix coding style issues |
just run-dev |
Spin up the full local development stack |
just run-dev launches a complete local environment: a Synapse homeserver, Element Web, and a Postgres
database. The app starts in development mode at http://localhost:5173.
(If user creation fails on first run, re-run the command; the server may still be starting up.)
Open http://localhost:5173 and log in with:
| Field | Value |
|---|---|
| Login | admin |
| Password | admin |
| Homeserver URL | http://localhost:8008 |
Element Web is available at http://localhost:8080.

