FreeBSD.software
Home/Blog/How to Install Nextcloud on FreeBSD
tutorial2026-03-29

How to Install Nextcloud on FreeBSD

Complete guide to installing Nextcloud on FreeBSD. Covers NGINX + PHP-FPM setup, PostgreSQL database, SSL with Let's Encrypt, cron jobs, apps, and performance tuning.

# How to Install Nextcloud on FreeBSD

Nextcloud gives you a self-hosted alternative to Google Drive, Dropbox, and Office 365 -- file sync, calendar, contacts, video calls, and collaborative document editing under your own control. FreeBSD is an excellent platform for running it: ZFS provides checksummed, snapshot-capable storage; jails let you isolate the service cleanly; and the ports tree keeps every dependency a pkg install away.

This guide walks through a complete, production-grade Nextcloud deployment on FreeBSD using NGINX, PHP-FPM, PostgreSQL, Redis, and Let's Encrypt. By the end you will have a fully working instance with caching, background jobs, and a solid backup strategy.

Why Self-Host Nextcloud on FreeBSD

Three reasons stand out over managed cloud storage:

**Privacy and data sovereignty.** Your files live on hardware you control. No third party scans your documents, trains models on your data, or changes terms of service on you. For businesses handling client data or anyone subject to GDPR, this matters.

**ZFS for data integrity.** FreeBSD's first-class ZFS support means every block of your Nextcloud data is checksummed. Silent bit rot -- the kind that corrupts a file without any error message -- simply does not happen. ZFS snapshots also give you instant, space-efficient rollback points before upgrades or bulk changes.

**Stability and performance.** FreeBSD's network stack and I/O subsystem are battle-tested in hosting environments. Combined with NGINX and PHP-FPM, you get a lean, predictable server that does not surprise you with unattended reboots or forced updates.

Prerequisites

Before starting, make sure you have:

- A FreeBSD 14.x server with root access (a fresh install is ideal).

- A registered domain name (e.g., cloud.example.com) with DNS A/AAAA records pointing to your server's IP.

- Ports for HTTP (80) and HTTPS (443) open in your firewall.

- At least 1 GB of RAM and 20 GB of disk space (more for heavy use).

This guide assumes a clean FreeBSD 14.2-RELEASE system. All commands run as root unless noted otherwise.

Installing Dependencies

Nextcloud requires a web server, PHP with several extensions, and a database. We use NGINX, PHP 8.3 with FPM, and PostgreSQL 16.

sh

pkg update && pkg upgrade -y

pkg install -y \

nginx \

php83 php83-fpm php83-extensions \

php83-curl php83-dom php83-fileinfo php83-gd php83-iconv \

php83-intl php83-mbstring php83-opcache php83-pdo_pgsql \

php83-pecl-APCu php83-pecl-redis php83-pgsql php83-session \

php83-simplexml php83-xml php83-xmlreader php83-xmlwriter \

php83-zip php83-zlib php83-bcmath php83-gmp php83-exif \

postgresql16-server postgresql16-client \

redis \

certbot py311-certbot-nginx \

sudo

Enable all services at boot:

sh

sysrc nginx_enable=YES

sysrc php_fpm_enable=YES

sysrc postgresql_enable=YES

sysrc redis_enable=YES

Initialize and start PostgreSQL:

sh

/usr/local/etc/rc.d/postgresql initdb

service postgresql start

Start Redis:

sh

service redis start

For a deeper look at the web server layer, see our [NGINX setup guide](/blog/nginx-freebsd-production-setup/). For PostgreSQL specifics, the [PostgreSQL on FreeBSD guide](/blog/postgresql-freebsd-setup/) covers tuning and maintenance.

Database Setup

Create a dedicated PostgreSQL user and database for Nextcloud. Do not use the default postgres superuser for the application.

sh

sudo -u postgres psql

Inside the PostgreSQL shell:

sql

CREATE USER nextcloud WITH PASSWORD 'a-strong-random-password-here';

CREATE DATABASE nextcloud OWNER nextcloud;

GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud;

\q

Replace a-strong-random-password-here with a real password. Use openssl rand -base64 32 to generate one.

Downloading and Installing Nextcloud

Grab the latest stable release from the official site and extract it to the web root.

sh

cd /tmp

fetch https://download.nextcloud.com/server/releases/latest.tar.bz2

fetch https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256

# Verify the checksum

sha256 -c latest.tar.bz2.sha256

