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:
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.
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:
- AppOrder – rearrange applications in the toolbar
- Bookmarks
- Calendar – CalDAV server
- Contacts – CardDAV server
- External Sites – Embed other web apps within the NextCloud interface
- Metadata – additional file metadata
- Keeweb – Web interface for Keeweb databse [see below]
- Notes
- Tasks – CalDav todos
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.
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.
- Download the NextCloud Keeweb app
- Extract it to your nextcloud/apps directory
- 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 AppOrder & External 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:
APP | PLATFORM | CLIENT FOR | COST | NOTES |
---|---|---|---|---|
Tusk | Chrome | Passwords | FREE | A secure Chrome extension with Autofill |
CloudNotes | iOS | Notes | $2 | Great replacement for default Apple app. |
Nextcloud Desktop Clients | OS X / Linux / Windows | Files | FREE | Easy WebDAV syncing |
NextCloud Mobile Clients | iOS / Android / Windows Mobile | Files | FREE | Not that useful on iOS, I prefer FolderSync Pro for Android |
Folder Sync Pro | Android | Files | $3 | Sync anything on your phone to NextCloud easily |
NextCloud Notes | Android | Notes | $2.50 | Simple note editor with great Android integration. |
Keepass2Android | Android | Passwords | FREE | Excellent Android integration |
OpenTasks | Android | Tasks | FREE | Good client, allows seamless integration with other Android apps |
2Do | OS X / iOS / Android | Tasks | Great iOS client, very similar interface to OpenTasks. Haven't used other versions | |
BusyCal | OS X / iOS | Calendar, Tasks | $50 / $5 | Well worth the cost, this is what the default Apple app should be |
BusyContacts | OS X / iOS | Contacts | $50 | Another solid app worth the cost from BusyMac |
DAVDroid | Android | Calendar, Contacts | $4.70 | Seamless integration with Android apps |
Evolution | Linux | Calendar, Contacts, Tasks | FREE | IMO 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!
Qownnotes is also a great note-taking alternative. I’ve moved most of my work notetaking off to there.
Awesome thank you for the recommendation. I have been messing around with Joplin, but this looks like it might be even better.
The uploadsize.conf is no longer a part of the image you referenced. Any suggestion on a work around?
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.
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
Yes a proxy is the way to handle multiple services on the same port.
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”
You have volumes listed twice!
[…] 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 […]