This guide covers how to install Nextcloud with the following stack:
- Nginx 1.28 (stable branch)
- Latest Nextcloud Server stable
- PostgreSQL 17
- PHP-FPM 8.4
- APCu
- Memcached
- Redis 8
Includes:
- Nextcloud adjustements from AIO/Server tuning manual section.
- Memories app setup.
- PostgreSQL Database tuning acording to HW specs/Number of connections.
- PHP-FPM.ini & pool parameter tuning.
- Unix socket support for Database and Redis.
- GPU Passthrough to LXC for video transcoding support.
- Mount ZFS disk pool for additional space and Nextcloud data folder.
- Push notifications support.
- Automatic preview generation.
- Automatic updates for Nextcloud apps
Extras:
- Selfhost/Proxy/HTTPS/SSL Support with Nginx Proxy Manager LXC.
- OnlyOffice Document Server.
- How to install Adminer for database administration GUI.
- How to migrate to a newer PHP version.
- How to migrate to a newer PostgreSQL version.
- How to upgrade Debian to a newer release.
- How to upgrade Nextcloud.
- How to make a LXC Backup in Proxmox.
- How to add local external storage to LXC/Nextcloud (work in progress).
This guide assumes you have:
- A working Proxmox node.
- At least 1 ZFS Pool or LVM disk to storage the LXC. (2 are recomended, 1 to save the LXC itself and 1 to store the nextcloud data).
- Intermediate Linux, Shell, Unix Permission Skills.
- For selfhosting, a proxy host, a fully working domain pointing to your public IP and a DDNS service, the 443 port forwarded in your router and pointing to the proxy host. (This guide only covers Nginx Proxy Manager LXC proxy host settings).
- At least 4GB Ram free, 4 cores, 64GB free space for the LXC.
- Integrated or dedicated graphics card for video transcoding, otherwise, stick to ffmpeg and CPU transcoding. (Intel/AMD preferred, but you can install nvidia drivers).
Official Reddit post here
Table of Contents:
- Guide
- Preparing the Storage
- Creating the LXC Container
- Container Setup
- Preparing the necessary stuff
- Server Tuning
- Configuring NGINX
- Nextcloud Server Setup
- Begin the Nextcloud installation
- Nextcloud post-installation adjustements
- Adding Push Notifications support
- Setup automatic preview generation
- Memories app setup
- Automatic updates for Nextcloud apps
- Container deletion
- Extras
For this guide we will use an unprivileged LXC, if you don't know how to handle the permissions and ownership, please read this explanation before starting.
In this case I'll use a ZFS dataset created on an existing pool. To create one:
zfs create disk2/ncdata
Now get the mountpoint of the dataset with:
zfs get mountpoint disk2/ncdata
We need this path to mount it in the LXC later.
First download the latest Debian standard template:
Now Lets Create the LXC:
Set a hostname, ID number and a password for the root user.
Select the Debian template from your storage.
Choose the storage where the LXC will be saved, set 64GB for disk size, for mount options select: discard (only if your storage is SSD), noatime, lazytime.
Set the desired amount of CPU cores, in this case I'll set it to 8.
Set at least 4GB of ram and 1GB for swap.
For network, assign a static IPv4 address with its gateway. If your ISP provides a fully working IPv6 select SLAAC, if not, just leave it static.
For DNS you can use the host settings, or another dns provider like 8.8.8.8,1.1.1.1
Finish the container creation.
Now is the time to add the mountpoint for the Nextcloud data directory storage, go to your Proxmox shell and execute:
zfs get mountpoint disk2/ncdata
pct set 110 -mp0 /srv/nas/disk2/ncdata,mp=/mnt/ncdata
# Adjust the container ID and mount path to yours.
# You can bind mount another folders as needed.
Now set the ownership for data folder:
chown -R 100033:100033 /srv/nas/disk2/ncdata
(OPTIONAL) GPU Passthrough for video transcoding.
Go to your Nextcloud container resources section and add a device passthrough.
In the Proxmox Shell get the card number with:
ls /dev/dri
For the path: /dev/dri/renderD128, set GID 104 (render group in Debian), access mode 0666.
Add another device with the card number, set GID 44 (video group), access mode 0666.
With all of this, we are ready to Power ON and setup the Container.
First enter the container and setup your timezone and language locale:
dpkg-reconfigure tzdata
dpkg-reconfigure locales
Edit /etc/apt/sources.list and add "non-free" and "non-free-firmware" to the repositories:
deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware
deb http://security.debian.org bookworm-security main contrib non-free non-free-firmware
Then apply pending updates:
apt update && apt upgrade -y
Reboot the container:
reboot
(Optional but recommended) Create a new sudo user for administrative tasks:
apt install sudo
useradd ncadmin -m -g users -s /bin/bash
passwd ncadmin
groupadd ncadmin -g 1000
usermod -aG sudo ncadmin
usermod -aG ncadmin ncadmin
Switch to the new user:
su - ncadmin
Now we will use ncadmin for every command in this guide, or you can stick with the root user.
Install a firewall:
sudo apt install -y ufw
Allow the required ports in ufw for this setup:
sudo ufw enable
sudo ufw allow 22,80,443,5432,6739,7867,9000/tcp
sudo ufw allow 443/udp
sudo ufw reload
In this guide we will use external repositories to facilitate upgrading versions of any part of the stack, but you can compile it from source or use the provided packages from the distribution.
Add Sury's Nginx & PHP repositories, provided by an Official Debian Developer:
sudo apt install -y lsb-release ca-certificates curl
sudo curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/nginx/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/nginx.list'
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
sudo apt update
Install Nginx packages:
sudo apt install -y nginx nginx-extras
Install PostgreSQL packages:
sudo apt install -y postgresql-common
Add the official PostgreSQL repository:
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
Press enter and then install postgresql-17:
sudo apt install -y postgresql-17 postgresql-client-17
Install PHP packages:
sudo apt install -y php8.4-{fpm,pgsql,gd,curl,mbstring,xml,zip,intl,bcmath,gmp,imagick,redis,apcu,smbclient,ldap,imap} imagemagick librsvg2-bin libmagickcore-6.q16-6-extra
Add the Official Redis server repository:
sudo apt install -y lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt update
Install Redis:
sudo apt install -y redis
NOTE: If you want to install a specific version of Redis from this repository, please check here.
Another required packages:
sudo apt install -y unzip zip wget curl vim ffmpeg git gnupg 7zip net-tools
Drivers for AMD GPUS:
sudo apt install -y firmware-amd-graphics libgl1-mesa-dri libglx-mesa0 mesa-vulkan-drivers
Drivers for Intel GPUS:
sudo apt install -y intel-media-va-driver-non-free i965-va-driver-shaders
Drivers for Nvidia GPUS:
sudo apt install -y nvidia-driver nvidia-vaapi-driver
Enable and Start the necessary services:
sudo systemctl enable --now nginx php8.4-fpm postgresql redis-server
Database tuning and Unix socket configuration:
Use the following page to get the appropiate configuration acording to your hardware specs and number of connections. https://pgtune.leopard.in.ua/
Now edit /etc/postgresql/17/main/postgresql.conf and set the values given by the page.
Then proceed editing this lines for the Unix socket:
listen_addresses = '' # If you still need TCP connection leave it to listen_addresses = 'localhost'
unix_socket_directories = '/var/run/postgresql'
unix_socket_group = 'www-data'
unix_socket_permissions = 0770
Save the file And now add the postgres user to the www-data group:
sudo usermod -aG www-data postgres
Edit /etc/postgresql/17/main/pg_hba.conf to enable access using unix socket like this:
# "local" is for Unix domain socket connections only
local all all scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all scram-sha-256
Restart postgresql:
sudo systemctl restart postgresql
Redis tuning and Unix socket configuration:
This repository provides a custom configuration file to not mess the main configuration of Redis.
The file only sets the necessary configuration for this setup, you can add more as needed.
First we need to create the directory where all custom configuration for Redis will reside:
sudo mkdir /etc/redis/conf.d
Now Edit and set the following in /etc/redis/redis.conf at the end of the file:
include /etc/redis/conf.d/*.conf
NOTE: In future major Redis upgrades, APT will prompt you to decide what to do with the configuration files, for this setup, always select "Install the package maintainer's version", and later reapply the include /etc/redis/conf.d/*.conf command in the main configuration file of Redis
Set your redis password in the custom configuration file:
sudo nano /opt/nextconf/redis/custom.conf
port 0
unixsocket /run/redis/redis-server.sock
unixsocketperm 770
maxclients 10240
requirepass yourpassword # Set a strong password here
Copy the configuration file to the directory:
sudo cp -r /opt/nextconf/redis/custom.conf /etc/redis/conf.d
Add the www-data user to redis group:
sudo usermod -aG redis www-data
Restart redis:
sudo systemctl restart redis-server
(Optional) Add a cronjob to optimize redis: Clone this repository and add a cronjob with the script:
git clone https://github.com/JMarcosHP/Nextcloud-Guide
sudo cp -r Nextcloud-Guide/nextconf /opt
cd /opt/nextconf/redis
Edit redis-optimization.sh and set your redis password:
redis-cli -s /run/redis/redis-server.sock -a 'yourredispassword'
Save the script and give exectution permissions.
sudo chmod +x redis-optimization.sh
Add the cronjob:
sudo crontab -e
# Redis Optimization
5 1 * * * /opt/nextconf/redis/redis-optimization.sh
PHP-FPM Tuning:
This repository includes two file templates for PHP configuration to facilitate migration over versions.
For the main configuration, edit the file nextcloud.ini and set your redis password, adjust or add another configuration as needed:
sudo nano /opt/nextconf/php/nextcloud.ini
session.save_path = "unix:///run/redis/redis-server.sock?auth=yourredispassword&database=1" ; Make sure your password doesn't contain "&" character as it's reserved to indicate the database index.
...
The main configuration template provides the following:
output_buffering = off
max_execution_time = 86400
default_socket_timeout = 86400 ; Always set the same value of max_execution_time
memory_limit = 1024M ; Adjust if you need more.
post_max_size = 16G ; Adjust if you need more.
upload_max_filesize = 16G ; Always set the same value of post_max_size
session.save_handler = redis
session.save_path = "unix:///run/redis/redis-server.sock?auth=yourredispassword&database=1" ; Make sure your password doesn't contain "&" character as it's reserved to indicate the database index.
session.serialize_handler = igbinary
session.gc_maxlifetime = 86400
redis.session.locking_enabled = 1
redis.session.lock_retries = -1
redis.session.lock_wait_time = 10000
opcache.enable = 1
opcache.enable_cli = 1
opcache.jit = 1255
opcache.jit_buffer_size = 8M
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 64
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2
opcache.validate_timestamps = 1
opcache.save_comments = 1
apc.serializer = igbinary
apc.shm_size = 128M
igbinary.compact_strings = On
; High failure protection
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s
After you ajusted your configuration, copy the file to the PHP folder:
sudo cp -r /opt/nextconf/php/nextcloud.ini /etc/php/8.4/mods-available
For the PHP-FPM pool configuration, first execute the php-fpm-autocalculation script to get the appropiate values for your hardware:
cd /opt/nextconf/php
sudo chmod +x php-fpm-autocalculation.sh
./php-fpm-autocalculation.sh
Then select an option and set these values to the zz-nextcloudpool.conf template:
sudo nano /opt/nextconf/php/zz-nextcloudpool.conf
Copy the file to the pool.d/ folder:
sudo cp -r /opt/nextconf/php/zz-nextcloudpool.conf /etc/php/8.4/fpm/pool.d
Finally apply the configuration:
sudo phpenmod -v 8.4 -s fpm nextcloud
sudo systemctl restart php8.4-fpm
I included in this repository a Nginx configuration file based in the Nextcloud manual and notify_push requirements, you can choose the http file or the https variant, for the https variant you can adapt it if you already have your own certificate, or read this guide if you want to selfhost it using Nginx Proxy Manager later.
Disable Nginx welcome page:
sudo rm -r /etc/nginx/sites-enabled/default
Copy the nginx file:
sudo cp -r /opt/nextconf/nginx/nextcloud-http.conf /etc/nginx/sites-available
Or
sudo cp -r /opt/nextconf/nginx/nextcloud-https.conf /etc/nginx/sites-available
For the https variant.
And add the symlink to sites-enabled:
sudo ln -s /etc/nginx/sites-available/nextcloud-http.conf /etc/nginx/sites-enabled/
Or
sudo ln -s /etc/nginx/sites-available/nextcloud-https.conf /etc/nginx/sites-enabled/
Check syntax and reload nginx:
sudo nginx -t
sudo systemctl reload nginx
Create the Nextcloud database and user:
NOTE: Use your own strong password.
sudo -u postgres psql <<EOF
CREATE DATABASE nextcloud TEMPLATE template0 ENCODING 'UTF-8';
CREATE USER nextcloud WITH PASSWORD 'changeme';
ALTER DATABASE nextcloud OWNER TO nextcloud;
GRANT ALL ON DATABASE nextcloud TO nextcloud;
EOF
Download & extract Nextcloud server:
cd /var/www
sudo wget https://download.nextcloud.com/server/releases/latest.zip
sudo unzip latest.zip
sudo chown -R www-data:www-data /var/www/nextcloud
sudo rm -r latest.zip
sudo mkdir /mnt/ncdata/skeleton
sudo chown -R www-data:www-data /mnt/ncdata/skeleton
Open your web browser and go to: http://[LXC_EXTERNAL_IP]
Set a name and password for the nextcloud admin account, for the database use the same name, user and password created in this step.
For the Nextcloud data dir, set the configured mountpoint of your ZFS dataset, in this case /mnt/ncdata
In database host, use the unix socket path: /var/run/postgresql
for the port just leave it blank.
And click Install.
Select apps as needed, or click Skip to not install anything.
And there we go!
Go to the administration settings to see what we need to adjust/fix.

Fix database index:
sudo -E -u www-data php -f /var/www/nextcloud/occ db:add-missing-indices
sudo -E -u www-data php -f /var/www/nextcloud/occ maintenance:repair --include-expensive
Configuring Background Jobs:
Go to basic settings and select Cron.
Then open your LXC terminal and add the cronjob:
sudo crontab -u www-data -e
# Nextcloud Background Jobs
*/5 * * * * php -f /var/www/nextcloud/cron.php
# Optional background cronjobs provided by this repository
# Notify Maintenance Mode
0 0 * * * bash /opt/nextconf/cron/maintenance-notify.sh
# Enable Maintenance mode
0 1 * * * bash /opt/nextconf/cron/maintenance-mode.sh on
# Disable Maintenance mode
50 4 * * * bash /opt/nextconf/cron/maintenance-mode.sh off
If you want to setup automatic updates for nextcloud apps, please check here.
For the email configuration, you can use your own gmail account following this video.
Or if you have a web domain you can use an email provider, I recommend you the free tier of Mailjet. Please check this guide for more details.
Once you got your mailjet credentials you can add it to nextcloud like this:

Adding redis, memcached and apcu support.
Edit /var/www/nextcloud/config/config.php with the following:
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' =>
array (
'host' => '/run/redis/redis-server.sock',
'port' => 0,
'password' => 'yourredispassword',
'dbindex' => 1,
'timeout' => 0.5,
),
Another adjustements based in the Nextcloud-AIO configuration, pick the ones you need:
'skeletondirectory' => '/mnt/ncdata/skeleton', // To create new user accounts without the initial files.
'log_type' => 'file',
'logfile' => '/var/www/nextcloud/data/nextcloud.log',
'log_rotate_size' => 10485760,
'log.condition' =>
array (
'apps' =>
array (
0 => 'admin_audit',
),
),
'trusted_proxies' =>
array (
0 => '127.0.0.1',
1 => '::1',
),
'preview_max_x' => 2048,
'preview_max_y' => 2048,
'jpeg_quality' => 60,
'preview_max_memory' => 512,
'enabledPreviewProviders' =>
array (
0 => 'OC\\Preview\\Image',
1 => 'OC\\Preview\\MarkDown',
2 => 'OC\\Preview\\MP3',
3 => 'OC\\Preview\\TXT',
4 => 'OC\\Preview\\OpenDocument',
5 => 'OC\\Preview\\Krita',
6 => 'OC\\Preview\\Movie',
7 => 'OC\\Preview\\PDF',
8 => 'OC\\Preview\\HEIC',
9 => 'OC\\Preview\\TIFF',
),
'enable_previews' => true,
'share_folder' => '/Shared',
'maintenance_window_start' => 10, // It run maintenance tasks at 06:00AM UTC and up.
'allow_local_remote_servers' => true,
'davstorage.request_timeout' => 86400,
'htaccess.RewriteBase' => '/', // For pretty urls
'dbpersistent' => false,
'default_phone_region' => 'US', // Set this based on your country code.
'trashbin_retention_obligation' => 'auto, 30',
'versions_retention_obligation' => 'auto, 30',
'activity_expire_days' => 30,
'simpleSignUpLink.shown' => false,
'auth.bruteforce.protection.enabled' => true, // Enable brute force settings
'ratelimit.protection.enabled' => true, // Similar to fail2ban
'files.chunked_upload.max_size' => 104857600,
'files_external_allow_create_new_local' => true,
'forbidden_filename_characters' =>
array (
0 => '<',
1 => '>',
2 => ':',
3 => '"',
4 => '|',
5 => '?',
6 => '*',
7 => '\\',
8 => '/',
9 => '~',
10 => '$',
),
'forbidden_filename_extensions' =>
array (
0 => ' ',
1 => '.',
2 => '.filepart',
3 => '.part',
),
'forbidden_filename_basenames' =>
array (
0 => 'con',
1 => 'prn',
2 => 'aux',
3 => 'nul',
4 => 'com0',
5 => 'com1',
6 => 'com2',
7 => 'com3',
8 => 'com4',
9 => 'com5',
10 => 'com6',
11 => 'com7',
12 => 'com8',
13 => 'com9',
14 => 'com¹',
15 => 'com²',
16 => 'com³',
17 => 'lpt0',
18 => 'lpt1',
19 => 'lpt2',
20 => 'lpt3',
21 => 'lpt4',
22 => 'lpt5',
23 => 'lpt6',
24 => 'lpt7',
25 => 'lpt8',
26 => 'lpt9',
27 => 'lpt¹',
28 => 'lpt²',
29 => 'lpt³',
),
Apply the configuration with:
sudo systemctl restart nginx php8.4-fpm redis-server
CONGRATULATIONS!, now your Nextcloud server is fully operational.
If you want to configure the proxy for selfhosting, please check this guide.
First enable notifications, open a web browser and login with the admin account. Go to the Administration settings => Notifications And set this configuration:
Install the notify_push app with:
sudo -E -u www-data php -f /var/www/nextcloud/occ app:install notify_push
Then copy the systemd service unit in /etc/systemd/system/notify_push.service provided by this repository:
sudo cp -r /opt/nextconf/notify/notify_push.service /etc/systemd/system/
NOTE: If you used the Nginx configuration of this repository you don't need to edit it, because already has the required proxy_pass location for notifications. Only adjust the systemd unit if you are using https.
Reload Systemd and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now notify_push.service
Configure the app with the correct URL:
# Example http://192.168.1.9/push
sudo -E -u www-data php -f /var/www/nextcloud/occ notify_push:setup http://[EXTERNAL LXC IP]/push
If you already configured your server behind a ssl proxy, simply execute:
sudo -E -u www-data php -f /var/www/nextcloud/occ notify_push:setup https://yourdomain.example/push
Changes to the systemd unit are not needed in this case. However if you are on full https without proxy or a local https instance then change the systemd unit first.
Finally restart Nginx and PHP:
sudo systemctl restart nginx php8.4-fpm
NOTE: Some browsers will block notifications and sound by default in http websites.
This repository includes a script to test notifications:
cd /opt/nextconf/cron
sudo chmod +x maintenance-notify.sh
sudo -u www-data ./maintenance-notify.sh
You will see a notification of the web browser.
Install the previews app:
sudo -E -u www-data php -f /var/www/nextcloud/occ app:install previewgenerator
Add the cronjob:
sudo chmod +x /opt/nextconf/cron/previews.sh
sudo crontab -u www-data -e
# Nextcloud Previews
*/5 * * * * /opt/nextconf/cron/previews.sh
Install the memories app:
sudo -E -u www-data php -f /var/www/nextcloud/occ app:install memories
Download the planet database:
sudo -E -u www-data php -f /var/www/nextcloud/occ memories:places-setup
Now go to the configuration page and check if everything is OK.
Recommended configuration for memories:
(Only with GPU Passthrough, enable VA-API, for nvidia you need to install the corresponding driver with: sudo apt install nvidia-driver)
If you want to automatically update your installed apps, simply add this cronjob as www-data user.
sudo crontab -u www-data -e
# Update Nextcloud apps
0 5 * * 0 bash /opt/nextconf/cron/update-apps.sh
In my case I want to update all my apps At 05:00 on Sunday. You can adjust your schedule using the cron syntax.
NOTE: Please execute this script after maintenance mode operations, as it is discouraged by the Nextcloud manual and can introduce issues after updates.
If you want to delete the container and start from scratch without losing data, first:
Shutdown the container
Go to the container resources configuration, and detach every bind-mounted directories you configured.
Delete the container, please only check "Purge from job configurations", never check "Destroy unreferenced disks owned by guest".
Some useful guides to complement your fresh Nextcloud instance.
- Selfhost/Proxy/HTTPS/SSL Support with Nginx Proxy Manager LXC
- How to install OnlyOffice Document Server 9
- How to install Adminer for database administration GUI
- How to migrate to a newer PHP version
- How to migrate to a newer PostgreSQL version
- How to upgrade Debian to a newer release
- How to upgrade Nextcloud
- How to make a LXC Snapshot Backup in Proxmox