tar xjf latest.tar.bz2 -C /usr/local/www/

chown -R www:www /usr/local/www/nextcloud

Create the data directory outside the web root for security:

sh

mkdir -p /var/nextcloud/data

chown www:www /var/nextcloud/data

chmod 750 /var/nextcloud/data

PHP-FPM Pool Configuration

Create a dedicated FPM pool for Nextcloud. This isolates it from other PHP applications and lets you tune resources independently.

Edit /usr/local/etc/php-fpm.d/nextcloud.conf:

ini

[nextcloud]

user = www

group = www

listen = /var/run/php-fpm-nextcloud.sock

listen.owner = www

listen.group = www

listen.mode = 0660

pm = dynamic

pm.max_children = 16

pm.start_servers = 4

pm.min_spare_servers = 2

pm.max_spare_servers = 8

pm.max_requests = 500

env[HOSTNAME] = $HOSTNAME

env[PATH] = /usr/local/bin:/usr/bin:/bin

env[TMP] = /tmp

env[TMPDIR] = /tmp

env[TEMP] = /tmp

php_admin_value[memory_limit] = 512M

php_admin_value[upload_max_filesize] = 16G

php_admin_value[post_max_size] = 16G

php_admin_value[max_execution_time] = 3600

php_admin_value[max_input_time] = 3600

php_admin_value[output_buffering] = 0

php_admin_value[opcache.enable] = 1

php_admin_value[opcache.memory_consumption] = 128

php_admin_value[opcache.interned_strings_buffer] = 16

php_admin_value[opcache.max_accelerated_files] = 10000

php_admin_value[opcache.revalidate_freq] = 1

php_admin_value[opcache.save_comments] = 1

Remove or rename the default pool to avoid conflicts:

sh

mv /usr/local/etc/php-fpm.d/www.conf /usr/local/etc/php-fpm.d/www.conf.bak

Copy the production PHP configuration:

sh

cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini

Start PHP-FPM:

sh

service php-fpm start

NGINX Virtual Host Configuration

Create /usr/local/etc/nginx/conf.d/nextcloud.conf. This configuration follows the Nextcloud hardening recommendations and includes proper headers, request size limits, and PHP-FPM pass-through.

First, make sure your main nginx.conf includes the conf.d directory. Add this inside the http block if it is not already there:

nginx

