A Nextcloud container solution using Free and Open Source (FOSS) tools 🤝
This project is being tested againt Podman as container runtime with docker/compose as compose engine.
Future goals are to also support Kubernetes.
Note
🚧🚧🚧
This project is still under heavy development. Do not use in production setups! There will be breaking changes in the near future.
🚧🚧🚧
- Support by Strukturpiloten
- Motivation
- Other Projects
- Prerequisites
- Installation
- Resources
- External Issues affecting this Project
- Contribution
Strukturpiloten is a German consulting crew specializing in process optimization, automation, Linux, network engineering, and DevOps.
We build scalable, open, and human-centered IT systems — from containers to culture.
Need mission control for your next project?
👉 Get in touch
Powered by curiosity. Guided by structure.
We at Strukturpiloten love Free and Open Source Software (FOSS) and therefore also want to use FOSS software as underlay. When it comes to container runtimes we prefer Podman (Website) over Docker due to its daemonless architecture and improved security model.
There are already official and community backed Nextcloud Docker containers available, but none of them support Podman out of the box. This project aims to provide an easy to use Nextcloud setup using Podman as container runtime in the first step. Furthermore we intend to provide a Kubernetes setup that can be derived from this Podman project in the near future.
All other projects that we know of use Docker as container runtime. The official Nextcloud container even needs a docker.sock bind mount to work.
Official Nextcloud All-in-One Docker project. To run this project root access to the docker.sock is required.
Community backed Nextcloud Docker container. Can be used as stand-alone container that accesses other services (database, etc.) or can be used with a compose.yaml file.
The LinuxServer.io project also has a Nextcloud docker container. Can be used as stand-alone container that accesses other services (database, etc.) or can be used with a compose.yaml file.
Podman requires a proper setup for non-root users. Please follow the official Podman installation instructions.
The following packages need to be installed, but package names may differ depending on your Linux distribution:
podmandocker-compose- not to be confused withpodman-compose!
Sadly this project is not compatible with podman-compose as podman-compose lacks several fundamental features that are already implemented in docker-compose 😢
Podman Quadlets have not been implemented by this project as many people using Docker and docker/compose don't know about Quadlets yet. Therefore we stick to the more common docker/compose way of doing things.
It is also recommended to set up IPv4 and IPv6 (dual-stack) on your system.
There's a whole example setup with commands at the end of this chapter.
Create a username and group for running the containers, e.g.:
- User:
podman - Group:
podman
Make your user services reboot persistent by enabling linger for your podman user. Run this command as root user:
loginctl enable-linger podmanAlso add the podman.sock systemd socket for non-root users. Run this command with your podman user:
systemctl --user enable --now podman.socketThe whole setup looks like this:
username=podman
groupadd ${username}
useradd -g ${username} -m ${username}
loginctl enable-linger ${username}
sudo -u ${username} systemctl --user enable --now podman.socketYou can access the podman user with another account with sudo rights:
sudo -i -u podmanAllow non-root users to bind to privileged ports <1024.
Run these commands as root to allow non-root users to bind to privileged ports starting from port 0. The second command will make it persistent across reboots:
Caution
This change impacts the whole system and allow also non-root users to bind to privileged ports. Make sure that you understand the security implications of this change.
echo 'net.ipv4.ip_unprivileged_port_start=0' >> /etc/sysctl.conf
sysctl -pMake sure that the following ports and protocols are open in your firewall:
80/tcp: HTTP/1.1, HTTP/280/udp: HTTP/3443/tcp: HTTP/1.1 with TLS/SSL, HTTP/2 with TLS443/udp: HTTP/3 with TLS
This section will show a step-by-step example installation.
The setup differentiates between these directories:
- This repository is only used for the logic and not your (user) data and configs
data: Store your (user) files in one or multiple data directoriesconfigs: Store your config files in one or multiple config directories
Therefore these directories will be used for this example setup:
/mnt/nextcloud: Parent working directory (pwd)/mnt/nextcloud/configs: Your config files/mnt/nextcloud/data: Your (user) files/mnt/nextcloud/nextcloud: This repository
So let's start:
cd /mnt/nextcloudmkdir data
mkdir configsClone the repository to your local machine:
git clone https://github.com/Strukturpiloten/nextcloud.gitThere are now three directories in /mnt/nextcloud:
configsdatanextcloud
Copy the example environment file and edit it to your needs:
cd /mnt/nextcloudcp nextcloud/.env.example configs/.envCheck if UID and GID variables are set for your podman user. You can get the values with these commands:
echo "$UID"
echo "$GID"If they are not set you can get the values:
id -u
id -gEdit the configs/.env file and set at least the following variables:
PODMAN_NAMESPACE: E.g.customername,yourcompanynamePODMAN_STAGE: E.g.test,prod- Change
PODMAN_UIDandPODMAN_GIDif needed - All variables containing the following values:
/your/absolute/path/to/: Set the absolute paths to your data and config directoriesa_secure_password: Use a separate secure password for each variabledomain.example.com: Your domain name
NEXTCLOUD_SMTP_,NEXTCLOUD_MAIL_andNEXTCLOUD_DEFAULT_variables
The following variables will not be changed for this example setup, because we will use the default config files where possible. These are the default values that are also present in our .env file. The configs path refers to /mnt/nextcloud/nextcloud/configs and not /mnt/nextcloud/configs as the environment variables are consumed be podman compose in the nextcloud directory. The default values are relative and not absolute paths:
PODMAN_PHPFPM_CONF_FILE_HOST=configs/phpfpm/conf/zzz-www.conf
# PODMAN_PHPFPM_CONF_FILE_HOST=/your/absolute/path/to/configs/phpfpm/conf/zzz-www.conf
PODMAN_PHPFPM_INI_FILE_HOST=configs/phpfpm/ini/nextcloud.ini
# PODMAN_PHPFPM_INI_FILE_HOST=/your/absolute/path/to/configs/phpfpm/ini/nextcloud.ini
PODMAN_MANAGER_CRON_ROOT_FILE_HOST=configs/phpfpm/cron/cron_root
# PODMAN_MANAGER_CRON_ROOT_FILE_HOST=/your/absolute/path/to/configs/phpfpm/cron/cron_rootThat leads us to the following changes in the configs/.env file for this example:
# namespace and stage
PODMAN_NAMESPACE=examplecompany
PODMAN_STAGE=prod
# PODMAN_UID=${UID}
# PODMAN_GID=${GID}
PODMAN_UID=2000
PODMAN_GID=2000
# databases
PODMAN_SQL_DATABASE=postgres
PODMAN_KEY_VALUE_DATABASE=valkey
# data paths
PODMAN_SSL_DIR_HOST=/mnt/nextcloud/configs/ssl
PODMAN_NGINX_CONF_DIR_HOST=/mnt/nextcloud/configs/nginx/conf
PODMAN_CLAMAV_DATA_DIR_HOST=/mnt/nextcloud/data/clamav
PODMAN_POSTGRES_DATA_DIR_HOST=/mnt/nextcloud/data/postgres
PODMAN_VALKEY_DATA_DIR_HOST=/mnt/nextcloud/data/valkey
PODMAN_NEXTCLOUD_DATA_DIR_HOST=/mnt/nextcloud/data/nextcloud
PODMAN_NEXTCLOUD_USER_DATA_DIR_HOST=/mnt/nextcloud/data/nextcloud_data
# secrets - do not use these example secrets for your setup!
POSTGRES_PASSWORD=doNotUseThisSecretForPostgres
WHITEBOARD_JWT_SECRET_KEY=doNotUseThisSecretForWhiteboard
VALKEY_PASSWORD=doNotUseThisSecretForValkey
NEXTCLOUD_ADMIN_PASSWORD=doNotUseThisSecretForNextcloudAdminUser
NEXTCLOUD_DOMAIN=nextcloud.example.com
NEXTCLOUD_TRUSTED_DOMAINS="localhost nextcloud.example.com"
NEXTCLOUD_SMTP_HOST=nix
NEXTCLOUD_SMTP_SECURE=nix
NEXTCLOUD_SMTP_PORT=nix
NEXTCLOUD_SMTP_AUTHTYPE=nix
NEXTCLOUD_SMTP_NAME=nix
NEXTCLOUD_MAIL_FROM_ADDRESS=nix
NEXTCLOUD_MAIL_DOMAIN=nix
NEXTCLOUD_DEFAULT_LANGUAGE=de_DE
NEXTCLOUD_DEFAULT_PHONE_REGION=DE
NEXTCLOUD_DEFAULT_TIMEZONE=Europe/BerlinNow we need to create the config directories and files. As bare minimum the Nginx config file needs to be changed, check the Minimal Example Setup for further details. Depending on your needs you can also copy/create all config files and edit them to your needs, check the All Configs section.
For your example setup we only need to edit the Nginx config file. Therefore we will only create the required directories and copy the default config files into our configs directory.
cd /mnt/nextcloudmkdir -p configs/nginx/confCopy the default file into the directory:
cp nextcloud/configs/nginx/conf/nextcloud_default.conf configs/nginx/conf/nextcloud.confYou need to edit the Nginx nextcloud.conf file as it contains the default domain cloud.example.com that needs to be changed to your domain like this:
sed -i 's/cloud.example.com/yourdomain.example.com/g' configs/nginx/conf/nextcloud.confAll other config files use some default values that can be used out of the box for a small setups.
If you need to change all service configs you need to create the following directories:
cd /mnt/nextcloudmkdir -p configs/nginx/conf
mkdir -p configs/phpfpm/conf
mkdir -p configs/phpfpm/ini
# SQL database (choose your fighter)
mkdir -p configs/mariadb
mkdir -p configs/mysql
mkdir -p configs/postgres
# key-value database
mkdir -p configs/valkey
# Key-value database
mkdir -p configs/valkey
# Nextcloud scripts for the "manager" container
mkdir -p configs/managerCopy all default files into the directories:
# nginx
cp nextcloud/configs/nginx/conf/nextcloud_default.conf configs/nginx/conf/nextcloud.conf
# phpfpm
cp nextcloud/configs/phpfpm/conf/zzz-www_default.conf configs/phpfpm/conf/zzz-www.conf
cp nextcloud/configs/phpfpm/ini/nextcloud_default.ini configs/phpfpm/ini/nextcloud.ini
# manager
cp nextcloud/configs/manager/nextcloud_config_default.php configs/manager/nextcloud_config.php
cp nextcloud/configs/manager/nextcloud_setup_default.sh configs/manager/There are no default config files for MariaDB, MySQL, Postgres and Valkey, so you need to create them on your own if needed. Also check the environment variables containing path values in configs/.env that need to be uncommented and set accordingly. The path variable names end with _FILE_HOST and _DIR_HOST.
You need to edit the Nginx nextcloud.conf file as it contains the default domain cloud.example.com that needs to be changed to your domain like this:
sed -i 's/cloud.example.com/yourdomain.example.com/g' configs/nginx/conf/nextcloud.confAll other config files use some default values that can be used out of the box for a small setups.
Depending on your needs and your other setups you may or may not want to use a separate SSL directory. In this case we will use it as it's a simple way to move forward with this example setup:
cd /mnt/nextcloudmkdir -p configs/sslThe path /mnt/nextcloud/configs/ssl has also been set for the environment variable PODMAN_SSL_DIR_HOST.
You need to put your SSL certificate and key into the configs/ssl directory. The default Nginx config nextcloud_default.conf references these file names:
ssl_certificate.crt
ssl_certificate_key.keyIf you don't have SSL certificates yet, you can create self-signed certificates for testing purposes:
cd /mnt/nextcloudopenssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-subj "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname" \
-keyout configs/ssl/ssl_certificate_key.key -out configs/ssl/ssl_certificate.crtWe chose Postgres as SQL database for this example setup. Therefore we will use the postgres profile when starting the containers. You can use one of these profile names for the SQL database:
mariadbmysqlpostgres
These profiles are available for the key-value database:
valkeyredis
cd /mnt/nextcloudcd nextcloudBuild the containers:
podman compose --env-file "../configs/.env" --profile "postgres" --profile "valkey" buildStart the containers:
podman compose --env-file "../configs/.env" --profile "postgres" --profile "valkey" up -dCheck their status:
podman psThe output will look like this:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29d755bf2a4d docker.io/library/tempcloud... 34 minutes ago Up 34 minutes 6379/tcp tempcloud2-nextcloud-prod-valkey-1
31e6257367e1 docker.io/clamav/clamav:1.5... 34 minutes ago Up 34 minutes 3310/tcp, 7357/tcp tempcloud2-nextcloud-prod-clamav-1
dd227375136e ghcr.io/nextcloud-releases/... 34 minutes ago Up 34 minutes (healthy) 3002/tcp tempcloud2-nextcloud-prod-whiteboard-1
2da070fd3166 docker.io/library/postgres:... postgres 34 minutes ago Up 34 minutes 5432/tcp tempcloud2-nextcloud-prod-postgres-1
343ec463b816 docker.io/library/nginx:1.2... nginx -g daemon o... 34 minutes ago Up 34 minutes 0.0.0.0:80->80/tcp... tempcloud2-nextcloud-prod-nginx-1
d3fa28c652c6 docker.io/library/tempcloud... php-fpm 34 minutes ago Up 34 minutes 9000/tcp tempcloud2-nextcloud-prod-phpfpm-1
ecc2cd2b5032 docker.io/library/tempcloud... sh /etc/entrypoin... 34 minutes ago Up 34 minutes 9000/tcp tempcloud2-nextcloud-prod-manager-1The first startup may take some time. You can check the logs of the startup with:
podman logs -f tempcloud2-nextcloud-prod-manager-1The installation and configuration will be finished when these log lines appear:
Nextcloud configuration: completed
Nextcloud maintenance: mode off
Maintenance mode already disabled
Manager script: Setup completed successfully
Nextcloud script: Completed
Service: Starting cron
1/1 [============================] 100%time="2025-12-03T09:34:13Z" level=warning msg="process reaping disabled, not pid 1"
time="2025-12-03T09:34:13Z" level=info msg="read crontab: /etc/crontabs/root"Open your browser and enter your domain name. You should see the Nextcloud login page. You can now log in with the admin user and the password you set for the variable NEXTCLOUD_ADMIN_PASSWORD in the configs/.env file.
Note
Sometimes you need to login twice at the very first startup.
To make sure that your Nextcloud starts automatically after a system reboot, you can create a systemd service file. The following parameters need to be adapted:
- Description
- WorkingDirectory
- ExecStart
- ExecStop
Create the systemd service file podman-examplecompany-nextcloud-prod.service under ~/.config/systemd/user with the following content:
Description=Podman examplecompany-nextcloud-prod
After=network.target
After=systemd-user-sessions.service
After=network-online.target
After=podman.socket
Requires=podman.socket
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/mnt/nextcloud
ExecStart=/usr/bin/env podman compose --env-file "../configs/.env" --profile "postgres" --profile "valkey" start
ExecStop=/usr/bin/env podman compose --env-file "../configs/.env" --profile "postgres" --profile "valkey" stop
[Install]
WantedBy=default.targetStop your containers:
cd /mnt/nextcloudpodman compose --env-file "../configs/.env" --profile "postgres" --profile "valkey" stopEnable and start the systemd service:
Note
Systemd linger needs to be enabled for the podman user as described in the User Setup section.
systemctl --user enable --now examplecompany-nextcloud-prod.serviceCheck the container status:
podman psIf the server gets rebooted the containers will be started automatically. If the containers don't get started check the service status:
systemctl --user status examplecompany-nextcloud-prod.serviceIf the service didn't get started check that your podman user exists under the Systemd linger directory:
ls -l /var/lib/systemd/lingerAlso check the current boot log as the podman or root user depending on the current state:
journalctl -b 0Overview of the used documentations, projects and containers.
- https://github.com/nextcloud/whiteboard
- https://help.nextcloud.com/t/how-do-i-setup-the-websocket-server-for-whiteboard-real-time-collaboration/229171/3
- https://github.com/coturn/coturn
- https://hub.docker.com/r/coturn/coturn
- https://help.nextcloud.com/t/howto-setup-nextcloud-talk-with-turn-server/30794/112
- https://www.c-rieger.de/nextcloud-und-coturn/
Use an external TURN server or use our Coturn project for Podman (coming soon™️).
- https://github.com/strukturag/nextcloud-spreed-signaling
- https://www.c-rieger.de/nextcloud-hpb-talk-signaling-server/
- https://help.nextcloud.com/t/high-performance-backend-talk-easiest-and-simplest/206836/3
- https://help.nextcloud.com/t/server-stun-and-high-performance-backend-server-talk/190072/3
- https://help.nextcloud.com/t/nextcloud-talk-high-performance-backend/167217/16
Contributions are very welcome! If you find any issues or have ideas for improvements, please open an issue and a pull request. Feel free to open a discussion for general questions or suggestions.
Thank you for your support! ❤️