Install an ownCloud server

ownCloud is a platform that acts as a cloud storage. You can freely deploy your own because ownCloud is open source.

Information and requirements

These elements are to be taken into consideration to follow this article:

Update the system

sudo dnf -y update

Install PHP

Install Remi’s RPM repository

sudo dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

List available modules for PHP

sudo dnf module list php
Rocky Linux 8 - AppStream
Name          Stream           Profiles                           Summary
php           7.2 [d]          common [d], devel, minimal         PHP scripting language
php           7.3              common [d], devel, minimal         PHP scripting language
php           7.4              common [d], devel, minimal         PHP scripting language

Remi's Modular repository for Enterprise Linux 8 - x86_64
Name          Stream           Profiles                           Summary
php           remi-7.2         common [d], devel, minimal         PHP scripting language
php           remi-7.3         common [d], devel, minimal         PHP scripting language
php           remi-7.4         common [d], devel, minimal         PHP scripting language
php           remi-8.0         common [d], devel, minimal         PHP scripting language
php           remi-8.1         common [d], devel, minimal         PHP scripting language

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled

Enable PHP 7.4 module

sudo dnf -y module enable php:remi-7.4

Check if PHP 7.4 is enabled

sudo dnf info php
[...]
Name:        : php
Version      : 7.4.24
[...]

Install required packages

They are all necessary for the smooth running of the installation.

sudo dnf -y install httpd firewalld vim mod_ssl redis php php-common php-pdo unzip php-pecl-zip php-xml php-intl php-mbstring php-gd php-mysqlnd php-process php-pecl-redis5 php-pecl-apcu policycoreutils-python-utils

Add the MariaDB repository

Copy the following snippet into /etc/yum.repos.d/MariaDB.repo.

# MariaDB 10.6 CentOS repository list - created 2021-09-27 12:36 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.6/centos8-amd64
module_hotfixes=1
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

Install MariaDB

sudo dnf -y install MariaDB-server MariaDB-client

Disable the InnoDB read only compressed option

Add the following option into /etc/my.cnf.d/server.cnf

[mariadb-10.6]
innodb_read_only_compressed=0

Enable and start services

sudo systemctl enable --now mariadb.service

Modify authorized ports

sudo firewall-cmd --add-port={80/tcp,443/tcp} --permanent
sudo firewall-cmd --reload

Install MariaDB

sudo mariadb-secure-installation
<ENTER>
n
Y
<root password>
<confirm>
Y
Y
Y
Y

Configure database

Choose a really strong password instead of P@ssw0rd.

mariadb -u root -p
<root password>
SET old_passwords=0;
CREATE USER "owncloud" IDENTIFIED BY "P@ssw0rd";
CREATE DATABASE owncloud;
GRANT ALL PRIVILEGES ON owncloud.* TO "owncloud";
FLUSH PRIVILEGES;
EXIT;

You can generate a strong password (here 40 characters but you can increase its size) with the following statement.

tr -cd "[:alnum:]" < /dev/urandom | fold -w40 | head -n1

Note: /dev/urandom and /dev/random are using the exact same CSPRNG (Cryptographically Secure PseudoRandom Number Generator).

Test the connection

mariadb -u owncloud -p owncloud
<owncloud's password>
EXIT;

HTTPD configurations

General configurations

By adding ServerTokens Prod directive, you remove the Apache2 version from HTTP headers, it’s a good practice for security reasons.

echo "ServerTokens Prod" | sudo tee -a /etc/httpd/conf/httpd.conf

Inside the <Directory "/var/www/html"> section, modify AllowOverride None to AllowOverride All. Any valid directive in the .htaccess context will be allowed in .htaccess files.

If you want to access to ownCloud server without adding /owncloud at the end of the domain name, you should do the following thing.

sudo sed -i '123i Alias "/" "/var/www/html/owncloud/"' /etc/httpd/conf/httpd.conf

General TLS configurations

Add these headers and the cache configuration for OCSP stapling just before the default virtual host (<VirtualHost _default_:443>) into /etc/httpd/conf.d/ssl.conf.

