How to set up and configure your own personal Nextcloud server
January 11, 2025
In this tutorial, I am going to walk you through how to configure your own personal Nextcloud server, starting from installing Ubuntu server all the way through configuring your router's DNS settings to allow for access to your data from any device, anywhere.
Requirements:
- Linux-compatible device (Raspberry Pi, old laptop, etc.)
- USB Flashdrive with >8GB capacity
- Active ethernet port
- Monitor and keyboard for one-time server setup
- Access to your router (for configuring ports and request routing)
- Access to a domain name with configurable DNS settings (Cloudflare is an inexpensive but reliable option)
Step 1: Server installation and configuration
The first step in getting your own Nextcloud server up and running is to install your server OS of choice on whichever system you are planning to use. I opted to use Ubuntu Server 24.04.1 LTS, as this has several years of guaranteed support from Canonical and using Ubuntu gives us native support for the Nextcloud snap, which greatly simplifies the process of setting up Nextcloud.
Install Ubuntu Server ISO
The ISO file for Ubuntu Server 24.04.1 LTS can be downloaded from Canonical's website. If you are going to run your server on a Raspberry Pi, you will need to make sure you get the ARM-based installer found here. There are many ways to write this ISO to your flashdrive -- I use Fedora Media Writer, but you can also use Rufus, or the Raspberry Pi Imager if you are going to be running your server off of a Pi.
Most of the OS install is fairly straightforward, you just need to pay attention at the stage when you are partitioning your storage drives and remember to expand the LVM group to the full size of the disk. You can read about this on Canonical's Ubuntu Server install page.
As you are installing the OS, you will also be presented with the option to import ssh keys with GitHub or
Launchpad, which allows the OS to be installed with password authentication disabled (which we will want
to do as soon as possible, for security reasons). It's recommended that you do this, because if you don't
cloud-init
will override your PasswordAuthentication setting for sshd and you will have to
manually correct its override.
The final piece of server configuration is to find out what the local IP address is of the server such that we can access it from other devices on the network, as well as assign it a static IP address from the router when we are port forwarding. To find the IP address, you will use
$ ifconfig
The output from ifconfig should contain an entry beginning with enp***
, indicating the active
ethernet connection. In this entry, you should see an IP address labeled inet
in the form
192.168.*.*
, referring to the local IPv4 address of your server. Make note of this IP address
for later.
Once you have completed this initial configuration, you will need a system restart with sudo
reboot
. After you have done this, you can unplug any peripherals from your system as the remainder
of the server setup can be done from another machine on your local network (via ssh).
Configure access permissions and local firewall
After the initial setup of the server with a username, hostname and password, you should be able to connect to it via ssh from another device on your network. Ideally, you would have imported the ssh keys such that no password is required to connect. If you didn't do this, though, it's alright! We'll tackle that now. Because password authentication is generally less secure than ssh, the very first thing we are going to do is generate an ssh key on your device and copy it to the server.
If you didn't copy your ssh keys from GitHub or Launchpad, we will need to use ssh-copy-id
to
do it. If you haven't already generated an ssh key on your system, you can run the following command to do so:
$ ssh-keygen -t rsa -b 4096
This command generates a 4096-bit ssh key with RSA encryption. You can read more about this command from the ssh academy page.
If you had previously generated an ssh key, you would see it in ~/.ssh/id_rsa.pub
Next, we use ssh-copy-id
to send the key to our server. This will require you to connect with
the same username and password that you configured as the administrative account on the server.
$ ssh-copy-id user@hostname
This will create an authorized_keys
file in the ~/.ssh/
directory on the server,
making the connection from your system to the server. If your system username matches the one configured
as admin on the server, you can omit the user@
portion of the command
Once we have done this, we need to disable password authentication. Head to
/etc/ssh/sshd_config
in your editor of choice (and sudo) and look for
PasswordAuthentication
. Change this from yes to no.
It is possible that there are other files which are trying to overwrite your sshd_config
file.
Specifically, check that /etc/ssh/sshd_config.d/*
doesn't have password authentication enabled.
If it does, make sure to set this value to no as well. If you didn't pre-populate an ssh key with GitHub or
Launchpad, cloud-init
tends to add an override here to allow password authentication so you
have some way to access the server remotely. Since you've now added an ssh key to this server, you want to
remove this password access override.
From this point onward, all configuration will be happening on the server (via ssh), *not* on your personal device (unless otherwise specified).
Step 2: Firewall configuration and initial Nextcloud setup
Configuring firewall rules with ufw
ufw
(uncomplicated firewall) is a popular program which allows the user to manage which ports
on their machine are accessible to other devices on their network. Because Nextcloud operates over the
internet (and utilizes a web interface), it will need access to the http and https ports (80 and 443).
Additionally, since we want our server to be accessible from other devices on the local network and enabling
ufw
would protect all unspecified ports, we also need to allow connections via ssh (port 22)
such that we don't kick ourselves off of the server unintentionally.
ufw
is installed (but inactive) by default on Ubuntu, and you can check your status with:
$ sudo ufw status
Once you have verified that ufw
is installed, we will add the rules to allow ssh, http and https:
$ sudo ufw allow ssh
$ sudo ufw allow http
$ sudo ufw allow https
Once we have configured the firewall, we need to enable it and ensure that it is working properly:
$ sudo ufw enable
$ sudo ufw reload
$ sudo ufw status
You should then see an output indicating that your firewall is active and ports 22, 80, and 443 are open.
Initializing Nextcloud admin account
We will be installing the Nextcloud snap, as it is well supported on Ubuntu and contains useful features for generating and restoring server backups.
First we install the Nextcloud snap with
$ sudo snap install nextcloud
Next, we need to initialize an admin account for Nextcloud using the IP address of the server that we took
note of in step 1 (192.168.*.*)
. On your non-server system, type the local IP address of the
server into your web browser and you should see a Nextcloud login page. This is because Nextcloud is
listening on ports 80 and 443 by default, and accessing it over the web (even just over the local network)
creates a connection with http (or https, if there are ssl certificates). The username and password that you
enter here will be the administrator of the server.
We do this now before we port forward for security reasons. If we port forward first, there is the chance
that an outside user could create an admin account before us on the server. Additionally, once we configure
nginx with a reverse proxy it will only handle client requests properly if accessed via the full web domain
(cloud.domainname.com
), not from a local IP address. We will talk more about how nginx works in
step 3.
Modifying Nextcloud server configuration
Once we have created our Nextcloud admin account by accessing the local IP address of the server, we need to change the http and https ports Nextcloud listens on since nginx itself listens on ports 80 and 443.
$ sudo snap set nextcloud ports.http=81 ports.https=444
It is important that you update the list of trusted domains from which you are going to access Nextcloud.
Regardless of whether you will host Nextcloud from a custom domain (cloud.domainname.com
) or from
your router's reverse DNS (yourdomain.tplinkdns.net
) (see step 4), you will need to specify
that address here.
$ sudo snap run nextcloud.occ config:system:set trusted_domains 1 --value=https://cloud.domainname.com
Additionally, since we are using nginx to proxy requests to our Nextcloud server, we will need to add
localhost (127.0.0.1)
to our list of trusted proxies
$ sudo snap run nextcloud.occ config:system:set trusted_proxies 0 --value=127.0.0.1
Step 3: nginx site configuration
After adjusting our Nextcloud ports, we now need to configure nginx to operate as a reverse proxy to appropriately handle client requests and ensure that users are being served the expected content. We will go into the specifics of how and why we are using nginx now.
An introduction to proxies
Forward and reverse proxies are the two primary ways in which device communications over the internet can be monitored and controlled. A forward proxy, commonly referred to simply as a proxy, sits between users on a local network and the outside internet and acts on behalf of the internal clients, forwarding their requests to external servers. The normal workflow of a forward proxy is as follows:
- Internal users make a request to the proxy
- The proxy forwards the request to external servers
- External servers see the proxy as the client
- Proxy returns response back to the internal client
A reverse proxy, on the other hand, sits between external clients and an internal server and acts on behalf of the server to process the incoming requests from external clients. A reverse proxy works as follows:
- External user makes request to what they think is the final server
- Reverse proxy receives the request
- Proxy forward request to appropriate internal server
- Internal server processes request and returns response through the proxy back to the client
Essentially, the biggest difference between forward and reverse proxies is the direction of their protection: forward proxies protect internal clients from external resources, while reverse proxies protect internal servers from external clients.
nginx as a reverse proxy
For our Nextcloud server, we use nginx as a reverse proxy for many reasons:
- Getting SSL certificates for an nginx reverse proxy is simple, and much easier than integrating https into Nextcloud directly
- It's an easy way to redirect all traffic to be SSL-encrypted (with https)
- The reverse proxy allows us to run more than one type of webserver on the same machine, and nginx will redirect the incoming requests to the appropriate backend based on the URL of the content being accessed
Installing and configuring nginx
We begin by installing nginx with
$ sudo apt install nginx
Next, we need to create a site in /etc/nginx/sites-available/
, which we are going to call
cloud
. This will allow us to access Nextcloud from the web using cloud.domainname.com
. Note that creating and modifying this file will require sudo.
server {
server_name cloud.domainname.com; # modify this to match the domain name of your server!
listen 80;
location / {
proxy_pass http://localhost:81;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
fastcgi_request_buffering off;
client_max_body_size 2048m;
}
You must enable your site by creating a link from sites-available to sites-enabled with
$ sudo ln -s /etc/nginx/sites-available/cloud /etc/nginx/sites-enabled/
and ensure that nginx is running with
$ sudo systemctl enable nginx
$ sudo systemctl restart nginx
Step 4: Port forwarding and DNS configuration
Before we can do certbot, we need to forward our http and https ports on the router so that connections outside of the local network have access to your Nextcloud server. This will require you to log into your router, likely through 192.168.1.1 or something similar. The "default gateway" entry in your device network settings will likely point you to the local IP address of your router.
From your router, go the the WAN settings and find port forwarding. You will want to forward ports 80 and 443 on the local IP address corresponding to the device on which your Nextcloud server is running. If your router asks for a choice on which protocol, TCP is just fine.
You will also need to set up reverse DNS here, so that you know the IP address of your house. Many routers
support this feature with something called Dynamic Domain Name System (DDNS), granting you access to the
router with a registered domain name like yourdomain.tplinkdns.net
or
yourdomain.asuscomm.com
. If your router has this feature, set it up. Otherwise, there are 3rd
party services which provide a similar reverse DNS functionality.
If you already have a domain name (which you should, since they are quite useful and inexpensive), you can
use it here to create a CNAME record for cloud.domainname.com
which points to
yourdomain.tplinkdns.net
or whatever your reverse DNS address is. If you don't have a domain
name and don't want to buy one, you can change the hostname in your nginx configuration to be your reverse
DNS address. You are limited to hosting only one webserver per reverse DNS address, though, but it will
work. Domain names are only ~$12/year, so I would recommend acquiring one. I use Cloudflare for
juliancalder.dev
, and it works great.
Step 5: certbot configuration
We use certbot to easily generate signed SSL certificates for our sites, allowing browsers to authenticate over HTTPS thus encrypting data to and from the site. First, we must ensure we have certbot installed with
$ sudo snap install certbot --classic
Note that if you aren't on Ubuntu, you have to make sure you have set up the symlink to allow classic snaps to be in your path -- see the snap documentation here.
Certbot will look for any websites accessible over http and give you a list from which you can choose which
ones you want to generate SSL certificates for. You can run the command below and it should automatically
detect and generate certificates for your site, after which time your site should be securely accessible
at cloud.yourdomain.com
$ sudo certbot --nginx
Step 6 (optional): Importing a Nextcloud backup
The snap version of Nextcloud has a very useful feature enabling you to import a backup of a preexisting server, making it much easier to migrate your server to new hardware (as I did when upgrading from a Raspberry Pi to my new 2700x-powered system). You can import the backup with
$ sudo nextcloud.import /path/to/your/backup
Before you do this, though, it is important that you verify that your backup is somewhere the Nextcloud
snap can read it, and that the backup is owned by root. Snaps are fully sandboxed applications, so they are
self-contained applications which only have access to the files and resources they need to operate. The
Nextcloud snap only has access to the internet and the ability to bind to a port, and importantly does not
have access to the filesystem outside of its own namespace (including /var/snap/nextcloud/
).
Therefore, you need to move your backup to somewhere in the filesystem that Nextcloud will be able to
access it
$ sudo mv /path/to/your/backup /var/snap/nextcloud/common/backup
$ sudo chown -R root:root /var/snap/nextcloud/common/backup
It may take a while to restore this backup depending on the size of the file, but once it is finished you should be able to use your devices syncing to the server without any interruptions. Once your backup has been imported, you can safely delete it (unless you want to hold onto it for some reason).
Conclusion
If you followed the steps above, you should now have an operational Nextcloud server! Depending on your
operating system, there are different Nextcloud desktop applications which will allow you to fairly
seamlessly integrate this cloud backup functionality into your existing desktop ecosystem. If possible,
I would recommend making symlinks from Nextcloud/Documents, Pictures, Music, etc
to your
home directory to take full advantage of the integration.
Note that it could take some time to sync all of your files the first time your server becomes operational.
I've had success syncing all of my files from my primary system, and then using a command like
rsync
to transfer my files to other systems on my home network to take full advantage of
hardware-limited ethernet transfer speeds.
References
This post (and this entire website, honestly) would not have been possible without the help of my brother Oliver (calder.dev). The Nextcloud git repo and forums also provided insight into some specific server configuration commands.