{"id":2134,"date":"2020-07-31T10:25:46","date_gmt":"2020-07-31T07:25:46","guid":{"rendered":"https:\/\/upcloud.com\/global\/us\/resources\/tutorials\/install-nextcloud-centos\/"},"modified":"2020-07-31T10:25:46","modified_gmt":"2020-07-31T07:25:46","slug":"install-nextcloud-centos","status":"publish","type":"tutorial","link":"https:\/\/upcloud.com\/global\/resources\/tutorials\/install-nextcloud-centos\/","title":{"rendered":"How to install Nextcloud on CentOS 8"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Nextcloud is an open-source file sync and sharing software that can be used as a replacement for Google Drive, Yandex Disk and similar cloud-based storage. Nextcloud now has Onlyoffice to allow shared document editing and Nextcloud Talk, to enable video conferencing, so is a virtual office productivity solution.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we will set up Nextcloud 18 on a single cloud server using nginx as the web server and PostgreSQL as the database engine.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/signup.upcloud.com\/\">Test hosting on UpCloud!<\/a><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up a new cloud server<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Login to UpCloud and deploy a new server. In this case, we are using a Simple plan server with 1GB Memory, 25 GB storage with the CentOS 8 template. Once your server is deployed login by using SSH.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh root@<span style=\"color: #ff0000;\">&lt;your-ip-address&gt;<\/span><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once logged in change the password, then enter the new password twice.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">passwd<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To secure the server, it is good to prevent login as the root user, thus another user needs to be created.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new username for yourself.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">adduser nextcloud<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then give the new user a password<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">passwd nextcloud<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Add the user to the wheel group to be able to invoke administrative privileges.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">usermod -aG wheel nextcloud<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then prevent root login by editing the <tt>\/etc\/ssh\/sshd_config<\/tt> file and set PermitRootLogin to no<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nano \/etc\/ssh\/sshd_config<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">PermitRootLogin no<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Exit the editor and restart SSHD service. Once the reboot process is finished, disconnect and log back into with the new username<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh nextcloud@<span style=\"color: #ff0000;\">&lt;your-ip-address&gt;<\/span><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">CentOS 8 offers some security protection when SE Linux is enabled. The primary purpose of SE Linux is to control file access permissions by following the principle of least privilege so that programs only access files that they need to. This is especially helpful when running a service such as NextCloud, but it does increase the complexity of the setup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We will change SE Linux from permissive mode to enforcing mode by setting the <tt>SELINUX=enforcing<\/tt><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/selinux\/config<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">SELINUX=enforcing<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then save the file and exit the editor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The changes will be applied at the next reboot but to save time, you can change the setting for the runtime using the command below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo setenforce enforcing<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you then check that SELinux mode.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sestatus<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The output should then give the following.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELinux status:               enabled\nSELinuxfs mount:              \/sys\/fs\/selinux\nSELinux root directory:       \/etc\/selinux\nLoaded policy name:           targeted\nCurrent mode:                 enforcing\nMode from config file:        permissive\nPolicy MLS status:            enabled\nPolicy deny_unknown status:   allowed\nMemory protection checking:   actual (secure)\nMax kernel policy version:    31<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lastly, update the installed software<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y update<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once done, continue below with the next step.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring a domain name<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You will need to configure a valid domain name to point to your cloud server IP address to be able to obtain SSL certificates as described later in this guide. If you do not have a domain name, you can use <a href=\"http:\/\/freenom.com\" target=\"_blank\" rel=\"noopener\">Freenom<\/a> to get a free temporary domain name.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can read more about domain name systems and how to configure DNS records to point your domain to the correct IP address at <a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/domain-name-system\/\" target=\"_blank\" rel=\"noreferrer noopener\">our guide to domain names<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing NGINX webserver<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next, we\u2019ll install NGINX to work as the underpinnings of our NextCloud server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But first, add the EPEL repository which<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y install epel-release<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then update the repositories and install Nginx<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y install nginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the installation<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nginx -v<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">should give an output similar to<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nginx version: nginx\/1.14.1<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable (ensure Nginx automatically starts upon reboot) and start Nginx<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo systemctl enable nginx\nsudo systemctl start nginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Nginx is running<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">curl -I 127.0.0.1<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which should give an output similar to<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">HTTP\/1.1 200 OK\nServer: nginx\/1.14.1\nDate: Thu, 30 Jul 2020 16:34:40 GMT\nContent-Type: text\/html\nContent-Length: 4057\nLast-Modified: Mon, 07 Oct 2019 21:16:24 GMT\nConnection: keep-alive\nETag: \"5d9bab28-fd9\"\nAccept-Ranges: bytes<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create a firewall rule to allow web access<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo firewall-cmd --zone=public --add-service=http --permanent\nsudo firewall-cmd --zone=public --add-service=https --permanent\nsudo firewall-cmd --reload<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Let&#8217;s Encrypt certificates<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Edit Nginx configuration to indicate the domain name<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/nginx\/nginx.conf<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Change the server name to use your domain, replace the <span style=\"color: #ff0000;\">my.domain.com<\/span> with yours.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">server_name <span style=\"color: #ff0000;\">my.domain.com www.my.domain.com<\/span>;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, save and exit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then reload NGINX to apply the changes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo systemctl reload nginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, install Certbot which will automate setting up the certificate.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf install -y certbot python3-certbot-nginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then obtain the certificates with the following command. Replace the <span style=\"color: #ff0000;\">my.domain.com<\/span> again with yours.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo certbot --nginx -d <span style=\"color: #ff0000;\">my.domain.com<\/span><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On the first run, you\u2019ll need to provide Certbot with some details.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It will then ask for your email address and that you read and agree to the terms of service.<\/li>\n\n\n\n<li>You can then choose to receive information from the Electronic Frontier Foundation (EFF).<\/li>\n\n\n\n<li>It should then indicate the my.domain.com and www.my.domain.com as domains to obtain certificates for, which you should agree to.<\/li>\n\n\n\n<li>Finally indicate that it should redirect all traffic from HTTP to HTTPS.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If successful, you\u2019ll see a confirmation of Certbot having obtained certificates for your domain.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing PostGRESQL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next, you\u2019ll need to install a database.&nbsp;We will use the external repository to install the latest version of PostgreSQL, version 12.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enable external PostgreSQL repository with the following command.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y install https:\/\/download.postgresql.org\/pub\/repos\/yum\/reporpms\/EL-8-x86_64\/pgdg-redhat-repo-latest.noarch.rpm<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Disable PostgreSQL from CentOS repository.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -qy module disable postgresql<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then install PostgreSQL from the external repository.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y install postgresql12 postgresql12-server<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Initialize the database and enable it to start automatically on when the server starts.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo \/usr\/pgsql-12\/bin\/postgresql-12-setup initdb\nsudo systemctl enable postgresql-12\nsudo systemctl start postgresql-12<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, set a password for the <tt>postgres<\/tt> user account using the command below, then enter a new password twice.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo passwd postgres<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once done, change to the <tt>postgres<\/tt> user account with the next command.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">su -l postgres<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enter the Postgres database software.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">psql<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then create a database for NextCloud. Replace the password with something secure.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE USER nextclouddbuser WITH PASSWORD '<span style=\"color: #ff0000;\">nextclouddbuserpassword<\/span>';<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create a database<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE DATABASE nextclouddb;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Give NextCloud user rights to access the database.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">GRANT ALL PRIVILEGES ON DATABASE nextclouddb TO nextclouddbuser;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Exit the database by typing in the following.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">q<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, exit the <tt>postgres<\/tt> user account.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">exit<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To enable connections to the database, the configuration must be modified, edit the <tt>pg_hba.conf<\/tt> file.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/var\/lib\/pgsql\/12\/data\/pg_hba.conf<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then find the host IPv4 line and set it as shown below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">host all all 127.0.0.1\/32 md5<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Similarly, change the line IPv6 host.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">host all all ::1\/128 md5<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, restart the Postgresql service to enable the changes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo systemctl restart postgresql-12<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Database ready and set! Continue below with the next step of the installation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Redis<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Redis is an open-source, in-memory data structure store we\u2019ll be using as a cache.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Install Redis with the following command.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf install -y redis<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then start and enable the Redis services.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo systemctl enable redis.service\nsudo systemctl start redis.service<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s all you need to do to configure Redis. Continue with PHP installation in the next section.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing PHP 7.4<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next, you\u2019ll need to install PHP. To begin, enable the REMI repository.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y install https:\/\/rpms.remirepo.net\/enterprise\/remi-release-8.rpm<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Install the utility packages.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf -y install yum-utils unzip policycoreutils-python-utils mlocate bzip2 wget tar<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable module stream for the REMI repository.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf module reset php\nsudo dnf -y module install php:remi-7.4<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Install PHP modules.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo dnf install -y php php-gd php-mbstring php-intl \nphp-pecl-apcu php-opcache php-json php-pecl-zip php-pear \nphp-pecl-imagick php-fpm php-pecl-redis5 \nphp-intl php-pgsql php-common php-pdo php-xml \nphp-lz4 php-xml php-pecl-crypto php-pecl-rar \nphp-pecl-pq php-pecl-lzf php-cli php-pecl-apcu-bc<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then set up PHP by first editing the <tt>\/etc\/php-fpm.d\/www.conf<\/tt> file.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/php-fpm.d\/www.conf<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Uncomment the following lines and change the admin memory limit to 512 megabytes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">;env[HOSTNAME] = $HOSTNAME\n;env[PATH] = \/usr\/local\/bin:\/usr\/bin:\/bin\n;env[TMP] = \/tmp\n;env[TMPDIR] = \/tmp\n;env[TEMP] = \/tmp\n...\n;php_admin_value[memory_limit] = 128M\n...\n;php_value[opcache.file_cache] = \/var\/lib\/php\/opcache<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, the lines should be as shown below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">env[HOSTNAME] = $HOSTNAME\nenv[PATH] = \/usr\/local\/bin:\/usr\/bin:\/bin\nenv[TMP] = \/tmp\nenv[TMPDIR] = \/tmp\nenv[TEMP] = \/tmp\n...\nphp_admin_value[memory_limit] = 512M\n...\nphp_value[opcache.file_cache] = \/var\/lib\/php\/opcache<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, create the following directories to store temporary information.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo mkdir -p \/var\/lib\/php\/{session,opcache,wsdlcache}\nsudo chown -R root:nginx \/var\/lib\/php\/{opcache,wsdlcache}\nsudo chown -R nginx:nginx \/var\/lib\/php\/session<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once done, start and enable PHP to run at boot.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo systemctl enable php-fpm\nsudo systemctl start php-fpm<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Downloading Nextcloud<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Get NextCloud server from their <a href=\"https:\/\/download.nextcloud.com\/\" target=\"_blank\" rel=\"noopener\">download page<\/a>. You can download the installation package using the following command. Check the web page for the latest version.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">wget https:\/\/download.nextcloud.com\/server\/releases\/nextcloud-18.0.7.tar.bz2<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, to verify the software package also download&nbsp;the SHA256 hash value, signature, and PGP key.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">wget https:\/\/download.nextcloud.com\/server\/releases\/nextcloud-18.0.7.tar.bz2.sha256\nwget https:\/\/download.nextcloud.com\/server\/releases\/nextcloud-18.0.7.tar.bz2.asc\nwget https:\/\/nextcloud.com\/nextcloud.asc<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then verify sha256sum with the command below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sha256sum -c nextcloud-18.0.7.tar.bz2.sha256 &lt; nextcloud-18.0.7.tar.bz2<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The output should be such as the example underneath.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nextcloud-18.0.7.tar.bz2: OK<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the signature, by first importing the key.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">gpg --import nextcloud.asc<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Which should give the following.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">gpg: directory '\/home\/nextcloud\/.gnupg' created\ngpg: keybox '\/home\/nextcloud\/.gnupg\/pubring.kbx' created\ngpg: \/home\/nextcloud\/.gnupg\/trustdb.gpg: trustdb created\ngpg: key D75899B9A724937A: public key \"Nextcloud Security &lt;security@nextcloud.com&gt;\" imported\ngpg: Total number processed: 1\ngpg:               imported: 1<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then check the signature.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">gpg --verify nextcloud-18.0.7.tar.bz2.asc nextcloud-18.0.7.tar.bz2<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Which should give output as below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">gpg: Signature made Wed 15 Jul 2020 20:07:06 UTC\ngpg:                using RSA key D75899B9A724937A\ngpg: Good signature from \"Nextcloud Security &lt;security@nextcloud.com&gt;\" [unknown]\ngpg: WARNING: This key is not certified with a trusted signature!\ngpg:          There is no indication that the signature belongs to the owner.\nPrimary key fingerprint: 2880 6A87 8AE4 23A2 8372  792E D758 99B9 A724 937A<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To verify the key, check it on a public Keyserver such as https:\/\/pgp.mit.edu\/, where you should search for 0xD75899B9A724937A<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, decompress the package to a folder.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">tar -xvf nextcloud-18.0.7.tar.bz2<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Copy the folder to the NGINX root directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo rm -rf \/usr\/share\/nginx\/html\nsudo cp -r nextcloud \/usr\/share\/nginx\/html<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Also, make the following data directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo mkdir \/usr\/share\/nginx\/data<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure that NGINX can read and write to the NextCloud folder<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo chown -R nginx:nginx \/usr\/share\/nginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then restart NGINX.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo systemctl restart nginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You\u2019ll also need to configure SELinux to allow access to the appropriate folders.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo semanage fcontext -a -t httpd_sys_rw_content_t '\/usr\/share\/nginx\/data(\/.*)?'\nsudo semanage fcontext -a -t httpd_sys_rw_content_t '\/usr\/share\/nginx\/html\/config(\/.*)?'\nsudo semanage fcontext -a -t httpd_sys_rw_content_t '\/usr\/share\/nginx\/html\/apps(\/.*)?'\nsudo semanage fcontext -a -t httpd_sys_rw_content_t '\/usr\/share\/nginx\/html\/.htaccess'\nsudo semanage fcontext -a -t httpd_sys_rw_content_t '\/usr\/share\/nginx\/html\/.user.ini'\nsudo semanage fcontext -a -t httpd_sys_rw_content_t '\/usr\/share\/nginx\/html\/3rdparty\/aws\/aws-sdk-php\/src\/data\/logs(\/.*)?'<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo restorecon -R '\/usr\/share\/nginx\/html\/'\nsudo restorecon -R '\/usr\/share\/nginx\/data\/'\nsudo setsebool -P httpd_can_network_connect on<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring NGINX and PHP for NextCloud<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now setup NGINX and PHP configuration files. Change the <tt>\/etc\/nginx\/nginx.conf<\/tt> to have the following contents.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/nginx\/nginx.conf<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"># For more information on configuration, see:\n# * Official English Documentation: http:\/\/nginx.org\/en\/docs\/\n# * Official Russian Documentation: http:\/\/nginx.org\/ru\/docs\/\n\nuser nginx;\nworker_processes auto;\nerror_log \/var\/log\/nginx\/error.log;\npid \/run\/nginx.pid;\n\n# Load dynamic modules. See \/usr\/share\/doc\/nginx\/README.dynamic.\ninclude \/usr\/share\/nginx\/modules\/*.conf;\n\nevents {\n    worker_connections 1024;\n}\n\nhttp {\n    log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n                    '$status $body_bytes_sent \"$http_referer\" '\n                    '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n    access_log \/var\/log\/nginx\/access.log main;\n    sendfile on;\n    tcp_nopush on;\n    tcp_nodelay on;\n    keepalive_timeout 65;\n    types_hash_max_size 2048;\n\n    include \/etc\/nginx\/mime.types;\n    default_type application\/octet-stream;\n\n    # Load modular configuration files from the \/etc\/nginx\/conf.d directory.\n    # See http:\/\/nginx.org\/en\/docs\/ngx_core_module.html#include\n    # for more information.\n    include \/etc\/nginx\/conf.d\/*.conf;\n\n    server {\n\n        # Load configuration files for the default server block.\n        include \/etc\/nginx\/default.d\/*.conf;\n\n        location \/ {\n        }\n    }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, create the NextCloud website configuration file <tt>\/etc\/nginx\/conf.d\/nextcloud.conf<\/tt><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/nginx\/conf.d\/nextcloud.conf<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Include the following in the configuration file. Due to the length of the file, you may need to copy it in parts. Replace all occurrences of <span style=\"color: #ff0000;\">my.domain.com<\/span> with your domain.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">upstream php-handler {\n    server unix:\/run\/php-fpm\/www.sock;\n}\n\nserver {\n    listen 80;\n    listen [::]:80;\n    server_name <span style=\"color: #ff0000;\">my.domain.com<\/span>;\n    # enforce https\n    return 301 https:\/\/$server_name:443$request_uri;\n}\n\nserver {\n    listen 443 ssl http2;\n    listen [::]:443 ssl http2;\n    server_name www.<span style=\"color: #ff0000;\">my.domain.com my.domain.com<\/span>;\n\n    ssl_certificate \/etc\/letsencrypt\/live\/<span style=\"color: #ff0000;\">my.domain.com<\/span>\/fullchain.pem; # managed by Certbot\n    ssl_certificate_key \/etc\/letsencrypt\/live\/<span style=\"color: #ff0000;\">my.domain.com<\/span>\/privkey.pem; # managed by Certbot\n    include \/etc\/letsencrypt\/options-ssl-nginx.conf; # managed by Certbot\n    ssl_dhparam \/etc\/letsencrypt\/ssl-dhparams.pem; # managed by Certbot\n\n    # Add headers to serve security-related headers\n    # Before enabling Strict-Transport-Security headers please read into this\n    # topic first.\n    add_header Strict-Transport-Security \"max-age=15768000; includeSubDomains; preload;\" always;\n    #\n    # WARNING: Only add the preload option once you read about\n    # the consequences in https:\/\/hstspreload.org\/. This option\n    # will add the domain to a hardcoded list that is shipped\n    # in all major browsers and getting removed from this list\n    # could take several months.\n    add_header Referrer-Policy \"no-referrer\" always;\n    add_header X-Content-Type-Options \"nosniff\" always;\n    add_header X-Download-Options \"noopen\" always;\n    add_header X-Frame-Options \"SAMEORIGIN\" always;\n    add_header X-Permitted-Cross-Domain-Policies \"none\" always;\n    add_header X-Robots-Tag \"none\" always;\n    add_header X-XSS-Protection \"1; mode=block\" always;\n\n    # Remove X-Powered-By, which is an information leak\n    fastcgi_hide_header X-Powered-By;\n\n    # Path to the root of your installation\n    root \/usr\/share\/nginx\/html\/;\n\n    location = \/robots.txt {\n        allow all;\n        log_not_found off;\n        access_log off;\n    }\n\n    # The following 2 rules are only needed for the user_webfinger app.\n    # Uncomment it if you're planning to use this app.\n    #rewrite ^\/.well-known\/host-meta \/public.php?service=host-meta last;\n\n    #rewrite ^\/.well-known\/host-meta.json \/public.php?service=host-meta-json last;\n\n    # The following rule is only needed for the Social app.\n    # Uncomment it if you're planning to use this app.\n    #rewrite ^\/.well-known\/webfinger \/public.php?service=webfinger last;\n\n    location = \/.well-known\/carddav {\n        return 301 $scheme:\/\/$host:$server_port\/remote.php\/dav;\n    }\n    location = \/.well-known\/caldav {\n        return 301 $scheme:\/\/$host:$server_port\/remote.php\/dav;\n    }\n\n    location ^~ {\n\n        # set max upload size\n        client_max_body_size 512M;\n        fastcgi_buffers 64 4K;\n\n        # Enable gzip but do not remove ETag headers\n        gzip on;\n        gzip_vary on;\n        gzip_comp_level 4;\n        gzip_min_length 256;\n        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;\n        gzip_types application\/atom+xml application\/javascript application\/json application\/ld+json application\/manifest+json application\/rss+xml application\/vnd.geo+json application\/vnd.ms-fontobject application\/x-font-ttf application\/x-web-app-manifest+json application\/xhtml+xml application\/xml font\/opentype image\/bmp image\/svg+xml image\/x-icon text\/cache-manifest text\/css text\/plain text\/vcard text\/vnd.rim.location.xloc text\/vtt text\/x-component text\/x-cross-domain-policy;\n\n        # Uncomment if your server is built with the ngx_pagespeed module\n        # This module is currently not supported.\n        # pagespeed off;\n\n        location \/ {\n            rewrite ^ \/index.php;\n        }\n\n        location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {\n            deny all;\n        }\n        location ~ ^\/(?:.|autotest|occ|issue|indie|db_|console) {\n            deny all;\n        }\n\n        location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {\n            fastcgi_split_path_info ^(.+?.php)(\/.*|)$;\n            set $path_info $fastcgi_path_info;\n            try_files $fastcgi_script_name =404;\n            include fastcgi_params;\n            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n            fastcgi_param PATH_INFO $path_info;\n            fastcgi_param HTTPS on;\n            # Avoid sending the security headers twice\n            fastcgi_param modHeadersAvailable true;\n            # Enable pretty urls\n            fastcgi_param front_controller_active true;\n            fastcgi_pass php-handler;\n            fastcgi_intercept_errors on;\n            fastcgi_request_buffering off;\n        }\n\n        location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {\n            try_files $uri\/ =404;\n            index index.php;\n        }\n\n        # Adding the cache control header for js, css and map files\n        # Make sure it is BELOW the PHP block\n        location ~ ^\/.+[^\/].(?:css|js|woff2?|svg|gif|map)$ {\n            try_files $uri \/index.php$request_uri;\n            add_header Cache-Control \"public, max-age=15778463\";\n            # Add headers to serve security related headers (It is intended\n            # to have those duplicated to the ones above)\n            # Before enabling Strict-Transport-Security headers please read\n            # into this topic first.\n            #add_header Strict-Transport-Security \"max-age=15768000; includeSubDomains; preload;\" always;\n            #\n            # WARNING: Only add the preload option once you read about\n            # the consequences in https:\/\/hstspreload.org\/. This option\n            # will add the domain to a hardcoded list that is shipped\n            # in all major browsers and getting removed from this list\n            # could take several months.\n            add_header Referrer-Policy \"no-referrer\" always;\n            add_header X-Content-Type-Options \"nosniff\" always;\n            add_header X-Download-Options \"noopen\" always;\n            add_header X-Frame-Options \"SAMEORIGIN\" always;\n            add_header X-Permitted-Cross-Domain-Policies \"none\" always;\n            add_header X-Robots-Tag \"none\" always;\n            add_header X-XSS-Protection \"1; mode=block\" always;\n\n            # Optional: Don't log access to assets\n            access_log off;\n        }\n\n        location ~ ^\/.+[^\/].(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {\n            try_files $uri \/index.php$request_uri;\n            # Optional: Don't log access to other assets\n            access_log off;\n        }\n    }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, increase the PHP memory limit.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/php.ini<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Change the <em>memory_limit<\/em> to 512 megabytes as below. You can use the search function in nano by pressing <em>ctrl+w<\/em>, typing in <em>memory_limit<\/em> and pressing the enter key.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">memory_limit = 512M<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Also, make the following change to the <tt>php-fpm<\/tt> configuration.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano \/etc\/php-fpm.d\/www.conf<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Change the user and group values from <tt>apache<\/tt> to <tt>nginx<\/tt> so that the lines read as shown underneath.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">user = nginx\ngroup = nginx<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Installing NextCloud<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Go to the NextCloud installation directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/usr\/share\/nginx\/html<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then install Nextcloud using the following command. Note that all commands for <tt>php occ<\/tt> need to be called from the <tt>\/usr\/share\/nginx\/html<\/tt> directory. Make sure you set the database password the same as you did when creating the database. Also, create a password for your admin account on Nextcloud web panel.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo -u nginx php occ maintenance:install \n--data-dir \/usr\/share\/nginx\/data \n--database \"pgsql\" \n--database-name \"nextclouddb\" \n--database-user \"nextclouddbuser\" \n--database-pass \"<span style=\"color: #ff0000;\">nextclouddbuserpassword<\/span>\" \n--admin-user \"nextcloudadmin\" \n--admin-pass \"<span style=\"color: #ff0000;\">nextcloudadminpassword<\/span>\"<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The install will take a moment, once done, you\u2019ll get a confirmation that Nextcloud was installed successfully.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, configure the database to secure the server by running the following command.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo -u nginx php occ db:add-missing-indices<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Before running the file cache conversion, first, enable the maintenance mode.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo -u nginx php occ maintenance:mode --on<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then run the conversion and select yes when asked to confirm.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo -u nginx php occ db:convert-filecache-bigint<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, turn maintenance mode off again.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo -u nginx php occ maintenance:mode --off<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Modify the file <tt>\/usr\/share\/nginx\/html\/config\/config.php<\/tt> to allow your domain name as a location to access Nextcloud from and to use caching.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo nano config\/config.php<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Change the contents to include the following. Replace <span style=\"color: #ff0000;\"><tt>my.domain.com<\/tt><\/span> again with your own and insert the <tt>memcache<\/tt> and <tt>redis<\/tt> configurations following the allowed domains array.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">...\n  array (\n    0 =&gt; 'localhost',\n    1 =&gt; '<span style=\"color: #ff0000;\">my.domain.com<\/span>',\n  ),\n  'memcache.distributed' =&gt; 'OCMemcacheRedis',\n  'memcache.locking' =&gt; 'OCMemcacheRedis',\n  'memcache.local' =&gt; 'OCMemcacheAPCu',\n  'redis' =&gt; array(\n    'host' =&gt; 'localhost',\n    'port' =&gt; 6379,\n  ),\n  'datadirectory' =&gt; '\/usr\/share\/nginx\/data',\n...<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">With all that done, reboot your Nextcloud server to make sure all settings have been applied successfully.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo reboot<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once the server is up again, all services should resume and the website comes online. Continue below with the finishing touches to install some apps and make sure your Nextcloud server is secure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring Nextcloud<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Log in to your Nextcloud instance through the web interface. Go to your Nextcloud website and sign in using the admin user and password as set in the Nextcloud install command.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">https:\/\/my.domain.com\/login<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once logged in, you\u2019ll see the Nextcloud dashboard. To make the last few configurations, go to the Apps view by clicking the cogwheel and the <em>Apps<\/em> link.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/nextcloud-apps.png\" alt=\"Nextcloud apps menu\" class=\"wp-image-16233\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Then on the Apps list, go to the <em>App bundles<\/em> by clicking the menu link on the left.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/nextcloud-app-bundles.png\" alt=\"Nextcloud app bundles\" class=\"wp-image-16232\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the App bundles view, enable and install the <em>Hub bundle<\/em> by clicking the <em>Enable all<\/em> button. Nextcloud will then begin downloading the selected apps and including them for your website.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/nextcloud-activating-bundle.png\" alt=\"Activating app bundle in Nextcloud\" class=\"wp-image-16231\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, you should see the selected apps enabled.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Log out of your instance and reboot the server once more.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo reboot<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, once the reboot process is complete, log back in.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check that document editing (Only Office and Community Document Server) and Talk applications work. You can test these by opening the Example.md file for edit. You can close the editor by clicking the X on the top right corner.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/nextcloud-documents.png\" alt=\"Nextcloud document editor\" class=\"wp-image-16234\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Next, check the server for any configuration warnings and that the software is up to date in the admin overview. If everything has been configured correctly, you should see a green check icon indicating all checks were passed.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/security-check-nextcloud.png\" alt=\"Security check on Nextcloud\" class=\"wp-image-16237\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Lastly, you can also use the Nextcloud security scanner to check your Nextcloud installation. Go to <a href=\"https:\/\/scan.nextcloud.com\/\" target=\"_blank\" rel=\"noopener\">https:\/\/scan.nextcloud.com\/<\/a> and enter your Nextcloud domain name in the text field, then click scan.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You should get a full score with A+ results as shown below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/nextcloud-security-scan-1.png\" alt=\"Nextcloud security scan using the external scanner\" class=\"wp-image-16238\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Afterwards, you should also consider to further secure your instance by, for example, <a href=\"https:\/\/upcloud.com\/global\/resources\/tutorials\/install-fail2ban-centos\/\" target=\"_blank\" rel=\"noreferrer noopener\">installing Fail2Ban<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"author":45,"featured_media":16241,"comment_status":"open","ping_status":"closed","template":"","community-category":[223,250],"class_list":["post-2134","tutorial","type-tutorial","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2134","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial"}],"about":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/types\/tutorial"}],"author":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/users\/45"}],"replies":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/comments?post=2134"}],"version-history":[{"count":0,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2134\/revisions"}],"wp:attachment":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/media?parent=2134"}],"wp:term":[{"taxonomy":"community-category","embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/community-category?post=2134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}