Skip to content

Traefik

Traefik is the reverse proxy and TLS termination point for all services. It runs in a NixOS container on the host network (no private network).

Source: server/containers/traefik.nix

Network

PropertyValue
Private networkNo (host network)
Ports80 (HTTP), 443 (HTTPS)
SubdomainN/A (routes to other services)

TLS Configuration

Certificate Resolution

Certificates are obtained from Let's Encrypt using the DNS-01 challenge via Cloudflare:

nix
certificatesResolvers.letsencrypt.acme = {
  email = "test.rearrange726@passfwd.com";
  storage = "${config.services.traefik.dataDir}/acme.json";
  dnsChallenge = {
    provider = "cloudflare";
    resolvers = [ "1.1.1.1:53" "8.8.8.8:53" ];
  };
};

The Cloudflare DNS API token is provided via agenix:

nix
age.secrets.cloudflare_dns_token = {
  mode = "440";
  owner = "traefik";
  group = "traefik";
  file = ../secrets/cloudflare_dns_token.age;
};

The secret is passed to Traefik via environmentFiles, which sets the CF_DNS_API_TOKEN environment variable.

TLS Versions

Two TLS profiles are defined:

Default (strict):

nix
default = {
  sniStrict = true;
  minVersion = "VersionTLS13";
};

Intermediate (for older clients):

nix
intermediate = {
  minVersion = "VersionTLS12";
  cipherSuites = [
    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"
    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
  ];
};

The default profile enforces TLS 1.3 with strict SNI. Services that need TLS 1.2 compatibility can reference the intermediate profile.

Entrypoints

nix
entryPoints = {
  web = {
    address = ":80";
    http.redirections.entrypoint = { to = "websecure"; scheme = "https"; };
  };
  websecure = {
    address = ":443";
    asDefault = true;
    http.tls.certResolver = "letsencrypt";
  };
};
  • Port 80 -- HTTP, always redirects to HTTPS.
  • Port 443 -- HTTPS, default entrypoint with automatic TLS.

API & Dashboard

Both are disabled for security:

nix
api = {
  debug = false;
  insecure = false;
  dashboard = false;
};

Dynamic Configuration

Traefik's dynamic configuration (routers, services, middlewares) is not defined in this file. Instead, each service module injects its own routing configuration:

nix
# In containers/immich.nix:
containers.traefik.config.services.traefik.dynamicConfigOptions.http = {
  services.immich.loadBalancer.servers = [{ url = "http://10.10.10.5:2283"; }];
  routers.immich = {
    rule = "Host(`photos.nemnix.site`)";
    service = "immich";
    entrypoints = [ "websecure" ];
    middlewares = [ "authelia" ];
  };
};

NixOS module merging combines all these definitions into a single Traefik configuration. This is a powerful pattern that keeps routing config co-located with each service.

Route Summary

SubdomainServiceAuthelia
auth.nemnix.siteAutheliaNo
adguard.nemnix.siteAdGuard HomeYes
photos.nemnix.siteImmichYes
vault.nemnix.siteVaultwardenNo
cloud.nemnix.siteOpenCloudNo

Logging

nix
log = {
  level = "INFO";
  format = "json";
};

Structured JSON logging at INFO level. Access logs are not explicitly configured.