Hi,
this Tuturial describes the steps to setup owncloud on top of debian/raspian with lighttpd as webserver and https encryption with certificates sign by Let’s encrypt campain.
Operating System
Install a minimal debian jessie system.
Login as root. On raspbian login as user pi change to root.
pi@raspown ~ $ sudo su -
If you want to setup the cloud by ssh and you want to login with root an password authentification set “PermitRootLogin” to “yes” in /etc/ssh/sshd_config.
Don’t forget to set it back to “without-password” after finishing.
Install required packages
root@raspown:~# apt-get -y install php5 php5-common php5-gd php-xml-parser php5-intl php5-json php5-mcrypt root@raspown:~# apt-get -y install php5-sqlite php5-mysql php5-pgsql smbclient php5-curl curl libcurl3 libcurl3-dev root@raspown:~# apt-get -y install lighttpd php5-cgi root@raspown:~# apt-get -y remove apache2 apache2-bin apache2-data libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0 root@raspown:~# apt-get -y install python-pip root@raspown:~# apt-get -y install git bash
For Raspbian Users. Do not start graphical desktop, just boot in text mode
root@raspown:~# systemctl get-default root@raspown:~# systemctl set-default -f multi-user.target
Set the hostname respectily full qualified domain name
root@raspown:~# hostnamectl set-hostname yourhost.yourdomain.net
Configure a static IP Address. Disable old (init) config style by saving /etc/network/interfaces and creating an empty file
root@raspown:~# mv /etc/network/interfaces /etc/network/interfaces.save root@raspown:~# touch /etc/network/interfaces
Setting up eth0. Create a file /etc/systemd/network/eth0.network, Name it as you want.
[Match]
# You can also use wildcards. Maybe you want enable dhcp
# an all eth* NICs
Name=eth0
[Network]
#DHCP=v4
# static IP
# 192.168.100.2 netmask 255.255.255.0
Address=192.168.100.2/24
Gateway=192.168.100.1
DNS=192.168.100.1
and enable systemd-networkd and resolved
root@raspown:~# systemctl enable systemd-networkd.service root@raspown:~# systemctl enable systemd-resolved.service
Define DNS Server. You can add the DNS Server either in the Network section of the NIC adapter config (see above) or in /etc/systemd/resolved.conf
Create a symlink
root@raspown:~# mv /etc/resolv.conf /etc/resolv.conf.save root@raspown:~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
Enable lighttpd on Port 80
Start the webserver and see if its running
root@raspown # lighty-enable-mod fastcgi-php root@raspown # systemctl enable lighttpd.service root@raspown # systemctl start lighttpd.service root@raspown # journalctl -xn
https certificates
Lets Encrypt
Create the certificates. Get project sources
root@raspown:~# git clone https://github.com/letsencrypt/letsencrypt
Install additional packages needed by letsencrypt create the virtual environment. Do not use the standard shell on Debian 8 based systems. Also the Python Package Index must be reachable:
root@raspown:~/letsencrypt# bash letsencrypt-auto -v
If you want to use your own key and signing request:
Create your server key and csr by openssl. Do not enter a challenge password at the end of the creation process otherwise lighttpd will prompt at each start for it.
root@raspown:~# mkdir -p /etc/lighttpd/ssl
Create Key and Signing request. For a better quality of random numbers consider to generate the key on a “real” PC. Note: The CommonName and the the subjectAltName of the siging request must set to the domain name to which the certificate should belongs to. The output format of the csr must set to DER.
Create an x509 v3 exentension file /etc/lighttpd/ssl/ssl_v3.cfg
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[ v3_req ]
basicConstraints = CA:FALSE
nsCertType = server,client
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth,clientAuth,emailProtection,codeSigning,timeStamping
subjectAltName = @alt_names
[alt_names]
DNS.1 = yourhost.yourdomain.net
# DNS.2 =
[req_distinguished_name]
Generate Key and signing request
root@raspown:~# openssl req -nodes -new -newkey rsa:2048 -sha256 -outform DER -out /etc/lighttpd/ssl/server.der -keyout /etc/lighttpd/ssl/server.key -subj '/C=DE/ST=Franken/L=Nuremberg/O=Your Company/OU=Your OU/emailAddress=webmaster@yourdomain.net/CN=yourhost.yourdomain.net/' -config /etc/lighttpd/ssl/ssl_v3.cfg # Sets the following parameters # Country Name (2 letter code) [AU]:DE # State or Province Name (full name) [Some-State]:Franken # Locality Name (eg, city) []:Nuremberg # Organization Name (eg, company) [Internet Widgits Pty Ltd]:Your Company # Organizational Unit Name (eg, section) []:Your OU # Common Name (e.g. server FQDN or YOUR name) []:yourhost.yourdomain.net # Email Address []:webmaster@yourdomain.net # A challenge password []: # An optional company name []:
Verify that your csr contains all your parameter:
root@raspown:~# openssl req -inform der -in /etc/lighttpd/ssl/server.der -noout -text
Get the certificate from the LetsEncrypt CA. This example is based on the webroot authenticator to validate the domain (DV). Means, the letsencrypt-auto script creates a file in the webroot of your webserver which will be read during the domain validation process by the LetsEncrypt webservice.
Before you call the script make sure your webserver is reachable from the internet by your dns name at port 80 (letsencrypt http-01 challenge).
If your Webserver is behind a DSL Router ensure you have configured a port forwarding rule from port 80 to the internal ip address of your webserver. The default lighttpd Webroot for Port 80 is at /var/www/html.
If you want to use your own csr and webroot authentification you have to specify a webroot-map in letsencrypts config file to define a conjunction between domain name and webroot path otherwise an error “PluginError–webroot-path must be set” occurs.
Create a config file /etc/letsencrypt/cli.ini
authenticator = webroot
webroot-path = /var/www/html
webroot-map = {"yourhost.yourdomain.net" : "/var/www/html"}
root@raspown:~/letsencrypt# bash letsencrypt-auto certonly --config /etc/letsencrypt/cli.ini --agree-tos --csr /etc/lighttpd/ssl/server.der --cert-path /etc/lighttpd/ssl/server.pem
And set restricted permissions for csr, certificate and key.
root@raspown:~# cat /etc/lighttpd/ssl/server.key /etc/lighttpd/ssl/server.crt > /etc/lighttpd/ssl/server.pem root@raspown:~# chown -R www-data:root /etc/lighttpd/ssl/ root@raspown:~# chmod 460 /etc/lighttpd/ssl/* root@raspown:~# chown -R www-data:www-data /etc/lighttpd/ssl/server.key root@raspown:~# chmod 400 /etc/lighttpd/ssl/server.key
For testing
For testing https you can use selfsigned certificates
root@raspown:~# mkdir -p /etc/lighttpd/ssl/ root@raspown:~# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/lighttpd/ssl/server.key -out /etc/lighttpd/ssl/server.crt root@raspown:~# cat /etc/lighttpd/ssl/server.key /etc/lighttpd/ssl/server.crt > /etc/lighttpd/ssl/server.pem
root@raspown:~# chown -R www-data:root /etc/lighttpd/ssl/ root@raspown:~# chmod 460 /etc/lighttpd/ssl/*
Configure Lighttpd
Append the following lines to your config file /etc/lighttpd/lighttpd.conf , ensure that the owncloud data directory is not readable from the web.
# If you want to use HTTP logging (troubleshooting) insert both lines below
# Consider to mount the log folder /var/log/lighttpd as
# tmpfs (but logs are lost after reboot) to avoid excessive writing to the SD Card.
# Add fstab
# tmpfs /var/log/lighttpd tmpfs rw,size=256M,noexec,nodev,nosuid,uid=33,gid=33 0 0
server.modules += ( "mod_accesslog" )
accesslog.filename = "/var/log/lighttpd/access.log"
# SSL Server settings
# redirect all to https
$HTTP["scheme"] == "http" {
# redirect all http traffic to https, expect the letsencrypt webroot auth requests
$HTTP["url"] !~ "^/\.well-known/" {
# capture vhost name with regex conditiona -> %0 in redirect pattern
# must be the most inner block to the redirect rule
$HTTP["host"] =~ ".*" {
url.redirect = (".*" => "https://%0$0")
}
}
}
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/ssl/server.pem"
# ssl.ca-file = "/etc/lighttpd/ssl/server.crt"
# Enter your hostname
server.name = "yourhost.yourdomain.net"
server.document-root = "/var/www/owncloud"
ssl.use-sslv2 = "disable"
ssl.use-sslv3 = "disable"
ssl.use-compression = "disable"
ssl.honor-cipher-order = "enable"
# A more secure cipher list. Not working with older Webbrowsers!
ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES128+EDH"
server.errorlog = "/var/log/lighttpd/serror.log"
accesslog.filename = "/var/log/lighttpd/saccess.log"
}
# Owncloud Data directory
$HTTP["url"] =~ "^/oc/data/" {
url.access-deny = ("")
}
# Owncloud root
$HTTP["url"] =~ "^/oc($|/)" {
dir-listing.activate = "disable"
}
# Letsencrypt webauth root
$HTTP["url"] =~ "^/\.well-known/" {
dir-listing.activate = "disable"
}
# Not Owncloud or Webauth
$HTTP["url"] !~ "^/oc$|^/oc/|^/\.well-known/" {
url.access-deny = ("")
}
Create the webserver root directory for your owncloud instance
root@raspown # mkdir -p /var/www/owncloud root@raspown # chown www-data:www-data /var/www/owncloud
Start the webserver and see if its running
root@raspown # lighty-enable-mod fastcgi-php root@raspown # systemctl enable lighttpd.service root@raspown # systemctl start lighttpd.service root@raspown # journalctl -xn
Owncloud
Installing owncloud(In this tutorial 8.2)
root@raspown # cd /var/www/owncloud root@owncloud:/var/www/owncloud# wget https://download.owncloud.org/community/owncloud-8.2.1.tar.bz2 root@owncloud:/var/www/owncloud# tar -xvjf owncloud-8.2.1.tar.bz2
Owncloud is now extracted to the subfolder owncloud in the webserver root /var/www/owncloud . I renamed this folder to oc. If you plan another name alter also the deny and dir-listing directive in lighttpd.conf to your folder.
root@owncloud:/var/www/owncloud# mv owncloud oc
Remove owncloud sources
root@owncloud:/var/www/owncloud# rm owncloud-8.2.1.tar.bz2
Set Folder permissions
root@owncloud:/var/www/owncloud# cd oc root@owncloud:/var/www/owncloud/oc# mkdir -p data root@owncloud:/var/www/owncloud/oc# chmod -R o-wxr /var/www/owncloud root@owncloud:/var/www/owncloud/oc# chown -R www-data:www-data /var/www/owncloud
Database
The default database backend of owncloud is sqlite. If you plan to synchronize your Data with the Ownclound Desktop Client a real Database System is recommended.
Here are the steps to setup a mysql Datebase. Install the server and choose secure password.
root@raspown # apt-get -y install mysql-server
Secure your installation
root@raspown # mysql_secure_installation Remove anonymous users? [Y/n] y ... Success! Disallow root login remotely? [Y/n] y ... Success! Remove test database and access to it? [Y/n] y - Dropping test database... ... Success! Reload privilege tables now? [Y/n] y ... Success!
Open the MySQL Console as Database root
root@raspown # mysql -u root -p
Create a User ocuser (Replace ocpassword with your Password 🙂 ) and the database owncloud and permit the user to the database.
mysql> create database owncloud;
mysql> CREATE USER 'ocuser'@'localhost' identified by 'ocpassword';
mysql> grant all on owncloud.* to 'ocuser'@'localhost';
mysql> FLUSH PRIVILEGES;
If you want to change the password
mysql> use mysql;
mysql> SET PASSWORD FOR 'ocuser'@'localhost' = PASSWORD('ocpassword');
Securing the installation
AppArmor
I use AppArmor to secure lighttpd and mysql. The raspbian kernel does not support AppArmor out of the box. To use AppArmor you have to recompile the kernel. My post provides a script which supports you :-). Debian Jessie has the support for AppArmor already included.
Installing and activating, on a PC with grub booloader add apparmor=1 security=apparmor to the kernel parameters in /etc/default/grub
root@raspown # apt-get install apparmor apparmor-profiles apparmor-utils root@raspown # cp /etc/default/grub /etc/default/grub.org root@raspown # perl -pi -e 's,GRUB_CMDLINE_LINUX="(.*)"$,GRUB_CMDLINE_LINUX="$1 apparmor=1 security=apparmor",' /etc/default/grub root@raspown # update-grub root@raspown # reboot
On an Raspberry edit /boot/cmdline.txt
root@raspown # sed -e's/\( root=\/dev\/mmcblk0p2\)/\1 apparmor=1 security=apparmor/g' /boot/cmdline.txt --in-place=.bak
Check if apparmor is correct installed
root@raspown # aa-status
Note: If error “apparmor filesystem is not mounted.” occurs you have to forgot to call update-grub 😉
By default a mysql profiles is loaded and enforced. Create a lighttpd profile /etc/apparmor.d/usr.sbin.lighttpd This profile is based on the example shipped with debian /usr/share/doc/apparmor-profiles/extras/usr.sbin.lighttpd and OpenSUSE
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# vim:syntax=apparmor
#include
/usr/sbin/lighttpd {
#include
#include
#include
# needed to change max file descriptors
capability sys_resource,
# network service ;)
capability net_bind_service,
# changing the uid/gid on startup
capability setgid,
capability setuid,
/etc/ld.so.cache r,
/etc/lighttpd r,
/etc/lighttpd/*.conf r,
/etc/lighttpd/conf.d/*.conf r,
/etc/lighttpd/auth.d/* r,
/etc/lighttpd/vhosts.d r,
/etc/lighttpd/vhosts.d/* r,
/usr/sbin/lighttpd mix,
/usr/lib/lighttpd/*.so mr,
/usr/lib64/lighttpd/*.so mr,
/etc/ssl/private/*.pem r,
/etc/lighttpd/ssl/server.pem r,
# home dir. e.g. used for sockets.
/var/lib/lighttpd/ r,
/var/lib/lighttpd/** rwl,
# mod_compress cache
/var/cache/lighttpd/ r,
/var/cache/lighttpd/** rwl,
# pid
/{,var/}run/lighttpd.pid rwl,
# log files
/var/log/lighttpd/*.log rw,
# Socket
/run/lighttpd/* w,
# exec
# /usr/bin/php-cgi Cx,
/usr/bin/php5-cgi Cx,
# include_shell
/bin/bash mix,
/bin/dash mix,
/bin/zsh mix,
/bin/cat mix,
# http docs
/var/www/ r,
/var/www/** r,
# Debian/Ubuntu integration in default installation
#include
/etc/mime.types r,
/usr/share/lighttpd/ r,
/usr/share/lighttpd/*.pl rmix,
/etc/lighttpd/conf-available/ r,
/etc/lighttpd/conf-available/*.conf r,
/etc/lighttpd/conf-enabled/ r,
/etc/lighttpd/conf-enabled/*.conf r,
profile /usr/bin/php5-cgi {
#include
/etc/* r,
/etc/ssl/openssl.cnf r,
/etc/php/** r,
/etc/php5/** r,
/lib/lib*so* mr,
/var/lib/php5/sessions/* rwk,
/var/www/ r,
/var/www/** r,
/var/www/owncloud/oc/apps/** rwk,
/var/www/owncloud/oc/config/** rwk,
/var/www/owncloud/oc/data/** rwk,
/tmp/ r,
/tmp/* rwk,
/usr/share/mysql/charsets/Index.xml r,
/usr/bin/php5-cgi r,
/usr/lib/lib*so* mr,
/usr/lib{,32,64}/** mr,
}
}
Set it in enforce mode
root@raspown # aa-enforce /usr/sbin/lighttpd root@raspown # systemctl restart lighttpd.service
Add the line
/etc/ld.so.cache r,
also into /usr/sbin/mysqld {} Section of /etc/apparmor.d/usr.sbin.mysqld
root@raspown # aa-enforce /usr/sbin/mysqld
If have already tested the apparmor profile for a while. If owncloud shows unexpected behaviours check the syslog for apparmor DENIES and send it to me:
root@raspown # journalctl -x --since yesterday|grep 'apparmor="DENIED"'
Tripwire
Next step in security is to monitor filesystem changes. Here are the steps to handle this with tripwire. For further information see documention
Install tripwire
root@raspown # apt-get install tripwire
Create a site key. The site key is used for creating and signing the policy
root@raspown # twadmin -m G -S /etc/tripwire/site.key -Q YourSecureSiteKeyPassword
Create a local key. The local key is used checking file integrity and update database on changes (OS Update..)
root@raspown # twadmin -m G -L /etc/tripwire/${HOSTNAME}-local.key -P -Q YourSecureLocalKeyPassword
Adjust the config /etc/tripwire/twcfg.txt as needed and create the config file from the text template
root@raspown # twadmin --create-cfgfile -S /etc/tripwire/site.key /etc/tripwire/twcfg.txt
Adjust the default policy /etc/tripwire/twpol.txt to your system. This is an good overview.
and append the rules for owncloud to the end of the file /etc/tripwire/twpol.txt
#
# owncloud
#
#
(
rulename = "owncloud Directories",
severity = $(SIG_MED)
)
{
/var/www/ -> $(SEC_BIN) (recurse = 1) ;
/var/www/owncloud/oc/config -> $(SEC_CONFIG) (recurse = 1) ;
!/var/www/owncloud/oc/data;
}
Create the policy file from text file
root@raspown # twadmin --create-polfile /etc/tripwire/twpol.txt
Do the init filesystem scan and create the database and eleminate all errors
root@raspown # tripwire --init
Checking your system is simple, the report is stored at /var/lib/tripwire/report/.
root@raspown # tripwire --check
If your database has to be updated, maybe you update your Linux OS, run “tripwire –update” against the latest report file. This opens an text editor. Edit only the changes (removing the [X] => [ ]) which should not be written to the database. Save the file and you will prompted for the local passphrase.
root@raspown # tripwire --update -r /var/lib/tripwire/report/report-20151118.twr
After updating the database its an good idea to copy the database file /var/lib/tripwire/*.twd to an storage which is readonly. Before each tripwire check command check also if the database in the /var/lib/tripwire and on the readonly storage is identically.
Setup an cron job which periodically starts an tripwire check
Owncloud Configuration
All backend service are now prepared and running. Open a brower and connect to your Owncloud Installation. Navigate to
https://yourFQDNHostname/oc/
Owncloud is now ready to configure and use 🙂
Michael