DEV Community

Cover image for Nextcloud on Raspberry Pi - Fedora + Podman Quadlets
Patrice Ferlet
Patrice Ferlet

Posted on

Nextcloud on Raspberry Pi - Fedora + Podman Quadlets

Let me show you how to install Nextcloud on a Raspberry Pi using Fedora, Podman and Quadlet (containers). It's simple !

What is Quadlet

A Quadlet is a way to create a service (with systemd) from a container. It uses Podman, a container engine. As it is OCI complient, the Docker images are compatibles with Podman.

Don't be impressed by the number of command and configuration lines in this article. The "Quadlet" part is very simple. Only the configurations required for Nginx, Nextcloud and the creation of a mount point for the hard disk are a little more tricky. But that's not Podman's fault.

Quadlet management is now integrated inside Podman. If you've got Podman, you can create Quadlets 😄

Podman is installed by default on Fedora 41. It works with amd64 and aarm64 CPU. So it works on Raspberry Pi too.

Quadlets are easy to write, easy to maintain, and it helps a lot to manage services as if they are real services.

What is Nextcloud

Nextcloud is a complete cloud service providing file shares, online office tools, messaging with visio-conference, and many others tools. It could be used as NAS as it provides a WebDav sharing service per user.

It works great on Raspberry Pi v4.

The prerequisites

You need to install Fedora 41 aarm64 version on your Raspberry (actually, it should work on others distributions, but I love Fedora).

Because I'm using Nextcloud to store files, I mounted a 2To USB SSD disk on the blue USB port (USB 3). I will show you how to make it available at boot time. If you want to use an internal directory, it's up to you. But, keep in mind that your SD card will not support read/write for a long time. It's recommended to use an external hard drive.

Then you'll need an SSH connection and root access.

Mounting the drive.

It's optional, you'll need this part only if you use an external hard drive.

First, please, format the partition to EXT4 or BTRFS. It's important in order not having problems with labeling and file authorizations. On my side, I only used the “Format drive” option in the file explorer on my personal computer.

Then, plug the drive on your Raspberry Pi (use the blue port if possible, as it is USB 3.0 and is faster).

You should now be able to access the drive. Use dmesg command line to check if the hard drive is detected and the device name (something like /dev/sda or /dev/sdb)

We need to mount it somewhere. I choose /mnt/nas.

Create a directory where to mount the drive :

sudo mkdir /mnt/nas
Enter fullscreen mode Exit fullscreen mode

Then, find the UUID of the partition on your hard drive. (Actually, we can mount the drive with its device path, but it may change later. It's safer to use the partition UUID)

My hard drive is detected as /dev/sda:

sudo lsblk --fs
NAME        FSTYPE FSVER LABEL         UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda
└─sda1      ext4   1.0   NAS           2ce801a3-4911-4d55-ad17-44b1c91d6391    1,7T     0% /mnt/nas
mmcblk1
├─mmcblk1p1 vfat   FAT32               22A3-9756                             562,3M     6% /boot/efi
├─mmcblk1p2 ext4   1.0                 c8e29478-8fe9-49bc-90cd-e816cbe753b8    579M    34% /boot
└─mmcblk1p3 btrfs        fedora_fedora 66ed970b-b91a-483e-9b82-b10fdfc12ea7   51,9G    10% /var/lib/containers/storage/overlay
                                                                                           /home
                                                                                           /
zram0                                                                                      [SWAP]
Enter fullscreen mode Exit fullscreen mode

I keep the UUID and I added this line in /etc/fstab :

UUID=2ce801a3-4911-4d55-ad17-44b1c91d6391 /mnt/nas      ext4    defaults        0 0
Enter fullscreen mode Exit fullscreen mode

Now, typing mount -a I can see that my hard drive is mounted in /mnt/nas:

mount | grep sda1
/dev/sda1 on /mnt/nas type ext4 (rw,relatime,seclabel,stripe=256)
Enter fullscreen mode Exit fullscreen mode

It's OK. Now, each time the Raspberry restart, the external disk is mounted at the right place.

Prepare TLS/SSL certificate

Because I want to use SSL (HTTPS), I will create the certificate. Everything is saved in the SSD hard drive to be able to reinstall everything without losing my mind.

You need to know the hostname you use to contact your Raspberry. In my case, my router applies .home on the network devices. As I set up my Rasbperry to be named "nas", the hostname is "nas.home". Be sure to be able to contact it (ping it)

# change these information
HOSTNAME=nas
DOMAIN=.home
O=Home
COUNTRY=FR
STATE=France
LOC=Laval

# to name your machine, DO NOT INCLUDE DOMAIN
hostnamectl hostname $HOSTNAME

# generate certificates
mkdir -p /mnt/nas/nginx/ssl

# 3650 days = 10 years
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout /mnt/nas/ssl/${HOSTNAME}${DOMAIN}.key \
  -out /mnt/nas/ssl/${HOSTNAME}${DOMAIN}.crt \
  -subj "/C=${COUNTRY}/ST=${STATE}/L=${LOCATION}/O=${O}/CN=${HOSTNAME}${DOMAIN}"
Enter fullscreen mode Exit fullscreen mode

The key and the certificate are now created.

You should backup the private key.

Nginx configuration

As we will use Nginx as a container, we need to make a reverse proxy to the container name. As we will name the Nextcloud container "Nextcloud", it's pretty simple. Replace the line I indicate if you have another name to use as server name.

Edit and save it in /mnt/nas/nginx/conf.d/nextcloud.conf:

server {
    listen [::]:443 ssl;
    listen 443 ssl;
    server_name nas.home; # replace this

    ssl_certificate /etc/nginx/ssl/nas.home.crt; # replace this
    ssl_certificate_key /etc/nginx/ssl/nas.home.key; # replace this

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    client_max_body_size 8G;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        # to the "nextcloud" container
        proxy_pass http://nexcloud:80;
        proxy_set_header Host $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;
        proxy_buffering off;
    }
}

