Saturday, August 31, 2013

How to Deploy ownCloud with postgresql, nginx, php-fpm, and chroot

ownCloud is a promising open-source, self-hosted alternative to Dropbox. While I can't quite endorse it for mission critical, large-scale deployment, I look forward to watching it mature. Recently, I spent about half a day getting it all working in my preferred deployment environment: nginx instead of Apache, postgresql instead of mysql, and carefully chrooted for better security isolation.

  1. On Debian Stable (Wheezy), you need these packages:
    apt-get install postgresql-9.1 nginx-light php5-fpm php5-gd php-xml-parser php5-intl php5-pgsql
  2. Download the ownCloud source tarball. I used owncloud-5.0.10.tar.bz2.
  3. Unpack it as /var/lib/owncloud/public.
  4. Make sure root owns all of it.
    chown -R root /var/lib/owncloud/public
  5. Create a dedicated owncloud user.
    adduser --system --no-create-home owncloud
  6. Give the owncloud user ownership of just the config and apps directories:
    chown -R owncloud:nogroup /var/lib/owncloud/public/config /var/lib/owncloud/public/apps
  7. Make the ownCloud data directory outside the web root, to make it less likely that a webserver misconfiguration will leave you with gaping security holes:
    mkdir /var/lib/owncloud/data
    chown owncloud:nogroup /var/lib/owncloud/data
  8. Put the bare minimum needed for a working chroot into /var/lib/owncloud:
  9. Create the postgres user and database. Normally I prefer to use peer authentication locally, so that passwords aren't necessary. But I don't think php5-pgsql supports that, so pick a password:
    sudo -u postgres createuser --pwprompt owncloud
    sudo -u postgres createdb -O owncloud owncloud
  10. Create a php-fpm process pool by putting this into /etc/php5/fpm/pool.d/owncloud.conf
  11. Configure nginx. This example puts owncloud into a subdirectory, so that it will be accessible like
  12. Now fire up nginx and php5-fpm
    service restart nginx
    service restart php5-fpm
  13. Visit You should be greeted with the ownCloud configuration page, where you'll need to choose postgresql as your database, enter your database username (owncloud) and password, and set the data directory to /var/lib/owncloud/public.
  14. Remember to schedule background tasks. Rather than put a working shell in my chroot, I just use the web-cron method. Edit the ownCloud user's crontab with "crontab -e -u owncloud" and add this:
    */5 *  *  *  * curl --resolve
  15. Optional step for the security paranoid: owncloud is running chrooted in a very spartan jail. But it still has access to the local loopback interface and the local network. I use iptables to prevent it from talking to anything other than my postgresql database (this breaks some automatic update / app-store features in owncloud):
    iptables -A OUTPUT -d -p tcp -m owner --uid-owner owncloud -m tcp --dport 5432 -j ACCEPT
    iptables -A OUTPUT -m owner --uid-owner owncloud -j REJECT --reject-with icmp-port-unreachable


  1. That's a great how-to, thank you. I found only one minor mistake: section 7. should be
    mkdir /var/lib/owncloud/public/data
    chown owncloud:nogroup /var/lib/owncloud/public/data

    1. Thanks.

      But it was actually intentional that I put the data directory outside of the public directory. This does require you to change the default location while configuring ownCloud, but I like the security benefit of keeping the data outside of the webserver's root.

    2. Yes, that's a valid point! I'll move it out of the public directory, as you suggest.

      Another smaller issue that I stumbled upon: Your php-fpm config file specifies
      pm.max_children = 5

      This is not enough for even a single user (I get lots of warning in the fpm logs saying " WARNING: [pool owncloud] server reached pm.max_children setting (5), consider raising it").

      My guess is that Owncloud's use of Ajax requires the web server to deal with quite a lot of parallel requests, I put the setting to 25 and didn't get any of those warnings since sthen

  2. Hi! I have followed your instructions, and gotten ownCloud 6.0.1 installed as you recommended. I got the warning about the data directory, I just went ahead and changed to inside public, until I get this installed. Now, when I browse to http://[mydomain.tld]/owncloud, I get the error:

    Setting locale to en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8 failed

    Please install one of theses locales on your system and restart your webserver.

    I've got the locale installed. Is this a consequence of the chroot?

  3. Clericare, I am repeating your config, but on Ubuntu Server Precise, (12.04 latest point release). So there have been some differences, which I want to document. I found that the locale error given by ownCloud 6.0.1 install, otherwise set up as exactly as possible according to your guide, needed to add the following to the chroot in order to work:

    myuser@mymachine:/var/lib/owncloud# tar -c /usr/lib/locale/locale-archive | tar x

    (so one could add it of course, to the line in your guide where you set up the chroot files)

    After doing this, and restarting nginx & php5-fpm, the owncloud setup page started without error.

  4. This comment has been removed by the author.

  5. Actually, after this point:

    the setup encountered another error:
    "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken.

    Please double check the installation guides."

    But this seems post-setup, your guide didn't mention this?

  6. Thanks for your edits Forrest. I didn't encounter the WebDAV issue, but ownCloud has been evolving quickly and I haven't played with any of the more recent versions yet.


Note: Only a member of this blog may post a comment.