Self Hosting: Complete Guide to Deploying Your Own Private NextCloud with Docker Compose

Home ServerLinuxSelf Hosted

Written by:

With all the revelations in the headlines about how exactly our private data is being mined to surveil and manipulate us, I’ve been thinking of more ways to take better control of my information. As they say, the internet is forever, and it’s become clear that once your information is out there all kinds of third parties may have access to it. While there is nothing particularly salacious in my calendar appointments or phone notes app, there is also no guarantee that future uses of this data by future technologies will be so benign. Just look at China’s “social credit” system.

Using the open source NextCloud software, I have deployed a private server that replaces all the common uses of cloud services: calendar, todo lists, files, passwords, bookmarks, contacts, and notes. All synchronized across all my devices on all platforms. Here’s my setup, deployed in Docker.

This is not the future we were promised.

USE CASE

I own a small business and my entire life is dictated by my todo list and calendar. Without it I’d be lost. I also have multiple work and personal computers, some OS X and some Linux, and also use both iOS and Android devices. I need my data everywhere. My NextCloud server replaces these cloud services with it’s NextCloud equivalent:

  • Dropbox – File syncing and sharing via WebDAV
  • iCloud/Google – Calendars, Todos, Contacts via CalDAV
  • Lastpass – Keeweb database
  • Chrome Bookmarks – Nextcloud Bookmarks
  • Evernote/iOS Notes – Nextcloud Notes apps

DEPLOYMENT

We’ve got some options here.

ON A RASPBERRY PI

NextCloudPi is an operating system designed for the Raspberry Pi platform. It is the most consumer-ready of options if you are not a technical user. Using the cheap Pi hardware, you can get NextCloud up without much hassle and without any technical knowledge. Check it out!

ON A VIRTUAL PRIVATE SERVER

This is what I do, because my internet connection is pretty limited and I need to share large files. So I have chosen to deploy this as a virtual private server with Digital Ocean. They make this easy with a Docker Droplet ready to go:

Digital Ocean Docker Droplet

Digital Ocean Docker Droplet

For my single-user purposes, the lowest $5/mo tier is enough. I also add a $10/mo 100gb block of storage space for syncing the contents of my phone. Choose your options based on what makes sense for how many users you have.

Once you’ve deployed your server, you will need to point a fully qualified domain name to your IP in order to set up HTTPS. With that all set, we can set up NextCloud in Docker.

To get a $10 credit for Digital Ocean to try this out for a few months for free, click here for my referral link.

If I had better internet I would just run this  in a VM on my Proxmox Intel NUC host! See this post for more info on setting up a NUC as low power home server with virtualization.


DOCKER COMPOSE

Docker Compose makes it easy to coordinate your applications as containers working together. My compose stack deploys NextCloud and MariaDB and their administration tools (PHPMyAdmin and Portainer). All of these are protected behind an encrypted reverse proxy using nginx. This is my docker-compose.yml file

version: '2'
services:

  db:
    image: mariadb
    container_name: db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: YOURPASSWORD
    volumes:
      - /PATH/TO/PERSISTENT/FILES/db:/var/lib/mysql
    ports:
      - "3306:3306"

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin
    restart: unless-stopped
    depends_on:
      - "db"
    environment:
      - VIRTUAL_HOST=mysql.YOURDOMAIN.com
      - LETSENCRYPT_HOST=mysql.YOURDOMAIN.com
      - LETSENCRYPT_EMAIL=YOUREMAIL
      - PMA_HOST=db
    ports:
      - "1666:80" 

  portainer:
    image: portainer/portainer
    container_name: portainer
    restart: always
    environment:
      - VIRTUAL_HOST=docker.YOURDOMAIN.com
      - LETSENCRYPT_HOST=docker.YOURDOMAIN.com
      - LETSENCRYPT_EMAIL=EMAIL
    volumes: 
      - /PATH/TO/PERSISTENT/FILES:/data
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - "9000:9000"

  nextcloud:
    image: nextcloud:apache
    container_name: nextcloud
    restart: unless-stopped
    environment:
      - VIRTUAL_HOST=cloud.YOURDOMAIN.com
      - LETSENCRYPT_HOST=cloud.YOURDOMAIN.com
      - LETSENCRYPT_EMAIL=YOUREMAIL
      - PGID=999
      - PUID=1000
    ports:
      - "666:80"
    volumes:
      - /PATH/TO/PERSISTENT/FILES/nextcloud:/var/www/html
      - /PATH/TO/PERSISTENT/FILES/nextcloud/uploadsize.conf:/etc/nginx/conf.d/uploadsize.conf
    depends_on:
      - "db"
    links:
      - "redis"
    networks:
      - proxy-tier
      - default
 
  redis:
    image: redis
    container_name: redis
    volumes:
      -/PATH/TO/PERSISTENT/FILES/redis:/data
    restart: unless-stopped
  proxy:
    build: ./proxy   
    container_name: proxy
    restart: unless-stopped
    labels:
      com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - certs:/etc/nginx/certs:ro
      - vhost.d:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
    environment:
      - DEFAULT_HOST=cloud.YOURDOMAIN.com
    ports:
      - "80:80"
      - "443:443"
    networks:
      - "default"
      - "proxy-tier"

  proxy-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt
    restart: unless-stopped
    environment:
      - NGINX_PROXY_CONTAINER=proxy
    depends_on:
      - "proxy"
    volumes_from:
      - "proxy"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - "default"
      - "proxy-tier"

