Build Guide: Nextcloud Server
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.
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)
- 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
yumon 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.
sudo -u...prepending the
curlcommand? Why not just run
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...
...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:
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.
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
- Runtime & support libraries for the PHP language, which Nextcloud is written in
- wget (for easily downloading files from command line)
- unzip (self explanatory)
Login to your server as root:
Now, run the following commands to install the necessary packages:
apt install apache2 apt install python-certbot-apache
apt install mariadb-server
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
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:
And change it to:
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)
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.
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:
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):
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):
2: Redirect. This will ensure that all connections to your server are done securely over
Now restart Apache to apply your settings:
systemctl restart apache2
Great! Basic TLS is setup on your server!
Before we go any further, we'll harden the TLS configuration. This is your own personal cloud, storing your sensitive data, after all.
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:
ServerName, add the following
<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:
This makes your Nextcloud server tell all web browsers/clients connecting to it:
"Hey, I'm an
httpsonly server! If you see me accepting plaintext
httprequests 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:
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]
y, you don't need them
Disallow root login remotely? [Y/n]
y. Don't worry, this is just for the database and won't mess with your
Remove test database and access to it? [Y/n]
y, you don't need the test database.
Reload privilege tables now? [Y/n]
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:
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
CREATE DATABASE nextcloud_db;
Now you'll need to create a MariaDB user to access this database. We'll call this user
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
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:
mariadb. I promise it's easier than exiting vim!
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...
...and copy all the files recursively in the resulting
nextcloud folder into
cp -rf ./nextcloud/. /var/www/html
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
.user.ini files, which are used for Apache and PHP configuration. We'll get into this later.
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,
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
This one's easy. Just make the directory, wherever you want...
...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:
In the "Data Folder" box, type the path of the directory you chose to hold your data; in this case,
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 -
.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).
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
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
Edit it, and find the following lines:
PHP memory limit: (
memory_limit = 512M
Largest size of a POST request (
post_max_size = 512M
Maximum file upload size: (
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?
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.
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:
Find the lines:
Uncomment all of them (delete the semicolons[
;] in front of them).
Now, set them to the following values:
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
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
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.
MariaDB session with the
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
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:
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
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
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!
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!
That's it for today, folks. Where you go from here is up to you.
I hope you learned something :)