include /usr/local/etc/nginx/conf.d/*.conf;

Now create the virtual host:

nginx

upstream php-handler {

server unix:/var/run/php-fpm-nextcloud.sock;

}

server {

listen 80;

listen [::]:80;

server_name cloud.example.com;

# Redirect all HTTP to HTTPS

return 301 https://$server_name$request_uri;

}

server {

listen 443 ssl http2;

listen [::]:443 ssl http2;

server_name cloud.example.com;

# SSL configuration -- managed by certbot (see next section)

ssl_certificate /usr/local/etc/letsencrypt/live/cloud.example.com/fullchain.pem;

ssl_certificate_key /usr/local/etc/letsencrypt/live/cloud.example.com/privkey.pem;

ssl_protocols TLSv1.2 TLSv1.3;

ssl_ciphers HIGH:!aNULL:!MD5;

ssl_prefer_server_ciphers on;

ssl_session_cache shared:SSL:10m;

ssl_session_timeout 10m;

# Nextcloud root

root /usr/local/www/nextcloud;

# Security headers

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

add_header Referrer-Policy "no-referrer" always;

add_header X-Content-Type-Options "nosniff" always;

add_header X-Download-Options "noopen" always;

add_header X-Frame-Options "SAMEORIGIN" always;

add_header X-Permitted-Cross-Domain-Policies "none" always;

add_header X-Robots-Tag "noindex, nofollow" always;

add_header X-XSS-Protection "1; mode=block" always;

# Remove X-Powered-By header

fastcgi_hide_header X-Powered-By;

# Max upload size

client_max_body_size 16G;

client_body_timeout 3600s;

fastcgi_buffers 64 4K;

# Disable gzip to avoid the BREACH attack

gzip off;

# Pagespeed is not supported

# pagespeed off;

# The settings below effectively turn off the floc tracking

add_header Permissions-Policy "interest-cohort=()";

# Rule borrowed from .htaccess to handle Microsoft DAV clients

location = / {

if ( $http_user_agent ~ ^DavClnt ) {

return 302 /remote.php/webdav/$is_args$args;

}

}

location = /robots.txt {

allow all;

log_not_found off;

access_log off;

}

# Make a regex exception for /.well-known so that clients can still

# access it despite the existence of the location ~ block below

location ^~ /.well-known {

# The rules in this block are an adaptation of the rules

# having /.well-known in the Nextcloud .htaccess

location = /.well-known/carddav { return 301 /remote.php/dav/; }

location = /.well-known/caldav { return 301 /remote.php/dav/; }

location /.well-known/acme-challenge { try_files $uri $uri/ =404; }

location /.well-known/pki-validation { try_files $uri $uri/ =404; }

return 301 /index.php$request_uri;

}

# Rules borrowed from .htaccess

location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) {

return 404;

}

location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {

return 404;

}

# Ensure this block, which passes PHP files to the PHP process,

# is above the blocks which handle static assets.

location ~ \.php(?:$|/) {

rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;

fastcgi_split_path_info ^(.+?\.php)(/.*)$;

set $path_info $fastcgi_path_info;

try_files $fastcgi_script_name =404;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

fastcgi_param PATH_INFO $path_info;

fastcgi_param HTTPS on;

fastcgi_param modHeadersAvailable true;

fastcgi_param front_controller_active true;

fastcgi_pass php-handler;

fastcgi_intercept_errors on;

fastcgi_request_buffering off;

fastcgi_read_timeout 3600;

}

# Serve static files

location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {

try_files $uri /index.php$request_uri;

add_header Cache-Control "public, max-age=15778463, immutable";

access_log off;

}

location ~ \.woff2?$ {

try_files $uri /index.php$request_uri;

expires 7d;

access_log off;

}

# Rule borrowed from .htaccess

location /remote {

return 301 /remote.php$request_uri;

}

location / {

try_files $uri $uri/ /index.php$request_uri;

}

}

Replace every instance of cloud.example.com with your actual domain. Test and start NGINX:

sh

nginx -t

service nginx start

SSL with Let's Encrypt

Obtain a free TLS certificate using certbot. Before running certbot, temporarily comment out the SSL lines in the NGINX config (or use the HTTP-only server block) so NGINX can start without the certificates that do not exist yet.

A simpler approach: use certbot in standalone mode first, then switch to the full config.

sh

# Stop NGINX temporarily

service nginx stop

# Obtain the certificate

certbot certonly --standalone -d cloud.example.com \

--agree-tos --no-eff-email -m admin@example.com

Certificates land in /usr/local/etc/letsencrypt/live/cloud.example.com/. Now start NGINX with the full configuration:

sh

service nginx start

Set up automatic renewal with a cron job:

sh

crontab -e

Add:


0 3 * * * /usr/local/bin/certbot renew --quiet --deploy-hook "service nginx reload"

For a more detailed walkthrough of certificate management, see our [Let's Encrypt on FreeBSD guide](/blog/lets-encrypt-freebsd/).

Nextcloud Web Installer

Open https://cloud.example.com in your browser. Nextcloud's setup wizard appears and asks for:

1. **Admin account** -- choose a username and strong password. Do not use "admin" as the username.

2. **Data directory** -- enter /var/nextcloud/data (the directory you created earlier).

3. **Database** -- select PostgreSQL and fill in:

- Database user: nextcloud

- Database password: the password you set earlier

- Database name: nextcloud

- Database host: localhost

Click "Install" and wait. Nextcloud creates all the tables and generates the initial configuration. This takes a minute or two depending on disk speed.

After installation completes, you land on the Nextcloud dashboard. Before doing anything else, set up background jobs and caching.

Cron Job Setup

Nextcloud needs to run background tasks regularly -- clearing caches, sending notifications, running file scans. The default AJAX method is unreliable. Switch to system cron.

First, go to **Settings > Administration > Basic settings** in the Nextcloud web interface. Under "Background jobs", select **Cron**.

Then add the cron job for the www user:

sh

crontab -u www -e

Add this line:


*/5 * * * * /usr/local/bin/php -f /usr/local/www/nextcloud/cron.php

This runs Nextcloud's background tasks every 5 minutes. Verify it works after a few minutes by checking the "Last job ran" timestamp in the admin settings.

Essential config.php Tuning

Nextcloud's configuration lives in /usr/local/www/nextcloud/config/config.php. After the web installer runs, edit this file to add caching, trusted proxies, and other production settings.

sh

ee /usr/local/www/nextcloud/config/config.php

Add or modify these entries inside the $CONFIG array:

php

'memcache.local' => '\OC\Memcache\APCu',

