has_many :codes

Self-hosting Nextcloud with Dokku and s3 compatible storage

Published  

In a recent post I showed how to deploy a generic app with Dokku. I thought it would be nice to add one for Nextcloud, since it requires a couple of things that I haven't discussed in the previous post.

For those who are not familiar with Dokku, I recommend you read the previous post first or the official site. In short, it's an awesome open source PaaS similar to Heroku (albeit limited to one server).

If you are not familiar with Nextcloud, it's an feature-rich open source platform for file sharing, syncing (with apps for most operating systems and devices) and collaboration. It offers the ability to install "apps" with which you can replicate many of the features you can have with paid solutions like Google Workspace. Learn more here.

I particularly like Nextcloud because by self hosting I don't have to worry about privacy as much as I would have for example with Google. Plus it can be much cheaper than paid options like Google or Dropbox (speaking of file sharing/syncing), depending on where and how you self host it.

Let's see how to deploy it using Dokku on a Linux server. In this post I'll show how you can use an s3 compatible object storage service as the primary storage for Nextcloud - I am testing this with Wasabi at the moment. It's an awesome option so you don't need a server with a ton of local storage if you need to store a lot of data.

Creating the app

The first thing you need to do is of course install Dokku on your server, see previous post. Then, to create a Dokku app for Nextcloud, run:

dokku apps:create nextcloud

We'll want to deploy the official Docker image for Nextcloud, so to do that with Dokku we can run the following command:

dokku git:from-image nextcloud nextcloud:23.0.2-apache

At the time of this writing, the latest Nextcloud version is 23.0.2. Change the tag according to the version you want to install.

Mounting the local storage

Even though we are going to use an s3 service as primary storage for our data, we still need to store the Nextcloud configuration locally on the server. This is important if you want to back up the configuration, to be able to restore your setup on another server if needed.

First, create a directory where to store this configuration; Dokku by default uses `/var/lib/dokku/data/storage` as a container for directories to "mount" inside applications. So let's create a subdirectory for Nextcloud:

mkdir -p /var/lib/dokku/data/storage/nextcloud

Then, we need to mount this directory in the Nextcloud app:

dokku storage:mount nextcloud /var/lib/dokku/data/storage/nextcloud:/var/www/html

The command above mounts the directory we created as `/var/www/html` in the Nextcloud container, which is the expected location.

Supporting services

Nextcloud requires a database to store information about users and metadata (including metadata for user files if you, like in our case, store user data in an s3 bucket). It supports various databases but I prefer Postgres. To add a Postgres database to Nextcloud, we first need to install a Dokku plugin for Postgres and create an instance, then link it to the Nextcloud application:

dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
dokku postgres:create nextcloud-postgres
dokku postgres:link nextcloud-postgres nextcloud

We'll also use Redis for caching, to speed things up:

dokku plugin:install https://github.com/dokku/dokku-redis.git redis
dokku redis:create nextcloud-redis
dokku redis:link nextcloud-redis nextcloud

These commands will add the environment variables DATABASE_URL (for Postgres) and REDIS_URL (for Redis) to the Nextcloud application.

Next, we need to add some custom configuration to Nextcloud. Check which passwords and hosts Dokku has set for Postgres and Redis with the aforementioned environment variables, because Nextcloud expects different variables:

dokku config:show nextcloud

Then run:

dokku config:set nextcloud \
DOKKU_LETSENCRYPT_EMAIL=<your email address to issue a certificate with Let's Encrypt> \
POSTGRES_DB=nextcloud \
POSTGRES_USER=postgres \
POSTGRES_PASSWORD=<postgres password> \
POSTGRES_HOST=<the postgres host> \
REDIS_HOST=<redis host> \
REDIS_HOST_PASSWORD=<redis password> \
SMTP_HOST=<smtp host> \
SMTP_PORT=587 \
SMTP_SECURE=tls \
SMTP_AUTHTYPE=PLAIN \
SMTP_NAME=<smtp username> \
SMTP_PASSWORD=<smtp password> \
MAIL_FROM_ADDRESS=cloud \ # or whichever name you want to receive email notifications from; note that this should be set to the name part only of an email address
MAIL_DOMAIN=<email domain> \
OVERWRITEPROTOCOL=https \
NEXTCLOUD_TRUSTED_DOMAINS=<your full nextcloud domain, e.g. cloud.mydomain.com> \
NEXTCLOUD_ADMIN_USER=<first admin username> \
NEXTCLOUD_ADMIN_PASSWORD=<first admin password> \
OBJECTSTORE_S3_BUCKET=true \
OBJECTSTORE_S3_SSL=true \
OBJECTSTORE_S3_USEPATH_STYLE=false \
OBJECTSTORE_S3_LEGACYAUTH=false \
OBJECTSTORE_S3_AUTOCREATE=false \
OBJECTSTORE_S3_BUCKET=<s3 bucket to use as primary storage> \
OBJECTSTORE_S3_KEY=<s3 access key> \
OBJECTSTORE_S3_SECRET=<s3 secret key> \
OBJECTSTORE_S3_REGION=<s3 region> \
OBJECTSTORE_S3_HOST=<s3 endpoint hostname> \
OBJECTSTORE_S3_PORT=443

The configuration above:
  • ensures that we use the Postgres and Redis instances we created earlier
  • configures an SMTP provider so we can have Nextcloud send us notifications when for example sharing files and folders; if you don't have a provider of choice, I recommend Mailplace since it's very cheap and reliable
  • configures an s3 bucket as primary storage for user data; I recommend Wasabi for this since it only charges for the amount of data stored. Other providers charge for API requests too, and Nextcloud can make quite many of them
  • creates the first admin user

The command above will restart the application; during this process, the necessary tables will be initialized in the database and some data will be written to the bucket with the demo files for the first admin user. 

Certificate

Dokku uses Let's Encrypt to issue certificates for applications. First, ensure that you configure DNS so that your Nextcloud domain points to the IP of your server. First fix the port mapping for the reverse proxy since Dokku by default expects the container to expose port 5000:

dokku proxy:ports-set nextcloud http:80:80

Then add the domain to the application and request a certificate:

dokku domains:add nextcloud cloud.mydomain.com
dokku letsencrypt:enable nextcloud

Increasing the max upload size for browser transfers

When you use a desktop or mobile Nextcloud client to sync your files, Nextcloud will do the transfer is small chunks even for large files. If you happen to upload files with the web interface, you may hit a max upload limit with Nginx. You can optionally increase the max allowed upload size by adding a small config to Nginx;

mkdir -p /home/dokku/nextcloud/nginx.conf.d/
echo 'client_max_body_size 5120m;' > /home/dokku/nextcloud/nginx.conf.d/upload.conf
service nginx reload

The example above increases the max upload size to 5GB per file.

Done. Now open the Nextcloud domain in your browser and login as the first admin user to configure the rest.

Wrapping up

Dokku and Nextcloud are an awesome combination to have a file sharing/syncing and collaboration platform that is more private and can be cheaper than managed options in the market. However there are also some affordable managed Nextcloud services if you are not too worried about privacy but still want to save money. A very affordable and reliable option is Hetzner's Storage Share if you are happy with Germany as the location.
© Vito Botta