1# Nextcloud {#module-services-nextcloud} 2 3[Nextcloud](https://nextcloud.com/) is an open-source, 4self-hostable cloud platform. The server setup can be automated using 5[services.nextcloud](#opt-services.nextcloud.enable). A 6desktop client is packaged at `pkgs.nextcloud-client`. 7 8The current default by NixOS is `nextcloud31` which is also the latest 9major version available. 10 11## Basic usage {#module-services-nextcloud-basic-usage} 12 13Nextcloud is a PHP-based application which requires an HTTP server 14([`services.nextcloud`](#opt-services.nextcloud.enable) 15and optionally supports 16[`services.nginx`](#opt-services.nginx.enable)). 17 18For the database, you can set 19[`services.nextcloud.config.dbtype`](#opt-services.nextcloud.config.dbtype) to 20either `sqlite` (the default), `mysql`, or `pgsql`. The simplest is `sqlite`, 21which will be automatically created and managed by the application. For the 22last two, you can easily create a local database by setting 23[`services.nextcloud.database.createLocally`](#opt-services.nextcloud.database.createLocally) 24to `true`, Nextcloud will automatically be configured to connect to it through 25socket. 26 27A very basic configuration may look like this: 28```nix 29{ pkgs, ... }: 30{ 31 services.nextcloud = { 32 enable = true; 33 hostName = "nextcloud.tld"; 34 database.createLocally = true; 35 config = { 36 dbtype = "pgsql"; 37 adminpassFile = "/path/to/admin-pass-file"; 38 }; 39 }; 40 41 networking.firewall.allowedTCPPorts = [ 42 80 43 443 44 ]; 45} 46``` 47 48The `hostName` option is used internally to configure an HTTP 49server using [`PHP-FPM`](https://php-fpm.org/) 50and `nginx`. The `config` attribute set is 51used by the imperative installer and all values are written to an additional file 52to ensure that changes can be applied by changing the module's options. 53 54In case the application serves multiple domains (those are checked with 55[`$_SERVER['HTTP_HOST']`](https://www.php.net/manual/en/reserved.variables.server.php)) 56it's needed to add them to 57[`services.nextcloud.settings.trusted_domains`](#opt-services.nextcloud.settings.trusted_domains). 58 59Auto updates for Nextcloud apps can be enabled using 60[`services.nextcloud.autoUpdateApps`](#opt-services.nextcloud.autoUpdateApps.enable). 61 62## `nextcloud-occ` {#module-services-nextcloud-occ} 63 64The management command [`occ`](https://docs.nextcloud.com/server/stable/admin_manual/occ_command.html) can be 65invoked by using the `nextcloud-occ` wrapper that's globally available on a system with Nextcloud enabled. 66 67It requires elevated permissions to become the `nextcloud` user. Given the way the privilege 68escalation is implemented, parameters passed via the environment to Nextcloud are 69currently ignored, except for `OC_PASS` and `NC_PASS`. 70 71Custom service units that need to run `nextcloud-occ` either need elevated privileges 72or the systemd configuration from `nextcloud-setup.service` (recommended): 73 74```nix 75{ config, ... }: 76{ 77 systemd.services.my-custom-service = { 78 script = '' 79 nextcloud-occ … 80 ''; 81 serviceConfig = { 82 inherit (config.systemd.services.nextcloud-cron.serviceConfig) 83 User 84 LoadCredential 85 KillMode 86 ; 87 }; 88 }; 89} 90``` 91 92Please note that the options required are subject to change. Please make sure to read the 93release notes when upgrading. 94 95## Common problems {#module-services-nextcloud-pitfalls-during-upgrade} 96 97 - **General notes.** 98 Unfortunately Nextcloud appears to be very stateful when it comes to 99 managing its own configuration. The config file lives in the home directory 100 of the `nextcloud` user (by default 101 `/var/lib/nextcloud/config/config.php`) and is also used to 102 track several states of the application (e.g., whether installed or not). 103 104 All configuration parameters are also stored in 105 {file}`/var/lib/nextcloud/config/override.config.php` which is generated by 106 the module and linked from the store to ensure that all values from 107 {file}`config.php` can be modified by the module. 108 However {file}`config.php` manages the application's state and shouldn't be 109 touched manually because of that. 110 111 ::: {.warning} 112 Don't delete {file}`config.php`! This file 113 tracks the application's state and a deletion can cause unwanted 114 side-effects! 115 ::: 116 117 ::: {.warning} 118 Don't rerun `nextcloud-occ maintenance:install`! 119 This command tries to install the application 120 and can cause unwanted side-effects! 121 ::: 122 - **Multiple version upgrades.** 123 Nextcloud doesn't allow to move more than one major-version forward. E.g., if you're on 124 `v16`, you cannot upgrade to `v18`, you need to upgrade to 125 `v17` first. This is ensured automatically as long as the 126 [stateVersion](#opt-system.stateVersion) is declared properly. In that case 127 the oldest version available (one major behind the one from the previous NixOS 128 release) will be selected by default and the module will generate a warning that reminds 129 the user to upgrade to latest Nextcloud *after* that deploy. 130 - **`Error: Command "upgrade" is not defined.`** 131 This error usually occurs if the initial installation 132 ({command}`nextcloud-occ maintenance:install`) has failed. After that, the application 133 is not installed, but the upgrade is attempted to be executed. Further context can 134 be found in [NixOS/nixpkgs#111175](https://github.com/NixOS/nixpkgs/issues/111175). 135 136 First of all, it makes sense to find out what went wrong by looking at the logs 137 of the installation via {command}`journalctl -u nextcloud-setup` and try to fix 138 the underlying issue. 139 140 - If this occurs on an *existing* setup, this is most likely because 141 the maintenance mode is active. It can be deactivated by running 142 {command}`nextcloud-occ maintenance:mode --off`. It's advisable though to 143 check the logs first on why the maintenance mode was activated. 144 - ::: {.warning} 145 Only perform the following measures on 146 *freshly installed instances!* 147 ::: 148 149 A re-run of the installer can be forced by *deleting* 150 {file}`/var/lib/nextcloud/config/config.php`. This is the only time 151 advisable because the fresh install doesn't have any state that can be lost. 152 In case that doesn't help, an entire re-creation can be forced via 153 {command}`rm -rf ~nextcloud/`. 154 155 - **Server-side encryption.** 156 Nextcloud supports [server-side encryption (SSE)](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html). 157 This is not an end-to-end encryption, but can be used to encrypt files that will be persisted 158 to external storage such as S3. 159 160 - **Issues with file permissions / unsafe path transitions** 161 162 {manpage}`systemd-tmpfiles(8)` makes sure that the paths for 163 164 * configuration (including declarative config) 165 * data 166 * app store 167 * home directory itself (usually `/var/lib/nextcloud`) 168 169 are properly set up. However, `systemd-tmpfiles` will refuse to do so 170 if it detects an unsafe path transition, i.e. creating files/directories 171 within a directory that is neither owned by `root` nor by `nextcloud`, the 172 owning user of the files/directories to be created. 173 174 Symptoms of that include 175 176 * `config/override.config.php` not being updated (and the config file 177 eventually being garbage-collected). 178 * failure to read from application data. 179 180 To work around that, please make sure that all directories in question 181 are owned by `nextcloud:nextcloud`. 182 183 - **`Failed to open stream: No such file or directory` after deploys** 184 185 Symptoms are errors like this after a deployment that disappear after 186 a few minutes: 187 188 ``` 189 Warning: file_get_contents(/run/secrets/nextcloud_db_password): Failed to open stream: No such file or directory in /nix/store/lqw657xbh6h67ccv9cgv104qhcs1i2vw-nextcloud-config.php on line 11 190 191 Warning: http_response_code(): Cannot set response code - headers already sent (output started at /nix/store/lqw657xbh6h67ccv9cgv104qhcs1i2vw-nextcloud-config.php:11) in /nix/store/ikxpaq7kjdhpr4w7cgl1n28kc2gvlhg6-nextcloud-29.0.7/lib/base.php on line 639 192 Cannot decode /run/secrets/nextcloud_secrets, because: Syntax error 193 ``` 194 195 This can happen if [](#opt-services.nextcloud.secretFile) or 196 [](#opt-services.nextcloud.config.dbpassFile) are managed by 197 [sops-nix](https://github.com/Mic92/sops-nix/). 198 199 Here, `/run/secrets/nextcloud_secrets` is a symlink to 200 `/run/secrets.d/N/nextcloud_secrets`. The `N` will be incremented 201 when the sops-nix activation script runs, i.e. 202 `/run/secrets.d/N` doesn't exist anymore after a deploy, 203 only `/run/secrets.d/N+1`. 204 205 PHP maintains a [cache for `realpath`](https://www.php.net/manual/en/ini.core.php#ini.realpath-cache-size) 206 that still resolves to the old path which is causing 207 the `No such file or directory` error. Interestingly, 208 the cache isn't used for `file_exists` which is why this warning 209 comes instead of the error from `nix_read_secret` in 210 `override.config.php`. 211 212 One option to work around this is to turn off the cache by setting 213 the cache size to zero: 214 215 ```nix 216 { services.nextcloud.phpOptions."realpath_cache_size" = "0"; } 217 ``` 218 219 - **Empty Files on chunked uploads** 220 221 Due to a limitation of PHP-FPM, Nextcloud is unable to handle chunked 222 uploads. See upstream issue 223 [nextcloud/server#7995](https://github.com/nextcloud/server/issues/7995) 224 for details. 225 226 A workaround is to disable chunked uploads with 227 {option}`nextcloud.nginx.enableFastcgiRequestBuffering`. 228 229## Using an alternative webserver as reverse-proxy (e.g. `httpd`) {#module-services-nextcloud-httpd} 230 231By default, `nginx` is used as reverse-proxy for `nextcloud`. 232However, it's possible to use e.g. `httpd` by explicitly disabling 233`nginx` using [](#opt-services.nginx.enable) and fixing the 234settings `listen.owner` &amp; `listen.group` in the 235[corresponding `phpfpm` pool](#opt-services.phpfpm.pools). 236 237An exemplary configuration may look like this: 238```nix 239{ 240 config, 241 lib, 242 pkgs, 243 ... 244}: 245{ 246 services.nginx.enable = false; 247 services.nextcloud = { 248 enable = true; 249 hostName = "localhost"; 250 251 # further, required options 252 }; 253 services.phpfpm.pools.nextcloud.settings = { 254 "listen.owner" = config.services.httpd.user; 255 "listen.group" = config.services.httpd.group; 256 }; 257 services.httpd = { 258 enable = true; 259 adminAddr = "webmaster@localhost"; 260 extraModules = [ "proxy_fcgi" ]; 261 virtualHosts."localhost" = { 262 documentRoot = config.services.nextcloud.package; 263 extraConfig = '' 264 <Directory "${config.services.nextcloud.package}"> 265 <FilesMatch "\.php$"> 266 <If "-f %{REQUEST_FILENAME}"> 267 SetHandler "proxy:unix:${config.services.phpfpm.pools.nextcloud.socket}|fcgi://localhost/" 268 </If> 269 </FilesMatch> 270 <IfModule mod_rewrite.c> 271 RewriteEngine On 272 RewriteBase / 273 RewriteRule ^index\.php$ - [L] 274 RewriteCond %{REQUEST_FILENAME} !-f 275 RewriteCond %{REQUEST_FILENAME} !-d 276 RewriteRule . /index.php [L] 277 </IfModule> 278 DirectoryIndex index.php 279 Require all granted 280 Options +FollowSymLinks 281 </Directory> 282 ''; 283 }; 284 }; 285} 286``` 287 288## Installing Apps and PHP extensions {#installing-apps-php-extensions-nextcloud} 289 290Nextcloud apps are installed statefully through the web interface. 291Some apps may require extra PHP extensions to be installed. 292This can be configured with the [](#opt-services.nextcloud.phpExtraExtensions) setting. 293 294Alternatively, extra apps can also be declared with the [](#opt-services.nextcloud.extraApps) setting. 295When using this setting, apps can no longer be managed statefully because this can lead to Nextcloud updating apps 296that are managed by Nix: 297 298```nix 299{ config, pkgs, ... }: 300{ 301 services.nextcloud.extraApps = with config.services.nextcloud.package.packages.apps; { 302 inherit user_oidc calendar contacts; 303 }; 304} 305``` 306 307Keep in mind that this is essentially a mirror of the apps from the appstore, but managed in 308nixpkgs. This is by no means a curated list of apps that receive special testing on each update. 309 310If you want automatic updates it is recommended that you use web interface to install apps. 311 312## Known warnings {#module-services-nextcloud-known-warnings} 313 314### Logreader application only supports "file" log_type {#module-services-nextcloud-warning-logreader} 315 316This is because 317 318* our module writes logs into the journal (`journalctl -t Nextcloud`) 319* the Logreader application that allows reading logs in the admin panel is enabled 320 by default and requires logs written to a file. 321 322If you want to view logs in the admin panel, 323set [](#opt-services.nextcloud.settings.log_type) to "file". 324 325If you prefer logs in the journal, disable the logreader application to shut up the 326"info". We can't really do that by default since whether apps are enabled/disabled 327is part of the application's state and tracked inside the database. 328 329## Maintainer information {#module-services-nextcloud-maintainer-info} 330 331As stated in the previous paragraph, we must provide a clean upgrade-path for Nextcloud 332since it cannot move more than one major version forward on a single upgrade. This chapter 333adds some notes how Nextcloud updates should be rolled out in the future. 334 335While minor and patch-level updates are no problem and can be done directly in the 336package-expression (and should be backported to supported stable branches after that), 337major-releases should be added in a new attribute (e.g. Nextcloud `v19.0.0` 338should be available in `nixpkgs` as `pkgs.nextcloud19`). 339To provide simple upgrade paths it's generally useful to backport those as well to stable 340branches. As long as the package-default isn't altered, this won't break existing setups. 341After that, the versioning-warning in the `nextcloud`-module should be 342updated to make sure that the 343[package](#opt-services.nextcloud.package)-option selects the latest version 344on fresh setups. 345 346If major-releases will be abandoned by upstream, we should check first if those are needed 347in NixOS for a safe upgrade-path before removing those. In that case we should keep those 348packages, but mark them as insecure in an expression like this (in 349`<nixpkgs/pkgs/servers/nextcloud/default.nix>`): 350```nix 351# ... 352{ 353 nextcloud17 = generic { 354 version = "17.0.x"; 355 sha256 = "0000000000000000000000000000000000000000000000000000"; 356 eol = true; 357 }; 358} 359``` 360 361Ideally we should make sure that it's possible to jump two NixOS versions forward: 362i.e. the warnings and the logic in the module should guard a user to upgrade from a 363Nextcloud on e.g. 19.09 to a Nextcloud on 20.09.