NextCloud on OpenBSD

NextCloud on OpenBSD

NextCloud and OpenBSD are complimentary to one another. NextCloud is an awesome, secure and private alternative for propietary platforms, whereas OpenBSD forms the most secure and solid foundation to serve it on. Setting it up in the best way isn’t hard, especially using this step by step tutorial.


Setting up NextCloud manually offers some room for improvements:


Step 1. Preparations.

This guide should work with the latest -stable and the most recent -current. You might prefer a clean and fresh OpenBSD installation to prevent existing configurations from interfering. Without further ado, brew yourself a cup of coffee, disable any distractions and let’s go!

We’re going to install NextCloud on the subdomain and are using regular user johndoe. Take note of this and replace these values in commands and configuration files.

1.1: Login and set some defaults

After having logged in to the target machine – that is going to run your NextCloud machine – we’ll first set some sane defaults.

  1. Enable doas: # echo 'permit johndoe' >> /etc/doas.conf
  2. Edit /etc/ssh/sshd_config and set these values – unless you explicitly need them: LogLevel VERBOSE PermitRootLogin no MaxAuthTries 2 MaxSessions 2 AllowAgentForwarding no AllowTcpForwarding no TCPKeepAlive no Compression no ClientAliveInterval 2 ClientAliveCountMax 2
  3. Download the pf ruleset I’ve prepared for you and edit it (change the interface and enable the inet6 lines if you are using IPv6). When you are done, move it to the default config and check the syntax. ftp doas mv pf-nc.txt /etc/pf.conf doas pfctl -nf /etc/pf.conf

1.2: Download/install the prerequisites

