- **Technical difficulty:** ★★★☆☆
- **Server OS covered:** NixOS
**NextCloud** is very versatile and useful *(it can do files, calendars, contacts, and more.)* and it feels familiar to users coming from Google Drive, Dropbox, etc, which can make it a good choice to start your journey towards data sovereignty, and even onboard some friends/family.
However it is not trivial to setup NextCloud in a proper, reliable way. **This guide will attempt to present a nice and reliable way to setup NextCloud:**
- Using [NixOS](https://nixos.org), which is a fascinating Linux distribution where all computer configuration can be done *declaratively*, where you describe how you want your system to function in one or few files — which helps make the setup more **reliable, and clearer to understand.**
- Using [Tailscale](https://tailscale.com), which allows you to **securely access and share access to your home server to/from anywhere in the world**, and it is **super easy to use**
- Using [Caddy](https://caddyserver.com) to **very easily setup HTTPS**, to avoid having to deal with cumbersome self-signed certificates or HTTP warnings *(yuck!)*
- With easy to use [backups](https://borgbackup.org), to avoid data loss over time.
## Prerequisites
- A home server with NixOS installed (Here I am using NixOS 24.05)
- A [Tailscale](https://tailscale.com) account
- An external hard drive or other storage device for backups *(recommended but optional)*
- Basic knowledge of NixOS and Unix in general
## Step 1: Setup Tailscale
First, you need to setup Tailscale on your server. Tailscale is a VPN service that makes it easy to connect your devices and share them with others anywhere in the world.
For this step, I will borrow heavily from [this excellent guide](https://tailscale.com/kb/1096/nixos-minecraft).
1. Add `tailscale` to the `environment.systemPackages` in your `configuration.nix`:
```nix
{ config, pkgs, ... }:
{
# ...Your existing configuration
environment.systemPackages = with pkgs; [
# ...Your existing packages
tailscale # Add this line
];
# ...Your existing configuration
}
```
2. Obtain a **one-time** Tailscale auth key from the [Tailscale admin console](https://login.tailscale.com/admin/settings/keys).
![[Screenshot 2024-07-11 at 20.31.30.png]]
![[Screenshot 2024-07-11 at 20.32.37.png]]
> [!caution] Caution
> Please do not generate a reusable key for this purpose to make the next step secure.
3. Create a new file `tailscale.nix` in the same directory as your `configuration.nix`:
```nix
{ config, pkgs, lib, ... }:
{
# enable the tailscale service
services.tailscale.enable = true;
# Allow our Caddy service to access our Tailscale and automatically fetch/setup our HTTPS certificates
services.tailscale.permitCertUid = "caddy";
# create a oneshot job to authenticate to Tailscale
systemd.services.tailscale-autoconnect = {
description = "Automatic connection to Tailscale";
# make sure tailscale is running before trying to connect to tailscale
after = [ "network-pre.target" "tailscale.service" ];
wants = [ "network-pre.target" "tailscale.service" ];
wantedBy = [ "multi-user.target" ];
# set this service as a oneshot job
serviceConfig.Type = "oneshot";
# have the job run this shell script
script = with pkgs; ''
# wait for tailscaled to settle
sleep 2
# check if we are already authenticated to tailscale
status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)"
if [ $status = "Running" ]; then # if so, then do nothing
exit 0
fi
# otherwise authenticate with tailscale
${tailscale}/bin/tailscale up -authkey <PASTE_YOUR_AUTH_KEY_HERE>
'';
};
}
```
4. Paste the one-time auth key you obtained from the Tailscale admin console in the `tailscale.nix` file, where it says `<PASTE_YOUR_AUTH_KEY_HERE>`.
> [!info] Good to know
> It is generally considered bad practice to store secrets in plain text on a NixOS configuration file, as it can be easily leaked. However, in this case, since we generated a one-time key, **it is less of a concern since the key will be invalidated after we make our first connection to Tailscale.**
> [!caution] Caution
> Please make sure to connect to Tailscale before sharing your configuration file with anyone else, and maybe consider deleting the key from the file after you are done. If you need to use a reusable key, you should consider using a more secure method to store the key, such as using a Nix secret manager.
## Step 2: Setup NextCloud using the AIO docker image
NixOS offers a way to install NextCloud using the `nextcloud` module. However, I found it easier to use the [All-In-One Docker image](https://github.com/nextcloud/all-in-one). This way, you can avoid dealing with certain details like database setup, apache configuration, etc.
1. Enable Docker in your `configuration.nix`:
```nix
{ config, pkgs, ... }:
{
# ...Your existing configuration
virtualisation.docker.enable = true;
virtualisation.oci-containers.backend = "docker";
# ...Your existing configuration
}
```
2. Add a new `nextcloud.nix` file in the same directory as your `configuration.nix` with the following content:
```nix
{ self, config, lib, pkgs, ... }:
{
# Define the Docker service for the NextCloud All-In-One image
virtualisation.oci-containers.containers."nextcloud-aio-mastercontainer" = {
# Use the latest NextCloud All-In-One image
image = "nextcloud/all-in-one:latest";
# Options required by the NextCloud All-In-One image
extraOptions = [
"--init"
"--sig-proxy=false"
];
ports = [
# Forward the Nextcloud admin interface to port 8080
"8080:8080"
# Port 11000 is not explicitly forwarded here. NextCloud spawns new containers that forward on that port.
];
volumes = [
"nextcloud_aio_mastercontainer:/mnt/docker-aio-config"
# This gives the container access to the Docker socket, which gives it the ability to spawn new containers, which is required for NextCloud AIO to work
"/var/run/docker.sock:/var/run/docker.sock:ro"
];
environment = {
# Set the port for the Nextcloud main interface, we will forward port 443 to this port in Caddy
APACHE_PORT="11000";
# Bind to all interfaces
APACHE_IP_BINDING="0.0.0.0";
# We will use Caddy for reverse proxying and HTTPS, so we can skip domain validation
SKIP_DOMAIN_VALIDATION="true";
};
};
}
```
This is essentially the equivalent of running the recommended Nextcloud AIO docker command detailed [here](https://github.com/nextcloud/all-in-one#faq).
## Step 3: Setup Caddy for HTTPS
Nextcloud AIO seems to use HTTP or self-signed HTTPS, which can be cumbersome to deal with. We will use Caddy + Tailscale to automatically obtain and renew HTTPS certificates. Luckily, Tailscale works well with Caddy, so we can make this step easier.
1. Enable [MagicDNS](https://tailscale.com/kb/1081/magicdns#enabling-magicdns) on your [Tailscale admin console](https://login.tailscale.com/admin/dns).
2. Enable HTTPS certificate support on your [Tailscale admin console](https://login.tailscale.com/admin/dns).
3. Add a new `caddy.nix` file in the same directory as your `configuration.nix` with the following content:
```nix
{ config, pkgs, lib, ... }:
{
services.caddy = {
enable = true;
virtualHosts = {
# This will be the location where we will access Nextcloud
"<HOSTNAME>.<TAILNET_NAME>.ts.net:443" = {
# We reverse proxy this to our port 11000 using http
extraConfig = ''
reverse_proxy localhost:11000
'';
};
# This will be the location where we will access Nextcloud's installation and admin panel
"<HOSTNAME>.<TAILNET_NAME>.ts.net:444" = {
# We reverse proxy this to our port 8080. The Nextcloud container will try to use some self-signed certificate, but we can safely ignore it
extraConfig = ''
reverse_proxy https://localhost:8080 {
transport http {
tls_insecure_skip_verify
}
}
'';
};
};
};
}
```
Replace `<HOSTNAME>` with your computer hostname and `<TAILNET_NAME>` with your Tailscale network name. You can find your Tailnet name on your admin console. For example, if my computer's hostname is `home-server` and the tailnet name is `sparrow-pineapplefish`, then the full domain name we will use is `home-server.sparrow-pineapplefish.ts.net`
## Step 3: Import the new configuration files to your main configuration file
Import the new modules in your existing `configuration.nix`:
```nix
{ config, pkgs, ... }:
{
imports = [
# ...Your existing imports
# Add these files which we created
./tailscale.nix
./nextcloud.nix
./caddy.nix
];
# ...Your existing configuration
}
```
## Step 4: Apply the configuration
Run `sudo nixos-rebuild switch` to apply the new configuration. This will install Tailscale, Nextcloud, and Caddy on your system.
You may need to wait a few minutes for all the services to start up.
If you are having issues, you can check the status of the services using `tailscaled.service`, `systemctl status docker-nextcloud-aio-mastercontainer.service`, and `systemctl status caddy.service`.
## Step 5: NextCloud GUI setup
1. Access your Nextcloud admin panel by going to `https://<HOSTNAME>.<TAILNET_NAME>.ts.net:444` in your browser (replace `<HOSTNAME>` and `<TAILNET_NAME>` with your values).
2. The first screen will show you a passphrase for this admin panel. Copy it and save it somewhere safe.
![[aio-passphrase-screen.png]]
3. Continue and login to the admin panel.
4. Next, you will be asked to indicate the domain you will be using to access Nextcloud. Enter `<HOSTNAME>.<TAILNET_NAME>.ts.net`, replacing `<HOSTNAME>` and `<TAILNET_NAME>` with your values. (e.g. `home-server.sparrow-pineapplefish.ts.net`)
5. Then, you will be prompted to install the remaining nextcloud components. Follow the instructions on the screen. It might take several minutes for nextcloud to install everything
6. Once you are done, copy the admin password, which will be shown on the screen. Save it somewhere safe.
![[Screenshot 2024-07-11 at 19.23.52.png]]
8. You can now access your Nextcloud installation by going to `https://<HOSTNAME>.<TAILNET_NAME>.ts.net` in your browser. Login with `admin` and the password you copied in the previous step.
9. *(Optional)* You can create other users from within Nextcloud.
10. You are all set! You can now access your Nextcloud installation from anywhere in the world using the Tailscale, with HTTPS enabled
![[Screenshot 2024-07-11 at 19.24.28.png]]
## Step 5: (Bonus) Setup backups
1. Go to the admin panel of your Nextcloud installation at `https://<HOSTNAME>.<TAILNET_NAME>.ts.net:444`.
2. Scroll down, there will be a backup section. You can set a path where you want to store your backups. This should generally be an external drive or network location mounted on your NixOS system. Once you input the path, follow the instructions on-screen.![[Screenshot 2024-07-11 at 19.24.07.png]]
3. Each time you want to backup, you can go to the admin panel and click on the backup button. Please note that all containers will be stopped during the backup process, so it is recommended to do this during off-peak hours.
> [!info] Learn more
> *Psst!* By the way, this Nextcloud setup uses Borg backup for its backups. If you want to deepen your knowledge of this handy backup tool, check out this guide: [[Making backups with Borg]]
## Q&A
### Where is my data stored?
Under this setup, data will be stored in docker volumes. To find out, run this command to see the volumes.
```
$ sudo docker volume ls
DRIVER VOLUME NAME
local nextcloud_aio_apache
local nextcloud_aio_backup_cache
local nextcloud_aio_database
local nextcloud_aio_database_dump
local nextcloud_aio_elasticsearch
local nextcloud_aio_mastercontainer
local nextcloud_aio_nextcloud
local nextcloud_aio_nextcloud_data
local nextcloud_aio_redis
```
Each volume has a separate use in NextCloud. If you want to see where the files uploaded to NextCloud are stored in, you are looking for the `nextcloud_aio_nextcloud_data` volume.
To be able to see those files from your system, run:
```
$ sudo docker volume inspect nextcloud_aio_nextcloud_data
```
This will give you some information about the volume, including where it is mounted in your system. Likely that will be `/var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data`
### Things went wrong, how do I check the status of things?
**Checking the status of Tailscale:**
```
$ systemctl status tailscaled.service
```
**Checking the status of Caddy:**
```
$ systemctl status caddy.service
```
**Checking the status of NextCloud:**
```
$ systemctl status docker-nextcloud-aio-mastercontainer.service
```
### Other questions?
Please feel free to reach out to me! You can find various contact options here: https://danieldaquino.me