Nextcloud: add app using podman

Nextcloud is an essential privacy app that has been missing from FreedomBox for a long time. This is due to the difficulty of packaging it into Debian. To include Nextcloud in FreedomBox, we can use podman which can sit between the app and the rest of the system. In this issue, I'd like to list the required actions/configurations to setting up Nextcloud based on my testing. The commands below are executed as root, however, one of podman's great benefits is the ability to run rootless containers. It would be worth investigating a rootless setup for impoved security.

  • Create a dedicated virtual bridge adapter with a static IP. This is needed for communication between the container and the host when using MySQL and LDAP. Use the default subnet for the sake of simplicity. $ podman network create --driver bridge --subnet 172.16.16.0/24 --gateway 172.16.16.1 nextcloud-bridge-fbx. This will create cni-podman0 and veth727ced78 which ideally should be hidden from users in the Network app.
  • run the container:
$ podman run --detach \
                    # Only listen on localhost. This is useful to prevent exposing 8181 to the
                    # internet in situations discussed in https://salsa.debian.org/freedombox-team/freedombox/-/issues/789
                    --publish 127.0.0.1:8181:80 \
                    --network nextcloud-bridge-fbx \
                    --ip 172.16.16.2 \
                    # Will be stored under /var/lib/containers/storage/volumes/nextcloud-volume/_data/
                    --volume nextcloud-volume:/var/www/html \
                    --name nextcloud-fbx \
                    # enable autoupdates
                    --label io.containers.autoupdate=registry \
                    docker.io/library/nextcloud:stable-apache
  • Although for FreedomBox apps it's generally preferable to use SQLite, the official documentation advises against it. During the initial setup, the GUI warns: "SQLite should only be used for minimal and development instances. For production we recommend a different database backend. If you use clients for file syncing, the use of SQLite is highly discouraged."

Install default-mysql-server and create the database as described in the documentation. Instead of loclhost, use the container's IP address that we assigned earlier:

CREATE USER 'nextcloud_fbx'@'172.16.16.2' IDENTIFIED BY 'password';
CREATE DATABASE IF NOT EXISTS nextcloud_fbx CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON test.* TO 'nextcloud_fbx'@'172.16.16.2';
FLUSH PRIVILEGES;
  • Under [mysqld] add bind-address = 172.16.16.1 so that the host database the container can communicate with each other.

  • Do the initial setup with the Nextcloud console: podman exec --user www-data nextcloud-fbx php occ maintenance:install --database=mysql --database-name=nextcloud_fbx --database-host=172.16.16.1 --database-port=3306 --database-user=nextcloud_fbx --database-pass=password --admin-user=nextcloud-admin --admin-pass=admin-password

  • Configure the url values. overwriteprotocol and overwrite.cli.url should be http when Nextlcoud is configured with an onion domain:

$ podman exec --user www-data nextcloud-fbx php occ config:system:set trusted_domains 0 --value="localhost:4430"
$ podman exec --user www-data nextcloud-fbx php occ config:system:set trusted_proxies 0 --value="localhost:4430"
$ podman exec --user www-data nextcloud-fbx php occ config:system:set overwritewebroot --value="/nextcloud"
$ podman exec --user www-data nextcloud-fbx php occ config:system:set overwritehost --value="localhost:4430"
$ podman exec --user www-data nextcloud-fbx php occ config:system:set overwrite.cli.url --value="https://localhost:4430/nextcloud"
$ podman exec --user www-data nextcloud-fbx php occ config:system:set overwriteprotocol --value="https"

Apache configuration:

 <Location /nextcloud>
    ProxyPass    http://127.0.0.1:8181
    RequestHeader    set X-Forwarded-Proto 'https' env=HTTPS
    Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
</Location>

To surpass warnings shown in the Administration settings about Webadav service discovery the apache virtual host (not the config) has to be modified:

# https://docs.nextcloud.com/server/25/admin_manual/issues/general_troubleshooting.html#service-discovery
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule ^/\.well-known/carddav /nextcloud/remote.php/dav [R=301,L]
  RewriteRule ^/\.well-known/caldav /nextcloud/remote.php/dav [R=301,L]
  RewriteRule ^/\.well-known/webfinger /nextcloud/index.php/.well-known/webfinger [R=301,L]
  RewriteRule ^/\.well-known/nodeinfo /nextcloud/index.php/.well-known/nodeinfo [R=301,L]
</IfModule>

This might conflict with Radicale though.

  • Set up SSO
    • Create an empty config: podman exec --user www-data nextcloud-fbx php occ ldap:create-empty-config. In Owncloud it is possible to specify a name for the config, but this feature is missing from Nextcloud, so the config will be named s01. If the FreedomBox setup process fails for some reason and a new empty config is created, the number in the name will increment, so perhaps we should try to delete s01 before creating it.
    • The configuration values are taken from podman exec --user www-data nextcloud-fbx php occ ldap:show-config after configuring ldap on the GUI. Some values were automatically added, please review them:
 LDAP_SETTINGS = {
    'ldapBase': 'dc=thisbox',
    'ldapBaseGroups': 'dc=thisbox',
    'ldapBaseUsers': 'dc=thisbox',
    'ldapConfigurationActive': '1',
    'ldapGroupDisplayName': 'cn',
    'ldapGroupFilter': '(&(|(objectclass=posixGroup)))',
    'ldapGroupFilterMode': '0',
    'ldapGroupFilterObjectclass': 'posixGroup',
    'ldapGroupMemberAssocAttr': 'memberUid',
    'ldapHost': '172.16.16.1',
    'ldapLoginFilter': '(&(|(objectclass=posixAccount))(uid=%uid))',
    'ldapLoginFilterEmail': '0',
    'ldapLoginFilterMode': '0',
    'ldapLoginFilterUsername': '1',
    'ldapNestedGroups': '0',
    'ldapPort': '389',
    'ldapTLS': '0',
    'ldapUserDisplayName': 'cn',
    'ldapUserFilter': '(|(objectclass=posixAccount))',
    'ldapUserFilterMode': '0',
    'ldapUserFilterObjectclass': 'account',
    'ldapUuidGroupAttribute': 'auto',
    'ldapUuidUserAttribute': 'auto',
    'turnOffCertCheck': '0',
    'turnOnPasswordChange': '0',
    'useMemberOfToDetectMembership': '0'
     }

for k, v in LDAP_SETTINGS.items():
        subprocess.run(
         ['podman', 'exec', '--user', 'www-data', 'nextcloud-fbx', 'php', 'occ' , 'ldap:set-config',
          's01', k, v],
         check=True)
  • Create a systemd service as described here and here so the container can be properly managed by FreedomBox:
$ export XDG_RUNTIME_DIR=/run/user/0
$ podman generate systemd --new nextcloud-fbx > /etc/systemd/system/nextcloud-fbx.service
$ systemctl daemon-reload
$ systemctl enable nextcloud-fbx.service
$ systemctl start nextcloud-fbx.service
  • The admin password can be changed passing an environmental variable into the container:$ podman exec --user www-data --env=OC_PASS=$password -it nextcloud-fbx sh -c "/var/www/html/occ user:resetpassword --password-from-env nextcloud-admin
  • Tests to-do:
    • Create a timer for running $ podman auto-update consistently with unattended upgrades.
    • Test fail2ban filter
    • Automatically configure the local mail server in Nextcloud
    • Consider enforcing TOTP for better security.
Edited by Benedek Nagy