Self-Hosting Nextcloud

August 4, 2026

Nextcloud replaces Google Drive, Dropbox, and calendar/contact services with a self-hosted platform you control. On Gentoo, Nextcloud is available through Portage and deployed with webapp-config, which manages multiple web applications across virtual hosts. This post covers installing Nextcloud with Apache and PHP-FPM, configuring it with either SQLite (for standalone servers) or MySQL (for mail server integration), and hardening the setup for production use.

Prerequisites

Before starting:

Setting USE Flags

Nextcloud and PHP need specific USE flags on Gentoo. Create the package.use files:

For SQLite mode (standalone server):

cat > /etc/portage/package.use/nextcloud << 'EOF'
www-apps/nextcloud sqlite -mysql vhosts
EOF

cat > /etc/portage/package.use/php-nextcloud << 'EOF'
dev-lang/php xmlreader xmlwriter truetype gd curl intl bcmath gmp zip pdo sqlite fpm
EOF

For MySQL mode (shared with a mail server):

cat > /etc/portage/package.use/nextcloud << 'EOF'
www-apps/nextcloud -sqlite mysql vhosts
EOF

cat > /etc/portage/package.use/php-nextcloud << 'EOF'
dev-lang/php xmlreader truetype gd curl intl bcmath gmp zip fpm
EOF

Additional dependencies:

cat > /etc/portage/package.use/gd-nextcloud << 'EOF'
media-libs/gd truetype
EOF

cat > /etc/portage/package.use/imagemagick-nextcloud << 'EOF'
media-gfx/imagemagick -openmp
EOF

cat > /etc/portage/package.use/apache-nextcloud << 'EOF'
www-servers/apache apache2_modules_proxy apache2_modules_proxy_fcgi
EOF

The vhosts USE flag tells Portage to install Nextcloud into a location that webapp-config can manage, rather than directly into a document root.

Installing Nextcloud

emerge -av www-apps/nextcloud

This pulls in Nextcloud and its PHP dependencies. The compilation may take significant time depending on how many dependencies need rebuilding with the new USE flags.

Deploying with webapp-config

Gentoo's webapp-config deploys web applications into virtual host directories. Deploy Nextcloud for your domain:

webapp-config -I -h cloud.example.com -d / nextcloud $(qatom -F "%{PV}" $(portageq best_visible / www-apps/nextcloud))

This installs Nextcloud to /var/www/cloud.example.com/htdocs/. The version number is pulled dynamically from the installed package.

Alternatively, specify the version manually:

webapp-config -I -h cloud.example.com -d / nextcloud 29.0.0

Creating the Data Directory

Nextcloud's data directory should be outside the web root for security:

mkdir -p /var/nextcloud/data
chown apache:apache /var/nextcloud/data
chmod 750 /var/nextcloud/data

Configuring PHP-FPM

Create or edit the PHP-FPM pool configuration. On Gentoo, this is typically at /etc/php/fpm-php8.2/fpm.d/www.conf (adjust the version number):

[www]
user = apache
group = apache
listen = 127.0.0.1:9000
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

Adjust PHP settings for Nextcloud's requirements. Edit /etc/php/fpm-php8.2/php.ini:

memory_limit = 512M
upload_max_filesize = 512M
post_max_size = 512M
max_execution_time = 300
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 1

Start PHP-FPM:

rc-update add php-fpm default
rc-service php-fpm start

Configuring Apache

Enable the proxy modules in /etc/conf.d/apache2:

APACHE2_OPTS="-D DEFAULT_VHOST -D SSL -D SSL_DEFAULT_VHOST -D PROXY"

Create the PHP-FPM integration file at /etc/apache2/modules.d/70_php-fpm.conf:

<IfModule proxy_fcgi_module>
    <FilesMatch "\.php$">
        SetHandler "proxy:fcgi://127.0.0.1:9000"
    </FilesMatch>
    DirectoryIndex index.php index.html
</IfModule>

Virtual Host for Nextcloud

Create /etc/apache2/vhosts.d/cloud.example.com.conf:

For a standalone server behind a reverse proxy (no local TLS):

<VirtualHost *:80>
    ServerName cloud.example.com

    DocumentRoot "/var/www/cloud.example.com/htdocs"

    # Trust X-Forwarded-Proto from reverse proxy
    SetEnvIf X-Forwarded-Proto "https" HTTPS=on

    <Directory "/var/www/cloud.example.com/htdocs">
        Require all granted
        AllowOverride All
        Options FollowSymLinks
    </Directory>

    ErrorLog /var/log/apache2/cloud.example.com_error.log
    CustomLog /var/log/apache2/cloud.example.com_access.log combined
</VirtualHost>

For a server with local TLS (not behind a reverse proxy):