'memcache.distributed' => '\OC\Memcache\Redis',

'memcache.locking' => '\OC\Memcache\Redis',

'redis' => [

'host' => '/var/run/redis/redis.sock',

'port' => 0,

'timeout' => 1.5,

],

'overwrite.cli.url' => 'https://cloud.example.com',

'overwriteprotocol' => 'https',

'default_phone_region' => 'US',

'default_locale' => 'en_US',

'maintenance_window_start' => 1,

'trashbin_retention_obligation' => 'auto, 30',

'log_type' => 'file',

'logfile' => '/var/log/nextcloud.log',

'loglevel' => 2,

'log_rotate_size' => 104857600,

Create the log file:

sh

touch /var/log/nextcloud.log

chown www:www /var/log/nextcloud.log

Redis for Caching and File Locking

Redis dramatically improves Nextcloud performance by caching database queries, user sessions, and file lock states in memory. You already installed and enabled it earlier. Now configure it to use a Unix socket for lower latency.

Edit /usr/local/etc/redis.conf:

sh

# Find and modify these settings:

port 0

unixsocket /var/run/redis/redis.sock

unixsocketperm 770

Add the www user to the redis group so PHP-FPM can access the socket:

sh

pw groupmod redis -m www

Restart Redis:

sh

service redis restart

Verify the socket exists and has correct permissions:

sh

ls -la /var/run/redis/redis.sock

You should see srwxrwx--- with owner redis and group redis. Since www is now in the redis group, PHP-FPM can connect.

Recommended Apps

Nextcloud's app store has hundreds of add-ons. These are the essentials worth installing immediately from **Settings > Apps**:

**Calendar** -- CalDAV calendar with sharing, reminders, and iCal import. Replaces Google Calendar.

**Contacts** -- CardDAV address book. Syncs with mobile devices and desktop clients via standard protocols.

**Nextcloud Talk** -- Video calls, screen sharing, and chat. Works in the browser and through dedicated mobile apps. A solid replacement for Zoom or Teams for small teams.

**Nextcloud Office** (Collabora or ONLYOFFICE) -- Collaborative editing of documents, spreadsheets, and presentations directly in the browser. Requires a separate document server container or the built-in CODE app for small deployments.

**Notes** -- Simple markdown note-taking that syncs across devices.

**Deck** -- Kanban-style project boards. Lightweight alternative to Trello.

Install apps from the command line if you prefer:

sh

sudo -u www php /usr/local/www/nextcloud/occ app:install calendar

sudo -u www php /usr/local/www/nextcloud/occ app:install contacts

sudo -u www php /usr/local/www/nextcloud/occ app:install spreed

sudo -u www php /usr/local/www/nextcloud/occ app:install notes

sudo -u www php /usr/local/www/nextcloud/occ app:install deck

Backup Strategy

A proper backup covers three things: the Nextcloud files, the database, and the configuration. ZFS makes the file backup trivial.

ZFS Snapshots for Files and Data

If your Nextcloud data lives on a ZFS dataset (and it should), take regular snapshots:

sh

# Create a snapshot

zfs snapshot zroot/var/nextcloud@$(date +%Y-%m-%d_%H%M)

# List snapshots

zfs list -t snapshot | grep nextcloud

# Roll back to a snapshot (destructive -- removes newer data)

zfs rollback zroot/var/nextcloud@2026-03-29_0300

Automate daily snapshots with a cron job:

sh

0 2 * * * /sbin/zfs snapshot zroot/var/nextcloud@auto-$(date +\%Y-\%m-\%d)

Add a weekly cleanup to remove snapshots older than 30 days:

sh

0 4 * * 0 /sbin/zfs list -H -t snapshot -o name | grep 'zroot/var/nextcloud@auto-' | head -n -30 | xargs -n 1 zfs destroy

For more on ZFS snapshot management and send/receive for offsite replication, see our [ZFS on FreeBSD guide](/blog/zfs-freebsd-guide/).

PostgreSQL Database Backup

ZFS snapshots do not guarantee a consistent database state. Use pg_dump for database backups:

sh

sudo -u postgres pg_dump -Fc nextcloud > /var/backups/nextcloud-db-$(date +%Y-%m-%d).dump

Automate it:

sh

mkdir -p /var/backups

chown postgres:postgres /var/backups

Add to the postgres user's crontab:


0 2 * * * /usr/local/bin/pg_dump -Fc nextcloud > /var/backups/nextcloud-db-$(date +\%Y-\%m-\%d).dump

