Setup ownCloud on Ubuntu 20.04 | 18.04 with Nginx and Let’s Encrypt
This brief tutorial shows students and new users how to install ownCloud platform on Ubuntu 20.04 | 18.04 with Nginx HTTP server and Let’s encrypt wildcard SSL certificates.
OwnCloud is an open source, self-hosted file sync and share app platform that enables private cloud services on users’ own servers in their environments.
It provides similar functions like Dropbox and similar cloud storage services, and it’s free to download and install on your own servers without paying service providers.
You can use ownCloud to run your online cloud service platform and build amazing digital experiences with little efforts.
If you’re looking for a enterprise-grade cloud storage platform for your business or for individual needs, ownCloud should probably be a starting point for you. And if you want to learn how to easily install and mange it, then this post is all you need.
For more about ownCloud, please check their Homepage
To get started with installing ownCloud, follow the steps below:
Step 1: Install Nginx HTTP Server
ownCloud requires a web server to function, and Nginx is one of the most popular opensource web server available today.
To install Nginx on Ubuntu, run the commands below:
sudo apt update sudo apt install nginx
After installing Nginx, the commands below can be used to stop, start and enable Nginx service to always start up with the server boots.
sudo systemctl stop nginx.service sudo systemctl start nginx.service sudo systemctl enable nginx.service
To test whether Nginx is installed and functioning, open your web browser and browse to the server’s IP address or hostname.
http://localhost

If you see the above page in your browser, then Nginx is working as expected.
Step 2: Install MariaDB Database Server
You’ll also need a database server to run ownCloud. A database server is where ownCloud content get stored.
A true open source database server that you can use with ownCloud is MariaDB database server. It is fast, secure and the default server for almost all Linux servers.
To install MariaDB, run the commands below:
sudo apt-get install mariadb-server mariadb-client
After installing MariaDB, the commands below can be used to stop, start and enable MariaDB service to always start up when the server boots.
sudo systemctl stop mariadb.service sudo systemctl start mariadb.service sudo systemctl enable mariadb.service
Next, run the commands below to secure the database server with a root password if you were not prompted to do so during the installation.
sudo mysql_secure_installation
When prompted, answer the questions below by following the guide.
- Enter current password for root (enter for none): Just press the Enter
- Set root password? [Y/n]: Y
- New password: Enter password
- Re-enter new password: Repeat password
- Remove anonymous users? [Y/n]: Y
- Disallow root login remotely? [Y/n]: Y
- Remove test database and access to it? [Y/n]: Y
- Reload privilege tables now? [Y/n]: Y
To verify and validate that MariaDB is installed and working, login to the database console using the commands below:
sudo mysql -u root -p
type the root password when prompted.

