Part 1: Introduction
Part 2: Installing Debian 8
Part 3: Installing ownCloud 8
Part 4: Connecting to Active Directory
Part 5: Security
Part 6: Miscellany
Part 7: Server maintenance

This part is about basic security. OwnCloud lists a number of security options on their site. We’ll be going over their suggestions and add one extra while we’re at it. Everything combined should result in a server with a good baseline security.

Here are today’s activities.

Set the proper file permissions
OwnCloud provides a script to easily set the proper file permissions on ownCloud installations. Their page also lists all suggested permissions per directory or file so you can set the permissions for modified installations.

Here’s a small adaptation of the script:

Paste this in a file called

find ${ocpath}/ -type f -print0 | xargs -0 chmod 0640
find ${ocpath}/ -type d -print0 | xargs -0 chmod 0750
chown -R ${rootuser}:${htgroup} ${ocpath}/
chown -R ${htuser}:${htgroup} ${ocpath}/apps/
chown -R ${htuser}:${htgroup} ${ocpath}/config/
chown -R ${htuser}:${htgroup} ${datapath}/
chown -R ${htuser}:${htgroup} ${ocpath}/themes/
chown ${rootuser}:${htgroup} ${ocpath}/.htaccess
chown ${rootuser}:${htgroup} ${datapath}/.htaccess
chmod 0644 ${ocpath}/.htaccess
chmod 0644 ${datapath}/.htaccess

Edit ocpath and datapath to your own variables. htuser, htgroup and rootuser are correct if you’re installing on Debian with Apache, which we are. ocpath and datapath contain the correct values for our lab setup.

Make the script executable:

# chmod +x

Run the script:

# ./

If no errors occured you’re done!

Enter trusted domains
From the ownCloud site: in /var/www/owncloud/config/config.php change the array of trusted domains. Enter all names and addresses by which you want to be able to access ownCloud. I’ll be using the domainname is ownCloud’s local ip address.

'trusted_domains' =>
  array (
   0 => '',
   1 => '',

OwnCloud suggest whitelisting ‘localhost’ as well, but is automatically whitelisted and our server has no gui so I think you will survive the one time you need to type localhost’s IP address.

Give PHP read access to /dev/urandom (also: configure open_basedir)
open_basedir is a php.ini directive which specifies which paths PHP is allowed to access through script. If it’s not configured PHP can access any directory allowed by the filesystem. By default PHP in Debian 8 has no configuration for open_basedir so /dev/urandom may be accessed by PHP to acquire entropy.

Since ownCloud has no business being anywhere else on our system but in its own directories, /tmp/ and /dev/urandom let’s tell PHP about this. Open /etc/php5/apache2/php.ini and find the line that reads

; open_basedir

and change it to

open_basedir /var/www/owncloud/:/var/ownclouddata/:/var/log/owncloud.log:/tmp/:/dev/urandom

Reload Apache to have open_basedir take effect:

# service apache2 reload

Setting up SELinux in Debian is still a bit wonky. We’ll skip it for now. If you have genius suggestions feel free to mention them in the comments :)

Place data directory outside of the web root
We did that in the setup so we’re covered!

Disable preview image generation
This is really a choice between functionality and marginally more security. If you’re paranoid about it – or just don’t care about image previews – then disable it. Alternatively sign up for ownCloud’s newsletters and I think you’ll be notified soon enough if a security issue with image generation occurs.

Enable SSL
In Apache your have two choices for SSL: either you use a self-signed certificate (appropriately named a snakeoil certificate in Apache) or you pay a certificate vendor a fee for a commercial certificate.

We’ll first do the snakeoil, later on the commercial. The domain I’ll be using is You will need to use your own domain name and pay a DNS provider to tell the rest of the world about it. My DNS provider of choice is because they provide excellent service for a fair price.

I assume you already have you own domain name and have it pointed at your webserver. If not, just edit your hosts file for now. I’m testing on my Windows AD server so that’s where I’ll edit my hosts file: click Start, type Notepad, rightclick it and choose Run as administrator.


In Notepad open %windir%\system32\drivers\etc\hosts. and add this line:


Save the file and close Notepad. If you can’t save it, open Notepad as administrator.

Ping; it should resolve to



If you remembered to add to your trusted domains in ownCloud’s config.php you can now connect to ownCloud via

Connect to

Connect to

On your ownCloud server in /etc/apache2/sites-available open the file default-ssl.conf. Change

DocumentRoot /var/www/


DocumentRoot /var/www/owncloud

