Post

ENG | Working with podman containers, setting up Nextcloud as an example

ENG | Working with podman containers, setting up Nextcloud as an example

Work in progress

As of 2023-07-02 this article is work in progress. There are no screenshots and Nginx Proxy Manager is undocummented.

TODO: add .env file(s) to compose file

Introduction

This article describes how to use podman containers and nextcloud.

It’s demonstrated on clean install of Debian 12 Bookworm. You may want to skip Debian setup. Also, because it shows how to use podman in general (well, how I use podman as a noob) you may wan’t to skip NextCloud specific parts as well.

Debian: First things to do after install

This part was merged to Debian and Zimaboard install notes. Where you can ignore parts related to fixing grub bootloader and fstab.

Podman: Installing nextcloud using containers.

Install podman-compose if you don’t have it, docker-compose is an alternative.

Create docker directory for your project (optional).

Copy&paste these files and change passwords

Hint: Replace passwords and don’t use the most popular passwords of 2023

1
cat ~/docker/.env
1
2
3
4
5
TIMEZONE=Europe/Prague
NC_MYSQL_USER=nextcloud
NC_MYSQL_DATABASE=nextcloud
NC_MYSQL_PASSWORD=NcMySqlPassword123
NC_MYSQL_ROOT_PASSWORD=NcMySqlRootPassword123
1
cat ~/docker/docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
version: 3.5

volumes:

  nextcloud-database:
  nextcloud-config:
  nextcloud-data:

services:

  nextcloud-db:
    image: lscr.io/linuxserver/mariadb:latest
    container_name: nextcloud-mariadb
    restart: unless-stopped
    environment:
      - PUID=1000
      - TZ=${TIMEZONE}
      - MYSQL_DATABASE=${NC_MYSQL_DATABASE}
      - MYSQL_USER=${NC_MYSQL_USER}
      - MYSQL_PASSWORD=${NC_MYSQL_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${NC_MYSQL_ROOT_PASSWORD}
    volumes:
      - nextcloud-database:/config

  nextcloud-app:
    # This is bad idea
    image: lscr.io/linuxserver/nextcloud:latest    
    container_name: nextcloud-app
    environment:
      - PUID=1000
      - PGID=100
      - TZ=${TIMEZONE}
    volumes:
      - nextcloud-config:/config
      - nextcloud-data:/data
    restart: unless-stopped
    ports:
      - 8081:80
    depends_on:
      - nextcloud-db

Now pull images (this will download roughly 350MB), podman-compose must be executed in a directory with docker-compose.yml file

1
podman-compose pull

Then start the podman as a foreground process to see some possible errors. Running it for the first time may take tens seconds. Next time use podman-compose up -d or use systemctl service to start it automatically. More on that later.

1
2
cd docker
podman-compose up

NOTE: data are saved in ~/.local/share/containers/storage/volumes

Nextcloud: Essential setup

Log in using web interface (running on port 8081)

Click on Storage&Database 🔽

Select MySQL/MariaDB and fill data corresponding to your ~/docker/.env file.

TODO: screenshots

Podman: Starting containers on the next boot

Shutdown containers if they are running

1
cd ~/docker && podman-compose down

Create file systemd unit file for user (replace pavel by your username)

1
2
3
mkdir -p ~/.config/systemd/user/
cd !:2
nano podman-compose.service
1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Podman Compose Service
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/pavel/docker
ExecStart=/usr/bin/podman-compose -f docker-compose.yml up -d
ExecStop=/usr/bin/podman-compose -f docker-compose.yml down

[Install]
WantedBy=default.target

Enable and start podman-compose service. From this moment, it will start when user logs in. Note that it might take maybe 30 seconds to start.

1
systemctl --user enable --now podman-compose.service

Useful commands are enable, start, stop, disable. Using enable --now is equal to calling enable and then start.

Because we want to start our container every time after boot, we can do (with root privileges), do the following.

1
2
su -
loginctl enable-linger <username>

At this point we have nextcloud accessible from a local network via HTTP which is not secure.

Nextcloud: Moving to HTTPS

There are a few options

  1. Use nginx proxy manager/traefik

TODO: make article

  1. Use cloudflare tunnel as decribed. If you have no idea what are cloudflare tunnels, read this

TODO: link

  • add new tunnel on cloudflare’s dashboard
  • add token to .env
  • add cloudflared to docker-compose.yml
  • systemctl --user restart podman-compose.service
  • Make a few modification to nextcloud’s config
    1
    2
    3
    4
    5
    
    pavel@debian:~$ podman exec -it nextcloud-app sh
    root@c159fc873cf8:/# cd config/www/nextcloud/
    apps/    config/  themes/
    root@c159fc873cf8:/# cd config/www/nextcloud/config/
    root@c159fc873cf8:/config/www/nextcloud/config# nano config.php
    
    • Add 1 => 'testcloud.domain.xyz', to put your domain (corresponding to cloudflare tunnel) to trusted ones
    • Add 'overwriteprotocol' => 'https' otherwise you will need to reload page after login attempt
    • Maybe discard 'overwrite.cli.url' => '' or replace it by empty string?
    • Maybe add this for extra security ()
      1
      2
      3
      4
      
      'trusted_proxies' =>
      array (
        0 => '10.89.0.0/24',
      ),
      
  1. Create certificate and reconfigure nginx (?)

Backup

See podman files and scripts which contains full docker-compose.yml file and backup scripts.

Update

Added 2023-07-27

Make backups! Seriously. Updates can suck.

Because I didn’t followed instructions, that were very easy to find navigating from linuxserver.io page to docker hub page and back, I run into problems. The Docker image had a new version of PHP. This lead into the error This version of Nextcloud is not compatible with > PHP 8.2 You are currently running 8.2.6. I was not aware that NextCloud is (or, by that time, was) stored in a volume and updated independently of the Docker image.

When I tried switching to old image and update NextCloud, I somehow run into problem when database was too new and NextCloud too old or NextCloud was incompatible with PHP.

Relevant links

  • https://help.nextcloud.com/t/this-version-of-nextcloud-is-not-compatible-with-php-8-2-you-are-currently-running-8-2-6/163319/19
  • https://hub.docker.com/r/linuxserver/nextcloud
  • https://info.linuxserver.io/issues/2023-06-25-nextcloud/

Data recovery (2023-09-02)

Updated 2023-09-02

For steps on how to get back lost data after a failed update, see Backup and disaster recovery plan

Dealing with frequent disk writes (2023-09-15)

Description of a problem

When I was running smartctl -x /dev/nvme0 after few weeks, saved the results and compared them with old ones, I was surprised by ammount of disc writes. Running iotop as a root with accumalated writes for two hours pointed to a culprit - mariadb in the nextcloud-db container. Brief reserched showed that it’s because Nextcloud has some cron job responsible for that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[pavel@marten -=- /home/pavel]$ podman exec -it nextcloud-app /bin/bash
root@41443129ac3f:/# cd /etc/crontabs/
root@41443129ac3f:/etc/crontabs# ls -la
total 4
drwxr-xr-x 1 root root   8 Sep  2 14:23 .
drwxr-xr-x 1 root root 192 Sep  2 14:23 ..
-rw------- 1 root root 552 Sep  2 14:23 root
root@41443129ac3f:/etc/crontabs# cat root 
# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
*/15    *       *       *       *       run-parts /etc/periodic/15min
0       *       *       *       *       run-parts /etc/periodic/hourly
0       2       *       *       *       run-parts /etc/periodic/daily
0       3       *       *       6       run-parts /etc/periodic/weekly
0       5       1       *       *       run-parts /etc/periodic/monthly
# nextcloud cron
*/5     *       *       *       *       s6-setuidgid abc php -f /config/www/nextcloud/cron.php
root@41443129ac3f:/etc/crontabs#

Fix

Initial idea was to create a volume for /etc/crontabs with a modified file, because changing in container images are not persistent. Surprisingly, after doing it, I found out that this file is overwritten after each container restart by the file in /config/crontab In the end it’s sufficient to do these steps (to run maintenance task once a day at 3:15):

  1. Run shell inside the container and last line of /config/crontab/root
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    [pavel@marten -=- /home/pavel/docker]$ podman exec -it nextcloud-app /bin/bash
    root@7ac9ef8ce9f1:/# vi etc/crontabs/root
    root@7ac9ef8ce9f1:/# cat etc/crontabs/root
    # do daily/weekly/monthly maintenance
    # min   hour    day     month   weekday command
    */15    *       *       *       *       run-parts /etc/periodic/15min
    0       *       *       *       *       run-parts /etc/periodic/hourly
    0       2       *       *       *       run-parts /etc/periodic/daily
    0       3       *       *       6       run-parts /etc/periodic/weekly
    0       5       1       *       *       run-parts /etc/periodic/monthly
    # nextcloud cron
    15     3       *       *       *       s6-setuidgid abc php -f /config/www/nextcloud/cron.php
    
  2. Restart the Nextcloud
1
2
3
root@7ac9ef8ce9f1:/# exit
exit
[pavel@marten -=- /home/pavel/docker]$ podman-compose -f docker-compose-nextcloud.yml up -d
This post is licensed under CC BY 4.0 by the author.