If you see a similar screen as shown above, then the server was successfully installed.
Step 3: Install PHP 7.4 and Related Modules
ownCloud is a PHP based application, and PHP is required to run it. Since some versions of Ubuntu don’t have the latest version of PHP, you can add a third-party PPA repository to install PHP from there.
The command below will add a third-party PPA to Ubuntu.
sudo apt-get install software-properties-common sudo add-apt-repository ppa:ondrej/php
Then update and upgrade to PHP 7.4
sudo apt update
Next, run the commands below to install PHP 7.4 and related modules.
sudo apt install php7.4-fpm php7.4-common php7.4-mysql php7.4-gmp php7.4-curl php7.4-intl php7.4-mbstring php7.4-xmlrpc php7.4-gd php7.4-xml php7.4-cli php7.4-zip
After installing PHP 7.4, go and configure some basic settings that may be required for ownCloud to function properly.
Run the commands below to open PHP
sudo nano /etc/php/7.4/fpm/php.ini
Below are good settings to configure for most ownCloud websites.
file_uploads = On allow_url_fopen = On short_open_tag = On memory_limit = 256M cgi.fix_pathinfo = 0 upload_max_filesize = 100M max_execution_time = 360 date.timezone = America/Chicago
That should get PHP 7.4 installed with some basic settings to allow ownCloud to function.
Step 4: Create ownCloud Database
When all the servers installed above, it’s now time to begin setting up ownCloud environment. First, run the steps below to create a blank database for ownCloud to use.
Logon to MariaDB database console using the commands below:
sudo mysql -u root -p
Then create a database called owncloud
CREATE DATABASE owncloud;
Next, create a database user called ownclouduser and set password
CREATE USER 'ownclouduser'@'localhost' IDENTIFIED BY 'new_password_here';
Then grant the user full access to the database.
GRANT ALL ON owncloud.* TO 'ownclouduser'@'localhost' WITH GRANT OPTION;
Finally, save your changes and exit.
FLUSH PRIVILEGES; EXIT;
Step 5: Download ownCloud
At this point, ownCloud is ready to be downloaded and installed. Use the commands below to download the latest version of ownCloud.
https://owncloud.org/download/
At the time of this writing, the current version is 10.4.1.
Run the commands below to download it.
Then run the commands below to create ownCloud directory and extract the downloaded content there.
cd /tmp wget https://download.owncloud.org/community/owncloud-10.4.1.zip unzip owncloud-10.4.1.zip sudo mv owncloud /var/www/owncloud
After that, run the commands below to set the correct permissions for ownCloud to function.
Then run command below to allow www-data user to own the ownCloud directory.
sudo chown -R www-data:www-data /var/www/owncloud/ sudo chmod -R 755 /var/www/owncloud/
Step 6: Configure Nginx
Below is where you configure Nginx VirtualHost file for the ownCloud site you’re creating. This file defines how client requests are handled and processed.
Run the commands below to create a new VirtualHost file called owncloud in the /etc/nginx/sites-available/ directory.
sudo nano /etc/nginx/sites-available/owncloud
A very good configuration settings for most ownCloud site on Nginx server is below. This configuration should work great.
Copy the content below and save into the file created above.
upstream php-handler {
server unix:/var/run/php/php7.4-fpm.sock;
}
server {
listen 80;
listen [::]:80;
root /var/www/owncloud;
index index.php index.html index.htm;
server_name example.com www.example.com;
client_max_body_size 512M;
fastcgi_buffers 8 4K;
fastcgi_ignore_headers X-Accel-Buffering;
gzip off;
location / {
rewrite ^ /index.php$uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
return 404;
}
location ~ ^/(?:.|autotest|occ|issue|indie|db_|console) {
return 404;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|ocm-provider/.+|core/templates/40[34]).php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_read_timeout 180;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^/(?:updater|ocs-provider|ocm-provider)(?:$|/) {
try_files $uri $uri/ =404;
index index.php;
}
}
Save the file and exit.
After saving the file above, run the commands below to enable the new site, then restart Nginx server.
sudo ln -s /etc/nginx/sites-available/owncloud /etc/nginx/sites-enabled/ sudo systemctl restart nginx.service
At this stage, ownCloud is ready and can be launched by going to the server’s IP or hostname.
http://example.com
However, if you want to enable SSL or accept web traffic over HTTPS, then you can continue below to install and configure Let’s Encrypt free SSL certificates.
Step 7: Install Let’s Encrypt Wildcard Certificates
At step 6, ownCloud is ready to use without SSL. However, if you want to serve web traffic over HTTPS, then installing and configuring Let’s Encrypt SSL certificate or other public certificates is a must.
To install Let’s Encrypt, run the commands below.
sudo apt update sudo apt-get install letsencrypt
The commands above will install certbot tool and all dependencies that will be allowed to make the tool function.
Let’s Encrypt provides many ways to challenge you to validate that you own the domain you want to provide SSL certificates for. You will not be able to generate certificates if you can’t prove that you own the domain you want to secure.
For wildcard certificates, the only challenge method Let’s Encrypt accepts is the DNS challenge, which we can invoke via the preferred-challenges=dns flag.
So, to generate a wildcard cert for domain *.example.com, you run the commands below:
sudo certbot certonly --manual --preferred-challenges=dns --email admin@example.com --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d example.com -d *.example.com
The command options above are explained below:
- certonly: Obtain or renew a certificate, but do not install
- –manual: Obtain certificates interactively
- –preferred-challenges=dns: Use dns to authenticate domain ownership
- –server: Specify the endpoint to use to generate
- –agree-tos: Agree to the ACME server’s subscriber terms
- -d: Domain name to provide certificates for
After executing the command above, Let’s Encrypt will provide a text string to add a text record to your DNS entry…
Example:
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator manual, Installer None ------------------------------------------------------------------------------- Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about EFF and our work to encrypt the web, protect its users and defend digital rights. ------------------------------------------------------------------------------- (Y)es/(N)o: y Obtaining a new certificate Performing the following challenges: dns-01 challenge for example.com ------------------------------------------------------------------------------- NOTE: The IP of this machine will be publicly logged as having requested this certificate. If you're running certbot in manual mode on a machine that is not your server, please ensure you're okay with that. Are you OK with your IP being logged? ------------------------------------------------------------------------------- (Y)es/(N)o: y ------------------------------------------------------------------------------- Please deploy a DNS TXT record under the name _acme-challenge.example.com with the following value: x4MrZ6y-JqFJQRmq_lGi9ReRQHPa1aTC9J2O7wDKzq8 Before continuing, verify the record is deployed.
Go to your DNS provider portal and add a text record for the string above and save…

