OwnCloud Logo

When Seafile Isn’t Enough, There’s OwnCloud

In an earlier post I wrote about using Seafile to provide secure private storage like Dropbox. Seafile specializes in file storage and sharing and works well if you’re an individual or an organization. What do you do if you want more?

Enter ownCloud. ownCloud aspires to be your complete cloud storage solution, providing file storage, calendars, contacts, password management, photo galleries, collaborative document editing, and more. It provides modular functionality that allows you to activate only the functionality that you need, and it also includes a rich collection of plugins that extend this functionality with community-contributed resources.

ownCloud ships its own Docker image, built on top of the PHP Docker image. It stores its data in /var/www/html, and if you mount a persistent volume at this location, you’ll be able to keep your data around even if you need to destroy or recreate the container. As you’ll see later in this tutorial, destroying the container is something that you’ll be doing more often than you think.

One drawback to this setup is that the directory is populated with ownCloud content when the container first starts, and after that the data from the persistent volume is…persistent. This means that if you run the container for ownCloud version 8 and then later run the container for version 9, you’ll find yourself still running a version 8 installation.

Another drawback is that ownCloud leaves it up to you to wrap your installation in HTTPS. When you’re running a standalone container like this, it might not be obvious how to do so easily.

In this post I’ll cover how to install ownCloud, how to put it behind an HAProxy container that terminates SSL, and how to upgrade it.

Let’s get started!

Will You Need An External Database?

The ownCloud container documentation includes a sample Docker Compose file that shows linking to an external MariaDB instance. By default OwnCloud will use SQLite, and for a small installation, SQLite is sufficient. SQLite doesn’t handle more advanced SQL instructions, and it doesn’t handle any sort of concurrent actions, so if you are using OwnCloud with more than one or two people, consider using an external MySQL-compatible database or Postgres. This can be another container, but don’t use a database container for every service you want to run.

This takes us into the realm of architecture. As soon as you think you might want an external database, consider which other services in your environment can use this database, and plan accordingly. Databases love RAM, and they do poorly when they aren’t configured properly for the resources available to them. If you install a MySQL or MariaDB container (or Postgres, or any NoSQL variant), configure it to make the best use of the system resources – allocate the right amount of RAM, and store the data in a location where it won’t be fighting with other processes for access to the underlying storage hardware. Dedicated, striped magnetic drives or SSDs will never steer you wrong.

Apache or FPM?

The ownCloud container is built on top of the PHP library image. This image provides two options for accessing the data – one via Apache with the PHP modules loaded in, and another via FastCGI using PHP-FPM. If you already have a frontend Apache instance, you can use the PHP-FPM image, which listens on port 9000. Configure Apache with mod_proxy_fcgi and a directive like:

You’ll have to start your Apache container with a link to the ownCloud container and make sure that the ownCloud container starts first. You can do this with --link and the depends_on directive in Docker Compose.

Sounds like a pain, right? PHP-FPM is a very fast PHP execution engine, but it requires additional consideration for how you’ll talk to it. For this tutorial we’ll use the Apache variant of ownCloud.

(It’s worth noting that if you’re using an orchestration system like Rancher, this is much easier. Rancher enables service discovery by DNS, so you don’t need hard links between containers. Your Apache instance can find the ownCloud instance by its container name.)

Installing The ownCloud Docker Container

Many instructions for launching containers tell you to use docker run but fail to include information about how to keep the container running. With only docker run you will find that your container is no longer running after you reboot the host or after the container dies. Docker provides the --restart option, which tells Docker to when to restart the container. You might think that the always option is the best, but this will do exactly what it sounds like — it will always restart the container….even if you’ve stopped it. A better option is unless-stopped, which will restart the container if it dies abnormally.

(Note: If you wish to start right away with the latest OwnCloud, replace :8 with :latest. We’re starting with 8 so we can upgrade it.)

This will fire up a copy of ownCloud with Apache listening on port 80. It also assumes that you’re not already running anything on port 80 and that you have the privileges to launch services there. These are arrogant assumptions – you’ll probably want to change 80:80 to 8000:80 or something similar and then proxy connections from a front-end load balancer like HAProxy, nginx, or another Apache process to this container. More on that later.

The ownCloud docs then tell you to point your browser to localhost, but that also assumes you’ve just launched your cloud server on your own machine. In reality, you probably have this running out on your CloudSigma instance, which for this article we’ll refer to as cloud.example.com. Make sure you have your DNS ducks all in a row, and when you point your browser, you should see something like this:

If you have an external MySQL or Postgres database, you can expand the dropdown for “Storage & Database” and set those options. Remember that localhost isn’t the host where your container is running but rather the container itself. If you have a database running on the host, use the FQDN or IP of the host instead.

At this point you’re asked to create an admin user and set the password, and you should pause and consider that we’re not running with TLS. The username and password you enter here could be intercepted by anyone with the ability to do so, and sending passwords across the Internet (or even across the LAN) in plaintext is a bad practice. Policies and procedures only have merit if we follow them, so let’s pause here and set up HAProxy.

Installing HAProxy On The Host

For container setups running on standalone hosts, HAProxy makes the most sense when run on the host itself. You’ll be able to add additional container services to it and reload it with minimal interruption to running services, whereas if you run it as a container you’ll have to restart the container with links to new services that you want HAProxy to proxy.

