- Nix 97.8%
- Shell 2.2%
| hosts/ess-helm | ||
| modules/nixos | ||
| overlays | ||
| pkgs | ||
| .envrc | ||
| .gitignore | ||
| .sops.yaml | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
ess-helm-nixos
NixOS module for Element Server Suite Community (ess-helm) on a single host: K3s + ingress-nginx inside, NixOS nginx as TLS-terminating reverse proxy in front.
Usage
{
inputs.ess-helm.url = "github:sid/ess-helm";
# ...
modules = [ ess-helm.nixosModules.ess-helm ];
}
{
services.ess-helm = {
enable = true;
serverName = "example.com";
openFirewall = true;
};
security.acme.defaults.email = "admin@example.com";
}
This deploys Synapse at example.com, MAS at auth., Element Web at chat., Element Admin at admin., Matrix RTC at mrtc. - all fronted by nginx with Let's Encrypt certificates. Override a subdomain via e.g. services.ess-helm.elementWeb.subdomain = "element";.
Notable options (see modules/nixos/ess-helm/ for all):
services.ess-helm.turn.tls.enable = true; # TURNS relay for restrictive firewalls
services.ess-helm.database.type = "nixos"; # dedicated host PostgreSQL instead of in-chart
services.ess-helm.ess.version = "26.X.Y"; # chart pin (+ hash) upgrades
services.ess-helm.bridges.whatsapp = { # mautrix bridges
enable = true;
admin = "@admin:example.com";
};
With database.type = "nixos", set sops secrets ess-postgres.synapse and ess-postgres.mas. Bundled Postgres data is not migrated automatically.
Bots
Forgejo notifications
Forgejo can post repository/organisation events (push, PR, issues, ...) directly into a Matrix room via its built-in Matrix webhook - no bot deployment required, just a bot user + access token, provisioned automatically:
services.ess-helm.bots.forgejo.enable = true;
After deployment, retrieve the credentials:
kubectl -n ess-bots get secret forgejo-matrix-credentials \
-o jsonpath='{.data.access-token}' | base64 -d
Then in Forgejo (repo or org Settings -> Webhooks -> Add webhook -> Matrix):
- Homeserver URL:
https://<serverName>(also stored ashomeserver-urlin the Secret) - Room: the room ID (e.g.
!abc123:<serverName>) - Access token: the value retrieved above
Use "Test delivery" to verify. To re-provision the token: kubectl -n ess-bots delete secret forgejo-matrix-credentials && systemctl restart ess-bot-forgejo-provision.
baibot (AI bot)
baibot is a standalone AI (LLM) Matrix bot. The module provisions the bot user + access token via MAS, deploys baibot into the baibot namespace and keeps its SQLite/session data on a PVC.
Non-secret config
services.ess-helm.bots.baibot = {
enable = true;
admin = "@admin:example.com";
config = {
agents.static_definitions = [
{
id = "ollama";
provider = "ollama";
config = {
base_url = "http://ollama.example.com:11434/v1";
api_key = null;
text_generation.model_id = "gemma2:2b";
};
}
];
initial_global_config.handler.text_generation = "ollama";
};
};
Secret config
To provide API keys and other optional secrets, provide a complete config.yml via sops instead:
Add a key ess-helm/baibot-config your secrets.yaml containing a full baibot config.yml. See upstream config.yml.dist at the pinned image tag.
services.ess-helm.bots.baibot = {
enable = true;
admin = "@admin:example.com";
secretsFile = config.sops.secrets."ess-helm/baibot-config".path;
};
Usage
Invite @baibot:<serverName> to a room or open a DM with it.
!bai help lists the available commands.
After the first start, the bot's runtime configuration is managed via chat (!bai config ...) as a bot admin.
Troubleshooting
systemctl status ess-bot-baibot-provision: Matrix user + token provisioning. Re-provision withkubectl -n baibot delete secret baibot-matrix-credentials && systemctl restart ess-bot-baibot-provision.kubectl -n baibot logs deploy/baibot: bot logs. The pod stays inCreateContainerConfigErroruntil the credentials Secret exists; it starts automatically afterwards.
DNS
One A record per hostname pointing at the host: example.com, auth., chat., admin., mrtc. (and turn. when TURNS is enabled).
Firewall
| Port | Protocol | Purpose |
|---|---|---|
| 80/443 | TCP | HTTP (ACME) / HTTPS |
| 30001 | TCP | Matrix RTC WebRTC |
| 30002 | UDP | Matrix RTC WebRTC (muxed) |
| 30003 | TCP | TURNS (when turn.tls.enable) |
| 30004 | UDP | plain TURN (otherwise) |