# Headers
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy no-referrer

# OCSP stapling
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

Set the Diffie-Hellman parameters. First, you must generate the parameters. Here, the size of the generated parameter set will be 4096 bits.

sudo openssl dhparam -out /etc/pki/tls/private/dhparam.pem 4096
sudo chmod 440 /etc/pki/tls/private/dhparam.pem

Then, specify to Apache2 where the file is located via the DHParameters directive.

# Key exchange
SSLOpenSSLConfCmd DHParameters "/etc/pki/tls/private/dhparam.pem"

Disable TLS session tickets and enable the addition of OCSP responses to TLS negociation just before the end of the virtual host (</VirtualHost>) into /etc/httpd/conf.d/ssl.conf.

SSLSessionTickets Off
SSLUseStapling On

Accept all protocols except those before TLSv1.2.

sudo sed -i "s/#SSLProtocol.*/SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1/" /etc/httpd/conf.d/ssl.conf

Generate a self-signed certificate (local server only)

Generate a private key for a curve. Here, I use the curve secp521r1 but you can use another one by executing openssl ecparam -list_curves.

sudo openssl ecparam -check -name secp521r1 -genkey -noout -out /etc/pki/tls/private/privkey.pem -rand /dev/urandom
checking elliptic curve parameters: ok

You can set the temporary curve used for ephemeral ECDH modes. You can use the same curve you just used to generate the private key. Add the following statement juste after the SSLOpenSSLConfCmd DHParameters directive into /etc/httpd/conf.d/ssl.conf.

SSLOpenSSLConfCmd Curves secp384r1

Create a self-signed certificate. Feel free to personalize the answers to the questions asked. This self-signed certificate is used for testing purposes so it is not essential that the information given is correct.

