ess-helm-nixos/README.md

2.9 KiB

ess-helm-nixos

NixOS configuration for hosting Element Server Suite Community on a single VPS using K3s, Helm, and NixOS-managed nginx as the TLS-terminating reverse proxy.

Architecture

Internet
   |
   v :80 / :443
NixOS nginx  (TLS via Let's Encrypt / ACME)
   |
   v :30080 (plain HTTP)
K3s ingress-nginx
   |
   v ClusterIP
ESS Helm chart
   ├── Synapse          ess-helm.de
   ├── MAS              auth.ess-helm.de
   ├── Element Web      chat.ess-helm.de
   ├── Element Admin    admin.ess-helm.de
   └── Matrix RTC SFU   mrtc.ess-helm.de  (:30001 TCP / :30002 UDP direct)

Matrix user IDs: @user:ess-helm.de

DNS setup

Create the following A records pointing to the VPS public IP:

Record Type Value
ess-helm.de A <VPS public IP>
auth.ess-helm.de A <VPS public IP>
chat.ess-helm.de A <VPS public IP>
admin.ess-helm.de A <VPS public IP>
mrtc.ess-helm.de A <VPS public IP>

Firewall

Port Protocol Purpose
80 TCP HTTP (ACME challenge + redirect to HTTPS)
443 TCP HTTPS (all ESS services via nginx)
30001 TCP Matrix RTC WebRTC TCP transport
30002 UDP Matrix RTC WebRTC muxed UDP transport

Verification

Usage

# flake.nix
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";

    ess-helm.url = "github:sid/ess-helm";
    ess-helm.inputs.nixpkgs.follows = "nixpkgs";

    synix.url = "git+https://git.sid.ovh/sid/synix.git?ref=release-25.11";
    synix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, nixpkgs, ess-helm, synix, ... }: {
    nixosConfigurations.my-server = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ess-helm.nixosModules.ess-helm
        synix.nixosModules.nginx
        ./configuration.nix
      ];
    };
  };
}
# configuration.nix
{
  services.ess-helm = {
    enable = true;
    serverName = "example.com";
    openFirewall = true;
    configureNginx = true;
  };

  security.acme.defaults.email = "admin@example.com";
  services.nginx = {
    enable = true;
    openFirewall = true;
    forceSSL = true;
  };
}

Subdomains default to auth., chat., admin., mrtc.. Override individually if needed:

services.ess-helm.elementWeb.subdomain = "element";  # -> element.example.com

Upgrade the ESS or ingress-nginx chart version:

services.ess-helm.ess = {
  version = "26.X.Y";
  hash = "...";
};

References