Operating a local Nextcloud server is actually quite simple and perfectly adequate for local or private use. Once this part is complete, a complete Nextcloud server can be accessed on the local network. In summary, the following steps are necessary to achieve the goal of this first part:
NEW: For the very impatient I have a console only section. There are only commands, no explanations.
This simplest expansion stage of the first part is NOT suitable for public operation!
Last updated:
In general, such services should be set up in a separate environment. This makes not only the security but also the maintenance much easier. Jails can be backed up relatively easily and only the packages that are absolutely necessary are installed.
nextcloud_db )nextcloud_user )N3XtCloud )The setup, including all optional possibilities, looks like this:
┌────────────────────────┐
│ FreeBSD │
│ ┌─────────────────────┐│
│ │ jails/nc ││
LAN: 0.0.0.0:443 ─┼─┼─► nginx/php ││
│ │ │ ││
│ │ └─► jail/pgsql ││
│ │ postgresql ││
│ └─────────────────────┘│
└────────────────────────┘
A separate jail is required if further web applications are to be built on Nginx/PHP.
Here we use web as the jail name.
Either use bastile console git to start a console in the created jail, or log in via SSH (if activated) with ssh USERNAME@IP or ssh USERNAME@HOSTNAME to then gain root rights with su.
Package sources should be customised, see separate article.
Now update the package source with pkg update and install the required packages: pkg install -y nextcloud-php84 nextcloud-appointments-php84 nextcloud-calendar-php84 nextcloud-contacts-php84 nextcloud-deck-php84 nextcloud-forms-php84 nextcloud-groupfolders-php84 nextcloud-end_to_end_encryption-php84 nextcloud-mail-php84 nextcloud-news-php84 nextcloud-notes-php84 nextcloud-talk-php84 nextcloud-tasks-php84 nextcloud-twofactor_admin-php84 nextcloud-twofactor_webauthn-php84 postgresql17-client php84-pdo_pgsql php84-pgsql php84-pecl-redis php84-pecl-imagick redis
Enable services so that they start automatically when the jail is started: service redis enable.
Please ensure that NEXTCLOUDDBNAME, NEXTCLOUDDBUSER and NEXTCLOUDDBPASS are replaced with your specifications.
If you have your own PostgreSQL jail, the database and database user must be created there..
su -m postgres -c "createuser -s NEXTCLOUDDBUSER --pwprompt"
su -m postgres -c "createdb -O NEXTCLOUDDBUSER -E Unicode -T template1 NEXTCLOUDDBNAME"
Redis is also a database that can be used optionally for caching and session management.
This reduces the load on the main database (and thus also on the backup) and speeds up operation, especially when a few more users are created.
The Redis user must first be added to the www group with pw groupmod redis -m www.
cp /usr/local/etc/redis.conf.sample /usr/local/etc/redis.conf
sed -i '' 's/port 6379/port 0/' /mnt/conf/redis.conf
sed -i '' 's/# unixsocket \/run\/redis.sock/unixsocket \/var\/run\/redis\/redis.sock/' /usr/local/etc/redis.conf
sed -i '' 's/# unixsocketperm 700/unixsocketperm 770/' /usr/local/etc/redis.conf
In /usr/local/etc/php.ini, there are several options that need to be adjusted for Nextcloud.
The clearest way to do this is with a separate ini file.
cat > /usr/local/etc/php/99-nextcloud.ini <<'EOF'
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=1
opcache.save_comments=1
redis.session.locking_enabled = 1
redis.session.lock_retries = -1
redis.session.lock_wait_time = 10000
EOF
sed -i '' 's/application\/javascript js;/application\/javascript js mjs;/' /usr/local/etc/nginx/mime.types
NGINX together with PHP forms the web server and thus also the foundation for Nextcloud.
/usr/local/etc/nginx/conf.d/nextcloud.conf = Nextcloud configurationcat > /usr/local/etc/nginx/conf.d/nextcloud.conf <<'EOF'
server {
listen 80;
listen 443 ssl;
# listen [::]:80;
# listen [::]:443 ssl;
http2 on;
server_tokens off;
root /usr/local/www/nextcloud/;
client_max_body_size 10G;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
client_body_buffer_size 512k;
ssl_certificate /usr/local/etc/ssl/nextcloud/cert.pem;
ssl_certificate_key /usr/local/etc/ssl/nextcloud/key.pem;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
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;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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;
fastcgi_hide_header X-Powered-By;
index index.php index.html /index.php$request_uri;
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;
}
location ^~ /.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; }
return 301 /index.php$request_uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
location ~ \.php(?:$|/) {
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 $request_filename;
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_max_temp_file_size 0;
}
location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
access_log off;
location ~ \.wasm$ {
default_type application/wasm;
}
}
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d;
access_log off;
}
location /remote {
return 301 /remote.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
EOF
Encryption should also be used internally.
mkdir -p /usr/local/etc/ssl/nextcloud
openssl req -x509 -nodes -days 3652 -sha512 -subj "/C=DE/CN=nextcloud" -newkey rsa:2048 -keyout "/usr/local/etc/ssl/nextcloud/key.pem" -out "/usr/local/etc/ssl/nextcloud/cert.pem"
Even without these adjustments, the Nextcloud installation could theoretically start, but it would encounter an error after entering the database information. Redis would then remain unused. Therefore, the supplied configuration file is expanded with a few additional points beforehand.
cat > /usr/local/www/nextcloud/config/config.php <<'EOF'
<?php
/** This is the bare minimum configuration for the bundled installer
* to function properly.
*/
$CONFIG = array (
// Set defaultphone region (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements)
'default_phone_region' => 'DE',
/** The FreeBSD package separates apps into bundled apps and user-
* installed apps. If this 'apps_paths' array is missing from
* your config, your Nextcloud installation is broken
*/
'apps_paths' =>
array (
0 =>
array (
'path' => '/usr/local/www/nextcloud/apps',
'url' => '/apps',
'writable' => true,
),
1 =>
array (
'path' => '/usr/local/www/nextcloud/apps-pkg',
'url' => '/apps-pkg',
'writable' => false,
),
),
// Log-files belong in the appropriate location
'logfile' => '/var/log/nextcloud/nextcloud.log',
// Enable user caching when option is enabled
'memcache.local' => '\OC\Memcache\APCu',
// Redis caching and session handling
'filelocking.enabled' => true,
'memcache.local' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'distributed' => '\\OC\\Memcache\\Redis',
'redis' =>
array(
'host' => '/var/run/redis/redis.sock',
'port' => 0,
'timeout' => 0.0,
),
);
EOF
The Nextcloud Installer requires write access to the configuration file.
chown www:www /usr/local/www/nextcloud/config/config.php
chmod 775 /usr/local/www/nextcloud/config/config.php
The logging directory is created with install -d -o www -g www /var/log/nextcloud/ and the correct permissions.
This brings us to the end of the preparations
and all services can now be started with service redis restart && service php_fpm restart && service nginx restart.
The Nextcloud Installer can also be accessed via a web page, but it is quicker to use occ.
Only database-host, database-name and database-user need to be adjusted, and the installation will be completed automatically.
su -m www -c "php /usr/local/www/nextcloud/occ maintenance:install --database-host 'localhost' --database 'pgsql' --database-name 'nextcloud_db' --database-user 'nextcloud_user' --database-pass 'N3XtCloud' --admin-user 'admin' --admin-pass 'N3XtCloud'"
Finally, a few last refinements that are sent directly afterwards via shell.
A few final database settings are made and the trusted_domain is set to ‘all’ to make setup easier, especially at the beginning.
This can be changed again later (if you want to use your own real domain).
su -m www -c "php /usr/local/www/nextcloud/occ app:enable admin_audit appointments calendar contacts deck encryption end_to_end_encryption files_external forms groupfolders mail news notes spreed suspicious_login tasks twofactor_admin twofactor_nextcloud_notification twofactor_totp twofactor_webauthn"
su -m www -c "php /usr/local/www/nextcloud/occ app:disable app_api"
su -m www -c "php /usr/local/www/nextcloud/occ db:add-missing-primary-keys"
su -m www -c "php /usr/local/www/nextcloud/occ db:add-missing-indices"
su -m www -c "php /usr/local/www/nextcloud/occ db:add-missing-columns"
su -m www -c "php /usr/local/www/nextcloud/occ db:convert-filecache-bigint --no-interaction"
su -m www -c "php /usr/local/www/nextcloud/occ maintenance:mimetype:update-db"
su -m www -c "php /usr/local/www/nextcloud/occ maintenance:repair --include-expensive"
su -m www -c "php /usr/local/www/nextcloud/occ config:system:set trusted_domains 1 --value=*"
su -m www -c "php /usr/local/www/nextcloud/occ config:system:set maintenance_window_start --value=17 --type=integer"
Nextcloud has its own task management system, which relies on tasks being triggered regularly in the system.
mkdir /usr/local/etc/cron.d/
echo "SHELL=/bin/sh" > /usr/local/etc/cron.d/nextcloud
echo "PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin" >> /usr/local/etc/cron.d/nextcloud
echo "*/5 * * * * www /usr/local/bin/php /usr/local/www/nextcloud/cron.php" >> /usr/local/etc/cron.d/nextcloud
Voilá
To ensure that the whole thing can also be used on mobile phones and other devices while on the move, this will be explained in part 2.
Instructions and lots more information can be found here.