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
- Enter trusted domains
- Give PHP read access to /dev/urandom (also: configure open_basedir)
- SELinux
- Place data directory outside of the web root
- Disable preview image generation
- Enable SSL: snakeoil
- Error: Your data directory and your files are probably accessible from the internet.
- Enable SSL: commercial certificate
- Make the Strict Transport Security warning go away
- Fail2ban
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 permissions.sh:
#!/bin/bash ocpath='/var/www/owncloud' datapath='/var/ownclouddata' htuser='www-data' htgroup='www-data' rootuser='root' 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 permissions.sh
Run the script:
# ./permissions.sh
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 owncloud.vorkbaard.nl. 192.168.1.3 is ownCloud’s local ip address.
'trusted_domains' => array ( 0 => 'owncloud.vorkbaard.nl', 1 => '192.168.1.3', ),
OwnCloud suggest whitelisting ‘localhost’ as well, but 127.0.0.1 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
SELinux
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 owncloud.vorkbaard.nl. 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 Webbed.nl 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:
192.168.1.3 owncloud.vorkbaard.nl
Save the file and close Notepad. If you can’t save it, open Notepad as administrator.
Ping owncloud.vorkbaard.nl; it should resolve to 192.168.1.3.

If you remembered to add owncloud.vorkbaard.nl to your trusted domains in ownCloud’s config.php you can now connect to ownCloud via http://owncloud.vorkbaard.nl.

On your ownCloud server in /etc/apache2/sites-available open the file default-ssl.conf. Change
DocumentRoot /var/www/
to
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 https://owncloud.vorkbaard.nl 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 owncloud.vorkbaard.nl (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.

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.)

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 Xolphin.nl 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:
- You generate a Certificate Signing Request (CSR) on your server.
- You send the CSR to the certificate vendor.
- 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.
- The vendor sends you one or more signed certificate files.
- You install the files in your webserver.
Let’s start with step 1: generate a CSR.
Adapted from SSLcertificaten.nl.
** Remember to replace owncloud.vorkbaard.nl with your own domain! **
# cd /etc/ssl/certs # openssl req -nodes -newkey rsa:2048 -keyout owncloud.vorkbaard.nl.key -out owncloud.vorkbaard.nl.csr
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: https://www.google.nl/search?q=csr+2+letter+country+code+list
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 Vorkbaard.nl
Organizational Unit Name (eg, section) []: ICT dept or whatever you like or is appropriate.
Common Name (eg, YOUR name) []: your (sub)domainname, e.g. owncloud.vorkbaard.nl. 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 owncloud.vorkbaard.nl.csr
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 owncloud.vorkbaard.nl.key
Move it to the private folder:
# mv owncloud.vorkbaard.nl.key /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 Xolphin.nl you’ll receive among other files a zip file containing four certificates:
- owncloud_vorkbaard_nl.crt
- COMODORSADomainValidationSecureServerCA.crt
- COMODORSAAddTrustCA.crt
- 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 > bundle.owncloud.vorkbaard.nl.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 bundle.owncloud.vorkbaard.nl.crt
Make sure that in any case bundle.owncloud.vorkbaard.nl.crt 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/bundle.owncloud.vorkbaard.nl.crt SSLCertificateKeyFile /etc/ssl/private/owncloud.vorkbaard.nl.key
Also while you’re in there just after
ServerAdmin webmaster@localhost
(which you should change to your own e-mail address) add:
ServerName owncloud.vorkbaard.nl
Save the file and reload Apache:
# service apache2 reload
Reload the webpage in your browser: https://owncloud.vorkbaard.nl
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 owncloud.vorkbaard.nl add:
<IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=15768000;includeSubDomains; preload" </IfModule>
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: https://wiki.debian.org/Exim)
# 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: vorkbaard.nl (replace with your own domain or just your system’s hostname (i.e. owncloud.vorkbaard.nl). 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: vorkbaard.nl (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:
root=username@gmail.com mailhub=smtp.gmail.com:587 hostname=username@gmail.com UseSTARTTLS=YES AuthUser=username@gmail.com AuthPass=p@55word FromLineOverride=yes
In /etc/ssmtp/revaliases create an alias for root by adding this line:
root:username@gmail.com:smtp.gmail.com
Replace all instances of username@gmail.com 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
Install:
# 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:
[Definition] 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: http://php.net/manual/en/timezones.php.
In /etc/fail2ban/jail.local add this jail:
[owncloud] 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 192.168.1.2
To manually check the Fail2ban’s ownCloud jail do
# fail2ban-client status owncloud
Next up: miscellaneous ownCloud tweaks.
Very nice tutorial!
I even learned a thing or two my self
Thanks! It was educational for me as well.
Hi Kapitein Vorkbaard
Thank you very much for this great tutorials!
I’m pretty sure you have one typo for /etc/fail2ban/filter.d/owncloud.conf
Probably wrong:
failregex={“reqId”:”.*”,”remoteAddr”:”.*”,”app”:”core”,”message”:”Login failed: ‘.*’ \Remote IP: ”\)”,”level”:2,”time”:”.*”}
Probably right: Note the additional “(” before “Remote IP”
failregex={“reqId”:”.*”,”remoteAddr”:”.*”,”app”:”core”,”message”:”Login failed: ‘.*’ \(Remote IP: ”\)”,”level”:2,”time”:”.*”}
Kind regards,
Tom
Thanks, I updated the article :)
Nice tutorial!!! Thanks alot!!
Probably you could help me with an error my log throw out:
touch(): open_basedir restriction in effect. File(/var/log/owncloud.log) is not within the allowed path(s): (/var/www/owncloud/:/var/ownclouddata/:var/log/owncloud.log:/tmp/:/dev/urandom) at /var/www/owncloud/lib/private/log/owncloud.php#53
Any ideas :-)
Kind regards,
Marius
You’re missing a forward slash in front of the third ‘var’ ;)
Thxs a lot!
Could you please help me with the open_basedir restriction?
I’m On windows 7 using Xammp, and the data is on a external disk:
D:\Owncloud_Data
I wrote:
open_basedir = /xampp/htdocs/owncloud;/dev/urandom;d://Owncloud_data
It’s not working
Thhxs!
It’s been a while but I think your folder Owncloud_Data needs to be accessible from your server with a path relative to your server, so try using its mounted name instead of its Windows name – something like /media/lxchel/usbdisk/Owncloud_Data or so.
Hi, the trick is using double quotation mark in the path:
open_basedir = “/xampp/htdocs/owncloud/;/dev/urandom;/xampp/htdocs/owncloud/lib/private/log/owncloud.php/;/tmp/;d:/Owncloud_Data/”
This way I don’t get the error “D:/Owncloud_Data is not valid”, but, I still get the error “/dev/urandom is not readable by PHP”
Not sure it helps but check this: https://forum.owncloud.org/viewtopic.php?t=34286