Wait a few mins before continuing from the prompt.
Some DNS providers take a wile to propagate changes so it may depend on your provider’s platform.
After the changes above and Let’s encrypt is able to validate that you own the domain, you should see a successful message as below:
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/example.com/privkey.pem Your cert will expire on 2020-01-09. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew"
The wildcard certificate is now generated and ready to be used.
To verify that the certificate is ready, run the commands below:
sudo certbot certificates
That should display similar screen as below:
Found the following certs: Certificate Name: example.com Domains: *.example.com Expiry Date: 2020-01-05 07:48:04+00:00 (VALID: 85 days) Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
Now, Let’s Encrypt’s certificates are valid for 90 days… You’ll want to setup a crob job to automate the renewal process… To do that, open crontab and add the entry below:
sudo crontab -e
Then add the line below and save…
0 1 * * * /usr/bin/certbot renew >> /var/log/letsencrypt/renew.log
Save and you’re done!
With Let’s Encrypt installed, reopen Nginx VirtualHost file created above and add Let’s Encrypt configurations to secure your website.
Run the commands below open the file.
sudo nano /etc/nginx/sites-available/owncloud
Then add the highlighted lines to the VirtualHost file as shown below:
upstream php-handler {
server unix:/var/run/php/php7.4-fpm.sock;
}
server {
listen 80;
listen [::]:80;
root /var/www/owncloud;
index index.php index.html index.htm;
server_name example.com www.example.com;
client_max_body_size 512M;
fastcgi_buffers 8 4K;
fastcgi_ignore_headers X-Accel-Buffering;
gzip off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS13+AESGCM+AES128:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1;
location / {
rewrite ^ /index.php$uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
return 404;
}
location ~ ^/(?:.|autotest|occ|issue|indie|db_|console) {
return 404;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|ocm-provider/.+|core/templates/40[34]).php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_read_timeout 180;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^/(?:updater|ocs-provider|ocm-provider)(?:$|/) {
try_files $uri $uri/ =404;
index index.php;
}
}
After the above, restart Nginx and PHP 7.4-FPM
sudo systemctl reload nginx sudo systemctl reload php7.4-fpm
Next, open your browser and browse to the server domain name. You should see ownCloud setup wizard to complete. Please follow the wizard carefully.
https://example.com/
ownCloud installer should begin the setup wizard. Choose the installation language and continue.

Accept the licensing terms, validate that all requirements are met, then contnue.
Next, type in the database name, username and password created above and continue.
After that, your store should be ready.

