Interested in the convenience of the cloud, but want meaningful ownership of your data? Looking for a starter project to get into Linux systems administration or work with the popular LAMP stack? Follow along to learn how to setup your own Nextcloud server - manually - from soup to nuts.
Based on an excellent video tutorial by Jacob from nerdonthestreet.com
Prerequisites:
You'll need a few things to get started:
- Your own domain
- A Linux server
- A password manager (seriously, you'll be creating a gazillion different username/password combinations very soon)
- A desire to learn
- Recommended: An SFTP client like Transmit (allows you to use nice GUI text editors like Atom or VS Code)
Notes:
- All commands listed here are to be run as root unless instructed otherwise
- This guide assumes you are using a Debian-based Linux distribution on your server, but that isn't required. Just make sure you know the equivalent commands for actions like package management on your preferred distro; for example, replace
apt
withyum
on CentOS or RHEL.
Step 0: Housekeeping
Find your server's IP address
If you're using a VPS, your server's IP address should be listed in your hosting provider's admin console. If not, such as if you're using a physical server on-prem, run the following:
sudo -u www-data curl ifconfig.me
This pings ifconfig.me, a cool website that tells you your public IP address, along with a bunch of other stuff.
Why the
sudo -u...
prepending thecurl
command? Why not just runcurl
?
Great question!
As a general rule, I don't like to download code, even that which is likely harmless, while elevated. This command runs curl
as the www-data
user, normally used only by apps like web servers (including apache
, the server we'll be using today). Not only is this user unprivileged, its' shell access is disabled (directs to /sbin/nologin/
). This means: the only way to run commands as this user is to actually run them using sudo -u www-data <command-to-run>
while logged in as a privileged user (in this case, root).
Update your server:
The packages on your server probably aren't all up to date. Let's fix that.
Login as root...
ssh root@<your-server-ip>
...and update all installed packages:
apt update && apt upgrade -y
Great, your packages are all up to date.
Go ahead and reboot your server now, in case any of them are kernelspace updates:
reboot now
Point your domain at your server
We need to make sure traffic meant for your Nextcloud server actually reaches your it!
Open your domain admin panel and create a new A
record. Point it at your server's IP address.
In the hostname
section, type a subdomain you want to use (if any). Otherwise, if you want to use the entire domain for your Nextcloud instance (not recommended), type an @
.
Note: Depending on your DNS provider, your domain settings may take a while to propagate. Don't be surprised if attempting to connect to your server via its domain doesn't work for a few minutes to a few hours.
Step 1: Install required packages
Our installation of Nextcloud will require the following components:
- Web server
- Apache Web server
- Certbot (for TLS)
- Database server
- MariaDB, a MySQL-compatible database software
- PHP
- Runtime & support libraries for the PHP language, which Nextcloud is written in
- Utilities
- wget (for easily downloading files from command line)
- unzip (self explanatory)
Login to your server as root:
ssh root@subdomain.domain.com
Now, run the following commands to install the necessary packages:
Apache:
apt install apache2
apt install python-certbot-apache
MariaDB:
apt install mariadb-server
PHP:
apt install php libapache2-mod-php php-mysql php-gd php-json php-curl
apt install php-mbstring php-intl php-imagick php-xml php-zip php-apcu
Utilities
apt install wget unzip
Step 2: Setup Apache web server
Start Apache 2:
systemctl start apache2
Enable the Apache daemon (so Apache starts whenever your machine does):
systemctl enable apache2
Add your domain name to Apache's configuration files
On your server, edit the file /etc/apache2/sites-available/000-default.conf
in your preferred text editor.
Find the line:
#ServerName www.example.com
And change it to:
subdomain.yourdomain.com
, replacing subdomain
and yourdomain
with your subdomain/domain. Delete the #
to uncomment the line.
Now restart Apache to apply the changes:
systemctl restart apache2
Step 3: Setup TLS (HTTPS)
We'll use cerbot
to obtain a free TLS certificate from LetsEncrypt. You installed it earlier as part of the python-certbot-apache
package. Time to set that up.
Run Certbot:
certbot --apache
Certbot will ask you to enter an email address for your site's administration:
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):
You can safely do this; don't worry, it isn't public. It'll also ask you to agree to the terms:
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel:
Choose A
to agree to the terms.
It'll then ask:
Which names would you like to activate HTTPS for?
-------------------------------------------------------------------------------
1: subdomain.yourdomain.com
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
Choose:
1
You should now see the following:
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver
configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
Choose 2: Redirect
. This will ensure that all connections to your server are done securely over https
.
Now restart Apache to apply your settings:
systemctl restart apache2
Great! Basic TLS is setup on your server!
Harden TLS
Before we go any further, we'll harden the TLS configuration. This is your own personal cloud, storing your sensitive data, after all.
We'll enable HSTS
(HTTP Strict Transport Security) by using a feature of Apache called mod headers
. This forces clients connecting to use an encrypted HTTPS connection, whether or not they requested it, reducing the possibility for attackers to conduct tls stripping attacks.
Edit the file: /etc/apache2/sites-enabled/000-default-le-ssl.conf
Below ServerName
, add the following IfModule
:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security “max-age=15552000; includeSubDomains; preload”
</IfModule>
Sweet, HSTS is enabled! Your config file should look something like this:
...
ServerName subdomain.yourdomain.com
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
</IfModule>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
...
Now that HSTS is enabled, run the following command to apply the changes:
a2enmod headers
This makes your Nextcloud server tell all web browsers/clients connecting to it:
"Hey, I'm an
https
only server! If you see me accepting plaintexthttp
requests in the future, don't connect! You're proably talking to a different server run by someone nefarious!"
Step 4: Install the database server
This is where the password manager comes in. Remembering long passwords that you're probably never going to type in again would be absurdity, so we'll ask our password manager to help us with that.
Generate and store a nice, long password, with no special characters. This will be the root password for our mariadb
database server.
Got it? Great!
Now, run the following command to install MariaDB:
mysql_secure_installation
You'll be asked to set the root password for MariaDB. Generate one in your password manager, then type it in.
You'll be asked a few more questions:
Remove anonymous users? [Y/n]
Answer y
, you don't need them
Disallow root login remotely? [Y/n]
Answer y
. Don't worry, this is just for the database and won't mess with your ssh
configuration.
Remove test database and access to it? [Y/n]
Answer y
, you don't need the test database.
Reload privilege tables now? [Y/n]
Answer y
to apply the changes immediately.
You should now see the following:
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Great! Your database server is now installed!
Step 5: Setup the database
Now that you've installed and secured MariaDB, the next step is to use it to setup a database for your Nextcloud server.
Start a MariaDB session by typing: mariadb
You'll see a new screen with a different prompt like this:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 30
Server version: 10.1.38-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
You're about to actually appreciate your caps lock key, for once in your life.
Using the following command, create a database called nextcloud_db
.
CREATE DATABASE nextcloud_db;
Now you'll need to create a MariaDB user to access this database. We'll call this user nextcloud
.
Your password manager is, once again, your best friend here. Have it generate and store another long password with no special characters.
Got one? Great, proceed.
To create the new user, use the following command:
CREATE USER nextcloud IDENTIFIED BY 'your-password-here';
Now you have to give this nextcloud
user access to the nextcloud_db
database.
Do this with the following commands:
GRANT USAGE ON nextcloud_db.* TO nextcloud@localhost IDENTIFIED BY 'password-from-last-command';
GRANT ALL privileges ON nextcloud_db.* TO nextcloud@localhost;
Kawabunga, you've given the database user the permissions it needs!
Now let's make sure the changes you made are applied with this command:
FLUSH PRIVILEGES;
Now, exit mariadb
. I promise it's easier than exiting vim!
Just type:quit;
That wasn't so tough now, was it?
Step 6: Install Nextcloud
All the necessary packages are installed. The web and database servers are setup. You've secured the installation and configured TLS. Yes, it's finally time. Let's install Nextcloud on your server!
Install files (source code)
Head over to the Nextcloud download page. Copy that big shiny "Download Nextcloud" link.
Now, head back to your ssh session. Download the latest release of Nextcloud on your server from that link you just copied:
sudo -u www-data wget https://download.nextcloud.com/server/releases/nextcloud-16.0.0.zip
Extract the download...
unzip nextcloud-16.0.0.zip
...and copy all the files recursively in the resulting nextcloud
folder into /var/www/html
.
cp -rf ./nextcloud/. /var/www/html
Note the .
after nextcloud/.
. Don't omit this! Adding the period after the /
tells the OS to copy all the files in this directory including the hidden ones - which we need! Specifically, the .htaccess
and .user.ini
files, which are used for Apache and PHP configuration. We'll get into this later.
Change Permissions
Great, you've gotten the goods Nextcloud needs to run, and put them in the right bin. Now we need to give your web server access to them.
Apache runs as a special Linux user, www-data
. To let it access the application files you just downloaded, you need to give this user recursive ownership of the directory we just put them in, /var/www/html
.
We can do this with the following command:
chown -R www-data:www-data /var/www/html/.
Once again - take care not to omit the .
at the end! We want to change ownership of all the files here, not just the visible ones!
Ha-zah! You've installed the Nextcloud package!
Choose where to store your files
We're almost ready to visit our web GUI to setup our server - but we need one more thing - a place to store our data!
You really can put this anywhere you like; though I advise against putting it in /var/www/html
for security reasons. For this example, we'll make a dedicated directory in the root of our drive, called nextcloud-data
.
This one's easy. Just make the directory, wherever you want...
mkdir /nextcloud-data
...and give ownership of it to the www-data
user so Apache (Nextcloud) can access it:
chown www-data:www-data /nextcloud-data
Now, restart Apache to make sure all our settings are applied:
systemctl restart apache2
7. GUI Setup
Now comes the fun part - seeing your Nextcloud instance actually work for the first time!
Open your preferred web browser and go to your newly-created Nextcloud server's domain:
Create an admin account. Note: This is just the admin account; you won't be using it for day-to-day activities. You can call it whatever you want. In the spirit of Linux, let's call this one: root
.
In the "Data Folder" box, type the path of the directory you chose to hold your data; in this case, /nextcloud-data
.
Scroll down. You'll see boxes for database user, database password, and database name.
Recall from earlier how we setup a database user nextcloud
, and a database, nextcloud_db
. Input these accordingly, along with the password you created. Leave the database location as localhost
, and ignore the instructions to specify a port.
Now click Finish. If all goes well, the page will lag for a second, like this...
...and in a few moments, will show you a nice splash screen, like this:
Congratulations! You have a basic, running Nextcloud server!
Step 8: Cleaning up
Your server is now technically operational - but don't stop here!
There's still a few steps to go to make sure your Nextcloud server operates at peak performance.
Hand over control of Apache to Nextcloud
Remember those two hidden files we paid such meticulous attention to earlier - .htaccess
and .user.ini
? This is where they come in.
.htaccess
, for example, is supposed to control how our Apache web server operates. Right now, our server is ignoring both of these files. Let's fix that.
Edit the file /etc/apache2/sites-enabled/000-default-le-ssl.conf
(the same one where enabled HSTS and mod headers).
Underneath the IfModule
we created earlier, add the following Directory statement:
<Directory /var/www/html/>
Options +FollowSymlinks
AllowOverride All
</Directory>
Your settings should now look like this:
...
ServerName subdomain.yourdomain.com
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
</IfModule>
<Directory /var/www/html/>
Options +FollowSymlinks
AllowOverride All
</Directory>
...
We've now told Apache to use the settings from the .htaccess
file located in /var/www/html/
, essentially handing off control of it to the Nextcloud application.
Set reasonable file operation limits
Right now, php
has very little memory to work with. So little, in fact, that it's practically useless. Let's give it a little more.
PHP's settings are controlled by the file /etc/php/7.2/apache2/php.ini
.
Edit it, and find the following lines:
PHP memory limit: (memory_limit
)
Set to: memory_limit = 512M
Largest size of a POST request (post_max_size
):
Set to:
post_max_size = 512M
Maximum file upload size: (upload_max_filesize
):
Set to: upload_max_filesize = 512M
Apply the configuration by restarting apache:
systemctl restart apache2
Great - PHP now has a reasonable amount of memory to work with!
Can I set these limits higher?
Great question!
While you can absolutely set higher limits than those shown in this tutorial, please note that the maximum memory_limit
you can set here is (predictably) dependent on your system's available RAM.
Setup Memory Caching
Memory caching increases the performance and responsiveness of your Nextcloud server by minimizing the amount of similar operations that have to be performed.
For this installation, we'll use the PHP extension php-apcu
that we installed earlier for our memcache.
Edit /var/www/html/config/config.php
Add the following line at the bottom of the configuration lines:
'memcache.local’ => ‘\OC\Memcache\APCu’,
Save the file end exit the text editor. Now edit the file:
/etc/php/7.2/apache2/php.ini
Find the lines:
opcache.enable
opcache.enable_cli
opcache.interned_strings_buffer
opcache.memory_consumption
opcache.max_accelerated_files
opcache.save_comments
opcache.revalidate_freq
Uncomment all of them (delete the semicolons[;
] in front of them).
Now, set them to the following values:
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1
Save the file and exit the editor.
Now, restart Apache to apply the changes:
systemctl restart apache2
Your memcache is setup!
Your Nextcloud server should now be nice and zippy!
Fix improperly displayed unicode characters
By default, MySQL
/mariadb
does not support 4-byte character strings. This means emojis and some other unicode characters won't display properly. That could be anything from mildly annoying to totally debilitating, depending on the language your Nextcloud server is set to. Note: I highly advise against skipping this step. All my Nextcloud servers are set to US English, and I still experienced this issue prior to making this change.
First, let's put Nextcloud into maintenance mode to avoid borking the database as we work on it. We do this using the occ
command, run as the user www-data
, because occ
is located in /var/www/html
, which we gave www-data
ownership of earlier.
We can do this with the following command:
sudo -u www-data php /var/www/html/occ maintenance:mode --on
You can verify that your server is indeed in maintenance mode by attempting to access it from your web browser. You should see this:
Now that our server is in maintenance mode, we can get to work.
Open a MariaDB
session with the mariadb
command:
root@testcloud:~# mariadb
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 192
Server version: 10.1.38-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
We now need to make a change to MariaDB's InnoDB settings to support these 4-byte characters.
Run the following command to alter the character set in our nextcloud_db
database to utf8mb4
:
ALTER DATABASE nextcloud_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
Now change MariaDB's InnoDB settings to Nextcloud's recommended values with the following commands:
SET GLOBAL innodb_file_format=barracuda;
SET GLOBAL innodb_file_per_table=on;
SET GLOBAL innodb_large_prefix=on;
Now quit MariaDB:
quit;
We've changed our MariaDB settings to be compatible with the changes we need to make to our Nextcloud database. Now we need to let Nextcloud know about these changes so it can apply them.
Run the following command to do so:
sudo -u www-data php /var/www/html/occ config:system:set mysql.utf8mb4 --type boolean --value="true"
Now that we've told Nextcloud about the changes to our database, we'll need to tell it to run the data conversions to apply them. We'll use the maintenance:repair
occ
command to do this.
sudo -u www-data php /var/www/html/occ maintenance:repair
It'll run a conversion and spit out lots of text (hopefully with no errors :)
Now that that's done, take your Nextcloud server out of maintenance mode with the following command:
sudo -u www-data php /var/www/html/occ maintenance:mode --off
Yahoo! Bing! Google! Your Nextcloud instance now supports unicode characters and will render them properly!
Step 9: Finishing touches
You actually could stop here if you wanted. Your server is fully setup and ready to roll. In fact, if you visit your server's Security & setup warnings section (subdomain.yourdomain.com/index.php/settings/admin/overview), you'll see a nice, friendly, green checkmark, letting you know everything's in good working order:
All the work we did in the that last 8 steps paid off - as you can see, no warnings or errors here!
But best practices are...the best practices...so let's follow some best practices! Say that 5 times fast!
Create a standard user account
As I alluded to earlier - running in a permanently elevated context is, generally speaking, a bad idea. If you were to run this way, and your credentials were ever stolen, the thieves would have unfettered, administrative access to your server in its' entirety. We don't want that!
Instead, let's make an unprivileged account for day-to-day use. Log into your Nextcloud instance in a web browser, click the profile icon in the top-right corner, and click the Users button.
You can figure the rest of this step out from here. I have faith in you.
Connect your email server
This is an optional step that may or may not apply to you. If you're using your server in a small, personal, single-user setting, you can ignore it. Otherwise, you should set this up. This allows users to self-reset their forgotten passwords, receive sharing notifications via email, and more.
From the Admin account, to Settings > Basic Settings > Email server.
Note that Nextcloud doesn't include its' own mail server; you'll need an external mail account that supports SMTP.
Probably goes without saying, but don't use your personal email for this! Make a service account on your domain like nextcloud-server@your-domain.com
.
The rest of this step is self-explanatory.
Step 10: Poke around!
This is the fun part! Add some apps to extend your Nextcloud experience!
If you've ever used Wordpress plugins, you'll find yourself right at home. The Nextcloud apps are generally of higher quality than most Wordpress plugins, however, and are almost all free & open source software.
The easiest way to add these is through the Apps interface in the admin account, right next to the Settings button in the corner menu you clicked earlier.
Want a web calendar interface for the CalDAV server built into your Nextcloud? Here you go!
Care to customize your colors, add a privacy policy, switch up your favicon or change the logo on your interface to match your company's? Go for it in the theming settings!
How about a nice web GUI for managing your contacts on the included CardDAV server? Nextcloud has you covered!
You get the idea. Running this server for your organization with an existing LDAP/AD server that you'd like to use for user management? There's an app for that!
Conclusion
That's it for today, folks. Where you go from here is up to you.
I hope you learned something :)
-Noah