summaryrefslogtreecommitdiff
path: root/hosts/surtr/http/webdav/default.nix
blob: f0aec1e9d7793ee4b25341d327df00f40dc5eb51 (plain)
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
{ config, libs, pkgs, flakeInputs, ... }:
let
  webdavSocket = config.services.uwsgi.runDir + "/webdav.sock";

  webdavApp = flakeInputs.mach-nix.lib.${config.nixpkgs.system}.buildPythonPackage {
    ignoreDataOutdated = true;
    pname = "py-webdav";
    version = builtins.readFile ./py-webdav/VERSION;
    src = ./py-webdav;
    python = "python3";
    requirements = ''
      PyNaCl ==1.5.*
      psycopg ==3.0.*
      WsgiDAV ==4.0.*
    '';
  };
in {
  config = {
    security.pam.services."webdav".text = ''
      auth requisite  pam_succeed_if.so user ingroup webdav quiet_success
      auth required   pam_unix.so likeauth nullok nodelay quiet
      account sufficient pam_unix.so quiet
    '';
    users.groups."webdav" = {};
    
    services.nginx = {
      upstreams."py-webdav" = {
        servers = {
          "unix://${webdavSocket}" = {};
        };
      };
      
      virtualHosts."webdav.141.li" = {
        forceSSL = true;
        sslCertificate = "/run/credentials/nginx.service/webdav.141.li.pem";
        sslCertificateKey = "/run/credentials/nginx.service/webdav.141.li.key.pem";
        sslTrustedCertificate = "/run/credentials/nginx.service/webdav.141.li.chain.pem";
        locations = {
          "/".extraConfig = ''
            root /srv/files/$remote_user;            

            auth_pam "WebDAV";
            auth_pam_service_name "webdav";
          '';

          "/py/".extraConfig = ''
            rewrite ^/py(.*) $1 break;

            include ${config.services.nginx.package}/conf/uwsgi_params;
            uwsgi_param SCRIPT_NAME /py;
            uwsgi_pass py-webdav;
          '';
        };
        extraConfig = ''
          dav_methods     PUT DELETE MKCOL COPY MOVE;
          dav_ext_methods PROPFIND OPTIONS;
          dav_access      user:rw;
          autoindex on;

          client_max_body_size    0;
          create_full_put_path    on;

          add_header Strict-Transport-Security "max-age=63072000" always;
        '';
      };
    };
    security.acme.domains."webdav.141.li" = {
      certCfg = {
        postRun = ''
          ${pkgs.systemd}/bin/systemctl try-restart nginx.service
        '';
      };
    };

    systemd.services.nginx.serviceConfig.LoadCredential = [
      "webdav.141.li.key.pem:${config.security.acme.certs."webdav.141.li".directory}/key.pem"
      "webdav.141.li.pem:${config.security.acme.certs."webdav.141.li".directory}/fullchain.pem"
      "webdav.141.li.chain.pem:${config.security.acme.certs."webdav.141.li".directory}/chain.pem"
    ];


    services.uwsgi.instance.vassals.webdav = {
      type = "normal";
      socket = webdavSocket;
      listen = 1024;
      master = true;
      vacuum = true;
      chown-socket = "${config.services.nginx.user}:${config.services.uwsgi.group}";
      
      plugins = ["python3"];
      pythonPackages = self: [webdavApp];
      module = "webdav";
      callable = "app";
    };
  };
}