sudo openssl req -utf8 -new -x509 -key /etc/pki/tls/private/privkey.pem -out /etc/pki/tls/certs/cert.pem -days 365 -rand /dev/urandom
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letters code) [XX]:FR
State or Province Name (full name) []:Rhone-Alpes
Locality Name (eg, city) [Default City]:Lyon
Organizational Name (eg, company) [Default Company Ltd]:ownCloud
Organizational Unit Name (eg, section) []:IT Department
Common Name (eg, your name or your server's hostname) []:owncloud.lan
Email Address []:contact@owncloud.lan

Set the correct permission.

sudo chmod 440 /etc/pki/tls/private/privkey.pem
sudo chmod 644 /etc/pki/tls/certs/cert.pem

Then, create the virtual host configuration into /etc/httpd/conf.d/vhost.conf.

<VirtualHost *:80>
    ServerName owncloud.lan:80
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName owncloud.lan:443
    ServerAlias owncloud.lan
    ServerAdmin contact@owncloud.lan

    SSLCertificateFile /etc/pki/tls/certs/cert.pem
    SSLCertificateKeyFile /etc/pki/tls/private/privkey.pem
    SSLCACertificateFile /etc/pki/tls/certs/cert.pem

    Protocols h2 http/1.1

    ErrorLog /var/log/owncloud/error_log
    CustomLog /var/log/owncloud/access_log combined
</VirtualHost>

Request a Let’s Encrypt certificate (public server only)

In case you wish to obtain free certificates (via Let’s Encrypt), two methods are available to you. Luck is on your side, you will find here the method to obtain a certificate from Let’s Encrypt, and here a slightly more advanced method that allows you to obtain a certificate based on elliptic curve cryptography (still via Let’s Encrypt).

The reverse proxy configuration is the exact same. Things you have to modify are the location of the certificate, private key and the chain of trust, but it is documented in the article previously mentionned.

Create the logs directory

sudo mkdir -p /var/log/owncloud

Edit the PHP configuration

By modifying this line, you remove the PHP version from HTTP headers, it’s a good practice for security reasons.

sudo sed -i "s/expose_php = On/expose_php = Off/" /etc/php.ini

Import the GPG key

sudo rpm --import https://download.opensuse.org/repositories/isv:/ownCloud:/server:/10/CentOS_8/repodata/repomd.xml.key

Add the repository

sudo curl -Lo /etc/yum.repos.d/owncloud.repo -sSf https://download.opensuse.org/repositories/isv:ownCloud:server:10/CentOS_8/isv:ownCloud:server:10.repo

Install ownCloud

sudo dnf -y install owncloud-complete-files

Edit the Redis configuration

Replace RediP@ssw0rd by a stronger password.

sudo sed -i "s/# requirepass foobared/requirepass $(echo -n "RedisP@ssw0rd" | sha256sum | sed "s/ .*$//")/" /etc/redis.conf
sudo sed -i "s/# unixsocket \/tmp\/redis.sock/unixsocket \/run\/redis\/redis.sock/" /etc/redis.conf
sudo sed -i "s/# unixsocketperm 700/unixsocketperm 770/" /etc/redis.conf

Enable and start Redis service

sudo systemctl enable --now redis.service

Flush Redis database

Replace <hashed password> by the hash (echo -n "your password here" | sha256sum) of the password choosen earlier.

sudo redis-cli -s /run/redis/redis.sock
auth <hashed password>
SELECT 0
FLUSHDB
QUIT

Set the SELinux context

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/owncloud/config(/.*)?"
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/owncloud/apps(/.*)?"
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/owncloud/apps-external(/.*)?"
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/owncloud/data(/.*)?"
sudo semanage fcontext -a -t httpd_sys_rw_content_t /var/www/html/owncloud/.htaccess
sudo restorecon -r -v /var/www/html/owncloud/

Enable and start HTTPD service

sudo systemctl enable --now httpd.service

Configurations from web interface

Browse the domain name that you have linked to your ownCloud server fill in the fields. Note that fields Database user, Database password, Database name and Database host appears when you choose MySQL/MariaDB database.

FieldValueComment
Usernameroot (whatever you want)it is the admin. account
Password-provide a strong password
Data folder/var/www/html/owncloud/datayou can keep the default value
Database userowncloud-
Database password-password of the owncloud user
Database nameownclouddatabase created earlier
Database hostlocalhost:3306make sure to specify the port

Once done, login as administrator and define the e-mail address of the administrator account in the section named General in the Personal panel.

Configure ownCloud cron job

Select the Cron radio button in the Generel section in the Admin panel.

Configure Redis

Add the following content at the end of /var/www/html/owncloud/config/config.php, after 'installed' => true, and be sure to put the hashed Redis password.

'memcache.local' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' =>
array(
        'host' => '/run/redis/redis.sock',
	'port' => 0,
	'timeout' => 0,
	'password' => '<the hashed password>',
	'dbindex' => 0
)

Add the user apache to the group redis to avoid permission issue regarding the socket.

sudo usermod -aG redis apache

SELinux configurations

Allow all daemons to use tcp wrappers.

sudo setsebool -P daemons_enable_cluster_mode on

Wait minutes and execute the following statements.

sudo ausearch -c 'php-fpm' --raw | sudo audit2allow -M phpfpm
sudo semodule -i phpfpm.pp

Recommendations

Protection against brute-force with Fail2ban

sudo dnf -y install fail2ban-server fail2ban-firewalld

First, we want to ban brute-force user login attempts. Copy the following snippet into /etc/fail2ban/filter.d/owncloud.conf.

[INCLUDES]
before = common.conf

[Definition]
failregex = {.*Login failed: \'.*\' \(Remote IP: \'<ADDR>\'\)"}
ignoreregex =

Create the jail by copying the following snippet into /etc/fail2ban/jail.d/owncloud.local.

[owncloud]
enabled = true
port = 80,443
filter = owncloud
action = iptables-allports[name=owncloud]
logpath = /var/www/html/owcloud/data/owncloud.log
maxretry = 3
bantime = 86400
findtime = 3600

Start the Fail2ban server and enable it at boot.

sudo systemctl enable --now fail2ban.service

Check the login attempts jail.

sudo fail2ban-client status owncloud
Status for the jail: owncloud
|- Filter
|  |- Currently failed: 0
|  |- Total failed:	0
|  `- File list:	/var/www/html/owncloud/data/owncloud.log
|
`- Actions
   |- Currently banned:	0
   |- Total banned:	0
   `- Banned IP list:

You can try to log in with bad credentials and executed a new time the previous command, the Currently failed and Total failed values will increment. Don’t abuse, you’ll be block otherwise!

Finally, you can unban an IP with the following command.

sudo fail2ban-client set owncloud unbanip <IP>

Delete skeleton directories and files

For each added user, two directories and a file will be created, you can delete the following directory to avoid this behavior.

sudo rm -rf /var/www/html/owncloud/core/skeleton/

SELinux configuration

Enable or disable updates via the web interface

To enable updates via the ownCloud web interface, you may need this to enable writing to the ownCloud directories. When the update is completed, disable write access.

sudo setsebool httpd_unified on|off

Disallow write access to the whole web directory

For security reasons it’s suggested to disable write access to all folders in /var/www/ (default).

sudo setsebool -P httpd_unified off

Allow access to a remote database

An additional setting is needed if your installation is connecting to a remote database.

sudo setsebool -P httpd_can_network_connect_db on|off

Allow access to LDAP server

Use this setting to allow LDAP connections.

sudo setsebool -P httpd_can_connect_ldap on|off

Allow access to remote network

ownCloud requires access to remote networks for functions such as Server-to-Server sharing, external storages or the ownCloud Marketplace. To allow this access use the following setting.

sudo setsebool -P httpd_can_network_connect on|off

Allow access to network memcache

This setting is not required if httpd_can_network_connect is already on.

sudo setsebool -P httpd_can_network_memcache on|off

Allow access to SMTP/sendmail

If you want to allow ownCloud to send out e-mail notifications via sendmail you need to use the following setting.

sudo setsebool -P httpd_can_sendmail on|off

Allow access to CIFS/SMB

If you have placed your datadir on a CIFS/SMB share use the following setting.

sudo setsebool -P httpd_use_cifs on|off

Allow access to FuseFS

If your owncloud data folder resides on a Fuse Filesystem, this setting is required as well.

sudo setsebool -P httpd_use_fusefs on|off

Allow access to GPG for Rainloop

If you use a the rainloop webmail client app which supports GPG/PGP, you might need this.

sudo setsebool -P httpd_use_gpg on|off

Backing up data

Create the folder that will receive the backups.

sudo mkdir -p /var/local/owncloud/backups

Copy the following snippet into /usr/local/sbin/ocbackup. Change <owncloud user password> by the password you have defined to the owncloud user. Because we use the short password flag -p, you cannot have a space between the flag and the password.

#! /usr/bin/env bash

backuptime=$(date +%Y-%m-%d)
dir=/var/local/owncloud/backups/$backuptime
mkdir $dir
rsync -Aax /var/www/html/owncloud/data/ $dir/data
rsync -Aax /var/www/html/owncloud/config/ $dir/config
mysqldump --single-transaction -h localhost -u owncloud -p<owncloud user password> owncloud > $dir/database.sql
tar -cf $dir.tar.gz --absolute-names $dir
rm -rf $dir

Make it executable.

sudo chmod +x /usr/local/sbin/ocbackup

Then, add these entries into the root’s user crontab (sudo crontab -e).

0 4 * * * /usr/local/sbin/ocbackup
0 6 * * * /usr/bin/find /var/local/owncloud/backups/ -type f -name '*.tar.gz' -mtime +1 -delete

Each day, at 4 a.m., the script will save data in a directory (format: Y-m-D) into /var/local/owncloud/backups. Then, each day at 6 a.m. all backup older than 4 days will be deleted. With this configuration, data can be retrieved in n-4 days. Increase this number to have more days of retention.

Configure e-mail server

When adding a user, you must define an e-mail address for him, this will send him an e-mail so that he can set his password. The section named General in the Admin panel allows you to define the mail server settings you want to use.

Your ownCloud server installation is now finished! You can see that all security and setup configuration checks are successfully passed in the section named General in the Admin panel.