The disadvantage to running HAProxy on the host is that your backend containers will need ports published on the host itself. You can publish them on localhost to keep them out of sight of the Internet, but you’re still in the business of managing ports. If you go this route, I suggest that you set up a wiki page to track application port assignments and don’t reuse the same port for different applications running on other hosts.

First, let’s restart our OwnCloud container on localhost:

Next, install HAProxy for your operating system. If you don’t have a valid certificate, you can very quickly make one by visiting this page. Once you have a certificate, append the key to the certificate (or, if there are chain certificates, append all certificates from most to least specific and then append the key), and save this as /etc/haproxy/server.pem. Set its mode to 0600 and its ownership to root.

You can find a configuration for HAProxy that maps to our ownCloud container on port 8000 at this link. Update this to change cloud.example.com to your FQDN, install it as /etc/haproxy/haproxy.cfg, owned by root with mode 0600, and reload HAProxy:

Return to your ownCloud URL with HTTPS, and if all was done correctly, you’ll be connected to the same install screen as before, but with HTTPS.

Continue the installation process, and after logging in, you should be met with a screen like the following:

At this point, if you installed the latest version of ownCloud, you can start using your new personal cloud server.

However, if you’d like to learn how to upgrade the installation, read on.

Upgrading ownCloud

As I stated earlier, ownCloud’s data is stored in a persistent folder, and thus if you recreate the container from the latest image, nothing will happen. The contents of your persistent folder prevent ownCloud from deploying the newest code.

In order to initiate the update process, you will need to follow a variant of these instructions and relaunch the container. After this step you will be able to update via the UI or via occ.

NOTE: Upgrades can go wrong. Always have a backup of your database and content, and make sure that you’ve tested that you’re able to restore from those backups before you perform any sort of action that can destroy your data.

ALSO NOTE: ownCloud requires that you go from one major version to the next. You are not permitted to skip versions. This means that we cannot go from 8.2 to 9.1 without first updating to 9.0. This tedious extra step can be avoided by staying current with updates, and if you do it wrong here, you’ll be left with a crippled installation.

Don’t Believe The Documentation

ownCloud’s Docker library README says that an upgrade can be forced by removing version.php. This was true until 9.1. If you’re upgrading to any version through 9.0, you can stop and remove the ownCloud container, remove version.php from your persistent directory (or rename it to version.php.old), and relaunch ownCloud with the newer version number in your launch command.

When the container starts and you log in, you’ll be greeted with this screen:

Click “Start update” to get started.

The New and Improved Way

The new way to perform a manual upgrade is as follows:

  1. Stop and remove the ownCloud container
  2. Make a complete copy of the ownCloud data and database
  3. In the original location, remove everything except config and data
  4. Relaunch the container with the new version tag

This variant of removing version.php prevents errors like the following:

After launching the container with the new version tag, ownCloud’s initialization process copies in all of the new code and prepares for the upgrade. You can perform the upgrade vi the UI or via occ.

Using occ

ownCloud ships with a utility called occ that you can find in your installation directory. This utility allows you to interact with OwnCloud via the command-line, performing tasks like user management, upgrades, and various other things. Full documentation on occ can be found here.

ownCloud recommends using occ for upgrades, particularly on larger installations, because PHP scripts can time out and leave the upgrade in an unknown state. Even without the threat of timeouts, if you’re managing an installation remotely, such as in CloudSigma’s ZRH facility, you don’t want to leave your upgrade to the whim of long distance Internet connectivity. Use a terminal management utility like screen or tmux to keep your session healthy, even if you’re disconnected.

To use occ with Docker, use the docker exec command, passing it -u www-data to run commands as the user who owns the file contents. This is what occ returns for our version 8 install:

After removing version.php and relaunching with 9.0, we get the following:

After upgrading, removing everything except data and config and relaunching with 9.1, we get the following:

We can perform both upgrades with occ upgrade.


Many things can go wrong with upgrading ownCloud. Your best bet is to search for specific error messages and read the corresponding Github issues. If HAProxy returns a 503, it’s likely because ownCloud is still in maintenance mode, and in this mode it returns a 503 with its information about being in maintenance mode. The provided HAProxy config accounts for this with the following directive, telling it to accept 2xx, 3xx, or 503 as valid server responses:

You can also check the output of the ownCloud container from the host itself using curl commands:


ownCloud is a fantastic system for running cloud services under your own control and can give you the benefit of a private environment with the on-demand resources of a public loud like CloudSigma. It covers a large area of functionality, and while this makes it powerful, it also makes it susceptible to issues. Do your best to keep it up to date, and be prepared to restore from backups after upgrades fail.

Running ownCloud within Docker gives you the ability to run it anywhere, and this freedom is a core component of taking back control of your data from those who use it for their own profit.

About Adrian Goins

Adrian started on this Internet adventure with a 300 baud modem in one hand and a C64 in the other. A voracious learner, he zipped through BASIC and BBSes and went bonkers when the Internet arrived. Within months of Slackware coming out he was running Linux systems for ISPs and firms in Colorado, and in a blink of an eye became the lead Java developer for a team at MCI/Worldcom. Two shakes of a lamb's tail after that he was building and managing datacenter environments for dotcoms in New York and London. He then founded a company that for the next 14 years provided outsourced IT management solutions for Fortune 1000 media companies. He is an expert in all things related to system/network/security administration, configuration management, and virtualization, and he has a black belt in making things work. When not building new systems or learning the limits of the latest bits of technology, he lives with his wife in Chile, builds advanced UAVs and aquaponics gardens, and raises peafowl, chickens, and dogs.

Leave a Reply