To restore:

sh

sudo -u postgres pg_restore -d nextcloud --clean /var/backups/nextcloud-db-2026-03-29.dump

Configuration Backup

Back up the Nextcloud config directory and NGINX configs:

sh

tar czf /var/backups/nextcloud-config-$(date +%Y-%m-%d).tar.gz \

/usr/local/www/nextcloud/config/ \

/usr/local/etc/nginx/conf.d/ \

/usr/local/etc/php-fpm.d/

Putting It Together

Enable Nextcloud maintenance mode before backing up for full consistency:

sh

sudo -u www php /usr/local/www/nextcloud/occ maintenance:mode --on

# Snapshot, dump, tar

zfs snapshot zroot/var/nextcloud@backup-$(date +%Y-%m-%d)

sudo -u postgres pg_dump -Fc nextcloud > /var/backups/nextcloud-db-$(date +%Y-%m-%d).dump

sudo -u www php /usr/local/www/nextcloud/occ maintenance:mode --off

Performance Tuning

PHP OPcache

OPcache is already configured in the PHP-FPM pool above. Verify it is active:

sh

sudo -u www php -i | grep opcache.enable

You should see opcache.enable => On. The settings in the FPM pool config give OPcache 128 MB of shared memory and room for 10,000 cached scripts, which is plenty for Nextcloud with apps.

For additional PHP tuning, enable JIT compilation in /usr/local/etc/php.ini:

ini

opcache.jit = 1255

opcache.jit_buffer_size = 128M

Restart PHP-FPM after changes:

sh

service php-fpm restart

NGINX FastCGI Cache

For multi-user installations where many people access the same shared files, a FastCGI cache can reduce PHP load significantly. Add this to the http block in nginx.conf:

nginx

fastcgi_cache_path /var/cache/nginx/nextcloud levels=1:2 keys_zone=nextcloud_cache:100m inactive=60m;

fastcgi_cache_key "$scheme$request_method$host$request_uri";

Create the cache directory:

sh

mkdir -p /var/cache/nginx/nextcloud

chown www:www /var/cache/nginx/nextcloud

Then in the PHP location block of your Nextcloud server config, add:

nginx

fastcgi_cache nextcloud_cache;

fastcgi_cache_valid 200 60m;

fastcgi_cache_use_stale error timeout updating http_500 http_503;

fastcgi_cache_bypass $http_cookie;

fastcgi_no_cache $http_cookie;

Be cautious with this: Nextcloud serves personalized content per-user, so the $http_cookie bypass is important. Test thoroughly. For most small-to-medium deployments, Redis caching alone is sufficient and the FastCGI cache adds complexity without proportional benefit. Consider it only if you see high PHP-FPM process counts under load.

System-Level Tuning

A few sysctl values help with busy Nextcloud servers:

sh

# /etc/sysctl.conf

kern.ipc.shmmax=2147483648

kern.ipc.shmall=524288

net.inet.tcp.sendbuf_max=16777216

net.inet.tcp.recvbuf_max=16777216

Apply without reboot:

sh

sysctl -f /etc/sysctl.conf

Updating Nextcloud

Run updates through the command line for reliability:

sh

# Enable maintenance mode

sudo -u www php /usr/local/www/nextcloud/occ maintenance:mode --on

# Take a snapshot before updating

zfs snapshot zroot/var/nextcloud@pre-update-$(date +%Y-%m-%d)

sudo -u postgres pg_dump -Fc nextcloud > /var/backups/nextcloud-pre-update-$(date +%Y-%m-%d).dump

# Run the updater

sudo -u www php /usr/local/www/nextcloud/updater/updater.phar

# Disable maintenance mode

sudo -u www php /usr/local/www/nextcloud/occ maintenance:mode --off

# Run any pending migrations

sudo -u www php /usr/local/www/nextcloud/occ upgrade

sudo -u www php /usr/local/www/nextcloud/occ db:add-missing-indices

sudo -u www php /usr/local/www/nextcloud/occ db:add-missing-columns

Troubleshooting

Check the Nextcloud log for application errors:

sh

tail -f /var/log/nextcloud.log

Check NGINX error log:

sh

tail -f /var/log/nginx/error.log

Check PHP-FPM log:

sh

tail -f /var/log/php-fpm.log

Run the built-in Nextcloud diagnostics:

sh

sudo -u www php /usr/local/www/nextcloud/occ status

