main
 1{
 2  config,
 3  ...
 4}:
 5{
 6  # XMPP server with Prosody - simplified configuration
 7  # VPN-only access at xmpp.sbr.pm (10.100.0.49)
 8
 9  services.prosody = {
10    enable = true;
11    admins = [ "vincent@xmpp.sbr.pm" ];
12
13    # SSL/TLS configuration
14    ssl = {
15      cert = "/var/lib/acme/xmpp.sbr.pm/fullchain.pem";
16      key = "/var/lib/acme/xmpp.sbr.pm/key.pem";
17    };
18
19    # Virtual host configuration
20    virtualHosts."xmpp.sbr.pm" = {
21      enabled = true;
22      domain = "xmpp.sbr.pm";
23      ssl = {
24        cert = "/var/lib/acme/xmpp.sbr.pm/fullchain.pem";
25        key = "/var/lib/acme/xmpp.sbr.pm/key.pem";
26      };
27    };
28
29    # Disable XEP-0423 compliance checking for now
30    xmppComplianceSuite = false;
31
32    # Security settings
33    c2sRequireEncryption = true; # Force TLS for client connections
34    allowRegistration = false; # Disable public registration
35  };
36
37  # ACME configuration
38  security.acme.acceptTerms = true;
39  security.acme.defaults.email = "vincent@sbr.pm";
40
41  # SSL certificates via ACME with Gandi DNS-01 challenge
42  security.acme.certs."xmpp.sbr.pm" = {
43    domain = "xmpp.sbr.pm";
44    dnsProvider = "gandiv5";
45    dnsResolver = "1.1.1.1:53"; # Use Cloudflare DNS for DNS-01 challenge
46    environmentFile = config.age.secrets."gandi.env".path;
47    group = "prosody"; # Allow prosody to read certificates
48    reloadServices = [ "prosody.service" ]; # Reload prosody when certificates are renewed
49    server = "https://acme-v02.api.letsencrypt.org/directory"; # Use Let's Encrypt production
50  };
51
52  # Age secret for Gandi API (shared with rhea for DNS-01 challenge)
53  age.secrets."gandi.env" = {
54    file = ../../secrets/rhea/gandi.env.age;
55    mode = "400";
56  };
57
58  # Firewall configuration - XMPP ports
59  networking.firewall.allowedTCPPorts = [
60    5222 # C2S (client-to-server) - main XMPP port
61  ];
62}