Install Nextcloud with PostgreSQL on Ubuntu 22.04

Most of the default installations of Nextcloud goes with MySQL/MariaDB, but Nextcloud support other databases too like PostgreSQL and SQLite. I will show you how to install Nextcloud with PostgreSQL on Ubuntu 22.04 in this article with Apache and PHP.

Let’s get started.

Packages installation

We will install all the required packages first including PostgreSQL.

apt install apache2 postgresql postgresql-contrib php-pgsql libapache2-mod-php php php-gmp php8.1-bcmath php-gd php-json php-curl php-mbstring php-intl php-imagick php-xml php-zip php-fpm php-redis php-apcu php-opcache php-ldap bzip2 zip unzip imagemagick vim ffmpeg redis-server

Enable PHP 8.1 FPM and it’s Apache configuration. This is for http2.

a2enconf php8.1-fpm
a2dismod php8.1
a2dismod mpm_prefork
a2enmod mpm_event

Enable Apache modules.

a2enmod ssl rewrite headers proxy proxy_http deflate cache proxy_wstunnel http2 proxy_fcgi env expires

Start and enable Apache and PHP-FPM.

systemctl start apache2
systemctl start php8.1-fpm

systemctl enable apache2
systemctl enable php8.1-fpm

PHP setup

As we will be using PHP FPM, so we will have to edit the php.ini configuration file inside fpm directory.

vim /etc/php/8.1/fpm/php.ini

*Line numbers are for information purpose only

output_buffering = off (line 226)
max_execution_time = 180 (line 409)
memory_limit = 512M (line 430)
post_max_size = 200M (line 698)
upload_max_filesize = 200M (line 850)
date.timezone = Europe/Berlin (line 968)

opcache.enable=1 (line 1767)
opcache.enable_cli=1 (line 1770)
opcache.memory_consumption=128 (line 1773)
opcache.interned_strings_buffer=8 (line 1776)
opcache.max_accelerated_files=10000 (line 1780)
opcache.revalidate_freq=1 (line 1798)
opcache.save_comments=1 (line 1805)

Check PHP timezone manual for your timezone. Restart PHP FPM afterwards.

systemctl restart php8.1-fpm

PostgreSQL setup

Start PostgreSQL with:

systemctl start postgresql

On initial systemctl startup if you get an error related to initdb: data folder does exist.

Login to PostgreSQL space as postgres user.

sudo -iu postgres

And run the following command.

initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'

exit

This time it will work.

systemctl start postgresql
systemctl enable postgresql

Now login again to PostgreSQL space as postgres user.

sudo -iu postgres

Create a user with createuser tool and -P flag to set a password. ncuser is the username.

createuser ncuser -P

Create a database with createdb tool.

createdb nextcloud

Once done, we will assign ncuser to nextcloud in psql shell.

Run the following command to grant all the privileges to user ncuser on nextcloud database.

psql

GRANT ALL PRIVILEGES ON DATABASE nextcloud TO ncuser;

\q

exit

Download Nextcloud

cd /var/www
wget https://download.nextcloud.com/server/releases/latest.zip

Unzip and move it to the web server root directory.

unzip latest.zip
rm -r /var/www/html/*
shopt -s dotglob
mv nextcloud/* html/

Change the owner and group of html directory.

chown -R www-data:www-data /var/www/html

Apache virtual host

cd /etc/apache2/sites-available
vim nextcloud.conf

Paste the following in it, change where necessary (Bold).

<VirtualHost *:80>
	ServerName DOMAIN.COM
	ServerAlias DOMAIN.COM
	DocumentRoot /var/www/html

	<Directory "/var/www/html">
		AllowOverride All
		Options -Indexes +FollowSymLinks
	</Directory>

	ErrorLog /var/log/apache2/DOMAIN.COM-error.log
</VirtualHost>

Enable this configuration and restart Apache.

a2dissite 000-default.conf
a2ensite nextcloud.conf

apachectl -t
systemctl restart apache2

Input your server URL/domain in the browser to start the setup process. Choose PostgreSQL as database.

SSL

Install Certbot and get a certificate for web root.

snap install certbot --classic
certbot certonly --webroot -w /var/www/html -d DOAMIN.COM

Apache Configuration

Final virtual host configuration /etc/apache2/sites-available/nextcloud.conf after getting SSL certificate.

<VirtualHost *:80>
	ServerName DOMAIN.COM
	ServerAlias www.DOMAIN.COM
	DocumentRoot /var/www/html
	RewriteEngine On
	RewriteCond %{HTTPS} off
	RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

	<Directory "/var/www/html">
		AllowOverride All
		Options -Indexes +FollowSymLinks
	</Directory>

	ErrorLog /var/log/apache2/DOMAIN.COM-error.log
</VirtualHost>

<VirtualHost *:443>
	ServerName DOMAIN.COM
	ServerAlias www.DOMAIN.COM
	DocumentRoot /var/www/html

	SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
	SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
	SSLHonorCipherOrder On
	Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
	Header always set X-Frame-Options DENY
	Header always set X-Content-Type-Options nosniff

	Protocols h2 http/1.1

	<Directory "/var/www/html">
		AllowOverride All
		Options -Indexes +FollowSymLinks
	</Directory>

	<FilesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf|ttf|woff)$">
		Header set Cache-Control "max-age=31536000, public"
	</FilesMatch>

	ErrorLog /var/log/apache2/DOMAIN.COM-error.log

	SSLEngine on
	SSLCertificateKeyFile /etc/letsencrypt/live/DOMAIN.COM/privkey.pem
	SSLCertificateFile /etc/letsencrypt/live/DOMAIN.COM/fullchain.pem
</VirtualHost>

And that would be it. Happy sharing.