That’s it!
Conclusion:
Congratulation! You have successfully installed ownCloud on Ubuntu 18.04 | 20.04. If you find any error above, please use the comment form below to report it.
Thanks,
You may also like the post below:
Hi. Thanks for your step-by-step guide.
It is very clear and all the steps work.
I have a problem, though.
In step 7 I changed example.com and http://www.example.com in the file /etc/nginx/sites-available/owncloud by ‘localhost linuxathome’, because I want to use it in a local network at home.
When I go to http://localhost or http://linuxathome
I only see the nginx welcome page.
Is there something else that we need to run?
How do I access the owncloud virtual host?
Thanks a lot in advance!
got the same problem :( did u fix it ?
Change in directory
cd / etc / apache2 / sites-available /
there you can find the file 000-default.conf. If the file name exists, this configuration may be read / heard BEFORE your configuration. To die out of you, simply:
mv 000-default.conf 000-default.conf.old (or anything) heard. This means the file name.
Restart the web server again with:
systemctl restart apache2.service
I hope it can help you if you have heard of a problem like I ran into.
Unfortunately owncloud doesn’t yet support PHP 7.4. Instead you have to use 7.3 until a new version of owncloud is released.
Hello,
I’ve followed every step with the following changes:
Php 7.3 instead of 7.4
“mydomain” instead of “example.com”
But nonetheless, I only have the Nginx homepage instead of owncloud setup wizard..
Is there something wrong in this tutorial?
Hello,
Have the same problems, just showing the Nginx page, even if complete the owncloud installation.
when you open example.com, it directs you to a web site, even changing to something like home.com, it gives an error, if I type the ip only nginx appears. something must be missing, because I did it based on these two tutorials and none worked
https://websiteforstudents.com/setup-owncloud-on-ubuntu-20-04-18-04-with-nginx-and-lets-encrypt/https://websiteforstudents.com/setup-owncloud-server-with- composer-on-ubuntu-16-04-18-04-and-nginx-mariadb-and-php-7-2-support /
wtf suffered same issue only nginx page open.
no reply…………
Same problem,
Thinks we have to choose an issue alone…..
More with nginx I hope…..
I think the problem is related to the configuration of php fpm with nginx.
https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
also some aspect of the config file
http://nginx.org/en/docs/beginners_guide.html
Dependencies in STEP ONE can not be found. Whole thing does not work. Real nice.
ssl on; line is missing from the configuration line
Here is the working nginx configuration:
upstream php-handler {
server unix:/var/run/php/php7.4-fpm.sock;
}
server {
listen 443 ssl;
server_name example.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ‘TLS13+AESGCM+AES128:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS’;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1;
# Add headers to serve security related headers
# Before enabling Strict-Transport-Security headers please read into this topic first.
#add_header Strict-Transport-Security “max-age=15552000; includeSubDomains”;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options “SAMEORIGIN”;
add_header X-XSS-Protection “1; mode=block”;
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Path to the root of your installation
root /var/www/owncloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# The following 2 rules are only needed for the user_webfinger app.
# Uncomment it if you’re planning to use this app.
#rewrite ^/.well-known/host-meta /owncloud/public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /owncloud/public.php?service=host-meta-json last;
# set max upload size
client_max_body_size 512M;
fastcgi_buffers 64 4K;
# Disable gzip to avoid the removal of the ETag header
gzip off;
# Uncomment if your server is build with the ngx_pagespeed module
# This module is currently not supported.
#pagespeed off;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
location / {
rewrite ^ /index.php$uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
return 404;
}
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
return 404;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|ocm-provider/.+|core/templates/40[34]).php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_read_timeout 180;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^/(?:updater|ocs-provider)(?:$|/) {
try_files $uri $uri/ =404;
index index.php;
}
# Adding the cache control header for js and css files
# Make sure it is BELOW the PHP block
location ~* \.(?:css|js)$ {
try_files $uri /index.php$uri$is_args$args;
add_header Cache-Control “public, max-age=7200”;
# Add headers to serve security related headers (It is intended to have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into this topic first.
#add_header Strict-Transport-Security “max-age=15552000; includeSubDomains”;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options “SAMEORIGIN”;
add_header X-XSS-Protection “1; mode=block”;
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Optional: Don’t log access to assets
access_log off;
}
location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
try_files $uri /index.php$uri$is_args$args;
# Optional: Don’t log access to other assets
access_log off;
}
}