<VirtualHost *:80>
    ServerName cloud.example.com
    Redirect permanent / https://cloud.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName cloud.example.com

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/example.com.key

    DocumentRoot "/var/www/cloud.example.com/htdocs"

    <Directory "/var/www/cloud.example.com/htdocs">
        Require all granted
        AllowOverride All
        Options FollowSymLinks
    </Directory>

    ErrorLog /var/log/apache2/cloud.example.com_ssl_error.log
    CustomLog /var/log/apache2/cloud.example.com_ssl_access.log combined
</VirtualHost>

Validate and restart Apache:

apache2ctl configtest
rc-service apache2 restart

Running the Nextcloud Installer

Web-Based Installation

Navigate to https://cloud.example.com/ in your browser. The installer asks for:

  1. Admin username and password
  2. Data directory path (/var/nextcloud/data)
  3. Database type (SQLite or MySQL)
  4. For MySQL: host, database name, user, and password

Command-Line Installation

For automated setups, use the occ command:

With SQLite:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ maintenance:install \
  --database "sqlite" \
  --admin-user "admin" \
  --admin-pass "your-admin-password" \
  --data-dir "/var/nextcloud/data"

With MySQL:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ maintenance:install \
  --database "mysql" \
  --database-host "localhost" \
  --database-name "nextcloud" \
  --database-user "nextcloud" \
  --database-pass "nextcloud-db-password" \
  --admin-user "admin" \
  --admin-pass "your-admin-password" \
  --data-dir "/var/nextcloud/data"

Post-Installation Configuration

Trusted Domains

Nextcloud only responds to requests for domains listed in its trusted domains configuration. Add your domain:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  trusted_domains 0 --value="cloud.example.com"

Trusted Proxy

If Nextcloud runs behind a reverse proxy, configure the trusted proxy to get correct client IPs:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  trusted_proxies 0 --value="10.0.0.0/8"

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  overwriteprotocol --value="https"

The overwriteprotocol setting ensures Nextcloud generates HTTPS URLs even though the backend receives HTTP from the proxy.

Background Jobs

Switch from AJAX-based cron to system cron for reliable background processing:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ background:cron

Add the cron job:

crontab -u apache -e

Add:

*/5 * * * * php -f /var/www/cloud.example.com/htdocs/cron.php

This runs Nextcloud's background jobs every 5 minutes.

Memory Cache

Enable APCu for local caching and Redis for file locking (if Redis is installed):

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  memcache.local --value="\OC\Memcache\APCu"

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  memcache.locking --value="\OC\Memcache\Redis"

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  redis host --value="127.0.0.1"

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  redis port --value=6379 --type=integer

Default Phone Region

Set the default phone region to avoid a warning in the admin panel:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ config:system:set \
  default_phone_region --value="US"

Upgrading Nextcloud

When a new version is available in Portage:

emerge -av www-apps/nextcloud

Then upgrade the deployment:

webapp-config -U -h cloud.example.com -d / nextcloud $(qatom -F "%{PV}" $(portageq best_visible / www-apps/nextcloud))

Run the database migration:

sudo -u apache php /var/www/cloud.example.com/htdocs/occ upgrade

Choosing SQLite vs MySQL

SQLite is the right choice for a standalone Nextcloud server with a small number of users. It requires no external database service, simplifies backups (the entire database is a single file), and has zero configuration overhead. The downside is limited concurrency — SQLite locks the entire database on writes, which causes slowdowns with multiple simultaneous users.

MySQL is necessary when Nextcloud shares a server with other database-backed applications (like a mail server with PostfixAdmin) or when you expect more than a handful of concurrent users. The performance difference is significant under load — MySQL handles concurrent connections without blocking.

For a personal server with 1-5 users, SQLite is fine. For anything shared or production-facing, use MySQL.

Verifying the Installation

# Apache is serving Nextcloud
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1/status.php

# PHP-FPM is processing requests
curl -s http://127.0.0.1/status.php | python3 -m json.tool

# occ works
sudo -u apache php /var/www/cloud.example.com/htdocs/occ status

# Check for warnings
sudo -u apache php /var/www/cloud.example.com/htdocs/occ check

The status.php endpoint returns JSON with the Nextcloud version and whether it's installed.

Summary

After completing these steps:

  • Nextcloud is deployed on Gentoo via webapp-config
  • Apache serves the application through PHP-FPM
  • The data directory is outside the web root
  • Background jobs run via system cron every 5 minutes
  • Memory caching is enabled via APCu and Redis
  • Trusted proxy settings ensure correct client IPs behind a reverse proxy

Nextcloud pairs with Syncthing for server-to-server file replication, and with a mail server for integrated calendar and contact sync via CalDAV/CardDAV.