This is a concise tutorial, it is not meant to be a hand holding step by step guide. Please comment or contact me if you find errors.
Prerequisites:
Setup a domain/sub domain with an A record to the ip of the server or a CNAME to a “dynamic DNS” hostname. I recommend https://freedns.afraid.org.
The server needs to have ports 80 and 443 reachable to the public. The DNS must be propagated for letsencrypt to be successful. These steps should work for other versions of Nextcloud. Leave a comment with your experience.
Start the install
apt-get install apache2 mariadb-server libapache2-mod-fcgid php-fpm php php-gd php-json php-mysql php-curl php-mbstring php-intl php-imagick php-xml php-zip php-bz2 python3-certbot-apache php-apcu redis-server php-redis php-bcmath php-gmp ffmpeg curl coreutils libmagickcore-7.q16-10-extra
Download Nextcloud
wget https://download.nextcloud.com/server/releases/latest-31.tar.bz2
Make sure the md5 matches
md5sum latest-31.tar.bz2
curl https://download.nextcloud.com/server/releases/latest-31.tar.bz2.md5
Extract the tar file and change permissions
tar xfv latest-31.tar.bz2
mv nextcloud/ /var/www/example.com/
chown www-data:www-data -R /var/www/example.com/
[Setup Apache]
Create a apache virtual site
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf
Edit (vi, nano, emacs)
/etc/apache2/sites-available/example.com.conf
uncomment and change
ServerName example.com
change the document root
DocumentRoot /var/www/example.com
change log location if you would like
ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
enable example.com in apache
a2ensite example.com
a2enmod proxy_fcgi setenvif rewrite headers env dir mime userdir dav ssl
a2enconf php8.4-fpm
service apache2 restart
Setup Letsencrypt
certbot --apache -d example.com
tell it to redirect http to https if it asks. Otherwise, it should do automatically
Edit
/etc/apache2/sites-enabled/example.com-le-ssl.conf
<Directory /var/www/example.com/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
To avoid certain race conditions between the /etc/apache2/sites-available/example.com.conf and /etc/apache2/sites-available/000-default.conf
I prefer to remove example.com.conf and move the http->https redirect into the 000-default.conf
cat /etc/apache2/sites-available/example.com.conf
….snip…
# after it has been globally disabled with “a2disconf”.
#Include conf-available/serve-cgi-bin.conf
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost># vim: syntax=apache ts=4 sw=4 sts=4 sr noet
copy the rewrite rule at the bottom:
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
edit and paste into the default conf apache config
Edit
/etc/apache2/sites-enabled/000-default.conf
This is what 000-default.conf should look like
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
[Configure PHP]
edit
/etc/php/8.4/fpm/php.ini
memory_limit = 768M
upload_max_filesize = 1024M
post_max_size = 1024M
max_execution_time = 300
also add this under the [opcache] section in
/etc/php/8.4/fpm/php.ini
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=200
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.save_comments=1
opcache.revalidate_freq = 1
[Create a database, user and password for nextcloud]
mariadb -uroot
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'PASSWORD';
CREATE DATABASE IF NOT EXISTS nextcloud;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES ON nextcloud.* TO 'nextcloud'@'localhost';
FLUSH privileges;
[Install Nextcloud]
run the installer at https://example.com/
[Setup Redis]
edit
/etc/redis/redis.conf
Under the # Unix socket. section add the following
port 0
unixsocket /run/redis/redis-server.sock
unixsocketperm 770
add www-data to redis group
usermod -a -G redis www-data
/etc/group will now have an entry like this “redis:x:119:www-data”
systemctl enable redis-server
Add the following to /var/www/example.com/config/config.php
This is using APCu for memcache and Redis for distributed caching and file locking. Here we use a socket to connect to redis-server.
'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
'host' => '/run/redis/redis-server.sock',
'port' => 0,
],
systemctl restart redis-server
systemctl restart apache2
add apc cli enabling line in here -> /etc/php/8.4/cli/php.ini
apc.enable_cli=1
Restart php to pick up above changes
systemctl restart php8.4-fpm.service
[Setup cron for Nextcloud]
crontab -u www-data -e
*/5 * * * * php -f /var/www/example.com/cron.php
done;
If building Nextcloud for many users it will be necessary to increase the php fpm pm settings in /etc/php/8.4/fpm/pool.d/www.conf and apache mpm event in /etc/apache2/mods-enabled/mpm_event.conf
This is a handy calculator to estimate values for php -> https://spot13.com/pmcalculator/
For a 16GB 8 Core server the following values might be appropriate:
Edit
/etc/php/8.4/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 550
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 50
pm.max_requests = 500
Additionally, apache multiprocessing module will need to be increased in
/etc/apache2/mods-enabled/mpm_event.conf
ServerLimit 20
StartServers 5
MinSpareThreads 50
MaxSpareThreads 100
ThreadsPerChild 25
MaxRequestWorkers 500
MaxConnectionsPerChild 100

