{ lib, config, pkgs, ... }: let localhost = config.my.localhost; collaboraPort = 9980; url = "cloud.${config.my.domain}"; collaboraProxy = "http://${localhost}:${toString collaboraPort}"; commonProxyConfig = '' proxy_set_header Host $host; ''; commonWebsocketConfig = '' proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; proxy_read_timeout 36000s; ''; in { options.my.servers = { nextcloud = { enable = lib.mkEnableOption "enable"; enableCron = lib.mkEnableOption "enable"; }; collabora.enable = lib.mkEnableOption "enable"; go-vod.enable = lib.mkEnableOption "enable"; }; config = lib.mkIf (config.my.servers.nextcloud.enable && config.my.servers.postgres.enable) { sops.secrets = { smtp-password = { }; nextcloud-adminpass = { owner = config.users.users.nextcloud.name; inherit (config.users.users.nextcloud) group; }; }; nixpkgs.config.permittedInsecurePackages = [ "nodejs-14.21.3" "openssl-1.1.1v" ]; users.users.nextcloud = { isSystemUser = true; extraGroups = [ "render" ]; packages = (with pkgs; [ mediainfo nodejs (python3.withPackages (ps: with ps; [ tensorflow ])) perl (perlPackages.buildPerlPackage rec { pname = "Image-ExifTool"; version = "12.70"; src = fetchurl { url = "https://exiftool.org/Image-ExifTool-${version}.tar.gz"; hash = "sha256-TLJSJEXMPj870TkExq6uraX8Wl4kmNerrSlX3LQsr/4="; }; }) ]); }; programs.msmtp = { enable = true; accounts.default = { auth = true; host = "smtp.gmail.com"; port = 587; tls = true; from = config.my.smtpemail; user = config.my.smtpemail; passwordeval = "cat ${config.sops.secrets.smtp-password.path}"; }; }; services = { nextcloud = { enable = true; https = true; package = pkgs.nextcloud29; appstoreEnable = true; configureRedis = true; extraAppsEnable = true; enableImagemagick = true; maxUploadSize = "16G"; hostName = url; extraApps = { inherit (config.services.nextcloud.package.packages.apps) calendar; }; config = { adminpassFile = config.sops.secrets.nextcloud-adminpass.path; dbtype = "pgsql"; dbhost = config.my.postgresSocket; dbtableprefix = "oc_"; dbname = "nextcloud"; }; phpOptions = { catch_workers_output = "yes"; display_errors = "stderr"; error_reporting = "E_ALL & ~E_DEPRECATED & ~E_STRICT"; expose_php = "Off"; "opcache.enable_cli" = "1"; "opcache.fast_shutdown" = "1"; "opcache.interned_strings_buffer" = "16"; "opcache.jit" = "1255"; "opcache.jit_buffer_size" = "256M"; "opcache.max_accelerated_files" = "10000"; "opcache.huge_code_pages" = "1"; "opcache.enable_file_override" = "1"; "opcache.memory_consumption" = "128"; "opcache.revalidate_freq" = "60"; "opcache.save_comments" = "1"; "opcache.validate_timestamps" = "0"; "openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt"; preview_max_x = 512; preview_max_y = 512; short_open_tag = "Off"; }; settings = { log_type = "file"; log_level = 3; trusted_proxies = [ "192.168.0.1" "192.168.0.0/24" "10.0.0.0/8" ]; trusted_domains = [ "cloud.rotehaare.art" "danilo-reyes.com" ]; overwrite_protocol = "https"; default_phone_region = "MX"; "allow_local_remote_servers" = true; mail_smtpmode = "sendmail"; mail_sendmailmode = "pipe"; "installed" = true; "memories.exiftool" = "/etc/profiles/per-user/nextcloud/bin/exiftool"; enabledPreviewProviders = [ "OC\\Preview\\Image" "OC\\Preview\\HEIC" "OC\\Preview\\TIFF" "OC\\Preview\\MKV" "OC\\Preview\\MP4" "OC\\Preview\\AVI" "OC\\Preview\\Movie" ]; }; phpExtraExtensions = all: [ all.pdlib all.bz2 ]; # phpExtraExtensions = all: [ ]; }; nginx = { enable = true; virtualHosts = { ${config.services.nextcloud.hostName} = { forceSSL = true; enableACME = true; http2 = true; serverAliases = [ "cloud.rotehaare.art" ]; locations = { "/".proxyWebsockets = true; "~ ^/nextcloud/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|oc[ms]-provider/.+|.+/richdocumentscode/proxy).php(?:$|/)" = { }; }; }; "collabora.${config.my.domain}" = lib.mkIf config.my.servers.collabora.enable { forceSSL = true; enableACME = true; http2 = true; locations = { # static files "^~ /loleaflet" = { proxyPass = collaboraProxy; extraConfig = commonProxyConfig; }; # WOPI discovery URL "^~ /hosting/discovery" = { proxyPass = collaboraProxy; extraConfig = commonProxyConfig; }; # Capabilities "^~ /hosting/capabilities" = { proxyPass = collaboraProxy; extraConfig = commonProxyConfig; }; # download, presentation, image upload and websocket "~ ^/lool" = { proxyPass = collaboraProxy; extraConfig = commonWebsocketConfig; }; # Admin Console websocket "^~ /lool/adminws" = { proxyPass = collaboraProxy; extraConfig = commonWebsocketConfig; }; }; }; }; }; }; virtualisation.oci-containers = { backend = "docker"; containers = { go-vod = lib.mkIf config.my.servers.go-vod.enable { autoStart = true; image = "radialapps/go-vod"; environment = { TZ = "America/Mexico_City"; NEXTCLOUD_HOST = "https://${config.services.nextcloud.hostName}"; NVIDIA_VISIBLE_DEVICES = "all"; }; volumes = [ "ncdata:/var/www/html:ro" ]; extraOptions = [ "--device=/dev/dri" # VA-API (omit for NVENC) ]; }; collabora = lib.mkIf config.my.servers.collabora.enable { autoStart = true; image = "collabora/code"; imageFile = pkgs.dockerTools.pullImage { imageName = "collabora/code"; imageDigest = "sha256:aab41379baf5652832e9237fcc06a768096a5a7fccc66cf8bd4fdb06d2cbba7f"; sha256 = "sha256-M66lynhzaOEFnE15Sy1N6lBbGDxwNw6ap+IUJAvoCLs="; }; ports = [ "9980:9980" ]; environment = { TZ = "America/Mexico_City"; domain = url; aliasgroup1 = "${url}:443"; aliasgroup2 = "cloud.rotehaare.art:443"; dictionaries = "en_CA en_US es_MX es_ES fr_FR it pt_BR ru"; extra_params = '' --o:ssl.enable=false --o:ssl.termination=true ''; }; extraOptions = [ "--cap-add" "MKNOD" ]; }; }; }; systemd = lib.mkIf config.my.servers.nextcloud.enableCron { services = { nextcloud-cron.path = [ pkgs.perl ]; nextcloud-cronjob = let nextcloud-cronjob = pkgs.writeScriptBin "nextcloud-cronjob" (builtins.readFile ../../scripts/nextcloud-cronjob.sh); in { description = "Runs various nextcloud-related cronjobs"; wantedBy = [ "multi-user.target" ]; path = [ pkgs.bash nextcloud-cronjob ]; serviceConfig = { Restart = "on-failure"; RestartSec = 30; ExecStart = "${nextcloud-cronjob}/bin/nextcloud-cronjob"; }; }; }; timers.nextcloud-cronjob = { enable = true; description = "Runs various nextcloud-related cronjobs"; wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = "*:0/10"; }; }; }; }; }