server {
    listen [::]:80;
    listen 80;
    server_name nas.home; # replace this

    # Redirect HTTP to HTTPS
    return 301 https://$host$request_uri;
}
Enter fullscreen mode Exit fullscreen mode

Create the Quadlets

It's now time to create our services. Instead of installing everything by service, we will use containers.

First, I need a "network". It's only to make all my containers communicating in the same namespace. This way, I don't have to publish unnecessary ports to the host. I only require the nginx ports.

touch /etc/containers/systemd/nextcloud.network
Enter fullscreen mode Exit fullscreen mode

The file can be empty, the default values are OK.

I then create 3 containers, but you can avoid the "valkey" container if you don't want to use it (it's a recommendation, it works without)

The "valkey" Quadlet is defined like this:

# /etc/containers/systemd/valkey.container
[Container]
Image=docker.io/valkey/valkey
ContainerName=valkey
Network=nexcloud.network


[Service]
Restart=always

[Install]
WantedBy=default.target
Enter fullscreen mode Exit fullscreen mode

The Nextcloud Quadlet is defined this way:

[Container]
Image=docker.io/nextcloud:30
ContainerName=nextcloud
Network=nexcloud.network

# where to store data
Volume=/mnt/nas/nextcloud:/var/www/html:z

# wait for valkey
Requires=valkey.container
After=valkey.container

[Service]
Restart=always

[Install]
WantedBy=default.target
Enter fullscreen mode Exit fullscreen mode

Note that the Nextcloud container should start only if Valkey is started.

Then, the nginx container:

[Container]
Image=docker.io/nginx:latest
ContainerName=nginx
Network=nexcloud.network
# export 80 and 443 ports to the network
Port=443:443
Port=80:80
# mount certificates and configuration
Volume=/mnt/nas/nginx/ssl:/etc/nginx/ssl:z
Volume=/mnt/nas/nginx/conf.d:/etc/nginx/conf.d:z
Enter fullscreen mode Exit fullscreen mode

After having created these 3 files, you can reload systemd and start containers :

systemctl daemon-reload
systemctl start valkey
systemctl start nextcloud
systemctl start nginx
Enter fullscreen mode Exit fullscreen mode

The ":z" suffix is required on Red Hat based distribution to set SeLinux labels to allow the write access. Debian based distribution ignores the prefix. So, keep it, there is no problem.

You'll probably need to open firewall ports:

firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Wait! There is something more to do! Do not navigate to Nextcloud yet!

Last configuration

Now that Nextcloud has started, you should have /mnt/nas/nextcloud/config/config.php file. You need to alter some points.

First, force HTTPS and hostname:

  'overwrite.cli.url' => 'https://nas.home', // your FQDN
  'overwritehost' => 'nas.home', // same, your FQDN
  'overwriteprotocol' => 'https',
Enter fullscreen mode Exit fullscreen mode

And, if you want to use Vakey, as I do, add this:

  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'redis' =>
  array(
    'host' => 'valkey', // this is the container name
    'port' => 6379,
  ),
Enter fullscreen mode Exit fullscreen mode

And now you can navigate to https://nas.home (use your own domain)

Precision

It is possible to not use Nginx container and use the Nginx package. But, on Red Hat based distribution, SELinux will refuse to leave Nginx to proxy pass to a container. If you decided to use nginx package:

  • change the Nextcloud container to bind 8080:80, or whatever you want
  • change nginx configuration to point on localhost:8080 instead of nextcloud:80
  • allow the HTTP connection from nginx to container:
setsebool -P httpd_can_network_connect on
Enter fullscreen mode Exit fullscreen mode

Restart nginx, nginx -s reload and it's OK.

Conclusion

You probably think it's a bit complex, but actually it's not.

Check one more time, the Quadlet section is very simple. The only "hard" topics are the hard drive mount point automation and the Nginx and Nextcloud configuration. Everything that is related to Podman and Quadlet was simple.

Also, I propose Valkey (a Redis fork by Linux Foundation), but you can avoid it.

Quadlet are very easy to use. As soon as you understand the syntax, you'll never use "compose" file anymore for long-term services.

Top comments (0)