volumes:
  certs:
  vhost.d:
  html:

networks:
  proxy-tier:

All that’s left to do here is run the command docker-compose up to build and run your container stack.

DEPLOYMENT NOTES

The MariaDB database and the NextCloud files are stored persistently on the local disk, these are passed as mounted volumes to the Docker container.

The reverse proxy will create a subdomain and encrypt it with Let’s Encrypt certificates for every container with the VIRTUAL_HOST and Let’s Encrypt information provided as environmental variables. It will pass the defined port for web access on port 80 on the subdomain. The limitation of this is you can only reverse proxy a single port per application.

RELATED >>  Self Hosting: Nextcloud with DigitalOcean Spaces for Main Storage

I had to make some tweaks to override the maximum allowed file upload size. The combo of these changes worked for me. First, create the uploadsize.conf file and place this in it:

client_max_body_size: 10G;

You can see above this is passed to NextCloud directly as a mounted volume, I also built the proxy container using the “build” option. Create the proxy folder and create a Dockerfile containing:

FROM jwilder/nginx-proxy:alpine

COPY uploadsize.conf /etc/nginx/conf.d/uploadsize.conf

The other issue I had was that I would often get random errors or connection issues in NextCloud until it was placed on a separate proxy-tier network.

A final tweak, to enable Redis for memory caching and relieve the SQL database of some load, edit the /PATH/TO/PERSISTENT/FILES/nextcloud/config/config.php file and add:

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

ALMOST DONE

You should be able to access NextCloud at https://cloud.yourdomain.com now. The related applications are also available at the subdomains defined above, for example to manage the Docker containers go to https://docker.yourdomain.com to access Portainer.

Run through the NextCloud setup and you now have a fully functioning, encrypted, private cloud.


NEXTCLOUD APPS

There are a lot of NextCloud apps that extend the functionality of the server. The ones I use are:

All of these are pretty much one-click install except for Keeweb, which took some fiddling.

If you need a more robust Notes solution (ie. more like Evernote) take a look at Joplin, which supports NextCloud.

Keeweb NextCloud App

Keeweb NextCloud App

CONFIGURING KEEWEB PASSWORD MANAGER

This was the trickiest bit to get going. One of the reasons being there are a lot of options for password managers, see discussion on Reddit here I am keeping an eye on the Passman project, but currently it lacks sufficient phone apps. So I chose the very widely supported Keeweb.

The NextCloud Keeweb app is no longer maintained but can be made to work with some manual changes.

  1. Download the NextCloud Keeweb app
  2. Extract it to your nextcloud/apps directory
  3. Edit the file nextcloud/apps/keeweb/appinfo/info.xml, on line 17 change max-version to 14 instead of 12

You can now activate the app through the NextCloud interface.

You will need to create your Keeweb.kdbx file with another client, then upload it somewhere on your NextCloud instance. To get around the limitations of this older NextCloud Keeweb app, use the AppOrderExternal Sites apps linked above to first remove the default icon for Keeweb, and then replace it with an External Sites link pointed directly at your KDBX file, like so:

