Nextcloud
Database
Install the "chaotic good" mysql server:
sudo apt install mariadb-server
Then, use the cli to create a new user and database for nextcloud:
sudo mysql
CREATE DATABASE nextcloud;
CREATE USER 'nextcloud' IDENTIFIED BY 'xxxxxxxxxxxxxxxxxxxxxxxxx';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud';
PHP components
Install all of the PHP pieces for the site:
sudo apt install php-fpm php8.2-curl php8.2-gd php8.2-xml php8.2-mbstring php8.2-zip php8.2-mysql php8.2-intl php8.2-bcmath php8.2-gmp php8.2-imagick imagemagick
Then, edit the main config to change the defaults:
sudo vim /etc/php/8.2/fpm/php.ini
memory_limit = 2048M
post_max_size = 2G
upload_max_filesize = 2G
It's also wise to install a memory cache as well:
sudo apt install php-apcu php8.2-apcu
Enable this for the site by adding to config.php
'memcache.local' => '\OC\Memcache\APCu',
Then edit /etc/php/8.2/mods-available/apcu.ini
and add:
apc.enable_cli=1
This is required for occ
and the cron jobs.
Nginx
Simply install Nginx web server:
sudo apt install nginx
And optionally the certbot components:
sudo apt install certbot python3-certbot-nginx
The nginx config:
upstream php-handler {
server unix:/var/run/php/php8.2-fpm.sock;
}
server {
listen 80;
listen [::]:80;
server_name cloud.onetwoseven.one;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name cloud.onetwoseven.one;
# Using LetsEncrypt for TLS:
ssl_certificate /etc/letsencrypt/live/cloud.onetwosevn.one/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cloud.onetwosevn.one/privkey.pem;
ssl_protocols TLSv1.3 TLSv1.2;
# HSTS settings
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains;" always;
# set max upload size and increase upload timeout:
client_max_body_size 2G;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# HTTP response headers borrowed from Nextcloud `.htaccess`
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 "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Path to the root of your installation
root /var/www/nextcloud;
index index.php index.html /index.php$request_uri;
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 regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
location ^~ /.well-known {
# The rules in this block are an adaptation of the rules
# in `.htaccess` that concern `/.well-known`.
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; }
# Let Nextcloud's API for `/.well-known` URIs handle all other
# requests by passing them to the front-end controller.
return 301 /index.php$request_uri;
}
# Rules borrowed from `.htaccess` to hide certain paths from clients
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/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; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # Enable pretty urls
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite)$ {
try_files $uri /index.php$request_uri;
expires 6M; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
location ~ \.wasm$ {
default_type application/wasm;
}
}
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}
location /remote {
return 301 /remote.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
You should also request a certificate:
sudo certbot certonly --nginx
Cron
The automated background job is an important part of how nextcloud tracks internal state. Ajax or web-cron are unreliable, it's best to use the built-in system.
/etc/cron.d/nextcloud
MAILTO=""
*/5 * * * * www-data php -f /var/www/nextcloud/cron.php
Antivirus
Install Clamd and configure it.
In NextCloud settings, install and enable the "Antivirus for Files" application.
Then, in the admin section change the mode to "Clamd Socket" to speed up scans.
Redis
Install redis and tools:
sudo apt install redis-server php-redis
Make sure the service is enabled on startup:
sudo systemctl enable redis-server
Restart php-fpm to use the new modules:
sudo systemctl restart php8.2-fpm
Then, modify the config.php file:
'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
'host' => 'localhost',
'port' => 6379,
],
After this is configured, the admin status page will update accordingly.
Email
The ideal way to configure email is using a local relay service, rather than programming the credentials into NextCloud. This gives you the robust retry queue and other very useful features.