all repos — nixfiles @ 7fc398dded782164e47cc201405cf36570e5d8ff

System and user configuration, managed by nix and home-manager

system/roles/webserver/reverse-proxy.nix (view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{
  config,
  pkgs,
  ...
}:
{
  imports = [
    ../../settings/services/caddy.nix
  ];
  age.secrets = {
    # TS_AUTHKEY for caddy-tailscale plugin
    caddy.file = ../../../secrets/caddy.age;
  };

  security.acme.defaults = {
    email = "security@${config.networking.domain}";
    validMinDays = 32;
  };

  services.tailscale.permitCertUid = config.services.caddy.user;
  services.caddy = {
    environmentFile = config.age.secrets.caddy.path;
    package = pkgs.caddy.withPlugins {
      plugins = [
        "github.com/caddyserver/cache-handler@v0.16.0"
        "github.com/tailscale/caddy-tailscale@v0.0.0-20260106222316-bb080c4414ac"
        "github.com/caddy-dns/rfc2136@v1.0.0"
        "pkg.jsn.cam/caddy-defender@v0.10.1"
        "github.com/mholt/caddy-ratelimit@v0.1.1-0.20260521172720-16aecbbcb8ca"
      ];
      hash = "sha256-qaHc2jmyFJ/MwazQpcdLe/fmEB13X1MtvfVBUR/MymA=";
    };
    globalConfig = ''
      cache
      tailscale {
        tags tag:app
      }
    '';
    extraConfig = ''
      (rate_limit) {
        rate_limit {
          log_key
          zone global_static {
            match {
              query query=*
            }
            key static
            events 180
            window 1m
          }
          zone net_short {
            match {
              query query=*
            }
            key {remote_host}
            ipv4_prefix 24
            ipv6_prefix 56
            events 10
            window 5s
          }
        }
      }
      (defender) {
        defender ratelimit {
          ranges all
        }
        defender tarpit {
          tarpit_config {
            timeout 30s
            bytes_per_second 500
            response_code 200
          }
        }
      }
      (goaccess) {
        handle_path /stats/* {
          root /srv/http/access/{args[0]}
          file_server
          log_skip
        }
      }
    '';
  };

  users.groups.caddy.members = [ "alin" ];
  users.groups.webservice = {
    members = [ "caddy" ];
  };
  systemd.tmpfiles.rules = [
    # setgid bit (2)
    # sticky bit (4)
    "d /run/web/ 6770 caddy webservice -"
  ];
  systemd.services.caddy.serviceConfig = {
    ReadWritePaths = [ "/run/web" ];
  };

  boot.kernel.sysctl =
    let
      buffer_size = 16 * 1024 * 1024;
      server_count = 2;
      max_clients = 100;
      page_size = 4096;
      # This server might have 100 clients simultaneously, so:
      #   max(tcp_wmem) * 2 * 100 / 4096
      mem = toString (buffer_size * server_count * max_clients / page_size);
    in
    {
      # Provide adequate buffer memory.
      # rmem_max and wmem_max are TCP max buffer size
      # settable with setsockopt(), in bytes
      # tcp_rmem and tcp_wmem are per socket in bytes.
      # tcp_mem is for all TCP streams, in 4096-byte pages.
      # The following are suggested on IBM's
      # High Performance Computing page
      "net.core.rmem_max" = buffer_size;
      "net.core.wmem_max" = buffer_size;
      "net.core.rmem_default" = buffer_size;
      "net.core.wmem_default" = buffer_size;
      "net.ipv4.tcp_rmem" = "4096 87380 ${toString buffer_size}";
      "net.ipv4.tcp_wmem" = "4096 87380 ${toString buffer_size}";
      "net.ipv4.tcp_mem" = "${mem} ${mem} ${mem}";

      "net.ipv4.tcp_sack" = 0;
      "net.ipv4.tcp_dsack" = 0;

      "net.ipv4.tcp_slow_start_after_idle" = 0;
    };

}