{
  lib,
  config,
  globals,
  ...
}: {
  options.nextcloud.enable = lib.mkEnableOption "nextcloud";

  config = lib.mkIf config.nextcloud.enable {
    kubernetes.resources = {
      secrets.database.stringData.databasePassword = "ref+sops://secrets.yml#/nextcloud/databasePassword";

      deployments = {
        server.spec = {
          selector.matchLabels = {
            app = "nextcloud";
            component = "server";
          };

          strategy = {
            type = "RollingUpdate";

            rollingUpdate = {
              maxSurge = 0;
              maxUnavailable = 1;
            };
          };

          template = {
            metadata.labels = {
              app = "nextcloud";
              component = "server";
            };

            spec = {
              volumes.data.persistentVolumeClaim.claimName = "data";

              containers.nextcloud = {
                image = globals.images.nextcloud;
                ports.web.containerPort = 80;

                env = {
                  POSTGRES_USER.value = "nextcloud";
                  POSTGRES_DB.value = "nextcloud";
                  POSTGRES_HOST.value = "lewis.dmz";

                  POSTGRES_PASSWORD.valueFrom.secretKeyRef = {
                    name = "database";
                    key = "databasePassword";
                  };
                };

                volumeMounts = [
                  {
                    name = "data";
                    mountPath = "/var/www/html";
                  }
                ];
              };

              securityContext = {
                fsGroup = 33;
                fsGroupChangePolicy = "OnRootMismatch";
              };

              affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution = [
                {
                  weight = 1;
                  preference.matchExpressions = [
                    {
                      key = "storageType";
                      operator = "In";
                      values = ["fast"];
                    }
                  ];
                }
              ];
            };
          };
        };

        database.spec = {
          selector.matchLabels = {
            app = "nextcloud";
            component = "database";
          };

          strategy = {
            type = "RollingUpdate";

            rollingUpdate = {
              maxSurge = 0;
              maxUnavailable = 1;
            };
          };

          template = {
            metadata.labels = {
              app = "nextcloud";
              component = "database";
            };

            spec = {
              containers.postgres = {
                image = globals.images.postgres15;
                imagePullPolicy = "IfNotPresent";
                ports.postgres.containerPort = 5432;

                env = {
                  POSTGRES_DB.value = "nextcloud";
                  POSTGRES_USER.value = "nextcloud";
                  PGDATA.value = "/pgdata/data";

                  POSTGRES_PASSWORD.valueFrom.secretKeyRef = {
                    name = "database";
                    key = "databasePassword";
                  };
                };

                volumeMounts = [
                  {
                    name = "database";
                    mountPath = "/pgdata";
                  }
                ];
              };

              volumes.database.persistentVolumeClaim.claimName = "database";
            };
          };
        };
      };

      services = {
        server.spec = {
          type = "LoadBalancer";
          loadBalancerIP = globals.nextcloudIPv4;

          selector = {
            app = "nextcloud";
            component = "server";
          };

          ports.web = {
            port = 80;
            targetPort = "web";
          };
        };

        database.spec = {
          selector = {
            app = "nextcloud";
            component = "database";
          };

          ports.postgres = {
            port = 5432;
            targetPort = "postgres";
          };
        };
      };
    };

    lab = {
      tailscaleIngresses.tailscale = {
        host = "nextcloud";
        service.name = "server";
      };

      longhorn.persistentVolumeClaim = {
        data = {
          volumeName = "nextcloud";
          storage = "50Gi";
        };

        database = {
          volumeName = "nextcloud-db";
          storage = "400Mi";
        };
      };
    };
  };
}