Enable the site:

# a2ensite default-ssl

Enable Apache’s SSL module:

# a2enmod ssl

Disable the non-ssl version of the site. Strictly this is optional but there’s no use for it anymore so why keep it?

# a2dissite 000-default.conf

Restart Apache so the SSL module and the changes in enabled/disabled sites take effect:

# service apache2 restart

Now go to and depending on which browser you are using you’ll get some sort or warning about the missing SSL certificate.


If you’re using Google Chrome like I am click the Advanced link.


Internet Explorer does a similar thing.


Click Proceed to (unsafe).


And Bob’s your uncle.

Now, if you are the only user and you’ll only be using ownCloud to sync to your desktop of mobile device you could stop here. Even though there’s no signed and trusted certificate the data that’s sent back and forth would be encrypted just the same.


Just tell your client to trust the certificate anyway.

This is the snakeoil method. It works but it doesn’t look nice and you know the site can be trusted but others don’t.

Error: Your data directory and your files are probably accessible from the internet.
OwnCloud does a strange thing after you enable SSL. On entering the Admin page it verifies whether the data directory (/var/www/owncloud/data by default but we changed it to /var/ownclouddata) is accessible through the internet. It should not be otherwise non-authorized users might type in direct URLs to files and download them. It does this by placing a .htaccess file in the data directory containing supplemental instructions for the webserver. If it can’t find the .htaccess file it will tell you.

It also verifies if it can read from and write to the data directory. It does this by placing a file called htaccesstest.txt in the data directory the moment you open the Admin page. It then tries to remove that file.

The problem is that in between it will do some other stuff for just over two minutes during which the animated ‘loading’ indicator will be shown. The test appears to hang so you might be tempted to reload the page. If you do that when the test has not fully completed the htaccesstest.txt is still there and ownCloud assumes it cannot read-and-write in the data directory and I guess just gives up on the .htaccess file altogether. It will tell you so in the Security & setup warnings section on the Admin page.

Data directory and .htaccess file security warning

Data directory and .htaccess file security warning

After a while though the htaccesstest.txt file disappears. If you:
– then reload the Admin page,
– would have waited for the tests to fully complete, or
– would have manually removed the htaccesstest.txt file
ownCloud will tell you that everything is fine.

I guess this is a bug in ownCloud which will be fixed in time. If you let ownCloud run its tests for two minutes and it tells you everything is in order then next time you can safely ignore the message about the .htaccess file not working and the data directory being in the web server document root. (If however it keeps complaining even after waiting out the full test round you should investigate further.)

Security & setup warnings: all checks passed

Security & setup warnings: all checks passed

Get a commercial certificate
When it comes to commercial certificates there are a lot of options and their prices vary from a small fee to thousands of euros. For private use or a small company what’s important is that things run smoothly and your users don’t get confusing warnings. The cheapest certificates suffice for that. The ones I buy are €8 per year, less if you get certs for more than one year at a time.

I get my certificates at because they provide very fast service and are very helpful. I’ll describe the process here but your experience will likely differ if you’re using a different certificate vendor.

Whichever provider you choose the process is always the same:

  1. You generate a Certificate Signing Request (CSR) on your server.
  2. You send the CSR to the certificate vendor.
  3. The vendor verifies your identity. Based on the kind of certificate you are buying this process is less or more elaborate. Basically the more you pay the stricter they are.
  4. The vendor sends you one or more signed certificate files.
  5. You install the files in your webserver.

Let’s start with step 1: generate a CSR.
Adapted from

** Remember to replace with your own domain! **

# cd /etc/ssl/certs
# openssl req -nodes -newkey rsa:2048 -keyout -out

You’ll need to enter information that corresponds with that of the domain name owner (DNS registry) or the Chamber of Commerce if applicable. [xx] denotes the standard value.

Country Name (2 letter code) [AU]: your country code. For the Netherlands this would be NL. If in doubt ask Google:
State or Province Name (full name) [Some-State]: your province
Locality Name (eg, city) []: your city
Organization Name (eg, company) [Internet Widgits Pty Ltd]: your exact company name if applicable, otherwise try your domain name. I tend to use
Organizational Unit Name (eg, section) []: ICT dept or whatever you like or is appropriate.
Common Name (eg, YOUR name) []: your (sub)domainname, e.g. Not your own name.
Email Address []: your@email.address
A challenge password []: do not enter anything here
An optional company name []: do not enter anything here

Print the CSR

# cat


