January 26, 2021

Dockerized Nextcloud on Raspberry Pi

Since 2010, I guess, I run Owncloud and later Nextcloud on different small “servers” in my home network. Recently, I had the impression that my instance, which I updated/upgraded many times, got a bit bloated and some things simply did not work correctly anymore.

The other day I decided that it is time to setup up a new instance from scratch. However, this time I did not want to have a complicated native installation running on nginx, php-fpm, mySQL, Redis and whatever dependency my old Nextcloud instance had. I wanted to go the dockerized way.

I know that there are a couple of projects that try to provide whole management interfaces to maintain a dockerized Nextcloud setup. They include automatic SSL (re)certification via Let’s encrypt, automated backups, … you name it. From earlier tests, I still had the impression that I do not understand how these things work, plus I already have my own way of dealing with SSL and backups as I also run other stuff at home. So I decided to go for the most simple way: the Docker image provided by Nextcloud that uses an Apache, php and tinySQL stack. Yes: tinySQL.

My theory was that for my scenario (private instance used by 1 - 2 persons) you do not need a database and caching server. And - at least so far - my impression was right. The new instance is running quicker than the old one.

So how do you set up the thing?

Step 1 is to get the basic installation ready. You can use the following docker-compose.yml for that purpose:

# docker-compose.yml
version: '3'

services:
 nextcloud:
  container_name: nextcloud
  image: nextcloud
  restart: always
  volumes:
    - /docker/nextcloud/www/:/var/www/html/
  ports:
    - 8080:80
  environment:
    - NEXTCLOUD_ADMIN_USER=pichANiceUserName
    - NEXTCLOUD_ADMIN_PASSWORD=pickAGoodPassword
    - SQLITE_DATABASE=data

Note: Using the volumes statement in the docker-compose-yml, we expose the container’s entire web root /var/www/html/ including all Nextcloud files to the host machine to /docker/nextcloud/www/. This causes some very important effects. a) without the volumes statement, there would be no persistence. docker-compose restart would destroy the old container with all your data in it and create a new container from scratch. b) you can easily edit configuration files. c) you can easily backup the instance with whatever backup script you like!

After docker-compose up -d you should have a new instance running on your server and you should be able to access it at http://localIP:8080 using the provided user/password. If you do not want to make the instance reachable by a public URL, you are done.

Step 2 is the first part of the SSL configuration. My approach for dockerized services is typically to use nginx as a reverse proxy and let nginx take care of SSL. This can be achieved as follows:

# /etc/nginx/sites-available/nextcloud.domain.foo.conf
server {
  server_name nextcloud.domain.foo;
  listen 80;
  add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
  server_tokens off;
  add_header X-Frame-Options SAMEORIGIN;
  add_header X-Content-Type-Options nosniff;
  client_max_body_size 50M;

  location / {
    proxy_pass http://localhost:8080;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 3m;
    proxy_send_timeout 3m;
    access_log /var/log/nginx/nextcloud_docker.access.log;
    error_log /var/log/nginx/nextcloud_docker.error.log;
  }
}

Activate the configuration with ln -s /etc/nginx/sites-available/nextcloud.domain.foo.conf /etc/nginx/sites-enabled/ and restart your nginx with service nginx restart.

The configuration does not yet include anything related to SSL. So, your Nextcloud will only be available at http://nextcloud.domain.foo. Furthermore, since certain overwrite statements are not yet in place, the instance probably does not work completely yet… We cover this in step 4.

Step 3: Install the Let’s Encrypt client with the needed nginx extension: apt install certbot python3-certbot python3-certbot-nginx. Then execute something like certbot --nginx -d nextcloud.domain.foo and follow all directions printed on screen. Yes, you want to redirect automatically from http to https. After you have completed all steps, you should have a shiny certificate for your domain and nextcloud.domain.foo.conf should be extended with all necessary SSL settings.

Step 4 finalizes the Nextcloud configuration with necessary overwrite statements that are needed as we run the instance behind nginx. For this purpose, edit /docker/nextcloud/www/config/config.php and add the following:

'overwritehost' => 'nextcloud.domain.foo',
'overwriteprotocol' => 'https',

Restart nginx (service nginx restart). Your instance should be available at https://nextcloud.domain.foo.

The last steps are to create a couple of cronjobs that take care for “maintenance”. Create a cronjob that runs once a month to take care for the re-certification of the domain (LE certificates are only valid for three months). For this purpose, I use a small script that performs the re-certification of my Nextcloud subdomain plus a couple of other things not shown here:

# renew.sh
#!/bin/bash
#...
/usr/bin/certbot certonly --nginx --force-renew  -d nextcloud.domain.foo
#...

Lastly, crontab -e and add something like 15 3 17 * * /path/to/renew.sh. Done.

Similarly, create a small script and cronjob that snapshots /docker/nextcloud/www/ a couple of times a day.

© ho1ger 2015 - 2021