https://cloud.YOURDOMAIN.com/apps/keeweb?open=/Documents/Keeweb.kdbx

RECOMMENDED CLIENT APPS

On the client side, we have many ways of interacting with our new server. The default applications on your device, Apple computers or Android phones, all work out of the box with the open CalDAV & CardDAV standards. Just change your server and account information. Beyond that, here are some compatible apps I have used and recommend:

APPPLATFORMCLIENT FORCOSTNOTES
TuskChromePasswordsFREEA secure Chrome extension with Autofill
CloudNotesiOSNotes$2Great replacement for default Apple app.
Nextcloud Desktop ClientsOS X / Linux / WindowsFilesFREEEasy WebDAV syncing
NextCloud Mobile ClientsiOS / Android / Windows MobileFilesFREENot that useful on iOS, I prefer FolderSync Pro for Android
Folder Sync ProAndroidFiles$3Sync anything on your phone to NextCloud easily
NextCloud NotesAndroidNotes$2.50Simple note editor with great Android integration.
Keepass2AndroidAndroidPasswordsFREEExcellent Android integration
OpenTasksAndroidTasksFREEGood client, allows seamless integration with other Android apps
2DoOS X / iOS / AndroidTasksGreat iOS client, very similar interface to OpenTasks. Haven't used other versions
BusyCalOS X / iOSCalendar, Tasks$50 / $5Well worth the cost, this is what the default Apple app should be
BusyContactsOS X / iOSContacts$50Another solid app worth the cost from BusyMac
DAVDroidAndroidCalendar, Contacts$4.70Seamless integration with Android apps
EvolutionLinuxCalendar, Contacts, TasksFREEIMO the best email/productivity client for Linux.

If you have any other useful tips or tweaks for NextCloud, or can recommend your favorite client app, please comment below!


9 Replies to “Self Hosting: Complete Guide to Deploying Your Own Private NextCloud with Docker Compose”

  1. Ben Yanke says:

    Qownnotes is also a great note-taking alternative. I’ve moved most of my work notetaking off to there.

    • brad says:

      Awesome thank you for the recommendation. I have been messing around with Joplin, but this looks like it might be even better.

  2. jimbob says:

    The uploadsize.conf is no longer a part of the image you referenced. Any suggestion on a work around?

    • brad says:

      You have to create it yourself, unless I am misunderstanding your question. I am not an nginx expert, but any file in that /etc/nginx/conf.d folder in the container will get read.

  3. Ben says:

    Hey, nice guide.
    I have the same setup for my Nextcloud, but now I have a problem hosting multiple ssl-encrypted services on the same port (e.g. 443). I want to host nextcloud in one container and bitwarden in another, both should be accessible from www in the browser, e.g. bitwarden.example.com and nextcloud.example.com. After the research I found a nice solution called Traefik. Meanwhile there aren’t as many tutorials as for nginx, but in my opinion it seems more interesting to use Traefik. Maybe this is an idea for you.
    Thank you and best regards

  4. Carlos Martinez says:

    This is great stuff, I have the docker-compose edited to reflect all of my information but when I run docker-compose up I get:
    “services.redis.volumes contains an invalid type, it should be an array”

    here is the redis section of my compose file.

    redis:
    image: redis
    container_name: redis
    volumes:
    -/mnt/5a80dd29-a846-44e2-8533-d5c01d3953c6/docker/nextcloud/redis:/data
    restart: unless-stopped
    proxy:
    build: ./proxy
    container_name: proxy
    restart: unless-stopped
    labels:
    com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: “true”
    volumes:
    – /var/run/docker.sock:/tmp/docker.sock:ro
    – certs:/etc/nginx/certs:ro
    – vhost.d:/etc/nginx/vhost.d
    – html:/usr/share/nginx/html
    environment:
    – DEFAULT_HOST=cloud.REMOVED.com
    ports:
    – “80:80”
    – “443:443”
    networks:
    – “default”
    – “proxy-tier”

  5. […] has been over a year since I originally set up my own self-hosted cloud using Nextcloud. I am happy to report back that I absolutely love it, and it has run flawlessly without error for […]

Leave a Reply

Your email address will not be published. Required fields are marked *