We’ll need some files further on, let’s make sure we have everything ready.

  1. Install PostgreSQL server: doas pkg_add postgresql-server
  2. Install PHP and some modules. If you are asked which PHP-version to install, answer PHP 7.2 each time. doas pkg_add php php-curl php-gd php-intl php-pdo_pgsql php-xml php-zip redis pecl72-redis
  3. Enable the PHP modules. doas cp /etc/php-7.2.sample/* /etc/php-7.2
  4. Automatically start these services. Do not start these services yet. doas rcctl enable postgresql php72_fpm redis
  5. Install a file so the webserver can resolve DNS queries from inside its chroot and another file so NextCloud can verify HTTPS certificates: doas mkdir -p /var/www/etc/ssl doas cp /etc/resolv.conf /var/www/etc/resolv.conf doas cp /etc/ssl/cert.pem /var/www/etc/ssl/cert.pem doas cp /etc/ssl/openssl.cnf /var/www/etc/ssl/openssl.cnf doas chown -R www:www /var/www/etc

Step 2. Preparations.

We need to prepare the webserver. Obviously, we’re using httpd(8) – see this article if you prefer nginx for some reason. We’re going to kick this chapter off with httpd itself.

2.1: Enable and configure httpd

Use this configuration as a starting point for your /etc/httpd.conf:

server "" {
        listen on * port 80
        root "/nextcloud"
        location "/.well-known/acme-challenge/*" {
                root { "/acme" }
                request strip 2

Check whether the configuration is deemed valid with doas httpd -n. Moving on to preparing acme-client for the SSL certificates, courtesy of Let’s Encrypt. Edit /etc/acme-client:

authority letsencrypt {
        api url ""
        account key "/etc/acme/letsencrypt-privkey.pem"
authority letsencrypt-staging {
        api url ""
        account key "/etc/acme/letsencrypt-staging-privkey.pem"
domain {
        alternative names { }
        domain key "/etc/ssl/private/"
        domain certificate "/etc/ssl/"
        domain full chain certificate "/etc/ssl/"
        sign with letsencrypt

And create the corresponding directories:

doas mkdir -p -m 700 /etc/acme
doas mkdir -p -m 700 /etc/ssl/acme/private
doas mkdir -p -m 755 /var/www/acme

Time to fetch the certificates!

doas rcctl enable httpd && doas rcctl start httpd && doas acme-client -vAD

If that went successful, grab the OCSP stapling file.

doas ocspcheck -N -o /etc/ssl/ /etc/ssl/

Edit the crontab to automatically renew the certificates and stapling file. Append the following in the crontab (doas crontab -e).

0 0 * * * acme-client && rcctl reload httpd
0 * * * * ocspcheck -N -o /etc/ssl/ /etc/ssl/ && rcctl reload httpd

2.2: Configuring httpd further

Edit /etc/httpd.conf with these values. Do not restart httpd afterwards!

server "" {
        listen on * tls port 443
        hsts {
        root "/nextcloud"
        directory index "index.php"
        tls {
                certificate "/etc/ssl/"
                key "/etc/ssl/private/"
                ocsp "/etc/ssl/"
                ciphers "ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA"
                dhe "auto"
                ecdhe "P-384"
        connection max request body 537919488
        location "/.well-known/acme-challenge/*" {
                root { "/acme" }
                request strip 2

        # First deny access to the specified files
        location "/db_structure.xml" { block }
        location "/.ht*"             { block }
        location "/README"           { block }
        location "/data*"            { block }
        location "/config*"          { block }
                location "/build*"              { block }
                location "/tests*"              { block }
                location "/config*"             { block }
                location "/lib*"                { block }
                location "/3rdparty*"           { block }
                location "/templates*"          { block }
                location "/data*"               { block }
                location "/.ht*"                { block }
                location "/.user*"              { block }
                location "/autotest*"           { block }
                location "/occ*"                { block }
                location "/issue*"              { block }
                location "/indie*"              { block }
                location "/db_*"                { block }
                location "/console*"            { block }

        location "/*.php*" {
                fastcgi socket "/run/php-fpm.sock"

server "" {
        listen on * port 80
        block return 301 "$REQUEST_URI"

Step 3: PHP kung fu and SQL jiujitsu

In the first step, we’ve installed PostgreSQL-server and PHP along with some extensions. We’ve met the preconditions, time to get this all up and running.

3.1: Kicking PostgreSQL online

Since this is the first time we’re using PostgreSQL on this machine, we’ll need to initialize the database.

doas su - _postgresql
mkdir /var/postgresql/data
initdb -D /var/postgresql/data -U postgres -A md5 -W

Switch back to our regular user, johndoe, by typing exit twice. Now, let’s start the database by issuing a single command.

doas rcctl enable postgresql && doas rcctl start postgresql

If you expect to house a busy NextCloud instance, you might want to do some configuration tweaking according to the instructions in cat /usr/local/share/doc/pkg-readmes/postgresql-server-{ver}.

3.2: PHP configuration

Now we have to change the PHP configuration with some higher limits – as the default only allows uploading of files that are two MB at max. Open /etc/php-7.2.ini and edit these values.

memory_limit = 512M
max_input_time = 180
upload_max_filesize = 512M
post_max_size = 32M

Next, edit /etc/php-fpm.conf.

security.limit_extensions =

Step 4: Finally, installing NextCloud

We’ve come quite a long way. Fortunately, we’re almost there! Grab the most current version of NextCloud and extract it to /var/www/nextcloud.

doas unzip -d /var/www
doas chown -R www:www /var/www/nextcloud

Before we can use NextCloud, we need to create a database to store the data. Replace secret-password with a strong passphrase of your liking.

doas su - _postgresql
psql -d template1 -U postgres
template1=# CREATE USER nextcloud WITH PASSWORD 'secret-password';
template1=# CREATE DATABASE nextcloud;
template1=# GRANT ALL PRIVILEGES ON DATABASE nextcloud to nextcloud;
template1=# \q

Check whether you are still running as the postgresql user with whoami – if so, just give it an exit to switch back to johndoe. Start the required services. We’ve set these services earlier to enabled, so with a restart, the services will also start on boot time.

doas rcctl start httpd redis php72_fpm postgresql

Fire up your browser and head to your subdomain. You should be greeted there with the installation wizard. Select PostgreSQL as your database, using as the server, nextcloud as the user and the password you’ve set. Take caution to place the datafolder outside htdocs, eg, in /var/www/ncdata.

After the installation, edit /var/www/nextcloud/config/config.php and add these lines before the closing );.

  'memcache.local' => '\OC\Memcache\Redis',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => array(
    'host' => '',
    'port' => 6379,

And last but not least, a cronjob for some regular housekeeping and indexing. By default, it runs one task with each pageload. The preferred way here is to set this via a cronjob.

doas crontab -e
*/15    *   *   *   *   /usr/bin/ftp -Vo - >/dev/null

FAQ – Frequently Asked Questions (almost completely made-up by the author)

Q: PHP throws an error about failing due to a missing pool

A: most likely, the shower in your condo doesn’t satisfy NC’s dependency on a pool. Nah, just kidding. Still researching when this error occurs, the fix is to define a pool in /etc/php-fpm.conf, I’ve written a short example found here:

Q: The error log mentiones: the Redis server went away

A: somewhat cryptic error message, I agree. Luckily, the Redis server didn't go on holiday nor went anywhere else out of your reach. This message merely means that the Redis server is most likely offline. Check with rcctl check redis.

Q: I got a nasty 500/520 error while trying to access NextCloud

A: Most likely, PHP went belly up or it won't start due to an error in the configuration. Check the daemon status with rcctl check php72_fpm or try to restart it with rcctl restart php72_fpm.

Q: How about security, how safe is my data?

A: OpenBSD is the most secure OS out there. Having said that, nothing is one hundred percent secure. If someone says otherwise, they are flat-out lying to you. This guide follows best practice methods. There is an additional step you could take, that this guide doesn't cover: using encryption from within the NextCloud webinterface. Be cautious, losing either your passphrase or your keys will result in inaccessible data. There is a recovery method, but each user has to allow that in the individual profile. It's disabled by default, being the sanest default.

Furthermore, NextCloud offers a security scan you can use to see whether your instance is safe and sound. You might need to click the refresh icon (on the result page) if you are doing a recheck.

This guide is updated occasionally, with help of the community – thank you all!