Select every line in the CSR including the BEGIN CERTIFICATE HERE and END CERTIFICATE HERE lines.

Change the permissions of the .key file OpenSSL generated so only root can read it:

# chmod 600

Move it to the private folder:

# mv /etc/ssl/private

Head over to your SSL provider’s website and start the certificate request process. They’ll provide you with a textbox to paste your CSR in.


Paste the CSR including the first and last lines.

The certificate vendor will need some information: your name, telephone number, payment method and a method to verify that you are indeed the owner of the (sub)domain you’re requesting the certificate for. These methods may include:
– you need to enter some file on your webserver
– you need to register a special subdomainname in your DNS
– you need to receive a mail at admin@ or some other static e-mail address.

After placing the order you may receive a verification mail with a code you need to fill out on the Comodo Security site, or some other SSL vendor.

If like me you placed your order with you’ll receive among other files a zip file containing four certificates:

  1. owncloud_vorkbaard_nl.crt
  2. COMODORSADomainValidationSecureServerCA.crt
  3. COMODORSAAddTrustCA.crt
  4. AddTrustExternalCARoot.crt

Depending on the kind of certificate you purchased you may or may not receive intermediate certificates.

To install the certificate in Apache on Debian 8 you need to concatenate the four certificates in the exact order I mentioned: first your own cert, then the Domain Validation Secure Server CA, then the Add Trust CA and finally the Add Trust External CA Root.

I think this is silly but there you go. In Linux you can do this with the following command:

# cat owncloud_vorkbaard_nl.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt >

In Windows just fire up Notepad and copy and paste the files. If you’re feeling geeky do

copy /a owncloud_vorkbaard_nl.crt + COMODORSADomainValidationSecureServerCA.crt +  COMODORSAAddTrustCA.crt + AddTrustExternalCARoot.crt

Make sure that in any case contains ALL lines from all four certificate files including the BEGIN and END CERTIFICATE lines with no empty lines in between.

In /etc/apache2/sites-available/default-ssl.conf replace the snakeoil by the real pixie dust: find the lines that read

# SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
# SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

and replace them by

SSLCertificateFile      /etc/ssl/certs/
SSLCertificateKeyFile   /etc/ssl/private/

Also while you’re in there just after

ServerAdmin webmaster@localhost

(which you should change to your own e-mail address) add:


Save the file and reload Apache:

# service apache2 reload

Reload the webpage in your browser:


To be honest it will probably fail because:

  • you made a typo somewhere
  • a file is not in the right place
  • you forgot to write https instead of http and also
  • forgot to do a2dissite 000-default
  • forgot to do service apache2 reload
  • you botched the concatenation of the bundle certificate
  • you overwrote your local hosts file
  • something else
  • a combination of the above

There are a million ways to get SSL to work (and a million more to screw it up, do it wrong or both). The way I’ve described here is a simple one because there’s only one site in your Apache configuration and this entire server is dedicated to ownCloud. Feel free to experiment with other methods. They can be just as good and a lot of them will be better.

Make the Strict Transport Security warning go away
From the ownCloud site:
In /etc/apache2/sites-available/default-ssl.conf just after ServerName add:

 <IfModule mod_headers.c>
      Header always set Strict-Transport-Security "max-age=15768000;includeSubDomains; preload"

Enable the Headers module and restart Apache:

# a2enmod headers
# service apache2 restart

Deny access after three wrong passwords
We’re going to use Fail2ban to deny access to ownCloud after entering a wrong username. After ten minutes the user may try again. The purpose of this is to prevent password hammering: infinitely guessing a user’s password to break in to their account.

Fail2ban is software that can take action based on the contents of logfiles. You define combinations of software (based on that software’s logfile) and actions. These combinations are called jails in Fail2ban. The actions can include blocking access (using the firewall) and sending a notification e-mail to the administrator.

First we’ll set up the mail part, then Fail2ban. If you don’t care about mails from Fail2ban you can skip this part.

The mail part
My provider blocks outgoing traffic on port 25. They do that in order to prevent clients from sending spam. As a result my server can no longer send mail to me. My workaround is to have my server use my Gmail account to send out mail as Gmail’s SMTP server accepts traffic on port 587 instead of 25.

Debian 8’s default MTA is Exim4. Exim is capable of sending mail through Gmail but I find SSMTP easier to use with Gmail so I’m going to set up SSMTP. As a reference I will also configure Exim4 to send out mail directly. You should use one or the other: SSMTP or Exim4, not both. Luckily Debian will disable Exim4 for you if you install SSMTP.

