Merge: nixos/nextcloud: remove with lib usage (#413393)

authored by Maximilian Bosch and committed by GitHub b79a62aa 1cc578e8

+218 -214
+218 -214
nixos/modules/services/web-apps/nextcloud.nix
··· 4 pkgs, 5 ... 6 }: 7 - 8 - with lib; 9 - 10 let 11 cfg = config.services.nextcloud; 12 13 overridePackage = cfg.package.override { ··· 43 nix-apps = { 44 enabled = cfg.extraApps != { }; 45 linkTarget = pkgs.linkFarm "nix-apps" ( 46 - mapAttrsToList (name: path: { inherit name path; }) cfg.extraApps 47 ); 48 writable = false; 49 }; ··· 63 '' 64 mkdir $out 65 ln -sfv "${overridePackage}"/* "$out" 66 - ${concatStrings ( 67 - mapAttrsToList ( 68 name: store: 69 - optionalString (store.enabled && store ? linkTarget) '' 70 if [ -e "$out"/${name} ]; then 71 echo "Didn't expect ${name} already in $out!" 72 exit 1 ··· 90 intl 91 sodium 92 ] # recommended 93 - ++ optional cfg.enableImagemagick imagick 94 # Optionally enabled depending on caching settings 95 - ++ optional cfg.caching.apcu apcu 96 - ++ optional cfg.caching.redis redis 97 - ++ optional cfg.caching.memcached memcached 98 - ++ optional (cfg.settings.log_type == "systemd") systemd 99 ) 100 ++ cfg.phpExtraExtensions all; # Enabled by user 101 extraConfig = toKeyValue cfg.phpOptions; 102 }; 103 104 - toKeyValue = generators.toKeyValue { 105 - mkKeyValue = generators.mkKeyValueDefault { } " = "; 106 }; 107 108 - phpCli = concatStringsSep " " ( 109 [ 110 - "${getExe phpPackage}" 111 ] 112 - ++ optionals (cfg.cli.memoryLimit != null) [ 113 "-dmemory_limit=${cfg.cli.memoryLimit}" 114 ] 115 ); ··· 198 let 199 s3 = c.objectstore.s3; 200 in 201 - optionalString s3.enable '' 202 'objectstore' => [ 203 'class' => '\\OC\\Files\\ObjectStore\\S3', 204 'arguments' => [ 205 'bucket' => '${s3.bucket}', 206 - 'verify_bucket_exists' => ${boolToString s3.verify_bucket_exists}, 207 'key' => '${s3.key}', 208 'secret' => nix_read_secret('s3_secret'), 209 - ${optionalString (s3.hostname != null) "'hostname' => '${s3.hostname}',"} 210 - ${optionalString (s3.port != null) "'port' => ${toString s3.port},"} 211 - 'use_ssl' => ${boolToString s3.useSsl}, 212 - ${optionalString (s3.region != null) "'region' => '${s3.region}',"} 213 - 'use_path_style' => ${boolToString s3.usePathStyle}, 214 - ${optionalString (s3.sseCKeyFile != null) "'sse_c_key' => nix_read_secret('s3_sse_c_key'),"} 215 ], 216 ] 217 ''; ··· 220 let 221 x = cfg.appstoreEnable; 222 in 223 - if x == null then "false" else boolToString x; 224 mkAppStoreConfig = 225 name: 226 { enabled, writable, ... }: 227 - optionalString enabled '' 228 - [ 'path' => '${webroot}/${name}', 'url' => '/${name}', 'writable' => ${boolToString writable} ], 229 ''; 230 in 231 pkgs.writeText "nextcloud-config.php" '' 232 <?php 233 - ${optionalString requiresRuntimeSystemdCredentials '' 234 function nix_read_secret($credential_name) { 235 $credentials_directory = getenv("CREDENTIALS_DIRECTORY"); 236 if (!$credentials_directory) { ··· 278 } 279 $CONFIG = [ 280 'apps_paths' => [ 281 - ${concatStrings (mapAttrsToList mkAppStoreConfig appStores)} 282 ], 283 - ${optionalString (showAppStoreSetting) "'appstoreenabled' => ${renderedAppStoreSetting},"} 284 - ${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"} 285 - ${optionalString (c.dbname != null) "'dbname' => '${c.dbname}',"} 286 - ${optionalString (c.dbhost != null) "'dbhost' => '${c.dbhost}',"} 287 - ${optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"} 288 - ${optionalString (c.dbtableprefix != null) "'dbtableprefix' => '${toString c.dbtableprefix}',"} 289 - ${optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_secret('dbpass'),"} 290 'dbtype' => '${c.dbtype}', 291 ${objectstoreConfig} 292 ]; ··· 296 "impossible: this should never happen (decoding generated settings file %s failed)" 297 )); 298 299 - ${optionalString (cfg.secretFile != null) '' 300 $CONFIG = array_replace_recursive($CONFIG, nix_read_secret_and_decode_json_file('secret_file')); 301 ''} 302 ''; ··· 304 { 305 306 imports = [ 307 - (mkRenamedOptionModule 308 [ "services" "nextcloud" "cron" "memoryLimit" ] 309 [ "services" "nextcloud" "cli" "memoryLimit" ] 310 ) 311 - (mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] '' 312 This option has no effect since there's no supported Nextcloud version packaged here 313 using OpenSSL for RC4 SSE. 314 '') 315 - (mkRemovedOptionModule [ "services" "nextcloud" "config" "dbport" ] '' 316 Add port to services.nextcloud.config.dbhost instead. 317 '') 318 - (mkRenamedOptionModule 319 [ "services" "nextcloud" "logLevel" ] 320 [ "services" "nextcloud" "settings" "loglevel" ] 321 ) 322 - (mkRenamedOptionModule 323 [ "services" "nextcloud" "logType" ] 324 [ "services" "nextcloud" "settings" "log_type" ] 325 ) 326 - (mkRenamedOptionModule 327 [ "services" "nextcloud" "config" "defaultPhoneRegion" ] 328 [ "services" "nextcloud" "settings" "default_phone_region" ] 329 ) 330 - (mkRenamedOptionModule 331 [ "services" "nextcloud" "config" "overwriteProtocol" ] 332 [ "services" "nextcloud" "settings" "overwriteprotocol" ] 333 ) 334 - (mkRenamedOptionModule 335 [ "services" "nextcloud" "skeletonDirectory" ] 336 [ "services" "nextcloud" "settings" "skeletondirectory" ] 337 ) 338 - (mkRenamedOptionModule 339 [ "services" "nextcloud" "globalProfiles" ] 340 [ "services" "nextcloud" "settings" "profile.enabled" ] 341 ) 342 - (mkRenamedOptionModule 343 [ "services" "nextcloud" "config" "extraTrustedDomains" ] 344 [ "services" "nextcloud" "settings" "trusted_domains" ] 345 ) 346 - (mkRenamedOptionModule 347 [ "services" "nextcloud" "config" "trustedProxies" ] 348 [ "services" "nextcloud" "settings" "trusted_proxies" ] 349 ) 350 - (mkRenamedOptionModule 351 [ "services" "nextcloud" "extraOptions" ] 352 [ "services" "nextcloud" "settings" ] 353 ) 354 - (mkRenamedOptionModule 355 [ "services" "nextcloud" "config" "objectstore" "s3" "autocreate" ] 356 [ "services" "nextcloud" "config" "objectstore" "s3" "verify_bucket_exists" ] 357 ) 358 ]; 359 360 options.services.nextcloud = { 361 - enable = mkEnableOption "nextcloud"; 362 363 - hostName = mkOption { 364 - type = types.str; 365 description = "FQDN for the nextcloud instance."; 366 }; 367 - home = mkOption { 368 - type = types.str; 369 default = "/var/lib/nextcloud"; 370 description = "Storage path of nextcloud."; 371 }; 372 - datadir = mkOption { 373 - type = types.str; 374 default = config.services.nextcloud.home; 375 - defaultText = literalExpression "config.services.nextcloud.home"; 376 description = '' 377 Nextcloud's data storage path. Will be [](#opt-services.nextcloud.home) by default. 378 This folder will be populated with a config.php file and a data folder which contains the state of the instance (excluding the database)."; 379 ''; 380 example = "/mnt/nextcloud-file"; 381 }; 382 - extraApps = mkOption { 383 - type = types.attrsOf types.package; 384 default = { }; 385 description = '' 386 Extra apps to install. Should be an attrSet of appid to packages generated by fetchNextcloudApp. 387 The appid must be identical to the "id" value in the apps appinfo/info.xml. 388 Using this will disable the appstore to prevent Nextcloud from updating these apps (see [](#opt-services.nextcloud.appstoreEnable)). 389 ''; 390 - example = literalExpression '' 391 { 392 inherit (pkgs.nextcloud31Packages.apps) mail calendar contacts; 393 phonetrack = pkgs.fetchNextcloudApp { ··· 399 } 400 ''; 401 }; 402 - extraAppsEnable = mkOption { 403 - type = types.bool; 404 default = true; 405 description = '' 406 Automatically enable the apps in [](#opt-services.nextcloud.extraApps) every time Nextcloud starts. 407 If set to false, apps need to be enabled in the Nextcloud web user interface or with `nextcloud-occ app:enable`. 408 ''; 409 }; 410 - appstoreEnable = mkOption { 411 - type = types.nullOr types.bool; 412 default = null; 413 example = true; 414 description = '' ··· 418 Set this to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting. 419 ''; 420 }; 421 - https = mkOption { 422 - type = types.bool; 423 default = false; 424 description = '' 425 Use HTTPS for generated links. ··· 427 Be aware that this also enables HTTP Strict Transport Security (HSTS) headers. 428 ''; 429 }; 430 - package = mkOption { 431 - type = types.package; 432 description = "Which package to use for the Nextcloud instance."; 433 relatedPackages = [ 434 "nextcloud30" 435 "nextcloud31" 436 ]; 437 }; 438 - phpPackage = mkPackageOption pkgs "php" { 439 default = [ "php83" ]; 440 example = "php82"; 441 }; 442 443 - finalPackage = mkOption { 444 - type = types.package; 445 readOnly = true; 446 description = '' 447 Package to the finalized Nextcloud package, including all installed apps. ··· 449 ''; 450 }; 451 452 - maxUploadSize = mkOption { 453 default = "512M"; 454 - type = types.str; 455 description = '' 456 The upload limit for files. This changes the relevant options 457 in php.ini and nginx if enabled. 458 ''; 459 }; 460 461 - webfinger = mkOption { 462 - type = types.bool; 463 default = false; 464 description = '' 465 Enable this option if you plan on using the webfinger plugin. ··· 467 ''; 468 }; 469 470 - phpExtraExtensions = mkOption { 471 - type = with types; functionTo (listOf package); 472 default = all: [ ]; 473 - defaultText = literalExpression "all: []"; 474 description = '' 475 Additional PHP extensions to use for Nextcloud. 476 By default, only extensions necessary for a vanilla Nextcloud installation are enabled, 477 but you may choose from the list of available extensions and add further ones. 478 This is sometimes necessary to be able to install a certain Nextcloud app that has additional requirements. 479 ''; 480 - example = literalExpression '' 481 all: [ all.pdlib all.bz2 ] 482 ''; 483 }; 484 485 - phpOptions = mkOption { 486 - type = 487 - with types; 488 - attrsOf (oneOf [ 489 - str 490 - int 491 - ]); 492 - defaultText = literalExpression ( 493 - generators.toPretty { } ( 494 - defaultPHPSettings // { "openssl.cafile" = literalExpression "config.security.pki.caBundle"; } 495 ) 496 ); 497 description = '' ··· 523 ''; 524 }; 525 526 - poolSettings = mkOption { 527 - type = 528 - with types; 529 - attrsOf (oneOf [ 530 - str 531 - int 532 - bool 533 - ]); 534 default = { 535 "pm" = "dynamic"; 536 "pm.max_children" = "120"; ··· 548 ''; 549 }; 550 551 - poolConfig = mkOption { 552 - type = types.nullOr types.lines; 553 default = null; 554 description = '' 555 Options for Nextcloud's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. 556 ''; 557 }; 558 559 - fastcgiTimeout = mkOption { 560 - type = types.int; 561 default = 120; 562 description = '' 563 FastCGI timeout for database connection in seconds. ··· 566 567 database = { 568 569 - createLocally = mkOption { 570 - type = types.bool; 571 default = false; 572 description = '' 573 Whether to create the database and database user locally. ··· 577 }; 578 579 config = { 580 - dbtype = mkOption { 581 - type = types.nullOr ( 582 - types.enum [ 583 "sqlite" 584 "pgsql" 585 "mysql" ··· 588 default = null; 589 description = "Database type."; 590 }; 591 - dbname = mkOption { 592 - type = types.nullOr types.str; 593 default = "nextcloud"; 594 description = "Database name."; 595 }; 596 - dbuser = mkOption { 597 - type = types.nullOr types.str; 598 default = "nextcloud"; 599 description = "Database user."; 600 }; 601 - dbpassFile = mkOption { 602 - type = types.nullOr types.str; 603 default = null; 604 description = '' 605 The full path to a file that contains the database password. 606 ''; 607 }; 608 - dbhost = mkOption { 609 - type = types.nullOr types.str; 610 default = 611 if pgsqlLocal then 612 "/run/postgresql" ··· 623 defaults to the correct Unix socket instead. 624 ''; 625 }; 626 - dbtableprefix = mkOption { 627 - type = types.nullOr types.str; 628 default = null; 629 description = '' 630 Table prefix in Nextcloud's database. ··· 634 with installations that were originally provisioned with Nextcloud <20. 635 ''; 636 }; 637 - adminuser = mkOption { 638 - type = types.str; 639 default = "root"; 640 description = '' 641 Username for the admin account. The username is only set during the ··· 643 ID internally, it cannot be changed later! 644 ''; 645 }; 646 - adminpassFile = mkOption { 647 - type = types.str; 648 description = '' 649 The full path to a file that contains the admin's password. The password is 650 set only in the initial setup of Nextcloud by the systemd service `nextcloud-setup.service`. ··· 652 }; 653 objectstore = { 654 s3 = { 655 - enable = mkEnableOption '' 656 S3 object storage as primary storage. 657 658 This mounts a bucket on an Amazon S3 object storage or compatible ··· 661 Further details about this feature can be found in the 662 [upstream documentation](https://docs.nextcloud.com/server/22/admin_manual/configuration_files/primary_storage.html) 663 ''; 664 - bucket = mkOption { 665 - type = types.str; 666 example = "nextcloud"; 667 description = '' 668 The name of the S3 bucket. 669 ''; 670 }; 671 - verify_bucket_exists = mkOption { 672 - type = types.bool; 673 default = true; 674 description = '' 675 Create the objectstore bucket if it does not exist. 676 ''; 677 }; 678 - key = mkOption { 679 - type = types.str; 680 example = "EJ39ITYZEUH5BGWDRUFY"; 681 description = '' 682 The access key for the S3 bucket. 683 ''; 684 }; 685 - secretFile = mkOption { 686 - type = types.str; 687 example = "/var/nextcloud-objectstore-s3-secret"; 688 description = '' 689 The full path to a file that contains the access secret. 690 ''; 691 }; 692 - hostname = mkOption { 693 - type = types.nullOr types.str; 694 default = null; 695 example = "example.com"; 696 description = '' 697 Required for some non-Amazon implementations. 698 ''; 699 }; 700 - port = mkOption { 701 - type = types.nullOr types.port; 702 default = null; 703 description = '' 704 Required for some non-Amazon implementations. 705 ''; 706 }; 707 - useSsl = mkOption { 708 - type = types.bool; 709 default = true; 710 description = '' 711 Use SSL for objectstore access. 712 ''; 713 }; 714 - region = mkOption { 715 - type = types.nullOr types.str; 716 default = null; 717 example = "REGION"; 718 description = '' 719 Required for some non-Amazon implementations. 720 ''; 721 }; 722 - usePathStyle = mkOption { 723 - type = types.bool; 724 default = false; 725 description = '' 726 Required for some non-Amazon S3 implementations. ··· 731 `http://hostname.domain/bucket` instead. 732 ''; 733 }; 734 - sseCKeyFile = mkOption { 735 - type = types.nullOr types.path; 736 default = null; 737 example = "/var/nextcloud-objectstore-s3-sse-c-key"; 738 description = '' ··· 755 }; 756 757 enableImagemagick = 758 - mkEnableOption '' 759 the ImageMagick module for PHP. 760 This is used by the theming app and for generating previews of certain images (e.g. SVG and HEIF). 761 You may want to disable it for increased security. In that case, previews will still be available ··· 769 configureRedis = lib.mkOption { 770 type = lib.types.bool; 771 default = config.services.nextcloud.notify_push.enable; 772 - defaultText = literalExpression "config.services.nextcloud.notify_push.enable"; 773 description = '' 774 Whether to configure Nextcloud to use the recommended Redis settings for small instances. 775 ··· 780 }; 781 782 caching = { 783 - apcu = mkOption { 784 - type = types.bool; 785 default = true; 786 description = '' 787 Whether to load the APCu module into PHP. 788 ''; 789 }; 790 - redis = mkOption { 791 - type = types.bool; 792 default = false; 793 description = '' 794 Whether to load the Redis module into PHP. ··· 796 See <https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/caching_configuration.html> 797 ''; 798 }; 799 - memcached = mkOption { 800 - type = types.bool; 801 default = false; 802 description = '' 803 Whether to load the Memcached module into PHP. ··· 807 }; 808 }; 809 autoUpdateApps = { 810 - enable = mkOption { 811 - type = types.bool; 812 default = false; 813 description = '' 814 Run a regular auto-update of all apps installed from the Nextcloud app store. 815 ''; 816 }; 817 - startAt = mkOption { 818 - type = with types; either str (listOf str); 819 default = "05:00:00"; 820 example = "Sun 14:00:00"; 821 description = '' ··· 823 ''; 824 }; 825 }; 826 - occ = mkOption { 827 - type = types.package; 828 default = occ; 829 - defaultText = literalMD "generated script"; 830 description = '' 831 The nextcloud-occ program preconfigured to target this Nextcloud instance. 832 ''; 833 }; 834 835 - settings = mkOption { 836 - type = types.submodule { 837 freeformType = jsonFormat.type; 838 options = { 839 840 - loglevel = mkOption { 841 - type = types.ints.between 0 4; 842 default = 2; 843 description = '' 844 Log level value between 0 (DEBUG) and 4 (FATAL). ··· 854 - 4 (fatal): Log only fatal errors that cause the server to stop. 855 ''; 856 }; 857 - log_type = mkOption { 858 - type = types.enum [ 859 "errorlog" 860 "file" 861 "syslog" ··· 868 See the [nextcloud documentation](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/logging_configuration.html) for details. 869 ''; 870 }; 871 - skeletondirectory = mkOption { 872 default = ""; 873 - type = types.str; 874 description = '' 875 The directory where the skeleton files are located. These files will be 876 copied to the data directory of new users. Leave empty to not copy any 877 skeleton files. 878 ''; 879 }; 880 - trusted_domains = mkOption { 881 - type = types.listOf types.str; 882 default = [ ]; 883 description = '' 884 Trusted domains, from which the nextcloud installation will be ··· 886 `services.nextcloud.hostname` here. 887 ''; 888 }; 889 - trusted_proxies = mkOption { 890 - type = types.listOf types.str; 891 default = [ ]; 892 description = '' 893 Trusted proxies, to provide if the nextcloud installation is being 894 proxied to secure against e.g. spoofing. 895 ''; 896 }; 897 - overwriteprotocol = mkOption { 898 - type = types.enum [ 899 "" 900 "http" 901 "https" ··· 909 Nextcloud may be served via HTTPS. 910 ''; 911 }; 912 - default_phone_region = mkOption { 913 default = ""; 914 - type = types.str; 915 example = "DE"; 916 description = '' 917 An [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) ··· 922 the `+49` prefix can be omitted for phone numbers. 923 ''; 924 }; 925 - "profile.enabled" = mkEnableOption "global profiles" // { 926 description = '' 927 Makes user-profiles globally available under `nextcloud.tld/u/user.name`. 928 Even though it's enabled by default in Nextcloud, it must be explicitly enabled ··· 947 description = '' 948 Extra options which should be appended to Nextcloud's config.php file. 949 ''; 950 - example = literalExpression '' 951 { 952 redis = { 953 host = "/run/redis/redis.sock"; ··· 960 ''; 961 }; 962 963 - secretFile = mkOption { 964 - type = types.nullOr types.str; 965 default = null; 966 description = '' 967 Secret options which will be appended to Nextcloud's config.php file (written as JSON, in the same ··· 971 }; 972 973 nginx = { 974 - recommendedHttpHeaders = mkOption { 975 - type = types.bool; 976 default = true; 977 description = "Enable additional recommended HTTP response headers"; 978 }; 979 - hstsMaxAge = mkOption { 980 - type = types.ints.positive; 981 default = 15552000; 982 description = '' 983 Value for the `max-age` directive of the HTTP ··· 987 directive and header. 988 ''; 989 }; 990 - enableFastcgiRequestBuffering = mkOption { 991 - type = types.bool; 992 default = false; 993 description = '' 994 Whether to buffer requests against fastcgi requests. This is a workaround ··· 1006 }; 1007 }; 1008 1009 - cli.memoryLimit = mkOption { 1010 - type = types.nullOr types.str; 1011 default = null; 1012 example = "1G"; 1013 description = '' ··· 1036 ''; 1037 1038 in 1039 - (optional (cfg.poolConfig != null) '' 1040 Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release. 1041 Please migrate your configuration to config.services.nextcloud.poolSettings. 1042 '') 1043 - ++ (optional (cfg.config.dbtableprefix != null) '' 1044 Using `services.nextcloud.config.dbtableprefix` is deprecated. Fresh installations with this 1045 option set are not allowed anymore since v20. 1046 1047 If you have an existing installation with a custom table prefix, make sure it is 1048 set correctly in `config.php` and remove the option from your NixOS config. 1049 '') 1050 - ++ (optional (versionOlder overridePackage.version "26") (upgradeWarning 25 "23.05")) 1051 - ++ (optional (versionOlder overridePackage.version "27") (upgradeWarning 26 "23.11")) 1052 - ++ (optional (versionOlder overridePackage.version "28") (upgradeWarning 27 "24.05")) 1053 - ++ (optional (versionOlder overridePackage.version "29") (upgradeWarning 28 "24.11")) 1054 - ++ (optional (versionOlder overridePackage.version "30") (upgradeWarning 29 "24.11")) 1055 - ++ (optional (versionOlder overridePackage.version "31") (upgradeWarning 30 "25.05")); 1056 1057 services.nextcloud.package = 1058 with pkgs; 1059 - mkDefault ( 1060 if pkgs ? nextcloud then 1061 throw '' 1062 The `pkgs.nextcloud`-attribute has been removed. If it's supposed to be the default ··· 1074 ); 1075 1076 services.nextcloud.phpOptions = mkMerge [ 1077 - (mapAttrs (const mkOptionDefault) defaultPHPSettings) 1078 { 1079 upload_max_filesize = cfg.maxUploadSize; 1080 post_max_size = cfg.maxUploadSize; ··· 1163 arg = "ADMINPASS"; 1164 value = ''"$(<"$CREDENTIALS_DIRECTORY/adminpass")"''; 1165 }; 1166 - installFlags = concatStringsSep " \\\n " ( 1167 - mapAttrsToList (k: v: "${k} ${toString v}") { 1168 "--database" = ''"${c.dbtype}"''; 1169 # The following attributes are optional depending on the type of 1170 # database. Those that evaluate to null on the left hand side ··· 1185 ${lib.getExe occ} maintenance:install \ 1186 ${installFlags} 1187 ''; 1188 - occSetTrustedDomainsCmd = concatStringsSep "\n" ( 1189 - imap0 (i: v: '' 1190 ${lib.getExe occ} config:system:set trusted_domains \ 1191 ${toString i} --value="${toString v}" 1192 '') (lib.unique ([ cfg.hostName ] ++ cfg.settings.trusted_domains)) ··· 1197 wantedBy = [ "multi-user.target" ]; 1198 wants = [ "nextcloud-update-db.service" ]; 1199 before = [ "phpfpm-nextcloud.service" ]; 1200 - after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.target"; 1201 - requires = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.target"; 1202 path = [ occ ]; 1203 restartTriggers = [ overrideConfig ]; 1204 script = '' 1205 - ${optionalString (c.dbpassFile != null) '' 1206 if [ -z "$(<"$CREDENTIALS_DIRECTORY/dbpass")" ]; then 1207 echo "dbpassFile ${c.dbpassFile} is empty!" 1208 exit 1 ··· 1222 exit 1 1223 fi 1224 1225 - ${concatMapStrings 1226 (name: '' 1227 if [ -d "${cfg.home}"/${name} ]; then 1228 echo "Cleaning up ${name}; these are now bundled in the webroot store-path!" ··· 1244 1245 ${lib.getExe occ} config:system:delete trusted_domains 1246 1247 - ${optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) '' 1248 # Try to enable apps 1249 - ${lib.getExe occ} app:enable ${concatStringsSep " " (attrNames cfg.extraApps)} 1250 ''} 1251 1252 ${occSetTrustedDomainsCmd} ··· 1356 PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin"; 1357 }; 1358 settings = 1359 - mapAttrs (name: mkDefault) { 1360 "listen.owner" = config.services.nginx.user; 1361 "listen.group" = config.services.nginx.group; 1362 } ··· 1410 services.nextcloud = { 1411 caching.redis = lib.mkIf cfg.configureRedis true; 1412 settings = mkMerge [ 1413 - ({ 1414 datadirectory = lib.mkDefault "${datadir}/data"; 1415 trusted_domains = [ cfg.hostName ]; 1416 "upgrade.disable-web" = true; 1417 # NixOS already provides its own integrity check and the nix store is read-only, therefore Nextcloud does not need to do its own integrity checks. 1418 "integrity.check.disabled" = true; 1419 - }) 1420 (lib.mkIf cfg.configureRedis { 1421 "memcache.distributed" = ''\OC\Memcache\Redis''; 1422 "memcache.locking" = ''\OC\Memcache\Redis''; ··· 1428 ]; 1429 }; 1430 1431 - services.nginx.enable = mkDefault true; 1432 1433 services.nginx.virtualHosts.${cfg.hostName} = { 1434 root = webroot; ··· 1527 }; 1528 extraConfig = '' 1529 index index.php index.html /index.php$request_uri; 1530 - ${optionalString (cfg.nginx.recommendedHttpHeaders) '' 1531 add_header X-Content-Type-Options nosniff; 1532 add_header X-XSS-Protection "1; mode=block"; 1533 add_header X-Robots-Tag "noindex, nofollow"; ··· 1535 add_header X-Frame-Options sameorigin; 1536 add_header Referrer-Policy no-referrer; 1537 ''} 1538 - ${optionalString (cfg.https) '' 1539 add_header Strict-Transport-Security "max-age=${toString cfg.nginx.hstsMaxAge}; includeSubDomains" always; 1540 ''} 1541 client_max_body_size ${cfg.maxUploadSize}; ··· 1548 gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; 1549 gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; 1550 1551 - ${optionalString cfg.webfinger '' 1552 rewrite ^/.well-known/host-meta /public.php?service=host-meta last; 1553 rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last; 1554 ''} ··· 1558 ]); 1559 1560 meta.doc = ./nextcloud.md; 1561 - meta.maintainers = teams.nextcloud.members; 1562 }
··· 4 pkgs, 5 ... 6 }: 7 let 8 + inherit (lib) 9 + mkIf 10 + mkMerge 11 + ; 12 + 13 cfg = config.services.nextcloud; 14 15 overridePackage = cfg.package.override { ··· 45 nix-apps = { 46 enabled = cfg.extraApps != { }; 47 linkTarget = pkgs.linkFarm "nix-apps" ( 48 + lib.mapAttrsToList (name: path: { inherit name path; }) cfg.extraApps 49 ); 50 writable = false; 51 }; ··· 65 '' 66 mkdir $out 67 ln -sfv "${overridePackage}"/* "$out" 68 + ${lib.concatStrings ( 69 + lib.mapAttrsToList ( 70 name: store: 71 + lib.optionalString (store.enabled && store ? linkTarget) '' 72 if [ -e "$out"/${name} ]; then 73 echo "Didn't expect ${name} already in $out!" 74 exit 1 ··· 92 intl 93 sodium 94 ] # recommended 95 + ++ lib.optional cfg.enableImagemagick imagick 96 # Optionally enabled depending on caching settings 97 + ++ lib.optional cfg.caching.apcu apcu 98 + ++ lib.optional cfg.caching.redis redis 99 + ++ lib.optional cfg.caching.memcached memcached 100 + ++ lib.optional (cfg.settings.log_type == "systemd") systemd 101 ) 102 ++ cfg.phpExtraExtensions all; # Enabled by user 103 extraConfig = toKeyValue cfg.phpOptions; 104 }; 105 106 + toKeyValue = lib.generators.toKeyValue { 107 + mkKeyValue = lib.generators.mkKeyValueDefault { } " = "; 108 }; 109 110 + phpCli = lib.concatStringsSep " " ( 111 [ 112 + "${lib.getExe phpPackage}" 113 ] 114 + ++ lib.optionals (cfg.cli.memoryLimit != null) [ 115 "-dmemory_limit=${cfg.cli.memoryLimit}" 116 ] 117 ); ··· 200 let 201 s3 = c.objectstore.s3; 202 in 203 + lib.optionalString s3.enable '' 204 'objectstore' => [ 205 'class' => '\\OC\\Files\\ObjectStore\\S3', 206 'arguments' => [ 207 'bucket' => '${s3.bucket}', 208 + 'verify_bucket_exists' => ${lib.boolToString s3.verify_bucket_exists}, 209 'key' => '${s3.key}', 210 'secret' => nix_read_secret('s3_secret'), 211 + ${lib.optionalString (s3.hostname != null) "'hostname' => '${s3.hostname}',"} 212 + ${lib.optionalString (s3.port != null) "'port' => ${toString s3.port},"} 213 + 'use_ssl' => ${lib.boolToString s3.useSsl}, 214 + ${lib.optionalString (s3.region != null) "'region' => '${s3.region}',"} 215 + 'use_path_style' => ${lib.boolToString s3.usePathStyle}, 216 + ${lib.optionalString (s3.sseCKeyFile != null) "'sse_c_key' => nix_read_secret('s3_sse_c_key'),"} 217 ], 218 ] 219 ''; ··· 222 let 223 x = cfg.appstoreEnable; 224 in 225 + if x == null then "false" else lib.boolToString x; 226 mkAppStoreConfig = 227 name: 228 { enabled, writable, ... }: 229 + lib.optionalString enabled '' 230 + [ 'path' => '${webroot}/${name}', 'url' => '/${name}', 'writable' => ${lib.boolToString writable} ], 231 ''; 232 in 233 pkgs.writeText "nextcloud-config.php" '' 234 <?php 235 + ${lib.optionalString requiresRuntimeSystemdCredentials '' 236 function nix_read_secret($credential_name) { 237 $credentials_directory = getenv("CREDENTIALS_DIRECTORY"); 238 if (!$credentials_directory) { ··· 280 } 281 $CONFIG = [ 282 'apps_paths' => [ 283 + ${lib.concatStrings (lib.mapAttrsToList mkAppStoreConfig appStores)} 284 ], 285 + ${lib.optionalString (showAppStoreSetting) "'appstoreenabled' => ${renderedAppStoreSetting},"} 286 + ${lib.optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"} 287 + ${lib.optionalString (c.dbname != null) "'dbname' => '${c.dbname}',"} 288 + ${lib.optionalString (c.dbhost != null) "'dbhost' => '${c.dbhost}',"} 289 + ${lib.optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"} 290 + ${lib.optionalString ( 291 + c.dbtableprefix != null 292 + ) "'dbtableprefix' => '${toString c.dbtableprefix}',"} 293 + ${lib.optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_secret('dbpass'),"} 294 'dbtype' => '${c.dbtype}', 295 ${objectstoreConfig} 296 ]; ··· 300 "impossible: this should never happen (decoding generated settings file %s failed)" 301 )); 302 303 + ${lib.optionalString (cfg.secretFile != null) '' 304 $CONFIG = array_replace_recursive($CONFIG, nix_read_secret_and_decode_json_file('secret_file')); 305 ''} 306 ''; ··· 308 { 309 310 imports = [ 311 + (lib.mkRenamedOptionModule 312 [ "services" "nextcloud" "cron" "memoryLimit" ] 313 [ "services" "nextcloud" "cli" "memoryLimit" ] 314 ) 315 + (lib.mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] '' 316 This option has no effect since there's no supported Nextcloud version packaged here 317 using OpenSSL for RC4 SSE. 318 '') 319 + (lib.mkRemovedOptionModule [ "services" "nextcloud" "config" "dbport" ] '' 320 Add port to services.nextcloud.config.dbhost instead. 321 '') 322 + (lib.mkRenamedOptionModule 323 [ "services" "nextcloud" "logLevel" ] 324 [ "services" "nextcloud" "settings" "loglevel" ] 325 ) 326 + (lib.mkRenamedOptionModule 327 [ "services" "nextcloud" "logType" ] 328 [ "services" "nextcloud" "settings" "log_type" ] 329 ) 330 + (lib.mkRenamedOptionModule 331 [ "services" "nextcloud" "config" "defaultPhoneRegion" ] 332 [ "services" "nextcloud" "settings" "default_phone_region" ] 333 ) 334 + (lib.mkRenamedOptionModule 335 [ "services" "nextcloud" "config" "overwriteProtocol" ] 336 [ "services" "nextcloud" "settings" "overwriteprotocol" ] 337 ) 338 + (lib.mkRenamedOptionModule 339 [ "services" "nextcloud" "skeletonDirectory" ] 340 [ "services" "nextcloud" "settings" "skeletondirectory" ] 341 ) 342 + (lib.mkRenamedOptionModule 343 [ "services" "nextcloud" "globalProfiles" ] 344 [ "services" "nextcloud" "settings" "profile.enabled" ] 345 ) 346 + (lib.mkRenamedOptionModule 347 [ "services" "nextcloud" "config" "extraTrustedDomains" ] 348 [ "services" "nextcloud" "settings" "trusted_domains" ] 349 ) 350 + (lib.mkRenamedOptionModule 351 [ "services" "nextcloud" "config" "trustedProxies" ] 352 [ "services" "nextcloud" "settings" "trusted_proxies" ] 353 ) 354 + (lib.mkRenamedOptionModule 355 [ "services" "nextcloud" "extraOptions" ] 356 [ "services" "nextcloud" "settings" ] 357 ) 358 + (lib.mkRenamedOptionModule 359 [ "services" "nextcloud" "config" "objectstore" "s3" "autocreate" ] 360 [ "services" "nextcloud" "config" "objectstore" "s3" "verify_bucket_exists" ] 361 ) 362 ]; 363 364 options.services.nextcloud = { 365 + enable = lib.mkEnableOption "nextcloud"; 366 367 + hostName = lib.mkOption { 368 + type = lib.types.str; 369 description = "FQDN for the nextcloud instance."; 370 }; 371 + home = lib.mkOption { 372 + type = lib.types.str; 373 default = "/var/lib/nextcloud"; 374 description = "Storage path of nextcloud."; 375 }; 376 + datadir = lib.mkOption { 377 + type = lib.types.str; 378 default = config.services.nextcloud.home; 379 + defaultText = lib.literalExpression "config.services.nextcloud.home"; 380 description = '' 381 Nextcloud's data storage path. Will be [](#opt-services.nextcloud.home) by default. 382 This folder will be populated with a config.php file and a data folder which contains the state of the instance (excluding the database)."; 383 ''; 384 example = "/mnt/nextcloud-file"; 385 }; 386 + extraApps = lib.mkOption { 387 + type = lib.types.attrsOf lib.types.package; 388 default = { }; 389 description = '' 390 Extra apps to install. Should be an attrSet of appid to packages generated by fetchNextcloudApp. 391 The appid must be identical to the "id" value in the apps appinfo/info.xml. 392 Using this will disable the appstore to prevent Nextcloud from updating these apps (see [](#opt-services.nextcloud.appstoreEnable)). 393 ''; 394 + example = lib.literalExpression '' 395 { 396 inherit (pkgs.nextcloud31Packages.apps) mail calendar contacts; 397 phonetrack = pkgs.fetchNextcloudApp { ··· 403 } 404 ''; 405 }; 406 + extraAppsEnable = lib.mkOption { 407 + type = lib.types.bool; 408 default = true; 409 description = '' 410 Automatically enable the apps in [](#opt-services.nextcloud.extraApps) every time Nextcloud starts. 411 If set to false, apps need to be enabled in the Nextcloud web user interface or with `nextcloud-occ app:enable`. 412 ''; 413 }; 414 + appstoreEnable = lib.mkOption { 415 + type = lib.types.nullOr lib.types.bool; 416 default = null; 417 example = true; 418 description = '' ··· 422 Set this to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting. 423 ''; 424 }; 425 + https = lib.mkOption { 426 + type = lib.types.bool; 427 default = false; 428 description = '' 429 Use HTTPS for generated links. ··· 431 Be aware that this also enables HTTP Strict Transport Security (HSTS) headers. 432 ''; 433 }; 434 + package = lib.mkOption { 435 + type = lib.types.package; 436 description = "Which package to use for the Nextcloud instance."; 437 relatedPackages = [ 438 "nextcloud30" 439 "nextcloud31" 440 ]; 441 }; 442 + phpPackage = lib.mkPackageOption pkgs "php" { 443 default = [ "php83" ]; 444 example = "php82"; 445 }; 446 447 + finalPackage = lib.mkOption { 448 + type = lib.types.package; 449 readOnly = true; 450 description = '' 451 Package to the finalized Nextcloud package, including all installed apps. ··· 453 ''; 454 }; 455 456 + maxUploadSize = lib.mkOption { 457 default = "512M"; 458 + type = lib.types.str; 459 description = '' 460 The upload limit for files. This changes the relevant options 461 in php.ini and nginx if enabled. 462 ''; 463 }; 464 465 + webfinger = lib.mkOption { 466 + type = lib.types.bool; 467 default = false; 468 description = '' 469 Enable this option if you plan on using the webfinger plugin. ··· 471 ''; 472 }; 473 474 + phpExtraExtensions = lib.mkOption { 475 + type = lib.types.functionTo (lib.types.listOf lib.types.package); 476 default = all: [ ]; 477 + defaultText = lib.literalExpression "all: []"; 478 description = '' 479 Additional PHP extensions to use for Nextcloud. 480 By default, only extensions necessary for a vanilla Nextcloud installation are enabled, 481 but you may choose from the list of available extensions and add further ones. 482 This is sometimes necessary to be able to install a certain Nextcloud app that has additional requirements. 483 ''; 484 + example = lib.literalExpression '' 485 all: [ all.pdlib all.bz2 ] 486 ''; 487 }; 488 489 + phpOptions = lib.mkOption { 490 + type = lib.types.attrsOf ( 491 + lib.types.oneOf [ 492 + lib.types.str 493 + lib.types.int 494 + ] 495 + ); 496 + defaultText = lib.literalExpression ( 497 + lib.generators.toPretty { } ( 498 + defaultPHPSettings // { "openssl.cafile" = lib.literalExpression "config.security.pki.caBundle"; } 499 ) 500 ); 501 description = '' ··· 527 ''; 528 }; 529 530 + poolSettings = lib.mkOption { 531 + type = lib.types.attrsOf ( 532 + lib.types.oneOf [ 533 + lib.types.str 534 + lib.types.int 535 + lib.types.bool 536 + ] 537 + ); 538 default = { 539 "pm" = "dynamic"; 540 "pm.max_children" = "120"; ··· 552 ''; 553 }; 554 555 + poolConfig = lib.mkOption { 556 + type = lib.types.nullOr lib.types.lines; 557 default = null; 558 description = '' 559 Options for Nextcloud's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. 560 ''; 561 }; 562 563 + fastcgiTimeout = lib.mkOption { 564 + type = lib.types.int; 565 default = 120; 566 description = '' 567 FastCGI timeout for database connection in seconds. ··· 570 571 database = { 572 573 + createLocally = lib.mkOption { 574 + type = lib.types.bool; 575 default = false; 576 description = '' 577 Whether to create the database and database user locally. ··· 581 }; 582 583 config = { 584 + dbtype = lib.mkOption { 585 + type = lib.types.nullOr ( 586 + lib.types.enum [ 587 "sqlite" 588 "pgsql" 589 "mysql" ··· 592 default = null; 593 description = "Database type."; 594 }; 595 + dbname = lib.mkOption { 596 + type = lib.types.nullOr lib.types.str; 597 default = "nextcloud"; 598 description = "Database name."; 599 }; 600 + dbuser = lib.mkOption { 601 + type = lib.types.nullOr lib.types.str; 602 default = "nextcloud"; 603 description = "Database user."; 604 }; 605 + dbpassFile = lib.mkOption { 606 + type = lib.types.nullOr lib.types.str; 607 default = null; 608 description = '' 609 The full path to a file that contains the database password. 610 ''; 611 }; 612 + dbhost = lib.mkOption { 613 + type = lib.types.nullOr lib.types.str; 614 default = 615 if pgsqlLocal then 616 "/run/postgresql" ··· 627 defaults to the correct Unix socket instead. 628 ''; 629 }; 630 + dbtableprefix = lib.mkOption { 631 + type = lib.types.nullOr lib.types.str; 632 default = null; 633 description = '' 634 Table prefix in Nextcloud's database. ··· 638 with installations that were originally provisioned with Nextcloud <20. 639 ''; 640 }; 641 + adminuser = lib.mkOption { 642 + type = lib.types.str; 643 default = "root"; 644 description = '' 645 Username for the admin account. The username is only set during the ··· 647 ID internally, it cannot be changed later! 648 ''; 649 }; 650 + adminpassFile = lib.mkOption { 651 + type = lib.types.str; 652 description = '' 653 The full path to a file that contains the admin's password. The password is 654 set only in the initial setup of Nextcloud by the systemd service `nextcloud-setup.service`. ··· 656 }; 657 objectstore = { 658 s3 = { 659 + enable = lib.mkEnableOption '' 660 S3 object storage as primary storage. 661 662 This mounts a bucket on an Amazon S3 object storage or compatible ··· 665 Further details about this feature can be found in the 666 [upstream documentation](https://docs.nextcloud.com/server/22/admin_manual/configuration_files/primary_storage.html) 667 ''; 668 + bucket = lib.mkOption { 669 + type = lib.types.str; 670 example = "nextcloud"; 671 description = '' 672 The name of the S3 bucket. 673 ''; 674 }; 675 + verify_bucket_exists = lib.mkOption { 676 + type = lib.types.bool; 677 default = true; 678 description = '' 679 Create the objectstore bucket if it does not exist. 680 ''; 681 }; 682 + key = lib.mkOption { 683 + type = lib.types.str; 684 example = "EJ39ITYZEUH5BGWDRUFY"; 685 description = '' 686 The access key for the S3 bucket. 687 ''; 688 }; 689 + secretFile = lib.mkOption { 690 + type = lib.types.str; 691 example = "/var/nextcloud-objectstore-s3-secret"; 692 description = '' 693 The full path to a file that contains the access secret. 694 ''; 695 }; 696 + hostname = lib.mkOption { 697 + type = lib.types.nullOr lib.types.str; 698 default = null; 699 example = "example.com"; 700 description = '' 701 Required for some non-Amazon implementations. 702 ''; 703 }; 704 + port = lib.mkOption { 705 + type = lib.types.nullOr lib.types.port; 706 default = null; 707 description = '' 708 Required for some non-Amazon implementations. 709 ''; 710 }; 711 + useSsl = lib.mkOption { 712 + type = lib.types.bool; 713 default = true; 714 description = '' 715 Use SSL for objectstore access. 716 ''; 717 }; 718 + region = lib.mkOption { 719 + type = lib.types.nullOr lib.types.str; 720 default = null; 721 example = "REGION"; 722 description = '' 723 Required for some non-Amazon implementations. 724 ''; 725 }; 726 + usePathStyle = lib.mkOption { 727 + type = lib.types.bool; 728 default = false; 729 description = '' 730 Required for some non-Amazon S3 implementations. ··· 735 `http://hostname.domain/bucket` instead. 736 ''; 737 }; 738 + sseCKeyFile = lib.mkOption { 739 + type = lib.types.nullOr lib.types.path; 740 default = null; 741 example = "/var/nextcloud-objectstore-s3-sse-c-key"; 742 description = '' ··· 759 }; 760 761 enableImagemagick = 762 + lib.mkEnableOption '' 763 the ImageMagick module for PHP. 764 This is used by the theming app and for generating previews of certain images (e.g. SVG and HEIF). 765 You may want to disable it for increased security. In that case, previews will still be available ··· 773 configureRedis = lib.mkOption { 774 type = lib.types.bool; 775 default = config.services.nextcloud.notify_push.enable; 776 + defaultText = lib.literalExpression "config.services.nextcloud.notify_push.enable"; 777 description = '' 778 Whether to configure Nextcloud to use the recommended Redis settings for small instances. 779 ··· 784 }; 785 786 caching = { 787 + apcu = lib.mkOption { 788 + type = lib.types.bool; 789 default = true; 790 description = '' 791 Whether to load the APCu module into PHP. 792 ''; 793 }; 794 + redis = lib.mkOption { 795 + type = lib.types.bool; 796 default = false; 797 description = '' 798 Whether to load the Redis module into PHP. ··· 800 See <https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/caching_configuration.html> 801 ''; 802 }; 803 + memcached = lib.mkOption { 804 + type = lib.types.bool; 805 default = false; 806 description = '' 807 Whether to load the Memcached module into PHP. ··· 811 }; 812 }; 813 autoUpdateApps = { 814 + enable = lib.mkOption { 815 + type = lib.types.bool; 816 default = false; 817 description = '' 818 Run a regular auto-update of all apps installed from the Nextcloud app store. 819 ''; 820 }; 821 + startAt = lib.mkOption { 822 + type = lib.types.either lib.types.str (lib.types.listOf lib.types.str); 823 default = "05:00:00"; 824 example = "Sun 14:00:00"; 825 description = '' ··· 827 ''; 828 }; 829 }; 830 + occ = lib.mkOption { 831 + type = lib.types.package; 832 default = occ; 833 + defaultText = lib.literalMD "generated script"; 834 description = '' 835 The nextcloud-occ program preconfigured to target this Nextcloud instance. 836 ''; 837 }; 838 839 + settings = lib.mkOption { 840 + type = lib.types.submodule { 841 freeformType = jsonFormat.type; 842 options = { 843 844 + loglevel = lib.mkOption { 845 + type = lib.types.ints.between 0 4; 846 default = 2; 847 description = '' 848 Log level value between 0 (DEBUG) and 4 (FATAL). ··· 858 - 4 (fatal): Log only fatal errors that cause the server to stop. 859 ''; 860 }; 861 + log_type = lib.mkOption { 862 + type = lib.types.enum [ 863 "errorlog" 864 "file" 865 "syslog" ··· 872 See the [nextcloud documentation](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/logging_configuration.html) for details. 873 ''; 874 }; 875 + skeletondirectory = lib.mkOption { 876 default = ""; 877 + type = lib.types.str; 878 description = '' 879 The directory where the skeleton files are located. These files will be 880 copied to the data directory of new users. Leave empty to not copy any 881 skeleton files. 882 ''; 883 }; 884 + trusted_domains = lib.mkOption { 885 + type = lib.types.listOf lib.types.str; 886 default = [ ]; 887 description = '' 888 Trusted domains, from which the nextcloud installation will be ··· 890 `services.nextcloud.hostname` here. 891 ''; 892 }; 893 + trusted_proxies = lib.mkOption { 894 + type = lib.types.listOf lib.types.str; 895 default = [ ]; 896 description = '' 897 Trusted proxies, to provide if the nextcloud installation is being 898 proxied to secure against e.g. spoofing. 899 ''; 900 }; 901 + overwriteprotocol = lib.mkOption { 902 + type = lib.types.enum [ 903 "" 904 "http" 905 "https" ··· 913 Nextcloud may be served via HTTPS. 914 ''; 915 }; 916 + default_phone_region = lib.mkOption { 917 default = ""; 918 + type = lib.types.str; 919 example = "DE"; 920 description = '' 921 An [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) ··· 926 the `+49` prefix can be omitted for phone numbers. 927 ''; 928 }; 929 + "profile.enabled" = lib.mkEnableOption "global profiles" // { 930 description = '' 931 Makes user-profiles globally available under `nextcloud.tld/u/user.name`. 932 Even though it's enabled by default in Nextcloud, it must be explicitly enabled ··· 951 description = '' 952 Extra options which should be appended to Nextcloud's config.php file. 953 ''; 954 + example = lib.literalExpression '' 955 { 956 redis = { 957 host = "/run/redis/redis.sock"; ··· 964 ''; 965 }; 966 967 + secretFile = lib.mkOption { 968 + type = lib.types.nullOr lib.types.str; 969 default = null; 970 description = '' 971 Secret options which will be appended to Nextcloud's config.php file (written as JSON, in the same ··· 975 }; 976 977 nginx = { 978 + recommendedHttpHeaders = lib.mkOption { 979 + type = lib.types.bool; 980 default = true; 981 description = "Enable additional recommended HTTP response headers"; 982 }; 983 + hstsMaxAge = lib.mkOption { 984 + type = lib.types.ints.positive; 985 default = 15552000; 986 description = '' 987 Value for the `max-age` directive of the HTTP ··· 991 directive and header. 992 ''; 993 }; 994 + enableFastcgiRequestBuffering = lib.mkOption { 995 + type = lib.types.bool; 996 default = false; 997 description = '' 998 Whether to buffer requests against fastcgi requests. This is a workaround ··· 1010 }; 1011 }; 1012 1013 + cli.memoryLimit = lib.mkOption { 1014 + type = lib.types.nullOr lib.types.str; 1015 default = null; 1016 example = "1G"; 1017 description = '' ··· 1040 ''; 1041 1042 in 1043 + (lib.optional (cfg.poolConfig != null) '' 1044 Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release. 1045 Please migrate your configuration to config.services.nextcloud.poolSettings. 1046 '') 1047 + ++ (lib.optional (cfg.config.dbtableprefix != null) '' 1048 Using `services.nextcloud.config.dbtableprefix` is deprecated. Fresh installations with this 1049 option set are not allowed anymore since v20. 1050 1051 If you have an existing installation with a custom table prefix, make sure it is 1052 set correctly in `config.php` and remove the option from your NixOS config. 1053 '') 1054 + ++ (lib.optional (lib.versionOlder overridePackage.version "26") (upgradeWarning 25 "23.05")) 1055 + ++ (lib.optional (lib.versionOlder overridePackage.version "27") (upgradeWarning 26 "23.11")) 1056 + ++ (lib.optional (lib.versionOlder overridePackage.version "28") (upgradeWarning 27 "24.05")) 1057 + ++ (lib.optional (lib.versionOlder overridePackage.version "29") (upgradeWarning 28 "24.11")) 1058 + ++ (lib.optional (lib.versionOlder overridePackage.version "30") (upgradeWarning 29 "24.11")) 1059 + ++ (lib.optional (lib.versionOlder overridePackage.version "31") (upgradeWarning 30 "25.05")); 1060 1061 services.nextcloud.package = 1062 with pkgs; 1063 + lib.mkDefault ( 1064 if pkgs ? nextcloud then 1065 throw '' 1066 The `pkgs.nextcloud`-attribute has been removed. If it's supposed to be the default ··· 1078 ); 1079 1080 services.nextcloud.phpOptions = mkMerge [ 1081 + (lib.mapAttrs (lib.const lib.mkOptionDefault) defaultPHPSettings) 1082 { 1083 upload_max_filesize = cfg.maxUploadSize; 1084 post_max_size = cfg.maxUploadSize; ··· 1167 arg = "ADMINPASS"; 1168 value = ''"$(<"$CREDENTIALS_DIRECTORY/adminpass")"''; 1169 }; 1170 + installFlags = lib.concatStringsSep " \\\n " ( 1171 + lib.mapAttrsToList (k: v: "${k} ${toString v}") { 1172 "--database" = ''"${c.dbtype}"''; 1173 # The following attributes are optional depending on the type of 1174 # database. Those that evaluate to null on the left hand side ··· 1189 ${lib.getExe occ} maintenance:install \ 1190 ${installFlags} 1191 ''; 1192 + occSetTrustedDomainsCmd = lib.concatStringsSep "\n" ( 1193 + lib.imap0 (i: v: '' 1194 ${lib.getExe occ} config:system:set trusted_domains \ 1195 ${toString i} --value="${toString v}" 1196 '') (lib.unique ([ cfg.hostName ] ++ cfg.settings.trusted_domains)) ··· 1201 wantedBy = [ "multi-user.target" ]; 1202 wants = [ "nextcloud-update-db.service" ]; 1203 before = [ "phpfpm-nextcloud.service" ]; 1204 + after = lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.target"; 1205 + requires = lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.target"; 1206 path = [ occ ]; 1207 restartTriggers = [ overrideConfig ]; 1208 script = '' 1209 + ${lib.optionalString (c.dbpassFile != null) '' 1210 if [ -z "$(<"$CREDENTIALS_DIRECTORY/dbpass")" ]; then 1211 echo "dbpassFile ${c.dbpassFile} is empty!" 1212 exit 1 ··· 1226 exit 1 1227 fi 1228 1229 + ${lib.concatMapStrings 1230 (name: '' 1231 if [ -d "${cfg.home}"/${name} ]; then 1232 echo "Cleaning up ${name}; these are now bundled in the webroot store-path!" ··· 1248 1249 ${lib.getExe occ} config:system:delete trusted_domains 1250 1251 + ${lib.optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) '' 1252 # Try to enable apps 1253 + ${lib.getExe occ} app:enable ${lib.concatStringsSep " " (lib.attrNames cfg.extraApps)} 1254 ''} 1255 1256 ${occSetTrustedDomainsCmd} ··· 1360 PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin"; 1361 }; 1362 settings = 1363 + lib.mapAttrs (name: lib.mkDefault) { 1364 "listen.owner" = config.services.nginx.user; 1365 "listen.group" = config.services.nginx.group; 1366 } ··· 1414 services.nextcloud = { 1415 caching.redis = lib.mkIf cfg.configureRedis true; 1416 settings = mkMerge [ 1417 + { 1418 datadirectory = lib.mkDefault "${datadir}/data"; 1419 trusted_domains = [ cfg.hostName ]; 1420 "upgrade.disable-web" = true; 1421 # NixOS already provides its own integrity check and the nix store is read-only, therefore Nextcloud does not need to do its own integrity checks. 1422 "integrity.check.disabled" = true; 1423 + } 1424 (lib.mkIf cfg.configureRedis { 1425 "memcache.distributed" = ''\OC\Memcache\Redis''; 1426 "memcache.locking" = ''\OC\Memcache\Redis''; ··· 1432 ]; 1433 }; 1434 1435 + services.nginx.enable = lib.mkDefault true; 1436 1437 services.nginx.virtualHosts.${cfg.hostName} = { 1438 root = webroot; ··· 1531 }; 1532 extraConfig = '' 1533 index index.php index.html /index.php$request_uri; 1534 + ${lib.optionalString (cfg.nginx.recommendedHttpHeaders) '' 1535 add_header X-Content-Type-Options nosniff; 1536 add_header X-XSS-Protection "1; mode=block"; 1537 add_header X-Robots-Tag "noindex, nofollow"; ··· 1539 add_header X-Frame-Options sameorigin; 1540 add_header Referrer-Policy no-referrer; 1541 ''} 1542 + ${lib.optionalString (cfg.https) '' 1543 add_header Strict-Transport-Security "max-age=${toString cfg.nginx.hstsMaxAge}; includeSubDomains" always; 1544 ''} 1545 client_max_body_size ${cfg.maxUploadSize}; ··· 1552 gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; 1553 gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; 1554 1555 + ${lib.optionalString cfg.webfinger '' 1556 rewrite ^/.well-known/host-meta /public.php?service=host-meta last; 1557 rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last; 1558 ''} ··· 1562 ]); 1563 1564 meta.doc = ./nextcloud.md; 1565 + meta.maintainers = lib.teams.nextcloud.members; 1566 }