sudo -u www php /usr/local/www/nextcloud/occ check

Common issues:

- **"Permission denied" errors** -- ensure all files under /usr/local/www/nextcloud and /var/nextcloud/data are owned by www:www.

- **"504 Gateway Timeout"** -- increase fastcgi_read_timeout in NGINX and max_execution_time in the PHP-FPM pool.

- **"Redis connection refused"** -- verify the socket path and that www is in the redis group. Run groups www to check.

- **Large file uploads fail** -- confirm client_max_body_size, upload_max_filesize, and post_max_size all match (16G in this guide).

FAQ

Can I use MySQL/MariaDB instead of PostgreSQL?

Yes. Replace the php83-pdo_pgsql and php83-pgsql packages with php83-pdo_mysql and php83-mysqli, install mariadb106-server, and select MySQL in the web installer. PostgreSQL generally performs better with Nextcloud at scale and has better support for the RETURNING clause used in newer Nextcloud versions. The Nextcloud developers recommend PostgreSQL for new installations.

How much RAM does Nextcloud need?

A single-user instance runs fine on 1 GB of RAM. For 10-50 users with active file syncing, allocate 4 GB minimum. Redis, PostgreSQL, and PHP-FPM each want their own share. On a 4 GB server, expect roughly 512 MB for PostgreSQL, 256 MB for Redis, and the rest shared between PHP-FPM workers and the OS.

Can I run Nextcloud in a FreeBSD jail?

Absolutely, and it is the recommended approach for production. Create a jail with VNET networking, install everything inside it, and use nullfs mounts or ZFS datasets for persistent data. Jails give you clean separation from other services and make migration straightforward -- just snapshot the jail's ZFS dataset and send it to a new host.

How do I enable two-factor authentication?

Install the "Two-Factor TOTP Provider" app from the Nextcloud app store. Each user can then enable TOTP (time-based one-time passwords) in their personal security settings. This works with apps like Aegis, andOTP, or any standard TOTP authenticator. For enforcement, admins can require 2FA for all users via **Settings > Administration > Security**.

How do I sync files from desktop and mobile?

Download the official Nextcloud client for Windows, macOS, Linux, iOS, or Android from nextcloud.com/install. Enter your server URL (https://cloud.example.com), log in, and choose which folders to sync. The desktop client supports selective sync, virtual files (on-demand download), and end-to-end encryption for sensitive folders.

How do I move the data directory to a different ZFS dataset?

Enable maintenance mode, stop PHP-FPM, then move the data:

sh

sudo -u www php /usr/local/www/nextcloud/occ maintenance:mode --on

service php-fpm stop

# Create a new dataset and move data

zfs create zroot/nextcloud-data

mv /var/nextcloud/data/* /nextcloud-data/

chown -R www:www /nextcloud-data

# Update config.php

# Change 'datadirectory' => '/nextcloud-data',

service php-fpm start

sudo -u www php /usr/local/www/nextcloud/occ maintenance:mode --off

Is Nextcloud Office usable for real work?

For basic document editing and collaboration, yes. Nextcloud integrates with Collabora Online (LibreOffice-based) or ONLYOFFICE. Both handle Word, Excel, and PowerPoint files. Complex formatting may not render perfectly compared to Microsoft Office, but for internal documents and team collaboration, it works well. For small deployments (1-5 concurrent editors), use the built-in CODE server. Larger teams should run a dedicated Collabora or ONLYOFFICE container.

Summary

You now have a production-ready Nextcloud instance on FreeBSD with:

- NGINX serving the frontend with TLS and security headers.

- PHP-FPM running a dedicated pool with optimized OPcache settings.

- PostgreSQL as the database backend.

- Redis handling distributed caching and file locking.

- System cron running background tasks every 5 minutes.

- Let's Encrypt providing automatic certificate renewal.

- ZFS snapshots and pg_dump for comprehensive backups.

This stack is stable, fast, and maintainable. FreeBSD's quarterly package updates and Nextcloud's built-in updater make ongoing maintenance straightforward. The combination of ZFS snapshots with database dumps means you can always roll back if something goes wrong during an upgrade.

For related guides, see our [NGINX production setup](/blog/nginx-freebsd-production-setup/), [PostgreSQL on FreeBSD](/blog/postgresql-freebsd-setup/), [Let's Encrypt on FreeBSD](/blog/lets-encrypt-freebsd/), and [ZFS on FreeBSD guide](/blog/zfs-freebsd-guide/).