Using Exim – only if your ISP allows outgoing traffic on port 25
Set up Exim (source:

# dpkg-reconfigure exim4-config

The Package configurator will open. Select the following settings:
General type of mail configuration: internet site; mail is sent and received directly using SMTP.


System mail name: (replace with your own domain or just your system’s hostname (i.e. The worst that can happen is your mail will be blocked by your spamfilter. Just whitelist your server’s IP address or the sender’s address then.


IP-addresses to listen on for incomming SMTP connections: // leave blank


Other destinations for which mail is accepted: (same as with System mail name).


Domains to relay mail for: // leave blank


Machines to relay mail for: // leave blank


Keep number of DNS-queries minimal (Dial-on-Demand) ?: No


Delivery method for local mail: Maildir format in home directory. Mbox format in /var/mail/ will also work but Maildir is what Debian advises so there you go. We’re not listening for incoming mail anyway, only outgoing.


Split configuration into small files ? : No


Update and restart Exim:

# update-exim4.conf
# service exim4 restart

Continue to the section about testing the e-mail capability.

Using SSMTP – if you want to send out mail using your Gmail account
Install SSMTP:

# aptitude install ssmtp

When the installer asks if you want to replace exim4 answer yes.

Open /etc/ssmtp/ssmtp.conf and edit (or add) the following values:

In /etc/ssmtp/revaliases create an alias for root by adding this line:

Replace all instances of with your own complete Gmail e-mail address. You may use your custom domain address here if you configured one with Google Apps. Replace P@55word with your own Gmail password or your app specific password if you enabled that.

Testing the e-mail functionality
Test your server’s mailing capability by sending a test mail:

# echo “test 01” | mailx -vvv -s “test 01” your@email.address

Replace your@email.address with your own e-mail address. I tend to use a sequence number in my test mails so you can see exactly which test mails have arrived. -vvv means: be very verbose about what you’re doing. If something goes wrong you will probably be able to see what it causes it.

Setting up Fail2ban

# aptitude install fail2ban

Fail2ban uses template and differential files. This means you get a .conf file and create .local files which contain only the parts that differ from the .conf. Essentially just copy the .conf and make changes there rather than in the .conf. It makes upgrading easier. We’re not upgrading right now but it’s always nice to know why you do what you’re doing. Directly changing the .conf would work as well.

# cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Remember the jail files? A jail in Fail2ban is a combination of logfiles and actions. Fail2ban can handle multiple jails. A filter is the part of the logfile Fail2ban should look for. Helpful users on the ownCloud forum have provided the regular expressions.

Create the file /etc/fail2ban/filter.d/owncloud.conf and add:

	failregex={“reqId”:”.*”,”remoteAddr”:”.*”,”app”:”core”,”message”:”Login failed: ‘.*’ \(Remote IP: ”\)”,”level”:2,”time”:”.*”}
	ignoreregex =

Make sure your /var/www/owncloud/config/config.php contains

	'logtimezone' => 'Europe/Amsterdam',

Or your own timezone. Find your timezone here:

In /etc/fail2ban/jail.local add this jail:

enabled = true
filter = owncloud
logpath = /var/log/owncloud.log
maxretry = 3
port = 443

You may edit maxretry to your own tastes of course. This is the amount of seconds an IP address is banned. Afterwards the ban is lifted.

If you want Fail2ban to send you an e-mail when someone is banned change destemail:

mta = mail
destemail = your@email.address

Set action:

  • action_ = just ban
  • action_mw = ban and mail
  • action_mwl = ban and mail with whois report and relevant log lines

I suggest _mwl but change it to your needs.

action = %(action_mwl)s

Start Fail2ban:

# fail2ban-client start

If it was already running:

# service fail2ban restart

Upon starting Fail2ban you should see any errors that were encountered. Pay close attention and troubleshoot when necessary. If you see no errors when starting Fail2ban then all should be fine. Fail2ban should also send you a mail to notify you that it has started. If you don’t receive this (and it’s not in your spambox as well) then you need to verify your server’s mail settings.

Now for the test. Open the ownCloud web interface and try to log in three (or whatever you set as the maximum) times with a wrong username-password combination.


If all is well you will now no longer be able to access your ownCloud site.


You should also receive an e-mail.


To manually unban a client do

# fail2ban-client set owncloud unbanip

To manually check the Fail2ban’s ownCloud jail do

# fail2ban-client status owncloud


Next up: miscellaneous ownCloud tweaks.