Nextcloud is like Dropbox, except that you host, control and own your data. Nextcloud is one of the most amazing open source software available out there. It can do a lot of things. A few of my favourites are:
- File hosting (Images, Videos)
- File syncing
- Auto upload of images/videos from your devices
- Contacts
- Calendars
- Tasks
- Notes
- Talk
And the list goes on. You can find out all the features you can have on Nextcloud HERE. Long story short: Nextcloud is amazing.
And this blog post is about setting up Nextcloud on your own server. I will be using a Digital Ocean Droplet with Ubuntu 16.04.
If you are looking for a cloud provider, I recommend Digital Ocean. They are simply amazing and cheap. You get a 1vCPU, 1GB ram cloud server for just 5$/month. Use my referral link and you will get 10$ and it might help me run this blog for free, without any ads. :)
Let’s get started.
Setting up Nginx Link to heading
We will be using Nginx as our web server. Let’s go ahead and install it
sudo apt-get update
sudo apt install nginx
Once nginx is installed, start it using
sudo systemctl restart nginx
If everything went, nginx should be up and running. You can verify that by visiting your VPS’s public IP in a browser. You can find out your server’s public ip by using the following
curl ifconfig.co
Setting up SSL using Let’s Encrypt Link to heading
We need to make sure that all our traffic from the web browser to the Nextcloud server is encrypted using SSL. Let’s encrypt is an amazing yet free way to get SSL certificates.
sudo apt install letsencrypt
We’ll be using a domain that points to the nextcloud instance you just setup. If you have a domain named
example.com
, then we’ll be usingcloud.example.com
for the Nextcloud instance. In the following examples, I will be usingcloud.example.com
and you should replace it with the domain name you will be using
Next, we will be adding a configuration that is exclusive to Let’s encrypt.
Create a file /etc/nginx/snippets/letsencrypt.conf
with the following content. You can use your editor of choice.
If you are not familiar with any command line text editors, I recommend you use nano.
sudo nano /etc/nginx/snippets/letsencrypt.conf
Paste the following
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
}
Then, press Ctrl+X
and then Y
and press enter. This file will let Let’s Encrypt verify your domain without causing any issues when you redirect all http traffic to https.
We need to create the directory /var/www/letsencrypt
manually too.
sudo mkdir /var/www/letsencrypt
Next, we need to configure our nginx server.
Create the file /etc/nginx/sites-enabled/nextcloud
with the following content
server {
listen 80;
listen [::]:80;
server_name cloud.example.com;
include /etc/nginx/snippets/letsencrypt.conf;
# enforce https
return 301 https://$server_name$request_uri;
}
Don’t forget to replace cloud.example.com
with your domain for nextcloud.
Retrieving the SSL certificates Link to heading
We have the webserver setup ready for us to retrieve the SSL certificates. Let’s go ahead and do that.
Run the following as root
Again, don’t forget to use the correct domain name. Also, give a valid email address. This will be used for alerts regarding renewals and in case you lose your certificates.
sudo letsencrypt certonly --email [email protected] --agree-tos -a webroot --webroot-path=/var/www/letsencrypt/ -d cloud.example.com
Once that is done, if everything went fine, you should see a message saying that it successfully retrieved the certificates.
Let’s encrypt certificates are valid for 90 days only and should be renewed before they expire. Luckily, when we install letsencrypt
package, it adds a cron to renew the certificates. But, we’ll need to reload nginx after the new certificates are retrieved. Let’s add a cron to do that.
Create a file /etc/cron.d/reload-nginx
with the following content
30 2 1 * * root /bin/systemctl reload nginx > /dev/null 2>&1
This will reload the nginx configuration every month so that it will use the newly fetched certificates.
Final Nginx configuration Link to heading
As of now, we have only installed Nginx, but we did not configure it.
Edi the file /etc/nginx/sites-enabled/nextcloud
and paste the following. In one of the previous step, we added a server block in the same file, please note that the same is present in the following snippet. So, you can simply delete /etc/nginx/sites-enabled/nextcloud
and create it again with the following.
upstream php-handler {
server unix:/var/run/php/php7.0-fpm.sock;
}
server {
listen 80;
listen [::]:80;
server_name cloud.example.com;
include /etc/nginx/snippets/letsencrypt.conf;
# enforce https
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name cloud.example.com;
ssl_certificate /etc/letsencrypt/live/cloud.example.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/cloud.example.com/privkey.pem;
# Add headers to serve security related headers
# Before enabling Strict-Transport-Security headers please read into this
# topic first.
# add_header Strict-Transport-Security "max-age=15768000;
# includeSubDomains; preload;";
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Path to the root of your installation
root /var/www/html/nextcloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# The following 2 rules are only needed for the user_webfinger app.
# Uncomment it if you're planning to use this app.
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
# last;
location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
# set max upload size
client_max_body_size 512M;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Uncomment if your server is build with the ngx_pagespeed module
# This module is currently not supported.
#pagespeed off;
location / {
rewrite ^ /index.php$uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
deny all;
}
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
#Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^/(?:updater|ocs-provider)(?:$|/) {
try_files $uri/ =404;
index index.php;
}
# Adding the cache control header for js and css files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js|woff|svg|gif)$ {
try_files $uri /index.php$uri$is_args$args;
add_header Cache-Control "public, max-age=15778463";
# Add headers to serve security related headers (It is intended to
# have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into
# this topic first.
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Optional: Don't log access to assets
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$uri$is_args$args;
# Optional: Don't log access to other assets
access_log off;
}
}
In this snippet, you will have to replace cloud.example.com
with your domain name. You can use this single command to do that
sudo sed -i "s/cloud.example.com/cloud.yourdomain.com/g" /etc/nginx/sites-enabled/nextcloud
That’s it. We are done with the nginx configuration. Please note that, nginx won’t start now because we haven’t installed php yet.
Installing and configuring the database for Nextcloud Link to heading
Nextcloud needs a database server to store the configurations and whatnot. We will be using mariadb
which is a fork of mysql
sudo apt install mariadb-server mariadb-client
This will install the database server and the client tool. Right now, the server does not have a password set. Let’s fix that
sudo mysql_secure_installation
This will ask you few questions. Answer them as follows
Enter current password for root (enter for none): <Enter>
Set root password? [Y/n]: Y
New password: <super-strong-mariadb-root-password>
Re-enter new password: <super-strong-mariadb-root-password>
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: Y
Make sure you replace super-strong-mariadb-root-password
with an actual, strong password.
Now, create a new file /root/.my.cnf
with the following content
[client]
user=root
password=super-strong-mariadb-root-password
This way, you don’t have to enter the mariadb root password every time you want to access the database console.
Restart the database server
sudo systemctl restart mysql.service
Create the database and user for nextcloud Link to heading
If you are logged in as the root user, type mysql
and press enter to get to the mariadb console. If you are not root, you can use mysql -u root -p
and then enter the mysql root password.
We will be creating a database and a database user for our Nextcloud installation
Do as follows. Replace strong_password
with an actual, strong password.
MariaDB [(none)]> create database nextcloud;
MariaDB [(none)]> CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'strong_password';
MariaDB [(none)]> GRANT ALL ON nextcloud.* TO 'nextcloud'@'localhost' IDENTIFIED BY 'strong_password' WITH GRANT OPTION;
MariaDB [(none)]> FLUSH PRIVILEGES;
Keep note of the password you chose there. We will need to update this later when Nextcloud asks us for the password.
Setting up Nextcloud Link to heading
Nextcloud is written in php. So, we need php to be able to run Nextcloud. Let’s install it.
sudo apt install unzip php-fpm php-mbstring php-xmlrpc php-soap php-apcu php-smbclient php-ldap php-redis php-gd php-xml php-intl php-json php-imagick php-mysql php-cli php-mcrypt php-ldap php-zip php-curl
Let’s download the latest stable version of Nextcloud. As of now, 13.01 is the latest version.
cd /tmp
wget https://download.nextcloud.com/server/releases/nextcloud-13.0.1.zip
unzip nextcloud-13.0.1.zip
sudo mv nextcloud /var/www/nextcloud
sudo chown -R www-data:www-data /var/www/nextcloud
And that’s it. As a last step in the configuration, let’s restart nginx so that it reloads the configuration and be ready to rock.
sudo systemctl restart nginx
Now, open http://cloud.yourdomain.com
in your browser, it should redirect to https://cloud.yourdomain.com
and you should be greeted with the Nextcloud final setup screen. It will ask for the database details. Give it as follows
- Database user : nextcloud
- Database pasword : The one you set in the previous step (strong_password in my case)
- Database name : nextcloud
Click on Finish setup.
That’s it. Congratulations. You have successfully installed Nextcloud and is ready to use. If you have a question, leave a comment and I will try to address it as soon as possible :)