NextCloud
Jail Creation
bastille create nextcloud 14.2-RELEASE 10.0.0.20/8 bastille0Installation
Database
We use mariadb as the database for NextCloud since it is the best supported option.
bastille pkg nextcloud install mariadb1011-server
bastille sysrc nextcloud mysql_enable=YES
bastille service nextcloud mysql-server startTo set up the database we connect to the mariadb instance in the jail. Use an empty password if promted:
bastille cmd nextcloud mysql -u rootThen, in the shell that opens, enter the following SQL commands. Replace changeme with a password of your choice. Be sure to use the ip address of the nextcloud jail as host for the nextcloud use (the part after the @).
CREATE DATABASE nextcloud;
CREATE USER 'nextcloud'@'10.0.0.20' IDENTIFIED by 'changeme';
GRANT ALL PRIVILEGES ON nextcloud. * TO 'nextcloud'@'10.0.0.20';
GRANT ALL PRIVILEGES ON *.* TO 'nextcloud'@'10.0.1.20' IDENTIFIED BY 'changeme' WITH GRANT OPTION;
--- exit the shell
exitNextcloud
Thankfully, we have a nextcloud package for FreeBSD which installs all the dependencies and puts all application files at /usr/local/www/nextcloud. We still need to install the SQlite PDO adapter, since this is required by Nextcloud Collectives.
bastille pkg nextcloud install nextcloud-php83 php83-pdo_sqlite php83-pecl-redisWebserver
Now we need a way to serve the Nextcloud files. Apache is often used for this, but we opt again for Caddy, since using it with PHP-FPM is dead simple.
bastille pkg nextcloud install caddyEdit the Caddyfile of the nextcloud jail:
micro /usr/local/bastille/jails/nextcloud/root/usr/local/etc/caddy/CaddyfileNote
Alternatively, you can also install an editor in the nextcloud jail and use bastille cmd nextcloud micro /usr/local/etc/caddy/Caddyfile to edit the file.
Use the following Configuration:
|
|
Enable the caddy service
bastille sysrc nextcloud caddy_enable=YESPHP Configuration
Use the production template as a starting point:
bastille cmd nextcloud cp /usr/local/etc/php.ini-production /usr/local/etc/php.iniChange the following values in the newly created php.ini
micro /usr/local/bastille/jails/nextcloud/root/usr/local/etc/php.ini
|
|
Create the temp-dir we just specified and make it writeable by the www user:
mkdir /usr/local/bastille/jails/nextcloud/root/var/nextcloud_temp
chown www:www /usr/local/bastille/jails/nextcloud/root/var/nextcloud_tempLets enable php_fpm on the nextcloud jail
bastille sysrc nextcloud php_fpm_enable=YESUncomment and adapt the following values in the php_fpm pool configuration
clear_env = no
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin:/usr/sbin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmpReverse-Proxy
Edit the Caddyfile of our reverse-proxy and a block to forward traffic to nextcloud:
micro /usr/local/bastille/jails/caddy/root/usr/local/etc/caddy/CaddyfileReplace ezdk.org with your own domain.
nextcloud.ezdk.org {
redir /.well-known/carddav /remote.php/dav/ 301
redir /.well-known/caldav /remote.php/dav/ 301
reverse_proxy 10.0.0.20:80 {
trusted_proxies 10.0.0.1/32
}
}Reload the config
bastille service caddy caddy reloadNextcloud Cronjobs
Nextcloud needs to run some background jobs periodically which are run with the cron.php script. Add the following line to the crontab file to have the www user run this script every 5 minutes :
micro /usr/local/bastille/jails/nextcloud/etc/crontab# Nextclouid Cronjobs
*/5 * * * * www /usr/local/bin/php -f /usr/local/www/nextcloud/cron.phpNextCloud Configuration
For good measure, lets restart the nextcloud jail, making sure all our settings are applied.
bastille restart nextcloudSetup
Go to nextcloud.<yourdomain.tld> to start the nextcloud setup. Enter a Username for the admin account and a password.
Under Storage & Database, change the db type to MariaDB, enter nextcloud for the username and Database name and enter the password you’ve used to create the user. Be sure to change the Database Host from localhost to 127.0.0.1:3306.
Setup will work for a while and then present you with a screen to install recommended apps. Only select the Calendar and Contacts apps for now. We will deal with the others later.
Afterwards, you should get logged in into your new nextcloud instance as an administrator.
LDAP Integration
Navigate to the Apps Menu through the Nextcloud Menu on the top-right. Go to Featured Apps and locate the app LDAP user and group backend in the list. Enable or install it. Open the Administrative Settings and navigate to “LDAP/AD integration”. Now follow the guide from lldap on how to integrate nextcloud, or simply adopt the settings from the following screenshots:

Log out as the Administrator and log in with the user you have created earlier in lldap.
If everything works well, log back in as an administrator, go to the Features Apps list and install Team Folders
Caching
The FreeBSD Nextcloud package allready set up APCu for local caching. We want to improve on it by using redis.
First, install redis, enable and start it:
bastille pkg nextcloud install redis
bastille sysrc nextcloud redis_enable=YES
bastille service nextcloud redis startDue to Localhost Pitfalls in Jails, we need to bind redis to the ip address of the jail. Edit the following two values in /usr/local/etc/redis.conf
micro /usr/local/bastille/jails/nextcloud/root/usr/local/etc/redis.conf
|
|
Now we are ready to adapt nextclouds caching settings in /usr/local/www/nextcloud/config/config.php. Change the following values in this file:
micro /usr/local/bastille/jails/nextcloud/root/usr/local/www/nextcloud/config/config.php
|
|
for good measure, lets restart the nextcloud jail:
bastille restart nextcloudDocument Backend
Without a Document Backend, users won’t be able to edit office documents in Nextcloud. They would only be able to Up- and Download files. There are currently two available document backends: Collabora and OnlyOffice. Collabora is based on LibreOffice and the default choice for Nextcloud. But Collabora has no plans of supporting FreeBSD and attemps to port it to FreeBSD are currently stuck. OnlyOffice on the other hand, provides native FreeBSD packages. So we choose OnlyOffice.
Jail Setup
The document backend is a separate application intended to run on a separate host or container. So we are creating a jail for it:
bastille create onlyoffice 14.2-RELEASE 10.0.0.21/8 bastille0
# for PostgreSQL we need to set an additional option for the jail
bastille config onlyoffice set allow.sysvipc 1
# restart it for good measure
bastille restart onlyofficeLets install the packages required for this container and enable all the services these will install (we will also install micro to have an editor ready in the jail):
bastille pkg onlyoffice install onlyoffice-documentserver py311-importlib-resources py311-setuptools postgresql16-server micro
bastille sysrc onlyoffice postgresql_enable=YES
bastille sysrc onlyoffice nginx_enable=YES
bastille sysrc onlyoffice rabbitmq_enable=YES
bastille sysrc onlyoffice supervisord_enable=YESDatabase
We will use Postgresql as the Database for OnlyOffice. Lets set it up now. We will have to execute quite a few commands and edit multiple files. It will be easier if we perform these steps directly in the jail. So let’s enter it:
bastille console onlyofficeFrom here, lets initialize the database:
service postgresql initdbWe need to tell postgres to listen on the ip of the jail. Edit the file /var/db/postgres/data16/pg_hba.conf and add the folowing at the end of the file. This will tell postgres to trust every connection coming from this address (the local jail).
|
|
We also need to edit /var/db/postgres/data16/postgresql.conf to tell postgres to listen on this interface. Edit the file and change the line containing listen_addresses to the following:
|
|
Now we are ready to create and configure the database for onlyoffice:
service postgresql start
psql -U postgres -c "CREATE DATABASE onlyoffice;"
psql -U postgres -c "CREATE USER onlyoffice WITH password 'onlyoffice';"
psql -U postgres -c "GRANT ALL privileges ON DATABASE onlyoffice TO onlyoffice;"
psql -U postgres -c "ALTER DATABASE onlyoffice OWNER to onlyoffice;"
psql -h10.0.0.21 -Uonlyoffice -d onlyoffice -f /usr/local/www/onlyoffice/documentserver/server/schema/postgresql/createdb.sqlRabbitMQ
RabbitMQ provides a Message Queue which OnlyOffice depends on. We configure it as follows:
service rabbitmq start
rabbitmqctl --erlang-cookie `cat /var/db/rabbitmq/.erlang.cookie` add_user onlyoffice onlyoffice # usr=onlyoffice, pw=onlyoffice
rabbitmqctl --erlang-cookie `cat /var/db/rabbitmq/.erlang.cookie` set_user_tags onlyoffice administrator
rabbitmqctl --erlang-cookie `cat /var/db/rabbitmq/.erlang.cookie` set_permissions -p / onlyoffice ".*" ".*" ".*"Documentserver
Now we are finally ready to configure the OnlyOffice Documentserver. We need to add our database and rabbitmq credentials to the configuratioon and add a specific block to set request-filtering-agent to allow requests from private ip addresses. You can edit the configuration with micro /usr/local/etc/onlyoffice/documentserver/local.json. Following is the content of this file, after adaption.
|
|
Open the supervisord configuration and add an include statement to include the onlyoffice supervisord files:
micro /usr/local/etc/supervisord.conf
|
|
Now we can start supervisord
service supervisord startnginx
OnlyOffice comes with pre-made configuration files for nginx. We will use this to expose it internally (but we still use our caddy reverse-proxy to expose it externally).
Lets edit /usr/local/etc/nginx/nginx.conf and on the line after http { enter the following include statement
|
|
There is already a server {} block in this file (inside the http { block). Remove the whole block.
Now run the following script:
documentserver-update-securelink.shAfter the script has run, open /usr/local/etc/onlyoffice/documentserver/nginx/ds.conf and remove the line listen [::]:80 default_server;. Our jail does not have a ipv6 stack and this line will cause an error. After that, rerun the previous script
documentserver-update-securelink.shNow the output should state that the config is sane and we are ready to start the nginx service
service nginx startWe now have everything set up in our onlyoffice-jail. Exit the shell to return to our hosts shell:
exitCaddy Configuration
To expose the documentserver open the Caddyfile of our reverse-proxy jail with micro /usr/local/bastille/jails/caddy/root/usr/local/etc/caddy/Caddyfile and add the following block:
|
|
And restart caddy:
bastille service caddy caddy reloadNextcloud Configuration
Log in to Nextcloud as an admin and install the ONLYOFFICE app. Open the administrator settings and in the OnlyOffice settings add https://docs.<domain> as the Docs address. Input http://10.0.0.21 as the address for internal request and http://nextcloud.<domain.tld> as the Nextcloud address for internal requests. (in the /etc/hosts file of the onlyoffice jail, nextcloud.domain.tld needs to point to the internal nextcloud ip)
Talk Backend
For voice and video communication, we also need a separate backend for which we will create a jail
bastille create talk 14.2-RELEASE 10.0.0.22/8 bastille0The talk backend depends on NATS and we’ll need to compile the signaling server ourselves. So let’s get all dependencies first.
bastille pkg talk install git go gmake nats-server protobuf3Enable and start the nats service
bastille sysrc talk nats_enable=YES
bastille service talk nats startNow on to build the spreed signaling server
# switch to the jail itself
bastille console talk
# clone the repo. Replace the branch with the current stable version
git clone --depth 1 --branch v2.0.2 https://github.com/strukturag/nextcloud-spreed-signaling.git
# cd into the repo
cd nextcloud-spreed-signaling
# build the signaling server
gmake build
# and check if it runs
./bin/signaling -h
# Copy the and binary and config file to /usr/local
cp ./bin/signaling /usr/local/bin/signaling
cp server.conf.in /usr/local/etc/signaling.conf
# exit the jail
exitInstall and enable janus
bastille pkg talk install janus
bastille sysrc talk janus_enable=YESThen edit the janus websocket configuration
micro /usr/local/bastille/jails/talk/root/usr/local/etc/janus/janus.transport.websockets.jcfgIn this file, uncomment the ws_ip line and change it to ws_ip = "10.0.0.22"
And start janus
bastille service talk janus startFor our signaling configuration, we need one random 64byte and three 32byte strings to use as keys. Generate them with the following commands and note them down.
cat /dev/urandom | env LC_CTYPE=C tr -dc a-zA-Z0-9 | head -c 64; echo
cat /dev/urandom | env LC_CTYPE=C tr -dc a-zA-Z0-9 | head -c 32; echo #execute three times for three different keysEdit the signaling config file
micro /usr/local/bastille/jails/talk/root/usr/local/etc/signaling.confand change the following values in the file accordingly:
[http]
listen = 10.0.0.22:8443
#Set to the jails ip and remove the hashtag in front
[app]
trustedproxies = 10.0.0.1
#IP of the caddy jail
[sessions]
hashkey = <your-64byte-random-string>
blockkey = <a-32byte-random-string>
[clients]
internalsecret = <a-32byte-random-string>
[backend]
backendtype = static
# uncomment the line
secret = <a-32byte-random-string>
# we need to add a common secret here - this is anoter 32byte random string
backends = nextcloud
# string does not matter, we define it later
allowed = nextcloud.ezdk.org, 10.0.0.1, 10.0.0.20
# nextcloud domain must be addded. This value needs to be newly added to the [backend] block
connectionsperhost = 128
[nextcloud]
# add this after the [backend-id] block
url = https://nextcloud.ezdk.org
secret =
#we leave this empty to apply the common shared secret
sessionlimit = 32
[nats]
url = nats://10.0.0.22:4222
# Change to the jails ip address
[mcu]
type = janus
url = ws://10.0.0.22:8188Edit the /etc/hosts file of the jail
micro /usr/local/bastille/jails/talk/root/etc/hostsand add the following entry. So that internally the services will send requests for nextcloud to the reverse proxy.
10.0.0.1 nextcloud.ezdk.orgWe still need a service for the signaling server. Lets make one by creating a file at /usr/local/etc/rc.d/signaling in the talk jail
micro /usr/local/bastille/jails/talk/root/usr/local/etc/rc.d/signalingand fill it with the following content
|
|
We need to make that script executable and then we can enable it as a service
chmod +x /usr/local/bastille/jails/talk/root/usr/local/etc/rc.d/signaling
bastille sysrc talk signaling_enable=YES
bastille service talk signaling startWe can test if everything worked by reading the welcome message from the api
bastille cmd talk curl localhost:8080/api/v1/welcomeYou should get the message {"nextcloud-spreed-signaling":"Welcome","version":"unreleased"}
Edit the /etc/hosts file of the nextcloud jail
micro /usr/local/bastille/jails/nextcloud/root/etc/hostsAnd add the following line to it so that the nextcloud instance will make requests for the signaling server to the reverse-proxy
10.0.0.1 signaling.ezdk.orgNow we only need to add a new subdomain to our main caddy configuration
micro /usr/local/bastille/jails/caddy/root/usr/local/etc/caddy/Caddyfilesignaling.ezdk.org {
reverse_proxy 10.0.0.22:8080 {
header_up X-Real_IP {remote-host}
}
}And reload the config as usual
bastille service caddy caddy reloadTalk App Setup
Login as an Admin to the nextcloud instance. Go to the Apps settings and enable the talk app.
Go to the administrative settings and on the Talk page press the + Add High-performance backend server button.
Enter https://signaling.ezdk.org as the URL for the backend and enter string you set as secret in the signaling configuratin as the shared secret.