Install Nextcloud on Ubuntu 18.04 with Nginx – Google Cloud. Nextcloud is a platform to protect your data with on-premises file sync and online collaboration technology.
In this guide you are going to learn how to install Nextcloud 15 on Ubuntu 18.04 with Nginx, PHP 7.3 and connect to Cloud SQL.
Prerequisites
- A running Compute Engine, see the Setting up Compute Engine Instance with Ubuntu 18.04
- Initial Ubuntu Server Set up.
- Install LEMP stack on Ubuntu in Google Cloud.
- Setup Google Cloud DNS for your Domain name.
- A running Cloud SQL instance, see How to set up Cloud SQL in Google Cloud
With the above-completed
Set Up Directory
Nextcloud will be located in the home directory and have the following structure
Replace yourdomainname.com
with your original domain name.
home
-- yourdomainname.com
---- logs
---- public
The public
directory is your website’s root directory and logs
directory for your error logs
Now we create these directories and set correct permissions
You need to SSH into your VM Instance and run these commands
mkdir -p yourdomainname.com/logs yourdomainname.com/public
Download Nextcloud
Once you have your directory set up in Google Compute Engine, you can download Nextcloud using the following command.
cd ~/yourdomainname.com/public
wget https://download.nextcloud.com/server/releases/latest.tar.bz2
Now Nextcloud will be downloaded and you need to extract the downloaded file.
sudo tar -xjf latest.tar.bz2
sudo mv ~/yourdomainname.com/public/nextcloud/* ~/yourdomainname.com/public
Now you can setup correct permissions to the files.
sudo chmod -R 755 yourdomainname.com
sudo chown -R username ~/yourdomainname.com
Configure Nginx for Nextcloud
Create a new Nginx configuration for your website in the sites-available
directory.
sudo nano /etc/nginx/sites-available/yourdomainname.com
Copy and paste the following configuration, ensure that you change the server_name, error_log and root directives to match your domain name. Hit CTRL+X
followed by Y
to save the changes.
server {
listen [::]:80;
listen 80;
server_name yourdomainname.com;
error_log /home/username/yourdomainname.com/logs/error.log;
root /home/username/yourdomainname.com/public/;
index index.php;
add_header X-Content-Type-Options nosniff;
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;
add_header Referrer-Policy no-referrer;
fastcgi_hide_header X-Powered-By;
location / {
rewrite ^ /index.php$request_uri;
}
location ~* .(svg|svgz)$ {
types {}
default_type image/svg+xml;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
fastcgi_read_timeout 3600;
fastcgi_index index.php;
fastcgi_buffers 64 4k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
location ~ .(?:css|js|woff2?|svg|gif)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
add_header X-Content-Type-Options nosniff;
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;
add_header Referrer-Policy no-referrer;
access_log off;
}
location ~ .(?:png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$request_uri;
# Optional: Don't log access to other assets
access_log off;
}
}
Hit Ctrl+X
followed by Y
and Enter
to save the file and exit.
To enable this newly created website configuration, symlink the file that you just created into sites-enabled
sudo ln -s /etc/nginx/sites-available/yourdomainname.com /etc/nginx/sites-enabled/yourdomainname.com
Check your configuration and restart Nginx for the changes to take effect.
sudo nginx -t
sudo service nginx restart
Create SSL certificate and enable HTTP/2
HTTPS
HTTPS is a protocol for secure communication between a server (instance) and a client (web browser). Due to the introduction of Let’s Encrypt, which provides free SSL certificates, HTTPS are adopted by everyone and also provides trust to your audiences.
HTTP/2
HTTP/2 is the latest version of the HTTP protocol and can provide a significant improvement to the load time of your sites. There really is no reason not to enable HTTP/2, the only requirement is that the site must use HTTPS.
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install python-certbot-nginx
Now we have installed Certbot by Let’s Encrypt for Ubuntu 18.04, run this command to receive your certificates.
sudo certbot --nginx certonly
Enter your email
and agree to the terms and conditions, then you will receive the list of domains you need to generate SSL certificate.
To select all domains simply hit Enter
The Certbot client will automatically generate the new certificate for your domain. Now we need to update the Nginx config.
Redirect HTTP Traffic to HTTPS with www in Nginx
Open your site’s Nginx configuration file add replace everything with the following. Replacing the file path with the one you received when obtaining the SSL certificate. The ssl_certificate directive
should point to your fullchain.pem file, and the ssl_certificate_key
directive should point to your privkey.pem file.
server {
listen [::]:80;
listen 80;
server_name yourdomainname.com www.yourdomainname.com;
return 301 https://yourdomainname.com$request_uri;
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name www.yourdomainname.com;
ssl_certificate /etc/letsencrypt/live/yourdomainname.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomainname.com/privkey.pem;
error_log /home/username/yourdomainname.com/logs/error.log;
root /home/username/yourdomainname.com/public/;
index index.php;
return 301 https://yourdomainname.com$request_uri;
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name yourdomainname.com;
ssl_certificate /etc/letsencrypt/live/yourdomainname.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomainname.com/privkey.pem;
error_log /home/username/yourdomainname.com/logs/error.log;
root /home/username/yourdomainname.com/public/;
index index.php;
add_header X-Content-Type-Options nosniff;
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;
add_header Referrer-Policy no-referrer;
fastcgi_hide_header X-Powered-By;
location / {
rewrite ^ /index.php$request_uri;
}
location ~* .(svg|svgz)$ {
types {}
default_type image/svg+xml;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
fastcgi_read_timeout 3600;
fastcgi_index index.php;
fastcgi_buffers 64 4k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
location ~ .(?:css|js|woff2?|svg|gif)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
add_header X-Content-Type-Options nosniff;
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;
add_header Referrer-Policy no-referrer;
access_log off;
}
location ~ .(?:png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$request_uri;
access_log off;
}
}
The http2
value is all that is needed to enable the HTTP/2 protocol.
Hit CTRL+X
followed by Y
to save the changes.
Check your configuration and restart Nginx for the changes to take effect.
sudo nginx -t sudo service nginx restart
Renewing SSL Certificate
Certificates provided by Let’s Encrypt are valid for 90 days only, so you need to renew them often. Now you set up a cronjob to check for the certificate which is due to expire in next 30 days and renew it automatically.
sudo crontab -e
Add this line at the end of the file
0 0,12 * * * certbot renew >/dev/null 2>&1
Hit CTRL+X
followed by Y
to save the changes.
This cronjob will attempt to check for renewing the certificate twice daily.
Install Nextcloud
You need to set up Cloud SQL and create a database, user to install Nextcloud 15. Learn to Setup Cloud SQL and connect with Compute Engine
Once Cloud SQL setup is ready and configured to allow connections from your VM Instance.
Visit your domain name in your web browser to install Nextcloud 15 from your browser
You should see the installation wizard to complete the install.
Enter the Cloud SQL details to connect to the database.

For Hostname enter your Cloud SQL IP Address
Enter database name, username, password and click Finish setup to complete the installation.
Wait for the installation to complete.
Once the installation is complete you should see the Nextcloud dashboard.

Conclusion
Now you have learned how to install Nextcloud on your Ubuntu server with Nginx in Google Cloud and secure it with Let’s Encrypt.
Thanks for your time. If you face any problem or any feedback, please leave a comment below.
Hey,
first, thank you for the guides. They are really great. However, with this setup I always get a 403 error before I even get to install Nextcloud.
I redid every step and it always leads to the same result. What am I missing? The error logs only show that access denied due to a rule being present. However, I don’t know which one this can be?
Do you have any ideas? Thank you already in advance. 🙂
Hi, Please check if you have provided correct permissions
Hi,
thank you for the fast reply. All permissions were correctly set. The issue was the nginx rule provided in this article. I am referring to this part:
location ~ ^\/(?:.|autotest|occ|issue|indie|db_|console) {
deny all;
}
Removed the catch-all dot so that:
location ~ ^\/(?:autotest|occ|issue|indie|db_|console) {
deny all;
}
and the instance is running.
Thank you though. 🙂
Thank you, it’s working with your correction 🙂