Nextcloud¶
Nextcloud is an open-source platform for hosting your own cloud for file storage, syncing, and collaboration. It provides features like file sharing, calendar, contacts, and document editing while keeping full control over your data. It’s ideal for those who prefer privacy, customization, and independence from large commercial cloud providers.
Nextcloud was initially released in 2016 as a fork of ownCloud and is maintained by Nextcloud GmbH.
Prerequisites¶
We're using PHP in the stable version 8.4:
[isabell@moondust ~]$ uberspace tool php version set 8.4
OK: Set version of php to 8.4
You'll need your MariaDB credentials:
[isabell@moondust ~]$ my_print_defaults client
--default-character-set=utf8mb4
--user=isabell
--password=MySuperSecretPassword
Installation¶
Download¶
cd to your document root, download the latest Nextcloud release and extract it on the fly, omitting the top-level directory from the archive:
[isabell@moondust ~]$ cd /var/www/virtual/$USER/html/
[isabell@moondust html]$ rm nocontent.html
[isabell@moondust html]$ curl https://download.nextcloud.com/server/releases/latest.tar.bz2 | tar -xjf - --strip-components=1
Create the database¶
First, create a MariaDB database for your Nextcloud installation:
[isabell@moondust ~]$ mariadb --verbose --execute="CREATE DATABASE ${USER}_nextcloud"
--------------
CREATE DATABASE isabell_nextcloud
--------------
Run the installation script¶
Execute the Nextcloud maintenance script occ with the following parameters. Set these three values to your account-specific credentials before running the command:
NEXTCLOUD_ADMIN_USER— the admin username for your first loginNEXTCLOUD_ADMIN_PASS— the admin passwordMARIADB_PASSWORD— your MariaDB password
[isabell@moondust ~]$ NEXTCLOUD_ADMIN_USER='MyUserName'
[isabell@moondust ~]$ NEXTCLOUD_ADMIN_PASS='MySuperSecretAdminPassword'
[isabell@moondust ~]$ MARIADB_PASSWORD='MySuperSecretMariaDBPassword'
[isabell@moondust ~]$ php occ maintenance:install --admin-user="${NEXTCLOUD_ADMIN_USER}" --admin-pass="${NEXTCLOUD_ADMIN_PASS}" --database='mysql' --database-name="${USER}_nextcloud" --database-user="${USER}" --database-pass="${MARIADB_PASSWORD}" --data-dir="${HOME}/nextcloud_data"
Nextcloud was successfully installed
Configuration¶
PHP settings¶
Follow Nextcloud's PHP configuration guidance using Uberspace's custom PHP configuration directory. Files in ~/.config/php/ apply to both PHP-FPM and command-line PHP, including cron and occ.
Create ~/.config/php/nextcloud.ini with the following content. If you already created separate files for these settings, update or consolidate them so they do not override each other:
memory_limit=512M
output_buffering=0
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=10000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.validate_timestamps=1
opcache.revalidate_freq=2
apc.enable_cli=1
apc.shm_size=128M
The memory limit applies per PHP process; concurrent requests and Collabora need additional memory. APCu's 128 MB is a starting point: check Administration settings > Overview for cache warnings and adjust to actual usage. OPcache caches compiled PHP code. Keep timestamp validation enabled so configuration changes and app updates are noticed.
Reload PHP-FPM to apply the configuration. Example output:
[isabell@moondust ~]$ uberspace web php reload
OK: PHP-FPM service reloaded
Check the command-line settings. Example output:
[isabell@moondust ~]$ php -r 'foreach (["memory_limit", "output_buffering", "apc.enable_cli", "apc.shm_size"] as $setting) { echo $setting, "=", ini_get($setting), PHP_EOL; }'
memory_limit=512M
output_buffering=0
apc.enable_cli=1
apc.shm_size=128M
Also check the PHP information in Administration settings > System for the web runtime. Command-line PHP alone does not prove that PHP-FPM has reloaded its settings.
For large uploads, adjust upload_max_filesize and post_max_size to your needs, with the latter at least as large as the former. Increase max_execution_time and max_input_time only if PHP logs show timeouts. An upload_tmp_dir override must use an existing, writable absolute path outside the document root with space for concurrent uploads. PHP settings do not override frontend timeouts or request-size limits, and chunked uploads do not have the same limits as a single POST request. Reload PHP-FPM after changing these settings.
Keep Uberspace's disable_functions and open_basedir defaults unless a specific requirement calls for a change; do not clear restrictions wholesale.
Set the admin user email address¶
Set the email address of the admin user to enable sending emails and receiving administration notifications.
[isabell@moondust ~]$ php occ user:setting $NEXTCLOUD_ADMIN_USER settings email "$USER@uber.space"
Set the trusted domain¶
Add the domain you'll use to access Nextcloud as a trusted domain:
[isabell@moondust ~]$ php occ config:system:set trusted_domains 0 --value="${USER}.uber.space"
System config value trusted_domains => 0 set to string isabell.uber.space
[isabell@moondust ~]$ php occ config:system:set overwrite.cli.url --value="https://${USER}.uber.space"
System config value overwrite.cli.url set to string https://isabell.uber.space
Logs¶
Create symlinks to the log files for easier access:
[isabell@moondust ~]$ ln --symbolic ~/nextcloud_data/nextcloud.log ~/logs/nextcloud.log
[isabell@moondust ~]$ ln --symbolic ~/nextcloud_data/updater.log ~/logs/nextcloud-updater.log
You can now log in to your Nextcloud using the domain you configured. Before using it in production, continue with the sections below to enable email, optimize performance, and set up background jobs.
Configure email¶
Go to settings > Administration > Basic settings and configure the email-server.
Background jobs¶
For the server to work properly, it's important to configure background jobs correctly. Cron is the recommended setting.
Add the following cronjob to your crontab:
*/5 * * * * sleep $(( 1 + RANDOM \% 60 )) ; php -f /var/www/virtual/$USER/html/cron.php > $HOME/logs/nextcloud-cron.log 2>&1
The actual cronjob is preceded by a random sleep of maximum one minute to prevent load peaks every 5 minutes due to simultaneous execution of all cronjobs.
The \% is required as crontab replaces % with new-line characters.
Configure Nextcloud to rely on the configured cronjob:
[isabell@moondust ~]$ php occ background:cron
Set mode for background jobs to 'cron'
Choose an off-peak maintenance window for daily jobs that can be delayed. This example starts a four-hour window at 01:00 UTC (02:00 CET or 03:00 CEST). It does not put Nextcloud into maintenance mode or postpone time-sensitive jobs. Example output:
[isabell@moondust ~]$ php /var/www/virtual/$USER/html/occ config:system:set maintenance_window_start --type=integer --value=1
System config value maintenance_window_start set to integer 1
APCu caching¶
To enable APCu memory caching, run:
[isabell@moondust ~]$ php occ config:system:set memcache.local --value='\OC\Memcache\APCu'
System config value memcache.local set to string \OC\Memcache\APCu
Valkey caching and file locking¶
Keep APCu as the local cache and use Valkey for shared caching and transactional file locks to reduce database load. Set up the private Unix-socket service in the Valkey / Redis Manual first, including its PING check. Uberspace provides the PHP Redis extension; Nextcloud uses its Redis adapter to connect to Valkey.
Configure the connection before enabling the caches. The commands below assume the Manual's socket path. Changing directories produces no output; example output for the configuration commands follows:
[isabell@moondust ~]$ cd /var/www/virtual/$USER/html/
[isabell@moondust html]$ php occ config:system:set redis host --value="$HOME/.valkey/valkey.sock"
System config value redis => host set to string /home/isabell/.valkey/valkey.sock
[isabell@moondust html]$ php occ config:system:set redis port --type=integer --value=0
System config value redis => port set to integer 0
[isabell@moondust html]$ php occ config:system:set memcache.distributed --value='\OC\Memcache\Redis'
System config value memcache.distributed set to string \OC\Memcache\Redis
[isabell@moondust html]$ php occ config:system:set memcache.locking --value='\OC\Memcache\Redis'
System config value memcache.locking set to string \OC\Memcache\Redis
Open Nextcloud and upload, rename, and delete a test file. Check Administration settings > Overview for caching or file-locking warnings. Keep Valkey running while Nextcloud is in use; do not flush or restart it during active file operations, because that removes locks. This setup leaves PHP session storage unchanged.
Client Push (optional)¶
Client Push reduces polling by compatible sync clients. Complete the Valkey setup above first. Install the app; example output (the version may differ):
[isabell@moondust ~]$ cd /var/www/virtual/$USER/html/
[isabell@moondust html]$ php occ app:install notify_push
notify_push 1.4.1 installed
notify_push enabled
Changing directories produces no output.
Local callback service¶
On Uberspace, the public frontend removes the forwarded address needed by Client Push's trusted-proxy check. Use a localhost-only Caddy service for callbacks to PHP-FPM. It handles only Client Push's routes and must not get a public web backend.
Create its configuration directory. This command produces no output:
[isabell@moondust ~]$ mkdir -p ~/.config/nextcloud-push
Create ~/.config/nextcloud-push/Caddyfile:
{
admin off
auto_https off
}
http://127.0.0.1:7868 {
bind 127.0.0.1
root * /var/www/virtual/{$USER}/html
handle /index.php/apps/notify_push/* {
php_fastcgi unix//var/lib/php-fpm/{$USER}/php-fpm.sock {
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
}
}
handle {
respond 404
}
}
Caddy expands {$USER} from the service environment. Create ~/.config/systemd/user/nextcloud-push-callback.service:
[Unit]
Description=Local Nextcloud Client Push callbacks
After=php-fpm.service
[Service]
ExecStart=/usr/bin/caddy run --config %h/.config/nextcloud-push/Caddyfile
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
Allow the loopback callback host and trust only its loopback source. The following indices assume this guide's fresh installation. If you already have additional trusted domains or proxies, append at unused indices instead of overwriting them. Example output:
[isabell@moondust ~]$ php /var/www/virtual/$USER/html/occ config:system:set trusted_domains 1 --value=127.0.0.1:7868
System config value trusted_domains => 1 set to string 127.0.0.1:7868
[isabell@moondust ~]$ php /var/www/virtual/$USER/html/occ config:system:set trusted_proxies 0 --value=127.0.0.1
System config value trusted_proxies => 0 set to string 127.0.0.1
Push service¶
Create ~/.config/systemd/user/notify_push.service with the following content. This uses the x86-64 binary shipped with the app:
[Unit]
Description=Nextcloud Client Push
After=valkey.service nextcloud-push-callback.service
Requires=nextcloud-push-callback.service
[Service]
Type=notify
Environment=PORT=7867
Environment=NEXTCLOUD_URL=http://127.0.0.1:7868
ExecStart=/var/www/virtual/%u/html/apps/notify_push/bin/x86_64/notify_push /var/www/virtual/%u/html/config/config.php
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
Load and start the service. Reloading produces no output; example output for enabling it follows:
[isabell@moondust ~]$ systemctl --user daemon-reload
[isabell@moondust ~]$ systemctl --user enable --now nextcloud-push-callback
Created symlink '/home/isabell/.config/systemd/user/default.target.wants/nextcloud-push-callback.service' → '/home/isabell/.config/systemd/user/nextcloud-push-callback.service'.
[isabell@moondust ~]$ systemctl --user enable --now notify_push
Created symlink '/home/isabell/.config/systemd/user/default.target.wants/notify_push.service' → '/home/isabell/.config/systemd/user/notify_push.service'.
Add an explicit Apache backend for / on your Nextcloud domain, then route /push to the service with the prefix removed. The domain-specific Apache route keeps normal Nextcloud requests working alongside the domain-specific push route. If that Apache route already exists, keep it. Replace the domain if you use a custom one. Example output:
[isabell@moondust ~]$ uberspace web backend add "$USER.uber.space/" apache
OK: Added webbackend 'isabell.uber.space/' to your Asteroid
[isabell@moondust ~]$ uberspace web backend add "$USER.uber.space/push" port 7867 --remove-prefix
OK: Added webbackend 'isabell.uber.space/push' to your Asteroid
Wait for the backend changes to take effect, then run the setup check. Example output:
[isabell@moondust ~]$ php /var/www/virtual/$USER/html/occ notify_push:setup "https://$USER.uber.space/push"
✓ redis is configured
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
✓ push server is a trusted proxy
✓ push server is running the same version as the app
configuration saved
All setup checks must pass. If the trusted-proxy check fails, check that the callback service is running and NEXTCLOUD_URL points to its loopback address. Do not add the public frontend or entire networks to trusted_proxies to work around a failed check. Nextcloud clients continue using the public HTTPS push URL; the HTTP callback never leaves your Asteroid.
URL rewriting¶
If you prefer cleaner URLs without index.php, run the following commands:
[isabell@moondust ~]$ php occ config:system:set htaccess.RewriteBase --value='/'
System config value htaccess.RewriteBase set to string /
[isabell@moondust ~]$ php occ maintenance:update:htaccess
.htaccess has been updated
Database maintenance¶
To optimize the database configuration, run these commands:
[isabell@moondust ~]$ cd html
[isabell@moondust html]$ php occ db:add-missing-indices --no-interaction
[isabell@moondust html]$ php occ db:add-missing-columns --no-interaction
[isabell@moondust html]$ php occ db:add-missing-primary-keys --no-interaction
[isabell@moondust html]$ php occ db:convert-filecache-bigint --no-interaction
Nextcloud Talk (optional)¶
Nextcloud Talk adds chat, audio and video calls, and screen sharing. Install its spreed app from your Nextcloud directory. Example output (the version depends on your Nextcloud release):
[isabell@moondust ~]$ cd /var/www/virtual/$USER/html/
[isabell@moondust html]$ php occ app:install spreed
spreed 22.0.18 installed
spreed enabled
Changing directories produces no output on success. If Talk is already installed but disabled, enable it under Apps > Your apps instead.
Open Talk in Nextcloud, create a conversation, and invite another user. Test sending messages and making a call with microphone and camera access allowed in both browsers. Test calls between different networks, for example your home connection and a mobile connection.
Calls across different networks
Talk provides a default STUN server, but many networks also need a TURN server to relay audio and video. Installing the Talk app alone does not provide one. Obtain a TURN service or set up a separate server following the Talk TURN documentation. In Administration settings > Talk > TURN servers, enter its hostname and port, shared secret, and supported protocols, then use the connection test. Use the values supplied by your TURN provider or server configuration.
The optional high-performance backend reduces bandwidth requirements for group calls and enables additional features. Configure an existing backend's URL and shared secret under Administration settings > Talk if you have one. Neither that backend nor a TURN server is installed by this guide.
Nextcloud Office (optional)¶
Nextcloud Office with Collabora Online lets you edit documents, spreadsheets, and presentations in your browser. It needs both the Office app (richdocuments) and a Collabora Online server.
The following steps run Collabora Online Development Edition (CODE) as a separate service on the same Asteroid. The standalone service and document conversion were tested with CODE 26.04.4.2 on Uberspace 8.0.99. Plan for at least 1 GB of RAM plus about 100 MB per concurrent user, in addition to Nextcloud's memory usage.
Install the Collabora server¶
Download the official x86-64 AppImage linked by the built-in CODE project's build script. Extract it once so the service does not need FUSE or unpack the image at every start:
[isabell@moondust ~]$ mkdir -p ~/collabora
[isabell@moondust ~]$ cd ~/collabora
[isabell@moondust collabora]$ curl --fail --location --silent --show-error https://www.collaboraoffice.com/downloads/Collabora-Office-AppImage-Release/collabora-online-release-LATEST.AppImage --output Collabora_Online.AppImage
[isabell@moondust collabora]$ chmod u+x Collabora_Online.AppImage
[isabell@moondust collabora]$ ./Collabora_Online.AppImage --appimage-extract > extract.log
These commands produce no terminal output on success. The extracted application is in ~/collabora/squashfs-root/; the list of extracted files is saved in extract.log.
Create the service¶
Create the systemd user service directory if needed. This command produces no output on success:
[isabell@moondust ~]$ mkdir -p ~/.config/systemd/user
Create ~/.config/systemd/user/collabora.service with the following content. Replace office.example.com with a dedicated domain for Collabora. The WOPI host https://%u.uber.space:443 allows the Nextcloud installation from this guide; if you use a custom Nextcloud domain, replace it with that domain's HTTPS URL and port 443.
[Unit]
Description=Collabora Online
[Service]
Type=simple
WorkingDirectory=%h/collabora
ExecStart=/usr/bin/setpriv --inh-caps=-all --ambient-caps=-all %h/collabora/squashfs-root/AppRun \
--o:security.capabilities=true \
--o:security.seccomp=true \
--o:net.listen=any \
--o:net.proto=IPv4 \
--o:net.proxy_prefix=false \
--o:ssl.termination=true \
--o:server_name=office.example.com \
--o:storage.wopi.alias_groups[@mode]=groups \
--o:storage.wopi.alias_groups.group.host[@allow]=true \
--o:storage.wopi.alias_groups.group.host=https://%u.uber.space:443
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
Systemd expands %h to your home directory and %u to your username. setpriv drops inherited and ambient capabilities: without it, Collabora's worker can refuse to start on Uberspace with coolforkit has some capabilities set. The two security options require worker isolation and syscall filtering. The bundled launcher runs Collabora on port 9983 with internal HTTP; Uberspace's frontend provides HTTPS. net.listen=any makes the service reachable by that frontend.
Load and start the service. The reload command produces no output on success; example output for enabling and checking the service follows:
[isabell@moondust ~]$ systemctl --user daemon-reload
[isabell@moondust ~]$ systemctl --user enable --now collabora
Created symlink '/home/isabell/.config/systemd/user/default.target.wants/collabora.service' → '/home/isabell/.config/systemd/user/collabora.service'.
[isabell@moondust ~]$ systemctl --user is-active collabora
active
The document workers take a few seconds to initialize. To inspect startup problems, read the journal. Example output (shortened):
[isabell@moondust ~]$ journalctl --user -u collabora -n 30 --no-pager
Oct 11 17:33:08 moondust.uberspace.de setpriv[12345]: Ready to accept connections on port 9983.
Configure HTTPS access¶
Configure DNS for office.example.com as described in the domain documentation, then register it and add a web backend for Collabora. Replace the example domain in both commands. Example output:
[isabell@moondust ~]$ uberspace web domain add office.example.com
OK: Added webdomain 'office.example.com' to your Asteroid
[isabell@moondust ~]$ uberspace web backend add office.example.com/ port 9983
OK: Added webbackend 'office.example.com/' to your Asteroid
Allow time for domain and certificate provisioning. Check the public discovery endpoint. Example output (shortened):
[isabell@moondust ~]$ curl --fail --silent --show-error https://office.example.com/hosting/discovery
<wopi-discovery>
<net-zone name="external-https">
...
</net-zone>
</wopi-discovery>
The document URLs in this XML must use your Collabora domain and https://.
Connect Nextcloud Office¶
Install the Office app from your Nextcloud directory. Example output (the version depends on your Nextcloud release):
[isabell@moondust ~]$ cd /var/www/virtual/$USER/html/
[isabell@moondust html]$ php occ app:install richdocuments
richdocuments 9.2.3 installed
richdocuments enabled
Changing directories produces no output on success. If Office is already installed but disabled, enable it under Apps > Your apps instead.
Open Administration settings > Office, select Use your own server, enter your Collabora server's HTTPS URL, and save. Wait for the connection check to succeed. Keep certificate verification enabled. Set Allow list for WOPI requests to the Collabora server's source IP addresses, as described in the Office configuration documentation. For a hosted Collabora service, ask your provider for these addresses.
In Files, create a new document, enter some text, close it, and reopen it to check that your changes were saved. Share it with another Nextcloud user and open it together to check collaborative editing.
Updates¶
Check the changelog regularly or subscribe to the project’s Github release feed with your favorite feed reader to stay informed about new updates and releases.
Update Talk, Office, and Client Push through Apps > Your apps whenever updates are available. The command-line script below also updates installed apps. A separately hosted TURN server or Talk backend needs its own updates. The Collabora service installed above is updated separately as described below.
If you update Client Push through the web interface, restart its service afterward. This command produces no output on success:
[isabell@moondust ~]$ systemctl --user restart notify_push
Repeat the Client Push setup check after updating. The script below restarts the service automatically if it is running.
The easiest way to update Nextcloud is to use the web updater provided in the admin section of the Web Interface. You can also update via the command line, to do so create ~/bin/nextcloud-update with the following content:
#!/usr/bin/env bash
## Updater automatically works in maintenance:mode.
## Use the Uberspace backup system for files and database if you need to roll back.
## The Nextcloud updater creates backups only to safe base and app code data and config files
## so it takes ressources you might need for your productive data.
## Deactivate NC-updater Backups with --no-backup
set -euo pipefail
# Identifier for the journal logs
JOURNAL_TAG="nextcloud-update"
# Use echo and pipe to logger to avoid issues with messages starting with hyphens
echo "--- $(date '+%F %T') --- Starting Nextcloud update script" | logger -t "$JOURNAL_TAG"
run() {
local tmp_log
tmp_log=$(mktemp)
# Execute the command
# 2>&1 -> Redirect stderr to stdout
# tee -> Save real-time output to the temp file
# logger -> Stream real-time output to the systemd journal
if ! "$@" 2>&1 | tee "$tmp_log" | logger -t "$JOURNAL_TAG"; then
echo "FEHLER bei: $*"
echo
cat "$tmp_log"
rm -f "$tmp_log"
exit 1
fi
rm -f "$tmp_log"
}
cd "/var/www/virtual/$USER/html/"
run php updater/updater.phar -vv --no-backup --no-interaction
## database optimisations
run php occ db:add-missing-primary-keys --no-interaction
run php occ db:add-missing-columns --no-interaction
run php occ db:add-missing-indices --no-interaction
run php occ db:convert-filecache-bigint --no-interaction
run php occ app:update --all
## App updates may require additional steps to be done by the `upgrade` command
run php occ upgrade
# Restart the optional push daemon after its app binary has been updated.
if systemctl --user is-active --quiet notify_push.service; then
run systemctl --user restart notify_push.service
fi
echo "--- Nextcloud update script finished successfully ---" | logger -t "$JOURNAL_TAG"
exit 0
Make the script executable:
[isabell@moondust ~]$ chmod +x ~/bin/nextcloud-update
To check for updates daily add another cronjob.
Tip
Use journalctl --user --unit nextcloud-update to read the logs of the script.
Update the Collabora server¶
Check the CODE release announcements for updates. Nextcloud's app updater does not update the standalone AppImage.
Download and extract the new AppImage into a staging directory while the existing service continues to run. Use an empty ~/collabora-update directory; keep ~/collabora.previous free for the previous installation. These commands produce no terminal output on success:
[isabell@moondust ~]$ mkdir ~/collabora-update
[isabell@moondust ~]$ cd ~/collabora-update
[isabell@moondust collabora-update]$ curl --fail --location --silent --show-error https://www.collaboraoffice.com/downloads/Collabora-Office-AppImage-Release/collabora-online-release-LATEST.AppImage --output Collabora_Online.AppImage
[isabell@moondust collabora-update]$ chmod u+x Collabora_Online.AppImage
[isabell@moondust collabora-update]$ ./Collabora_Online.AppImage --appimage-extract > extract.log
Ask users to close their documents before switching versions: stopping Collabora interrupts active editing sessions. Stop the service, keep the previous installation for rollback, and move the new installation into place. These commands produce no output on success:
[isabell@moondust ~]$ cd ~
[isabell@moondust ~]$ systemctl --user stop collabora
[isabell@moondust ~]$ mv ~/collabora ~/collabora.previous
[isabell@moondust ~]$ mv ~/collabora-update ~/collabora
[isabell@moondust ~]$ systemctl --user start collabora
Repeat the discovery check and open, edit, and reopen a document in Nextcloud. Keep the previous installation until these checks succeed. To roll back, stop the service, move the failed ~/collabora directory aside, restore ~/collabora.previous as ~/collabora, and start the service again. Remove the old installation after successful verification and before the next update.