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 https://example.com/owncloud:
  12. Now fire up nginx and php5-fpm
    service restart nginx
    service restart php5-fpm
    
  13. Visit https://yourserver.com/owncloud. 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 yourdomain.com:443:localhost https://yourdomain.com/owncloud/cron.php
    
  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 127.0.0.1/32 -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