diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..af20b15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+[._]*.s[a-w][a-z]
+[._]s[a-w][a-z]
+Session.vim
+.netrwhist
+*~
+tags
+.fuse_hidden*
+.directory
+.Trash-*
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..531d47c
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,24 @@
+
+Copyright (c) 2016, Aalaesar
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 14f2aea..9cb7d15 100644
--- a/README.md
+++ b/README.md
@@ -6,3 +6,526 @@ apt install ansible
ansible-pull -U "ssh://git@gitea.agofer.net:22001/jegomez/ansible-role-nextcloud.git"
```
+Based on [Aalaesar's role][1]
+
+[1]: https://github.com/aalaesar/install_nextcloud
+
+## install_nextcloud
+
+This role installs and configures an Nextcloud instance for a Debian/Ubuntu server.
+
+The role's main actions are:
+- [x] Packages dependencies installation.
+- [x] Database configuration (if located on the same host).
+- [x] Strengthened files permissions and ownership following Nextcloud recommendations.
+- [x] Web server configuration.
+- [x] Redis Server installation.
+- [x] Strengthened TLS configuration following _Mozilla SSL Configuration Generator_, intermediate profile by default, modern profile available.
+- [x] Post installation of Nextcloud applications
+
+## Requirements
+### Ansible version
+Ansible >2.4
+### Python libraries
+To use `ipwrap` filter in Ansible, you need to install the netaddr Python library on a computer on which you use Ansible (it is not required on remote hosts). It can usually be installed with either your system package manager or using pip:
+```bash
+$ pip install netaddr
+```
+### Setup module:
+The role uses facts gathered by Ansible on the remote host. If you disable the Setup module in your playbook, the role will not work properly.
+### Root access
+This role requires root access, so either configure it in your inventory files, run it in a playbook with a global `become: yes` or invoke the role in your playbook like:
+> playbook.yml:
+
+```YAML
+- hosts: dnsserver
+ become: yes
+ roles:
+ - role: aalaesar.install_nextcloud
+```
+
+## Role Variables
+
+Role's variables (and their default values):
+
+### Choose the version
+
+**_WARNING: Since Nexcloud 11 requires php v5.6 or later, command line installation will fail on old OS without php v5.6+ support._**
+
+_Known issue while installing Nextcloud 11 on an Ubuntu 14.04 system:_ [#27](https://github.com/aalaesar/install_nextcloud/issues/27)
+
+An URL will be generated following naming rules used in the nextcloud repository
+_Not following this rules correctly may make the role unable to download nextcloud._
+
+#### Repository naming rules:
+Some variables changes depending on the channel used and if get_latest is true.
+This table summarize the possible cases.
+
+|channel|latest|major&latest|major|full|special|
+|---|---|---|---|---|---|
+|**releases**|yes/no|_null_ \|9\|10\|...|_null_|"10.0.3"|_null_|
+|**prereleases**|_null_|_null_|_null_|"11.0.1"|_null_ \|"RC(n)\|beta(n)"|
+|**daily**|yes/no|_null_ \|master\|stable9\|...|master\|9\|10\|...|_null_|_null_ \|"YYYY-MM-DD"|
+
+**major&latest** = major value when latest is true
+_null_ = "not used"
+#### version variables:
+```YAML
+nextcloud_version_channel: "releases" # releases | prereleases | daily
+```
+Specify the main channel to use.
+```YAML
+nextcloud_get_latest: true
+```
+Specify if the "latest" archive should be downloaded.
+
+```YAML
+# nextcloud_version_major: 10
+```
+Specify what major version you desire.
+
+```YAML
+# nextcloud_version_full: "10.0.3"
+```
+The full version of the desired nextcloud instance. type **M.F.P** _(Major.Feature.Patch)_
+
+```YAML
+# nextcloud_version_special: ""
+```
+Specify a special string in the archive's filename.
+For prereleases: "RCn|beta" | for daily "YYYY-MM-DD"
+
+```YAML
+nextcloud_repository: "https://download.nextcloud.com/server"
+```
+Repository's URL.
+
+```YAML
+nextcloud_archive_format: "zip" # zip | tar.bz2
+```
+Choose between the 2 archive formats available in the repository.
+
+```YAML
+# nextcloud_full_url:
+```
+_If you don't like rules..._
+Specify directly a full URL to the archive. The role will skip the url generation and download the archive. **Requires nextcloud_version_major to be set along**.
+#### Examples:
+- Download your own archive:
+ (_you **must** specify the nextcloud major version along_)
+```YAML
+nextcloud_full_url: https://download.nextcloud.com/server/releases/nextcloud-23.0.0.zip
+nextcloud_version_major: 42
+```
+- Choose the latest release (default):
+```YAML
+nextcloud_version_channel: "releases"
+nextcloud_get_latest: true
+```
+- Choose the latest v23 release:
+```YAML
+nextcloud_version_channel: "releases"
+nextcloud_get_latest: true
+nextcloud_version_major: 23
+```
+- Choose a specific release:
+```YAML
+nextcloud_version_channel: "releases"
+nextcloud_get_latest: false
+nextcloud_version_full: "23.0.0"
+```
+- Get the nextcloud 24.0.1 prerelease 1:
+```YAML
+nextcloud_version_channel: "prereleases"
+nextcloud_version_full: "23.0.0"
+nextcloud_version_special: "RC3"
+```
+- Get the latest daily:
+```YAML
+nextcloud_version_channel: "daily"
+nextcloud_get_latest: true
+```
+- Get the latest daily for stable 10:
+```YAML
+nextcloud_version_channel: "daily"
+nextcloud_get_latest: true
+nextcloud_version_major: "stable23"
+```
+- Get the daily for master at january 1rst 2022:
+```YAML
+nextcloud_version_channel: "daily"
+nextcloud_get_latest: false
+nextcloud_version_major: "master"
+nextcloud_version_special: "2022-01-01"
+```
+### Main configuration
+```YAML
+nextcloud_trusted_domain:
+ - "{{ ansible_fqdn }}"
+ - "{{ ansible_default_ipv4.address }}"
+```
+The list of domains you will use to access the same Nextcloud instance.
+```YAML
+nextcloud_trusted_proxies: []
+```
+The list of trusted proxies IPs if Nextcloud runs through a reverse proxy.
+```YAML
+nextcloud_instance_name: "{{ nextcloud_trusted_domain | first }}"
+```
+The name of the Nextcloud instance. By default, the first element in the list of trusted domains
+### WebServer configuration
+```YAML
+nextcloud_install_websrv: true
+```
+The webserver setup can be skipped if you have one installed already.
+```YAML
+nextcloud_websrv: "apache2"
+```
+The http server used by nextcloud. Available values are: **apache2** or **nginx**.
+```YAML
+nextcloud_disable_websrv_default_site: false
+```
+Disable the default site of the chosen http server. (`000-default.conf` in Apache, `default` in Nginx.)
+```YAML
+nextcloud_websrv_template: "templates/{{nextcloud_websrv}}_nc.j2"
+```
+The jinja2 template creating the instance configuration for your webserver.
+You can provide your own through this parameter.
+```YAML
+nextcloud_webroot: "/opt/nextcloud"
+```
+The Nextcloud root directory.
+```YAML
+nextcloud_data_dir: "/var/ncdata"
+```
+The Nextcloud data directory. This directory will contain all the Nextcloud files. Choose wisely.
+```YAML
+nextcloud_admin_name: "admin"
+```
+Defines the Nextcloud admin's login.
+```YAML
+nextcloud_admin_pwd: "secret"
+```
+Defines the Nextcloud admin's password.
+**Not defined by default**
+If not defined by the user, a random password will be generated.
+
+```YAML
+nextcloud_max_upload_size: "512m"
+```
+Defines the max size allowed to be uploaded on the server.
+Use 0 to __disable__.
+
+### Redis Server configuration
+```YAML
+nextcloud_install_redis_server: true
+```
+Whenever the role should install a redis server on the same host.
+```YAML
+nextcloud_redis_host: '/var/run/redis/redis.sock'
+```
+The Hostname of redis server. It is set to use UNIX socket as redis is on same host. Set to hostname if it is not the case.
+```YAML
+nextcloud_redis_port: 0
+```
+The port of redis server. Port 0 is for socket use. Default redis port is 6379.
+```YAML
+nextcloud_redis_settings:
+ - { name: 'redis host', value: '"{{ nextcloud_redis_host }}"' }
+ - { name: 'redis port', value: "{{ nextcloud_redis_port }}" }
+ - { name: 'memcache.locking', value: '\OC\Memcache\Redis' }
+```
+Settings to use redis server with Nextcloud
+
+### Nextcloud Background Jobs
+```YAML
+nextcloud_background_cron: True
+```
+Set operating system cron for executing Nextcloud regular tasks. This method enables the execution of scheduled jobs without the inherent limitations the Web server might have.
+
+### Custom nextcloud settings
+```YAML
+nextcloud_config_settings:
+ - { name: 'overwrite.cli.url', value: 'https://{{ nextcloud_trusted_domain | first }}' }
+ - { name: 'memcache.local', value: '\OC\Memcache\APCu' }
+ - { name: 'open_basedir', value: '/dev/urandom' }
+ - { name: 'mysql.utf8mb4', value: 'true' }
+ - { name: 'updater.release.channel', value: 'production' } # production | stable | daily | beta
+```
+Setting custom Nextcloud setting in config.php ( [Config.php Parameters Documentations](https://docs.nextcloud.com/server/stable/admin_manual/) )
+
+Default custom settings:
+- **Base URL**: 'https:// {{nextcloud_instance_name}}'
+- **Memcache local**: APCu
+- **Mysql Character Set**: utf8mb4
+- **PHP read access to /dev/urandom**: Enabled
+- **Updater Relese Channel:** Production
+### Database configuration
+```YAML
+nextcloud_install_db: true
+```
+Whenever the role should install and configure a database on the same host.
+```YAML
+nextcloud_db_host: "127.0.0.1"
+```
+The database server's ip/hostname where Nextcloud's database is located.
+```YAML
+nextcloud_db_backend: "mysql"
+```
+Database type used by nextcloud.
+
+Supported values are:
+- mysql
+- mariadb
+- pgsql _(PostgreSQL)_
+
+```YAML
+nextcloud_db_name: "nextcloud"
+```
+The Nextcloud instance's database name.
+```YAML
+nextcloud_db_admin: "ncadmin"
+```
+The Nextcloud instance's database user's login
+```YAML
+nextcloud_db_pwd: "secret"
+```
+The Nextcloud instance's database user's password.
+
+**Not defined by default.**
+
+If not defined by the user, a random password will be generated.
+
+### TLS configuration
+```YAML
+nextcloud_install_tls: true
+```
+TLS setup can be skipped if you manage it separately (e.g. behind a reverse proxy).
+```YAML
+nextcloud_tls_enforce: true
+```
+Force http to https.
+```YAML
+nextcloud_mozilla_modern_ssl_profile: true
+```
+Force Mozilla modern SSL profile in webserver configuration (intermediate profile is used when false).
+```YAML
+nextcloud_hsts: false
+```
+Set HTTP Strict-Transport-Security header (e.g. "max-age=15768000; includeSubDomains; preload").
+
+_(Before enabling HSTS, please read into this topic first)_
+```YAML
+nextcloud_tls_cert_method: "self-signed"
+```
+Defines various method for retrieving a TLS certificate.
+- **self-signed**: generate a _one year_ self-signed certificate for the trusted domain on the remote host and store it in _/etc/ssl_.
+- **signed**: copy provided signed certificate for the trusted domain to the remote host or in /etc/ssl by default.
+ Uses:
+```YAML
+ # Mandatory:
+ nextcloud_tls_src_cert: /local/path/to/cert
+ # ^local path to the certificate's key.
+ nextcloud_tls_src_cert_key: /local/path/to/cert/key
+ # ^local path to the certificate.
+
+ # Optional:
+ nextcloud_tls_cert: "/etc/ssl/{{ nextcloud_trusted_domain }}.crt"
+ # ^remote absolute path to the certificate's key.
+ nextcloud_tls_cert_key: "/etc/ssl/{{ nextcloud_trusted_domain }}.key"
+ # ^remote absolute path to the certificate.
+```
+- **installed**: if the certificate for the trusted domain is already on the remote host, specify its location.
+ Uses:
+```YAML
+ nextcloud_tls_cert: /path/to/cert
+ # ^remote absolute path to the certificate's key. mandatory
+ nextcloud_tls_cert_key: /path/to/cert/key
+ # ^remote absolute path to the certificate. mandatory
+ nextcloud_tls_cert_chain: /path/to/cert/chain
+ # ^remote absolute path to the certificate's full chain- used only by apache - Optional
+```
+```YAML
+nextcloud_tls_session_cache_size: 50m
+```
+Set the size of the shared nginx TLS session cache to 50 MB.
+
+### System configuration
+
+install and use a custom version for PHP instead of the default one:
+```YAML
+php_ver: '7.1'
+php_custom: yes
+php_ver: "{{ php_ver }}"
+php_dir: "/etc/php/{{ php_ver }}"
+php_bin: "php-fpm{{ php_ver }}"
+php_pkg_apcu: "php-apcu"
+php_pkg_spe:
+ - "php{{ php_ver }}-imap"
+ - "php{{ php_ver }}-imagick"
+ - "php{{ php_ver }}-xml"
+ - "php{{ php_ver }}-zip"
+ - "php{{ php_ver }}-mbstring"
+ - "php-redis"
+php_socket: "/run/php/{{ php_ver }}-fpm.sock"
+php_memory_limit: 512M
+```
+
+```YAML
+nextcloud_websrv_user: "www-data"
+```
+system user for the http server
+```YAML
+nextcloud_websrv_group: "www-data"
+```
+system group for the http server
+```YAML
+nextcloud_mysql_root_pwd: "secret"
+```
+root password for the mysql server
+
+**Not defined by default**
+
+If not defined by the user, and mysql/mariadb is installed during the run, a random password will be generated.
+
+### Generated password
+The role uses Ansible's password Lookup:
+- If a password is generated by the role, ansible stores it **locally** in **nextcloud_instances/{{ nextcloud_trusted_domain }}/** (relative to the working directory)
+- if the file already exist, it reuse its content
+- see [the ansible password lookup documentation](https://docs.ansible.com/ansible/latest/plugins/lookup/password.html) for more info
+
+### Post installation:
+#### Applications installation
+
+Since **v1.3.0**, it is possible to download, install and enable nextcloud applications during a post-install process.
+
+The application (app) to install have to be declared in the `nextcloud_apps` dictionary in a "key:value" pair.
+- The app name is the key
+- The download link, is the value.
+
+```YAML
+nextcloud_apps:
+ app_name_1: "http://download_link.com/some_archive.zip"
+ app_name_2: "http://getlink.com/another_archive.zip"
+```
+
+Alternatively, if you need to configure an application after enabling it, you can use this structure.
+```YAML
+nextcloud_apps:
+ app_name_1:
+ source: "http://download_link.com/some_archive.zip"
+ conf:
+ parameter1: ldap:\/\/ldapsrv
+ parameter2: another_value
+```
+
+**Notes:**
+- Because the role is using nextcloud's occ, it is not possible to install an app from the official nextcloud app store.
+- If you know that the app is already installed, you can give an empty string to skip the download.
+- The app name need the be equal to the folder name located in the **apps folder** of the nextcloud instance, which is extracted from the downloaded archive.
+The name may not be canon some times. (like **appName-x.y.z** instead of **appName**)
+- The role will **not** update an already enabled application.
+- The configuration is applied only when the app in enabled the first time:
+Changing a parameter, then running the role again while the app is already enabled will **not** update its configuration.
+- this post_install process is tagged and can be called directly using the `--tags install_apps` option.
+
+## Dependencies
+
+none
+
+## Example Playbook
+### Case 1: Installing a quick Nextcloud demo
+In some case, you may want to deploy quickly many instances of Nextcloud on multiple hosts for testing/demo purpose and don't want to tune the role's variables for each hosts: Just run the playbook without any additional variable (all default) !
+
+```YAML
+---
+- hosts: server
+ roles:
+ - role: aalaesar.install_nextcloud
+```
+
+- This will install a Nextcloud 10.0.1 instance in /opt/nextcloud using apache2 and mysql.
+- it will be available at **https:// {{ ansible default ipv4 }}** using a self signed certificate.
+- Generated passwords are stored in **nextcloud_instances/{{ nextcloud_trusted_domain }}/** from your working directory.
+
+### Case 1.1: specifying the version channel, branch, etc.
+You can choose the version channel to download a specific version of nextcloud. Here's a variation of the previous case, this time installing the latest nightly in master.
+```YAML
+---
+- hosts: server
+ roles:
+ - role: aalaesar.install_nextcloud
+ nextcloud_version_channel: "daily"
+ nextcloud_version_major: "master"
+```
+
+### Case 2: Using letsencrypt with this role.
+This role is not designed to manage letsencrypt certificates. However you can still use your certificates with nextcloud.
+
+You must create first your certificates using a letsencrypt ACME client or an Ansible role like [this one] (https://github.com/jaywink/ansible-letsencrypt)
+
+then call _install_nextcloud_ by setting `nextcloud_tls_cert_method: "installed"`
+
+Here 2 examples for apache and nginx (because they have slightly different configurations)
+```YAML
+---
+- hosts: apache_server
+ roles:
+ - role: aalaesar.install_nextcloud
+ nextcloud_trusted_domain:
+ - "example.com"
+ nextcloud_tls_cert_method: "installed"
+ nextcloud_tls_cert: "/etc/letsencrypt/live/example.com/cert.pem"
+ nextcloud_tls_cert_key: "/etc/letsencrypt/live/example.com/privkey.pem"
+ nextcloud_tls_cert_chain: "/etc/letsencrypt/live/example.com/chain.pem"
+
+- hosts: nginx_server
+ roles:
+ - role: aalaesar.install_nextcloud
+ nextcloud_trusted_domain:
+ - "example2.com"
+ nextcloud_tls_cert_method: "installed"
+ nextcloud_tls_cert: "/etc/letsencrypt/live/example2.com/fullchain.pem"
+ nextcloud_tls_cert_key: "/etc/letsencrypt/live/example2.com/privkey.pem"
+```
+### Case 3: integration to an existing system.
+- An Ansible master want to install a new Nextcloud instance on an existing Ubuntu 14.04 server with nginx & mariadb installed.
+- As is server do not meet the php requirements for Nextcloud 11, he chooses to use the lastest Nextcloud 10 release.
+- He wants it to be accessible from internet at _cloud.example.tld_ and from his intranet at _dbox.intra.net_.
+- He already have a valid certificate for the intranet domain in /etc/nginx/certs/ installed
+- he wants the following apps to be installed & enabled : files_external, calendar, agenda, richdocuments (Collabora)
+- The richdocuments app has to be configured to point out to the Collabora domain.
+
+He can run the role with the following variables to install Nextcloud accordingly to its existing requirements .
+
+```YAML
+---
+- hosts: server
+ roles:
+ - role: aalaesar.install_nextcloud
+ nextcloud_version_major: 23
+ nextcloud_trusted_domain:
+ - "cloud.example.tld"
+ - "dbox.intra.net"
+ nextcloud_websrv: "nginx"
+ nextcloud_admin_pwd: "secret007"
+ nextcloud_webroot: "/var/www/nextcloud/"
+ nextcloud_data_dir: "/ncdata"
+ nextcloud_db_pwd: "secretagency"
+ nextcloud_tls_cert_method: "installed"
+ nextcloud_tls_cert: "/etc/nginx/certs/nextcloud.crt"
+ nextcloud_tls_cert_key: "/etc/nginx/certs/nextcloud.key"
+ nextcloud_mysql_root_pwd: "42h2g2"
+ nextcloud_apps:
+ files_external: "" #enable files_external which is already installed in nextcloud
+ calendar: "https://github.com/nextcloud/calendar/releases/download/v1.5.0/calendar.tar.gz"
+ contacts: "https://github.com/nextcloud/contacts/releases/download/v1.5.3/contacts.tar.gz"
+ richdocuments-1.1.25: # the app name is equal to the extracted folder name from the archive
+ source: "https://github.com/nextcloud/richdocuments/archive/1.1.25.zip"
+ conf:
+ wopi_url: 'https://office.example.tld'
+```
+
+## License
+
+BSD
diff --git a/local.yml b/local.yml
new file mode 100644
index 0000000..e9ba392
--- /dev/null
+++ b/local.yml
@@ -0,0 +1,11 @@
+- hosts: localhost
+ gather_facts: yes
+ user: root
+
+ roles:
+ - nextcloud
+
+ vars:
+ nextcloud_trusted_domain:
+ - cloud.agofer.net
+
diff --git a/roles/nextcloud/defaults/main.yml b/roles/nextcloud/defaults/main.yml
new file mode 100644
index 0000000..49e84b5
--- /dev/null
+++ b/roles/nextcloud/defaults/main.yml
@@ -0,0 +1,94 @@
+---
+# defaults file for nextcloud
+# [DOWNLOAD]
+ # An URL will be generated following naming rules used by nextcloud's repository
+ # Not following this rules correctly will make the role unable to download nextcloud.
+nextcloud_version_channel: "releases" # mandatory # releases | prereleases | daily
+ # channel releases requires version_full.
+ # channel prereleases requires version_full. Optional: version_special.
+ # channel daily requires requires version_full & version_special.
+nextcloud_get_latest: true # mandatory # specify if the latest archive should be downloaded.
+ # Override generated file name for channels: releases | daily.
+ # optional : version_major.
+# nextcloud_version_major: 10 # (9 | 10 | 11| ..) for releases | for daily : (master | stable9 | stable10 | ...)
+# nextcloud_version_full: "10.0.3" # full version string
+# nextcloud_version_special: "" # For prereleases: "RCn|beta" | for daily "YYYY-MM-DD"
+nextcloud_repository: "https://download.nextcloud.com/server" # Domain URL where to download Nextcloud.
+nextcloud_archive_format: "zip" # zip | tar.bz2
+# nextcloud_full_url: "https://download.nextcloud.com/server/releases/nextcloud-23.0.0.zip" # specify directly a full URL to the archive if you don't like rules.
+
+
+# [CONFIG]
+nextcloud_trusted_domain:
+ - "{{ ansible_fqdn }}"
+ - "{{ ansible_default_ipv4.address }}"
+
+nextcloud_ipv6: false
+
+nextcloud_trusted_proxies: []
+
+nextcloud_instance_name: "{{ nextcloud_trusted_domain | first }}"
+
+nextcloud_disable_websrv_default_site: false
+nextcloud_websrv_template: "templates/nginx_nc.j2"
+nextcloud_webroot: "/opt/nextcloud"
+nextcloud_data_dir: "/var/ncdata"
+nextcloud_admin_name: "admin"
+# nextcloud_admin_pwd: "secret"
+
+nextcloud_install_redis_server: true
+nextcloud_redis_host: '/var/run/redis/redis.sock'
+nextcloud_redis_port: 0
+
+nextcloud_redis_settings:
+ - { name: 'redis host', value: '"{{ nextcloud_redis_host }}"' }
+ - { name: 'redis port', value: "{{ nextcloud_redis_port }}" }
+ - { name: 'memcache.locking', value: '\OC\Memcache\Redis' }
+
+nextcloud_background_cron: True
+
+## Custom nextcloud settings
+## https://docs.nextcloud.com/server/12/admin_manual/configuration_server/config_sample_php_parameters.html
+nextcloud_config_settings:
+ - { name: 'overwrite.cli.url', value: 'https://{{ nextcloud_trusted_domain | first }}' }
+ - { name: 'memcache.local', value: '\OC\Memcache\APCu' }
+ - { name: 'open_basedir', value: '/dev/urandom' }
+ - { name: 'mysql.utf8mb4', value: 'true' }
+ - { name: 'updater.release.channel', value: 'production' } # production | stable | daily | beta
+
+# [DATABASE]
+nextcloud_install_db: true
+nextcloud_db_host: "127.0.0.1"
+nextcloud_db_backend: "mysql" # "mysql"/"mariadb" | "pgsql"
+nextcloud_db_name: "nextcloud"
+nextcloud_db_admin: "ncadmin"
+# nextcloud_db_pwd: "secret"
+
+# [TLS] parameters used in the apache2 & nginx templates
+## max file's size allowed to be uploaded on the server
+nextcloud_max_upload_size: 512m # in Byte or human readable size notation (g|m|k)
+nextcloud_mozilla_modern_ssl_profile: false # when false, intermediate profile is used
+nextcloud_tls_dhparam: "/etc/ssl/dhparam.pem"
+nextcloud_hsts: false # recommended >= 15552000
+# nextcloud_tls_cert: /path/to/cert
+# nextcloud_tls_cert_key: /path/to/cert/key
+# nextcloud_tls_cert_chain: /path/to/cert/chain
+# nextcloud_tls_src_cert: /path/to/cert
+# nextcloud_tls_src_cert_key: /path/to/cert/key
+nextcloud_tls_session_cache_size: 50m # in Byte or human readable size notation (g|m|k)
+
+# [APPS]
+nextcloud_apps: {}
+
+# [SYSTEM]
+#nextcloud_mysql_root_pwd: "secret"
+
+php_custom: false
+php_memory_limit: 512M
+
+# [system]
+# system_configuration for php 7.4:
+php_dir: "/etc/php/7.4"
+php_bin: "php-fpm7.4"
+
+php_socket: "/run/php/php7.4-fpm.sock"
diff --git a/roles/nextcloud/files/mysql_nextcloud.cnf b/roles/nextcloud/files/mysql_nextcloud.cnf
new file mode 100644
index 0000000..c2a1bdc
--- /dev/null
+++ b/roles/nextcloud/files/mysql_nextcloud.cnf
@@ -0,0 +1,12 @@
+################################################################################
+# This file was generated by Ansible
+# Do NOT modify this file by hand!
+################################################################################
+
+# Nextcloud mysql.cnf
+
+[mysqld]
+binlog_format = MIXED
+innodb_large_prefix=on
+innodb_file_format=barracuda
+innodb_file_per_table=true
\ No newline at end of file
diff --git a/roles/nextcloud/files/nextcloud_choosing_version.png b/roles/nextcloud/files/nextcloud_choosing_version.png
new file mode 100644
index 0000000..1748258
Binary files /dev/null and b/roles/nextcloud/files/nextcloud_choosing_version.png differ
diff --git a/roles/nextcloud/files/nextcloud_custom_mimetypemapping.json b/roles/nextcloud/files/nextcloud_custom_mimetypemapping.json
new file mode 100644
index 0000000..88c5ce5
--- /dev/null
+++ b/roles/nextcloud/files/nextcloud_custom_mimetypemapping.json
@@ -0,0 +1,182 @@
+{
+ "_comment" : "This file was generated by Ansible, Do NOT modify this file by hand!",
+
+ "3gp": ["video/3gpp"],
+ "7z": ["application/x-7z-compressed"],
+ "accdb": ["application/msaccess"],
+ "ai": ["application/illustrator"],
+ "apk": ["application/vnd.android.package-archive"],
+ "arw": ["image/x-dcraw"],
+ "avi": ["video/x-msvideo"],
+ "bash": ["text/x-shellscript"],
+ "blend": ["application/x-blender"],
+ "bin": ["application/x-bin"],
+ "bmp": ["image/bmp"],
+ "bpg": ["image/bpg"],
+ "bz2": ["application/x-bzip2"],
+ "cb7": ["application/x-cbr"],
+ "cba": ["application/x-cbr"],
+ "cbr": ["application/x-cbr"],
+ "cbt": ["application/x-cbr"],
+ "cbtc": ["application/x-cbr"],
+ "cbz": ["application/x-cbr"],
+ "cc": ["text/x-c"],
+ "cdr": ["application/coreldraw"],
+ "class": ["application/java"],
+ "cnf": ["text/plain"],
+ "conf": ["text/plain"],
+ "cpp": ["text/x-c++src"],
+ "cr2": ["image/x-dcraw"],
+ "css": ["text/css"],
+ "csv": ["text/csv"],
+ "cvbdl": ["application/x-cbr"],
+ "c": ["text/x-c"],
+ "c++": ["text/x-c++src"],
+ "dcr": ["image/x-dcraw"],
+ "deb": ["application/x-deb"],
+ "dng": ["image/x-dcraw"],
+ "doc": ["application/msword"],
+ "docm": ["application/vnd.ms-word.document.macroEnabled.12"],
+ "docx": ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
+ "dot": ["application/msword"],
+ "dotx": ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"],
+ "dv": ["video/dv"],
+ "eot": ["application/vnd.ms-fontobject"],
+ "epub": ["application/epub+zip"],
+ "eps": ["application/postscript"],
+ "erf": ["image/x-dcraw"],
+ "exe": ["application/x-ms-dos-executable"],
+ "fb2": ["application/x-fictionbook+xml", "text/plain"],
+ "flac": ["audio/flac"],
+ "flv": ["video/x-flv"],
+ "gif": ["image/gif"],
+ "gz": ["application/x-gzip"],
+ "gzip": ["application/x-gzip"],
+ "h": ["text/x-h"],
+ "hh": ["text/x-h"],
+ "hpp": ["text/x-h"],
+ "html": ["text/html", "text/plain"],
+ "htm": ["text/html", "text/plain"],
+ "ical": ["text/calendar"],
+ "ics": ["text/calendar"],
+ "iiq": ["image/x-dcraw"],
+ "impress": ["text/impress"],
+ "java": ["text/x-java-source"],
+ "jpeg": ["image/jpeg"],
+ "jpg": ["image/jpeg"],
+ "jps": ["image/jpeg"],
+ "js": ["application/javascript", "text/plain"],
+ "json": ["application/json", "text/plain"],
+ "k25": ["image/x-dcraw"],
+ "kdc": ["image/x-dcraw"],
+ "key": ["application/x-iwork-keynote-sffkey"],
+ "keynote": ["application/x-iwork-keynote-sffkey"],
+ "kra": ["application/x-krita"],
+ "lwp": ["application/vnd.lotus-wordpro"],
+ "m2t": ["video/mp2t"],
+ "m4a": ["audio/mp4"],
+ "m4b": ["audio/m4b"],
+ "m4v": ["video/mp4"],
+ "markdown": ["text/markdown"],
+ "mdown": ["text/markdown"],
+ "md": ["text/markdown"],
+ "mdb": ["application/msaccess"],
+ "mdwn": ["text/markdown"],
+ "mkd": ["text/markdown"],
+ "mef": ["image/x-dcraw"],
+ "mkv": ["video/x-matroska"],
+ "mobi": ["application/x-mobipocket-ebook"],
+ "mov": ["video/quicktime"],
+ "mp3": ["audio/mpeg"],
+ "mp4": ["video/mp4"],
+ "mpeg": ["video/mpeg"],
+ "mpg": ["video/mpeg"],
+ "mpo": ["image/jpeg"],
+ "msi": ["application/x-msi"],
+ "mts": ["video/MP2T"],
+ "mt2s": ["video/MP2T"],
+ "nef": ["image/x-dcraw"],
+ "numbers": ["application/x-iwork-numbers-sffnumbers"],
+ "odf": ["application/vnd.oasis.opendocument.formula"],
+ "odg": ["application/vnd.oasis.opendocument.graphics"],
+ "odp": ["application/vnd.oasis.opendocument.presentation"],
+ "ods": ["application/vnd.oasis.opendocument.spreadsheet"],
+ "odt": ["application/vnd.oasis.opendocument.text"],
+ "oga": ["audio/ogg"],
+ "ogg": ["audio/ogg"],
+ "ogv": ["video/ogg"],
+ "one": ["application/msonenote"],
+ "opus": ["audio/ogg"],
+ "orf": ["image/x-dcraw"],
+ "otf": ["application/font-sfnt"],
+ "pad": ["application/x-ownpad"],
+ "calc": ["application/x-ownpad"],
+ "pages": ["application/x-iwork-pages-sffpages"],
+ "pdf": ["application/pdf"],
+ "pfb": ["application/x-font"],
+ "pef": ["image/x-dcraw"],
+ "php": ["application/x-php"],
+ "pl": ["application/x-perl"],
+ "png": ["image/png"],
+ "pot": ["application/vnd.ms-powerpoint"],
+ "potm": ["application/vnd.ms-powerpoint.template.macroEnabled.12"],
+ "potx": ["application/vnd.openxmlformats-officedocument.presentationml.template"],
+ "ppa": ["application/vnd.ms-powerpoint"],
+ "ppam": ["application/vnd.ms-powerpoint.addin.macroEnabled.12"],
+ "pps": ["application/vnd.ms-powerpoint"],
+ "ppsm": ["application/vnd.ms-powerpoint.slideshow.macroEnabled.12"],
+ "ppsx": ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"],
+ "ppt": ["application/vnd.ms-powerpoint"],
+ "pptm": ["application/vnd.ms-powerpoint.presentation.macroEnabled.12"],
+ "pptx": ["application/vnd.openxmlformats-officedocument.presentationml.presentation"],
+ "ps": ["application/postscript"],
+ "psd": ["application/x-photoshop"],
+ "py": ["text/x-python"],
+ "raf": ["image/x-dcraw"],
+ "rar": ["application/x-rar-compressed"],
+ "reveal": ["text/reveal"],
+ "rss": ["application/rss+xml"],
+ "rtf": ["text/rtf"],
+ "rw2": ["image/x-dcraw"],
+ "sgf": ["application/sgf"],
+ "sh-lib": ["text/x-shellscript"],
+ "sh": ["text/x-shellscript"],
+ "srf": ["image/x-dcraw"],
+ "sr2": ["image/x-dcraw"],
+ "svg": ["image/svg+xml", "text/plain"],
+ "swf": ["application/x-shockwave-flash", "application/octet-stream"],
+ "tar": ["application/x-tar"],
+ "tar.bz2": ["application/x-bzip2"],
+ "tar.gz": ["application/x-compressed"],
+ "tbz2": ["application/x-bzip2"],
+ "tex": ["application/x-tex"],
+ "tgz": ["application/x-compressed"],
+ "tiff": ["image/tiff"],
+ "tif": ["image/tiff"],
+ "ttf": ["application/font-sfnt"],
+ "txt": ["text/plain"],
+ "vcard": ["text/vcard"],
+ "vcf": ["text/vcard"],
+ "vob": ["video/dvd"],
+ "vsd": ["application/vnd.visio"],
+ "wav": ["audio/wav"],
+ "webm": ["video/webm"],
+ "woff": ["application/font-woff"],
+ "wpd": ["application/vnd.wordperfect"],
+ "wmv": ["video/x-ms-wmv"],
+ "xcf": ["application/x-gimp"],
+ "xla": ["application/vnd.ms-excel"],
+ "xlam": ["application/vnd.ms-excel.addin.macroEnabled.12"],
+ "xls": ["application/vnd.ms-excel"],
+ "xlsb": ["application/vnd.ms-excel.sheet.binary.macroEnabled.12"],
+ "xlsm": ["application/vnd.ms-excel.sheet.macroEnabled.12"],
+ "xlsx": ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
+ "xlt": ["application/vnd.ms-excel"],
+ "xltm": ["application/vnd.ms-excel.template.macroEnabled.12"],
+ "xltx": ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"],
+ "xml": ["application/xml", "text/plain"],
+ "xrf": ["image/x-dcraw"],
+ "yaml": ["application/yaml", "text/plain"],
+ "yml": ["application/yaml", "text/plain"],
+ "zip": ["application/zip"]
+}
diff --git a/roles/nextcloud/files/nextcloud_file_name.xml b/roles/nextcloud/files/nextcloud_file_name.xml
new file mode 100644
index 0000000..3bc8063
--- /dev/null
+++ b/roles/nextcloud/files/nextcloud_file_name.xml
@@ -0,0 +1 @@
+7V1bj6s4Ev41kWYfOgpgbo+nu8/ZfZgeraZXuztPR07iJMwQYME5nZ5fvzbYxNhOIMSQiyZSt0JhjCl/n8tVLpyJ87Ld/z2H2eYtXaJ4Ys+W+4nzOrHtwArIfyr4rASu41eCdR4tK5F1ELxHfyImnDHpLlqiolEQp2mMo6wpXKRJgha4IYN5nn40i63SuHnXDK6RInhfwFiV/ida4g2TWrPZ4cQ/ULTesFsHLjsxh4s/1nm6S9j9JrazKj/V6S3kdbHyxQYu0w9B5HydOC95muLq23b/gmKqWq626rpvR87W7c5Rgrtc4HvVFT9gvEO8yWXD8CdXRvk4iF4wmzjPH5sIo/cMLujZD9L7RLbB25gcWeTrKorjlzROc3KcpAkp9LyExaa8nJ5nt0M5RvujbbZqTRCAoXSLcP5JirALgMeUx8BlO+z4Q+gqruCN0Eu2z4SQwWNd131QEfnCtHREY8H9acyfXVVj4f1pLLA7aMwZTGPg/jTmdNEYGEpjlg5jXozpg0Y/yNc1Lh+zEu1kwZwLfkUxggWipmUDiW2JeQnSgLl8FZEpNRGZ5oalSOg97387OsI/r9IEPxWl+ftCCoTZ/nCO17HdUbsXV21KI9LDvNH58DfndWQ5kkVFBhMuS9AeL+J0t/xOMFREafJdVZ9YXhBrapYf4xLkU0xHxLB/iaN1QmQ4zfR8OIJ3DSs6U8DyO1LAM8AA2zHDgJ8hRgW+PuznZL6HSsTcAtjp5RfXq2fMGuHvsaz0I2SpmvHIHJInd1oO6aYqRjiks7s9OPQGfydqoa1UWcQGyHHJ1ItFnUnB3Td+V6uNAj2fQrUy20rRf9HGDa5JG/cc2ij2pMb/t11ZbTeG6MzSUKypBe7zm64JIgpr4XSrKxoluqKZtla82Gia8HpKCY9G8FUJiXviN2RHC0JmlA9GeNmlH5fwuqhRDzv5nqFFBGnNxW61ivYt9B7BUK5yhMqAYV6z99EoVXCl3xOrhiGRHOXRkkgX5TFBImuEQGKB8/QPxIUT2/EWAZqv6jM8uO2Y0WcdymH6BJaqT9/V6DM0MSjZV9BnYM8dzxtLn7qY2mD6tPwr6DP0fAeOps86YDMKPkNFfWi5Ru/sMM3xJl2nCYy/HqTPTQULykT7CP9X+P4bLTJ16VFCGlafogeHc78jjD/Zchvc4ZSIDvf9OaVDbXlZU/v2Ke0X6S5fIK7fSoZhvkasmM2GOfqsJ/soRzHE0Y/mCtxFClcBXJCWYbUb4jjKCtSOYEhtJ30uMlehnVJaYN6BtECG8oi0E+W0jihZs34zAt2gCV1Xha7OUjkGkOs4QyCXoZVh1xKROxsfuYGKXK46c8gtL/2S5/BTKJClUYILoeZ/UoEQVXZA0wj4rtR5VY2Hrqyb1q13wfC9O7vB3rVvsneBa7h33UF697jVuZHeta5mdTTTeueb0gk4j2CyjjsYnTzFpIUp9YWerKDskDSP/iSWB8bm7ItjN3HoMByK9kWbIWDCvjz+zIjbkgZG/WthlLdGwGheLXwX/SdH4lzINYFIOc1Hg0hPg0hgAJFAdXWGReT4oyYfIUVEgquNmrw1AiKzHD3dPiodMCIqZ6oeHm2ctDXj5NU8SN4aAZWvMIo/bxeOwBkPjq6ac5WkQyBU9SW6orBUd1XMavMwVcSKASuayBss0GKhi1rNAxe4JydiDYxroiRu17kA6/en2dRzQrYMc56HorggviMZWi+chuKnWWHVbFbHAS3nOj5AWrG2g1ACn+D4HK7m1aerVYHwRIbrec6Rqy5cj4VgE5ZfRvd4CNZ4XK5zNoKJ8Qz7IPhSqAGW9T4m1IDqFqaZJhRp2J4PNseUkIWspYt8HbLqiH4nZAHdrNQzbf97ocgPLGnm5xxHUR+EqFPgXovqNEllup1mLZkiZ66nV6KfLGtKkPO37mvjfSdKBuZGsl0bdaquZhJ+/eW1vzpaVx6aDAVmNBjK62UjLjqAsYNCQw6P7B0wzfA4Kz+dh0dPMzyCmxgeQyCzrTE8tpf3zAa+QUuOUns+jWXpEmp+fSED7L45uPZPQtLfY44wbLnLRQ6oMGc07ZAGfE5dL7E7ow26rhrW7G1Be1jPHoliP1mz+7ClniV5a5pMlKG61fPuxxJczSXj7pdoGTzjlqEzEw29jLSFBU2iNT2NPXsI0HKzV1tuiMPA9UbjsG+pjz4shw+HFwQNw1EprIkLmp/cdaawLv1vXHe0l0G9YwfV9sLxjKou2iDrIll+oZtpTOp8zRMTyWPMsxQitxJq6aJgCXSEqtNtj2q/1wK7oG9d9ieXXRpnd6XudqV+rAYDJbKu5gxJFblyEoahEL2ybYQ7O9kupXwzU00pL7+0dnb5lvYoSwzN8he7mJ5ulvNoHOq6+DoSh6Q3NoAcaurKIYKNKXFWfQuw/81qAZiKJ4dZApP5wh+mK79AC/5dKWf47PIt7VHWVRyz/HLVIOqnLhfkVnORz3YGLyFt6/qc3ZHIwvqc5ft9WHvx+twpHA21FKyGC//CWies6bIZumbOC1jjxn9krJ2cEwyENc8fAlfdnWHrHgJaPHh1G96wp5oiwdPtEOefZfvKCT3yku/uslrc59/I5+nt7en1telpt+yd0Nf9FXFhKAVdXjoYMz7lBuNQ8vLENTWuNdpQz4f1W1x9DJrYMe7qaTy7W8LHeBiwb2lYdjRByjt42QbI73V7I75sc5/vJ8kqA5pknqFUBgZ5h04k/5XfftVm3d3GwK5k3YWnYxJKWsm55Q2noXB3o2OMcBHDoogWTcSovXoKK30zM6WObo0MVhb2WoFAV8JF72A6kFZFuwbT+2BBXXPR5QCTERFLQywiPgCclwVojzPSkNJuuSGYZtcpeRudbbRcluNSDOcofq63KdclqQmTi6CGh2ZzYLb7OmvYpB5rReAER1DCappNAeD7Q3MGGsHHk2XrajXqxwf243D7ejw2FND3ZuHpigzyWF33eXwe24/LY1fH4x77VyrZSpfuW9k1x6Ko+m6otMW+MaKj04gLcpY0O4oNFRMK1JjfO4oJUejGPqRq8vcL311vImxb+kInShu2h3yOp2YGBjLrZ5sGWsI4EaMV1owS1aZ5RbUJ0b9K9+AJSGGDcKK+RUCPv8EtfcXVef03ypcwgadGjjN+tMNpBmgsoAb36s690IEjh4dfUKnGg8Ov1Dhf/w8=
\ No newline at end of file
diff --git a/roles/nextcloud/handlers/main.yml b/roles/nextcloud/handlers/main.yml
new file mode 100644
index 0000000..a375e3e
--- /dev/null
+++ b/roles/nextcloud/handlers/main.yml
@@ -0,0 +1,41 @@
+---
+# handlers file for nextcloud
+- name: restart mysql
+ service:
+ name: mysql
+ state: restarted
+
+- name: start http
+ service:
+ name: nginx
+ state: started
+
+- name: restart http
+ service:
+ name: nginx
+ state: restarted
+
+- name: reload http
+ service:
+ name: nginx
+ state: reloaded
+
+- name: start php-fpm
+ service:
+ name: php{{ php_ver }}-fpm
+ state: started
+
+- name: reload php-fpm
+ service:
+ name: php{{ php_ver }}-fpm
+ state: reloaded
+
+- name: start redis
+ service:
+ name: redis-server
+ state: started
+
+- name: restart redis
+ service:
+ name: redis-server
+ state: restarted
diff --git a/roles/nextcloud/tasks/db_mysql.yml b/roles/nextcloud/tasks/db_mysql.yml
new file mode 100644
index 0000000..09a74da
--- /dev/null
+++ b/roles/nextcloud/tasks/db_mysql.yml
@@ -0,0 +1,89 @@
+---
+- name: "[mySQL: Debian] - Service is installed."
+ package:
+ name: "{{ 'default-' if ((ansible_distribution|lower) == 'debian' and nextcloud_db_backend == 'mysql') else '' }}{{ nextcloud_db_backend }}-server"
+ state: present
+ register: nc_mysql_db_install
+
+- name: "[mySQL] - Packages are installed."
+ package:
+ name: "{{ nc_mysql_deps }}"
+ state: present
+ vars:
+ nc_mysql_deps:
+ - "php{{ php_ver }}-mysql"
+ - "python{{ '3' if ansible_python.version.major == 3 else '' }}-pymysql"
+
+- name: "[mySQL] - generate {{ nextcloud_db_backend }} root Password:"
+ set_fact:
+ nextcloud_mysql_root_pwd: "{{ lookup( 'password', 'nextcloud_instances/'+ nextcloud_instance_name +'/mysql_root.pwd' ) }}"
+ when: nextcloud_mysql_root_pwd is not defined
+
+- name: "[mySQL] - save {{ nextcloud_db_backend }} root password in config file"
+ ini_file:
+ path: "{{ mysql_credential_file[(ansible_os_family|lower)] }}"
+ section: client
+ option: password
+ value: "{{ nextcloud_mysql_root_pwd }}"
+ no_log: true
+ when: mysql_credential_file[(ansible_os_family|lower)] is defined
+
+# use debian default credentials to work on user root password
+- name: "[mySQL] - Update {{ nextcloud_db_backend }} root password"
+ mysql_user:
+ name: root
+
+ password: "{{ nextcloud_mysql_root_pwd }}"
+ config_file: "{{ mysql_credential_file[(ansible_os_family|lower)] | default(omit) }}"
+ check_implicit_admin: yes
+ priv: "*.*:ALL,GRANT"
+ # Assuming the root user has only localhost access
+ host_all: yes
+
+
+- name: "[mySQL] - Delete the anonymous user."
+ mysql_user:
+ user: ""
+ state: "absent"
+ login_user: root
+ login_password: "{{ nextcloud_mysql_root_pwd }}"
+ config_file: "{{ mysql_credential_file[(ansible_os_family|lower)] | default(omit) }}"
+ ignore_errors: yes
+
+- name: "[mySQL] - Removes the MySQL test database"
+ mysql_db:
+ name: test
+ state: absent
+ login_user: root
+ login_password: "{{ nextcloud_mysql_root_pwd }}"
+ config_file: "{{ mysql_credential_file[(ansible_os_family|lower)] | default(omit) }}"
+ ignore_errors: yes
+
+- name: "[mySQL] - Set mysql config option for nextcloud"
+ copy:
+ dest: /etc/mysql/conf.d/nextcloud.cnf
+ src: files/mysql_nextcloud.cnf
+ notify: restart mysql
+
+- name: "[mySQL] - Generate database user Password."
+ set_fact:
+ nextcloud_db_pwd: "{{ lookup( 'password', 'nextcloud_instances/'+ nextcloud_instance_name +'/db_admin.pwd' ) }}"
+ when: nextcloud_db_pwd is not defined
+
+- name: "[mySQL] - Add Database {{ nextcloud_db_name }}."
+ mysql_db:
+ name: "{{ nextcloud_db_name }}"
+ login_user: root
+ login_password: "{{ nextcloud_mysql_root_pwd }}"
+ config_file: "{{ mysql_credential_file[(ansible_os_family|lower)] | default(omit) }}"
+ state: present
+
+- name: "[mySQL] - Configure the database user."
+ mysql_user:
+ name: "{{ nextcloud_db_admin }}"
+ password: "{{ nextcloud_db_pwd }}"
+ priv: "{{ nextcloud_db_name }}.*:ALL"
+ login_user: root
+ login_password: "{{ nextcloud_mysql_root_pwd }}"
+ config_file: "{{ mysql_credential_file[(ansible_os_family|lower)] | default(omit) }}"
+ state: present
diff --git a/roles/nextcloud/tasks/db_postgresql.yml b/roles/nextcloud/tasks/db_postgresql.yml
new file mode 100644
index 0000000..f543ffe
--- /dev/null
+++ b/roles/nextcloud/tasks/db_postgresql.yml
@@ -0,0 +1,32 @@
+---
+- name: "[PostgreSQL] - PostgreSQL packages are installed"
+ package:
+ name: "{{ pg_deps }}"
+ state: "present"
+ vars:
+ pg_deps:
+ - "postgresql"
+ - "php{{ php_ver }}-pgsql"
+ - "python{{ '3' if ansible_python.version.major == 3 else '' }}-psycopg2"
+
+- name: "[PostgreSQL] - generate nextcloud role password."
+ set_fact: nextcloud_db_pwd="{{ lookup( 'password', 'nextcloud_instances/'+ nextcloud_instance_name +'/pgsql_nc.pwd' ) }}"
+ when: nextcloud_db_pwd is not defined
+
+- name: "[PostgreSQL] - nextcloud role is created."
+ postgresql_user:
+ name: "{{ nextcloud_db_admin }}"
+ password: "{{ nextcloud_db_pwd }}"
+ encrypted: yes
+ state: present
+ role_attr_flags: CREATEDB
+ become_user: postgres
+ become: yes
+
+- name: "[PostgreSQL] - nextcloud database is created."
+ postgresql_db:
+ name: "{{ nextcloud_db_name }}"
+ state: present
+ owner: "{{ nextcloud_db_admin }}"
+ become_user: postgres
+ become: yes
diff --git a/roles/nextcloud/tasks/http_nginx.yml b/roles/nextcloud/tasks/http_nginx.yml
new file mode 100644
index 0000000..6f7c844
--- /dev/null
+++ b/roles/nextcloud/tasks/http_nginx.yml
@@ -0,0 +1,88 @@
+---
+- name: Configure php-fpm
+ lineinfile:
+ dest: "{{ php_dir }}/fpm/pool.d/www.conf"
+ regexp: '^\;env'
+ state: absent
+ # validate: "/usr/sbin/{{ php_bin }} -t #%s"
+ notify: reload php-fpm
+
+- name: "[NGINX] - Add path variable to php-fpm"
+ blockinfile:
+ dest: "{{ php_dir }}/fpm/pool.d/www.conf"
+ insertafter: '^; Default Value: clean env$'
+ marker: "; {mark} ANSIBLE MANAGED BLOCK"
+ block: |
+ env[HOSTNAME] = $HOSTNAME
+ env[PATH] = $PATH
+ env[TMP] = /tmp
+ env[TMPDIR] = /tmp
+ env[TEMP] = /tmp
+ notify: reload php-fpm
+
+- name: "[NGINX] - enable APC for php CLI"
+ lineinfile:
+ dest: "{{ php_dir }}/cli/php.ini"
+ line: "apc.enable_cli = 1"
+ insertbefore: "^; End:$"
+ state: present
+ # validate: "/usr/sbin/{{ php_bin }} -t #%s"
+ notify: reload php-fpm
+
+- name: "[NGINX] - enable PHP OPcache for php.ini"
+ lineinfile:
+ dest: "{{ php_dir }}/fpm/php.ini"
+ state: present
+ regexp: "{{ item.regexp }}"
+ line: "{{ item.line }}"
+ backrefs: yes
+ with_items:
+ - { regexp: 'opcache.enable=0', line: 'opcache.enable=1' }
+ - { regexp: 'opcache.enable_cli', line: 'opcache.enable_cli=1' }
+ - { regexp: 'opcache.interned_strings_buffer', line: 'opcache.interned_strings_buffer=8' }
+ - { regexp: 'opcache.max_accelerated_files', line: 'opcache.max_accelerated_files=10000' }
+ - { regexp: 'opcache.memory_consumption', line: 'opcache.memory_consumption=128' }
+ - { regexp: 'opcache.save_comments', line: 'opcache.save_comments=1' }
+ - { regexp: 'opcache.revalidate_freq', line: 'opcache.revalidate_freq=1' }
+ - { regexp: 'memory_limit', line: 'memory_limit={{ php_memory_limit }}'}
+ # validate: "/usr/sbin/{{ php_bin }} -t #%s"
+ notify: reload php-fpm
+
+
+- name: "[NGINX] - Public Diffie-Hellman Parameter are generated. This might take a while."
+ command: "openssl dhparam -out {{ nextcloud_tls_dhparam }} 2048"
+ args:
+ creates: "{{ nextcloud_tls_dhparam }}"
+
+- name: "[NGINX] - php handler configuration is present."
+ template:
+ dest: /etc/nginx/sites-available/php_handler.cnf
+ src: templates/nginx_php_handler.j2
+ notify: reload http
+
+- name: "[NGINX] - php handler is enabled"
+ file:
+ path: /etc/nginx/sites-enabled/php_handler
+ src: /etc/nginx/sites-available/php_handler.cnf
+ state: link
+ notify: reload http
+
+- name: "[NGINX] - generate Nextcloud configuration for nginx"
+ template:
+ dest: /etc/nginx/sites-available/nc_{{ nextcloud_instance_name }}.cnf
+ src: "{{ nextcloud_websrv_template }}"
+ notify: reload http
+
+- name: "[NGINX] - Enable Nextcloud in nginx conf"
+ file:
+ path: /etc/nginx/sites-enabled/nc_{{ nextcloud_instance_name }}
+ src: /etc/nginx/sites-available/nc_{{ nextcloud_instance_name }}.cnf
+ state: link
+ notify: reload http
+
+- name: "[NGINX] - Disable nginx default site"
+ file:
+ path: /etc/nginx/sites-enabled/default
+ state: absent
+ when: nextcloud_disable_websrv_default_site | bool
+ notify: reload http
diff --git a/roles/nextcloud/tasks/main.yml b/roles/nextcloud/tasks/main.yml
new file mode 100644
index 0000000..b1b0e1d
--- /dev/null
+++ b/roles/nextcloud/tasks/main.yml
@@ -0,0 +1,88 @@
+---
+# Main tasks in Nextcloud installation
+
+- name: Install required packages
+ apt:
+ name: '{{ required_packages }}'
+ state: present
+ notify:
+ - start http
+ - start php-fpm
+
+- fail:
+ msg: Debugging
+
+- name: Configure Nginx web server
+ include_tasks: http_nginx.yml
+
+- name: Configure Redis server
+ include_tasks: ./redis_server.yml
+ when: (nextcloud_install_redis_server | bool)
+
+- block:
+ - name: Configure mysql/mariadb database
+ include_tasks: ./db_mysql.yml
+ when: nextcloud_db_backend in ["mysql", "mariadb"]
+
+ - name: Configure PostgreSQL database
+ include_tasks: ./db_postgresql.yml
+ when: nextcloud_db_backend in ["pgsql"]
+ when: nextcloud_install_db
+
+- name: Check Nextcloud installed
+ stat: "path={{ nextcloud_webroot }}/index.php"
+ register: nc_nextcloud_installed
+
+- name: Downloading Nextcloud
+ include_tasks: ./nc_download.yml
+ when: not nc_nextcloud_installed.stat.exists
+
+- name: Check Nextcloud configuration exists.
+ stat: path="{{ nextcloud_webroot }}/config/config.php"
+ register: nc_nextcloud_conf
+
+- name: Check Nextcloud is configured
+ command: grep -q "{{ nextcloud_trusted_domain| first }}" {{ nextcloud_webroot }}/config/config.php
+ failed_when: False
+ changed_when: False
+ register: nc_nextcloud_configured
+ when: nc_nextcloud_conf.stat.exists
+
+- name: Nextcloud installation
+ include_tasks: ./nc_installation.yml
+ when: |
+ (not nc_nextcloud_conf.stat.exists) or
+ (nc_nextcloud_configured.rc is defined and nc_nextcloud_configured.rc != 0)
+
+- block:
+ - name: "[NC apps] - lists the number of apps available in the instance."
+ command: php occ app:list --output=json_pretty --no-warnings
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become: yes
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ changed_when: false
+ register: nc_apps_list
+
+ - name: "[NC apps] - convert list to yaml."
+ set_fact: nc_available_apps="{{ nc_apps_list.stdout | from_json }}"
+
+ - name: "[NC apps] - installation."
+ include_tasks: ./nc_apps.yml
+ # do if the app is not enabled and ( (archive path is not "") or (app is disabled) )
+ when:
+ - item.key not in nc_available_apps.enabled
+ - (item.value is not none) or (item.key in nc_available_apps.disabled)
+ with_dict: "{{ nextcloud_apps }}"
+ when:
+ - nextcloud_apps is defined
+ - nextcloud_apps is mapping
+
+- name: Add indices
+ command: php occ db:add-missing-indices
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become: yes
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
diff --git a/roles/nextcloud/tasks/nc_apps.yml b/roles/nextcloud/tasks/nc_apps.yml
new file mode 100644
index 0000000..835818c
--- /dev/null
+++ b/roles/nextcloud/tasks/nc_apps.yml
@@ -0,0 +1,63 @@
+---
+- name: parse the item values
+ set_fact:
+ nc_app_name: "{{ item.key }}"
+ nc_app_cfg: "{{ item.value }}"
+
+- block:
+ - name: "[ App {{ nc_app_name }} ] - Download Archive in apps folder."
+ unarchive:
+ copy: no
+ src: "{{ nc_app_cfg }}"
+ dest: "{{ nextcloud_webroot }}/apps/"
+ owner: "{{ nextcloud_websrv_user }}"
+ group: "{{ nextcloud_websrv_group }}"
+ creates: "{{ nextcloud_webroot }}/apps/{{ nc_app_name }}"
+ when: nc_app_cfg is not none
+
+ - name: "[ App {{ nc_app_name }} ] - enable the application."
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ app:enable "{{ nc_app_name }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ when: nc_app_cfg is string
+
+- block:
+ - name: verify the app's yaml declaration
+ assert:
+ that:
+ - (nc_app_cfg.source is defined) and (nc_app_cfg.source is string)
+ msg: "{{ nc_app_name }} is not well declared."
+
+ - name: "[ App {{ nc_app_name }} ] - Download Archive in apps folder."
+ unarchive:
+ copy: no
+ src: "{{ nc_app_cfg.source }}"
+ dest: "{{ nextcloud_webroot }}/apps/"
+ owner: "{{ nextcloud_websrv_user }}"
+ group: "{{ nextcloud_websrv_group }}"
+ creates: "{{ nextcloud_webroot }}/apps/{{ nc_app_name }}"
+ when: nc_app_cfg.source is not none
+
+ - name: "[ App {{ nc_app_name }} ] - enable the application."
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ app:enable "{{ nc_app_name }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ - block:
+ - name: "[ App {{ nc_app_name }} ] - Configure the application "
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ config:app:set {{ nc_app_name }} {{ item_cfg.key }} --value="{{ item_cfg.value }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ with_dict: "{{ nc_app_cfg.conf | default({}) }}"
+ loop_control:
+ loop_var: item_cfg
+ when: nc_app_cfg.conf is defined
+ when: (nc_app_cfg is mapping)
diff --git a/roles/nextcloud/tasks/nc_download.yml b/roles/nextcloud/tasks/nc_download.yml
new file mode 100644
index 0000000..7b11a34
--- /dev/null
+++ b/roles/nextcloud/tasks/nc_download.yml
@@ -0,0 +1,46 @@
+---
+- name: "[NC-DL] - Unzip is installed"
+ package: name=unzip state=present
+ when: nextcloud_archive_format == "zip"
+
+- name: "[NC-DL] - bunzip2 is installed"
+ package: name=bzip2 state=present
+ when: nextcloud_archive_format == "tar.bz2"
+
+- name: you must specify the major version
+ assert:
+ that: nextcloud_version_major is defined
+ when: nextcloud_full_url is defined
+
+#- name: "[NC-DL] - Create webroot folder"
+# file:
+# path: "{{ nextcloud_webroot }}"
+# recurese: yes
+# state: directory
+
+- name: "[NC-DL] - Create and set directory ownership & permissions for the webroot folder"
+ file:
+ path: "{{ nextcloud_webroot }}"
+ mode: "u=rwX,g=rX,o-rwx"
+ recurse: yes
+ state: directory
+ owner: "{{ nextcloud_websrv_user }}"
+ group: "{{ nextcloud_websrv_group }}"
+
+- block:
+ - name: "Download & extract Nextcloud to /tmp."
+ unarchive:
+ copy: no
+ src: "{{ nextcloud_full_url | default(nextcloud_calculated_url) }}"
+ dest: "/tmp/"
+ vars:
+ nextcloud_calculated_url: "{{ nextcloud_repository }}/{{ nextcloud_version_channel }}/{{ nextcloud_calculated_file }}"
+ nextcloud_calculated_file: "{{ [nextcloud_dl_file_name[just_a_dict_key], nextcloud_archive_format]|join('.') }}"
+ just_a_dict_key: "{{ 'latest' if ((nextcloud_get_latest|bool) and (nextcloud_version_channel != 'prereleases')) else nextcloud_version_channel }}"
+
+
+ - name: "[NC-DL] - Move extracted files to {{ nextcloud_webroot }}."
+ command: "cp -r /tmp/nextcloud/. {{ nextcloud_webroot }}/"
+
+ - name: "[NC-DL] - Remove nextcloud archive files"
+ file: path=/tmp/nextcloud state=absent
diff --git a/roles/nextcloud/tasks/nc_installation.yml b/roles/nextcloud/tasks/nc_installation.yml
new file mode 100644
index 0000000..ae9121d
--- /dev/null
+++ b/roles/nextcloud/tasks/nc_installation.yml
@@ -0,0 +1,168 @@
+---
+#########
+# Run command line installation.
+# the web server must be running by now in order to launch the installation
+- name: Trigger all pending handlers
+ meta: flush_handlers
+
+- name: "[NC] - Setting directory ownership & permissions for the data folder"
+ file:
+ path: "{{ nextcloud_data_dir }}"
+ mode: "u=rwX,g=rX,o-rwx"
+ recurse: yes
+ state: directory
+ owner: "{{ nextcloud_websrv_user }}"
+ group: "{{ nextcloud_websrv_group }}"
+
+- name: "[NC] - generate {{ nextcloud_admin_name }} password:"
+ set_fact: nextcloud_admin_pwd="{{ lookup( 'password', 'nextcloud_instances/'+ nextcloud_instance_name +'/web_admin.pwd length=10' ) }}"
+ when: nextcloud_admin_pwd is not defined
+
+- name: "[NC] - Set temporary permissions for command line installation."
+ file:
+ path: "{{ nextcloud_webroot }}"
+ state: directory
+ recurse: yes
+ owner: "{{ nextcloud_websrv_user }}"
+ group: "{{ nextcloud_websrv_group }}"
+
+- block:
+ - name: "[NC] - removing possibly old or incomplete config.php"
+ file:
+ path: "{{ nextcloud_webroot }}/config/config.php"
+ state: absent
+
+ - name: "[NC] - Run occ installation command"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: >
+ php occ maintenance:install
+ --database={{ nextcloud_tmp_backend }}
+ --database-host={{ nextcloud_db_host }}
+ --database-name={{ nextcloud_db_name }}
+ --database-user={{ nextcloud_db_admin }}
+ --database-pass={{ nextcloud_db_pwd }}
+ --admin-user={{ nextcloud_admin_name }}
+ --admin-pass={{ nextcloud_admin_pwd }}
+ --data-dir={{ nextcloud_data_dir }}
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ creates: "{{ nextcloud_webroot }}/config/config.php"
+ vars:
+ # mariadb is equal to mysql for occ
+ nextcloud_tmp_backend: "{{ 'mysql' if nextcloud_db_backend == 'mariadb' else nextcloud_db_backend }}"
+ notify: reload http
+
+ - name: "[NC] - Verify config.php - check filesize"
+ stat: path="{{ nextcloud_webroot }}/config/config.php"
+ register: nc_installation_confsize
+ failed_when: nc_installation_confsize.stat.size is undefined or nc_installation_confsize.stat.size <= 100
+
+ - name: "[NC] - Verify config.php - php syntax check"
+ command: "php -l {{ nextcloud_webroot }}/config/config.php"
+ register: nc_installation_confphp
+ changed_when: False
+ failed_when:
+ - nc_installation_confphp.rc is defined
+ - nc_installation_confphp.rc != 0
+
+ rescue:
+ # - name: Unfix su issue with occ
+ # include_tasks: tasks/unfix_su.yml
+ # when: ansible_become_method == "su"
+
+ - name: "[NC] - removing config.php when occ fail"
+ file:
+ path: "{{ nextcloud_webroot }}/config/config.php"
+ state: absent
+ failed_when: True
+
+- name: "[NC] - Set Trusted Domains"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ config:system:set trusted_domains {{ item.0 }} --value="{{ item.1 | ipwrap }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ with_indexed_items: "{{ nextcloud_trusted_domain }}"
+ changed_when: true
+
+- name: "[NC] - Set Trusted Proxies"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ config:system:set trusted_proxies {{ item.0 }} --value="{{ item.1 }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ with_indexed_items: "{{ nextcloud_trusted_proxies }}"
+ changed_when: true
+
+- name: "[NC] - Set Nextcloud settings in config.php"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ config:system:set {{ item.name }} --value="{{ item.value }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ with_items:
+ - "{{ nextcloud_config_settings }}"
+ changed_when: true
+
+- name: "[NC] - Set Redis Server"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ config:system:set {{ item.name }} --value="{{ item.value }}"
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ with_items:
+ - "{{ nextcloud_redis_settings }}"
+ when: (nextcloud_install_redis_server | bool)
+
+- name: "[NC] - Install Cronjob"
+ cron:
+ name: "Nextcloud Cronjob"
+ minute: "*/15"
+ user: "{{ nextcloud_websrv_user }}"
+ job: "php {{ nextcloud_webroot }}/cron.php"
+ cron_file: "nextcloud"
+ when: (nextcloud_background_cron | bool)
+
+- name: "[NC] - Set Cron method to Crontab"
+ become_user: "{{ nextcloud_websrv_user }}"
+ become_flags: "{{ ansible_become_flags | default(omit) }}"
+ become: yes
+ command: php occ background:cron
+ args:
+ chdir: "{{ nextcloud_webroot }}"
+ when: (nextcloud_background_cron | bool)
+
+- name: "[NC] - Set Custom Mimetype"
+ copy:
+ dest: "{{ nextcloud_webroot }}/config/mimetypemapping.json"
+ src: files/nextcloud_custom_mimetypemapping.json
+
+- name: "[NC] - Ensure Nextcloud directories are 0750"
+ command: find {{ nextcloud_data_dir }} -type d -exec chmod -c 0750 {} \;
+ register: nc_installation_chmod_result
+ changed_when: "nc_installation_chmod_result.stdout != \"\""
+
+- name: "[NC] - Ensure Nextcloud files are 0640"
+ command: find {{ nextcloud_data_dir }} -type f -exec chmod -c 0640 {} \;
+ register: nc_installation_chmod_result
+ changed_when: "nc_installation_chmod_result.stdout != \"\""
+
+- name: "[NC] - Setting stronger directory ownership"
+ file:
+ path: "{{ nextcloud_webroot }}/{{ item }}/"
+ recurse: yes
+ owner: "{{ nextcloud_websrv_user }}"
+ group: "{{ nextcloud_websrv_group }}"
+ state: directory
+ with_items:
+ - apps
+ - assets
+ - config
+ - themes
+ - updater
diff --git a/roles/nextcloud/tasks/redis_server.yml b/roles/nextcloud/tasks/redis_server.yml
new file mode 100644
index 0000000..3663946
--- /dev/null
+++ b/roles/nextcloud/tasks/redis_server.yml
@@ -0,0 +1,13 @@
+---
+- name: "[REDIS] - Required packages are installed."
+ package: "name={{ redix_deps + php_pkg_spe }} state=present"
+ vars:
+ redix_deps:
+ - redis-server
+ notify: start redis
+
+- name: "[REDIS] - Redis configuration is present."
+ template:
+ dest: /etc/redis/redis.conf
+ src: templates/redis.conf.j2
+ notify: restart redis
diff --git a/roles/nextcloud/templates/nginx_nc.j2 b/roles/nextcloud/templates/nginx_nc.j2
new file mode 100644
index 0000000..4b7944f
--- /dev/null
+++ b/roles/nextcloud/templates/nginx_nc.j2
@@ -0,0 +1,146 @@
+################################################################################
+# This file was generated by Ansible for {{ansible_fqdn}}
+# Do NOT modify this file by hand!
+################################################################################
+
+server {
+ server_name {{ nextcloud_trusted_domain | ipwrap | join(' ') }};
+
+ listen 80;
+
+ # set max upload size and increase upload timeout:
+ client_max_body_size {{ nextcloud_max_upload_size }};
+ client_body_timeout 300s;
+ fastcgi_buffers 64 4K;
+
+{% if (nextcloud_computed_major_version|int) > 13 %}
+ # Enable gzip but do not remove ETag headers
+ gzip on;
+ gzip_vary on;
+ gzip_comp_level 4;
+ gzip_min_length 256;
+ gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
+ 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/wasm 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;
+{% else %}
+ # Disable gzip to avoid the removal of the ETag header
+ gzip off;
+{% endif %}
+
+ # Pagespeed is not supported by Nextcloud, so if your server is built
+ # with the `ngx_pagespeed` module, uncomment this line to disable it.
+ #pagespeed off;
+
+ # HTTP response headers borrowed from Nextcloud `.htaccess`
+ add_header Referrer-Policy "no-referrer" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header X-Download-Options "noopen" always;
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Permitted-Cross-Domain-Policies "none" always;
+ add_header X-Robots-Tag "none" always;
+ add_header X-XSS-Protection "1; mode=block" always;
+
+ # Remove X-Powered-By, which is an information leak
+ fastcgi_hide_header X-Powered-By;
+
+ # Path to the root of your installation
+ root {{ nextcloud_webroot }};
+
+ # Specify how to handle directories -- specifying `/index.php$request_uri`
+ # here as the fallback means that Nginx always exhibits the desired behaviour
+ # when a client requests a path that corresponds to a directory that exists
+ # on the server. In particular, if that directory contains an index.php file,
+ # that file is correctly served; if it doesn't, then the request is passed to
+ # the front-end controller. This consistent behaviour means that we don't need
+ # to specify custom rules for certain paths (e.g. images and other assets,
+ # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
+ # `try_files $uri $uri/ /index.php$request_uri`
+ # always provides the desired behaviour.
+ index index.php index.html /index.php$request_uri;
+
+ # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
+ location = / {
+ if ( $http_user_agent ~ ^DavClnt ) {
+ return 302 /remote.php/webdav/$is_args$args;
+ }
+ }
+
+ location = /robots.txt {
+ allow all;
+ log_not_found off;
+ access_log off;
+ }
+
+ # Make a regex exception for `/.well-known` so that clients can still
+ # access it despite the existence of the regex rule
+ # `location ~ /(\.|autotest|...)` which would otherwise handle requests
+ # for `/.well-known`.
+ location ^~ /.well-known {
+ # The rules in this block are an adaptation of the rules
+ # in `.htaccess` that concern `/.well-known`.
+
+ location = /.well-known/carddav { return 301 /remote.php/dav/; }
+ location = /.well-known/caldav { return 301 /remote.php/dav/; }
+
+ location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
+ location /.well-known/pki-validation { try_files $uri $uri/ =404; }
+
+ # Let Nextcloud's API for `/.well-known` URIs handle all other
+ # requests by passing them to the front-end controller.
+ return 301 /index.php$request_uri;
+ }
+
+ # Rules borrowed from `.htaccess` to hide certain paths from clients
+ location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
+ location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
+
+ # Ensure this block, which passes PHP files to the PHP process, is above the blocks
+ # which handle static assets (as seen below). If this block is not declared first,
+ # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
+ # to the URI, resulting in a HTTP 500 error response.
+ location ~ \.php(?:$|/) {
+ # Required for legacy support
+ rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;
+
+ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+ set $path_info $fastcgi_path_info;
+
+ try_files $fastcgi_script_name =404;
+
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $path_info;
+ fastcgi_param HTTPS on;
+
+ fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
+ fastcgi_param front_controller_active true; # Enable pretty urls
+ fastcgi_pass php-handler;
+
+ fastcgi_intercept_errors on;
+ fastcgi_request_buffering off;
+ }
+
+ location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite)$ {
+ try_files $uri /index.php$request_uri;
+ expires 6M; # Cache-Control policy borrowed from `.htaccess`
+ access_log off; # Optional: Don't log access to assets
+
+ location ~ \.wasm$ {
+ default_type application/wasm;
+ }
+ }
+
+ location ~ \.woff2?$ {
+ try_files $uri /index.php$request_uri;
+ expires 7d; # Cache-Control policy borrowed from `.htaccess`
+ access_log off; # Optional: Don't log access to assets
+ }
+
+ # Rule borrowed from `.htaccess`
+ location /remote {
+ return 301 /remote.php$request_uri;
+ }
+
+ location / {
+ try_files $uri $uri/ /index.php$request_uri;
+ }
+}
diff --git a/roles/nextcloud/templates/nginx_php_handler.j2 b/roles/nextcloud/templates/nginx_php_handler.j2
new file mode 100644
index 0000000..3035cd8
--- /dev/null
+++ b/roles/nextcloud/templates/nginx_php_handler.j2
@@ -0,0 +1,9 @@
+################################################################################
+# This file was generated by Ansible for {{ansible_fqdn}}
+# Do NOT modify this file by hand!
+################################################################################
+
+upstream php-handler {
+ #server 127.0.0.1:9000;
+ server unix:{{ php_socket }};
+}
diff --git a/roles/nextcloud/templates/redis.conf.j2 b/roles/nextcloud/templates/redis.conf.j2
new file mode 100644
index 0000000..ec52a3c
--- /dev/null
+++ b/roles/nextcloud/templates/redis.conf.j2
@@ -0,0 +1,957 @@
+################################################################################
+# This file was generated by Ansible for {{ansible_fqdn}}
+# Do NOT modify this file by hand!
+################################################################################
+
+# Redis configuration file example.
+#
+# Note that in order to read the configuration file, Redis must be
+# started with the file path as first argument:
+#
+# ./redis-server /path/to/redis.conf
+
+# Note on units: when memory size is needed, it is possible to specify
+# it in the usual form of 1k 5GB 4M and so forth:
+#
+# 1k => 1000 bytes
+# 1kb => 1024 bytes
+# 1m => 1000000 bytes
+# 1mb => 1024*1024 bytes
+# 1g => 1000000000 bytes
+# 1gb => 1024*1024*1024 bytes
+#
+# units are case insensitive so 1GB 1Gb 1gB are all the same.
+
+################################## INCLUDES ###################################
+
+# Include one or more other config files here. This is useful if you
+# have a standard template that goes to all Redis servers but also need
+# to customize a few per-server settings. Include files can include
+# other files, so use this wisely.
+#
+# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
+# from admin or Redis Sentinel. Since Redis always uses the last processed
+# line as value of a configuration directive, you'd better put includes
+# at the beginning of this file to avoid overwriting config change at runtime.
+#
+# If instead you are interested in using includes to override configuration
+# options, it is better to use include as the last line.
+#
+# include /path/to/local.conf
+# include /path/to/other.conf
+
+################################ GENERAL #####################################
+
+# By default Redis does not run as a daemon. Use 'yes' if you need it.
+# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
+daemonize yes
+
+# When running daemonized, Redis writes a pid file in /var/run/redis.pid by
+# default. You can specify a custom pid file location here.
+pidfile /var/run/redis/redis-server.pid
+
+# Accept connections on the specified port, default is 6379.
+# If port 0 is specified Redis will not listen on a TCP socket.
+{% if nextcloud_redis_port is defined %}
+port {{ nextcloud_redis_port|int}}
+{% endif %}
+
+# TCP listen() backlog.
+#
+# In high requests-per-second environments you need an high backlog in order
+# to avoid slow clients connections issues. Note that the Linux kernel
+# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
+# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
+# in order to get the desired effect.
+tcp-backlog 511
+
+# By default Redis listens for connections from all the network interfaces
+# available on the server. It is possible to listen to just one or multiple
+# interfaces using the "bind" configuration directive, followed by one or
+# more IP addresses.
+#
+# Examples:
+#
+# bind 192.168.1.100 10.0.0.1
+{% if nextcloud_redis_host is defined and (nextcloud_redis_port|int) > 0 %}
+bind {{ nextcloud_redis_host }}
+{% endif %}
+
+# Specify the path for the Unix socket that will be used to listen for
+# incoming connections. There is no default, so Redis will not listen
+# on a unix socket when not specified.
+#
+# unixsocket /var/run/redis/redis.sock
+# unixsocketperm 700
+{% if nextcloud_redis_port is defined and (nextcloud_redis_port|int) == 0 %}
+unixsocket {{ nextcloud_redis_host }}
+unixsocketperm 777
+{% endif %}
+
+
+# Close the connection after a client is idle for N seconds (0 to disable)
+timeout 0
+
+# TCP keepalive.
+#
+# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
+# of communication. This is useful for two reasons:
+#
+# 1) Detect dead peers.
+# 2) Take the connection alive from the point of view of network
+# equipment in the middle.
+#
+# On Linux, the specified value (in seconds) is the period used to send ACKs.
+# Note that to close the connection the double of the time is needed.
+# On other kernels the period depends on the kernel configuration.
+#
+# A reasonable value for this option is 60 seconds.
+tcp-keepalive 0
+
+# Specify the server verbosity level.
+# This can be one of:
+# debug (a lot of information, useful for development/testing)
+# verbose (many rarely useful info, but not a mess like the debug level)
+# notice (moderately verbose, what you want in production probably)
+# warning (only very important / critical messages are logged)
+loglevel notice
+
+# Specify the log file name. Also the empty string can be used to force
+# Redis to log on the standard output. Note that if you use standard
+# output for logging but daemonize, logs will be sent to /dev/null
+logfile /var/log/redis/redis-server.log
+
+# To enable logging to the system logger, just set 'syslog-enabled' to yes,
+# and optionally update the other syslog parameters to suit your needs.
+# syslog-enabled no
+
+# Specify the syslog identity.
+# syslog-ident redis
+
+# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
+# syslog-facility local0
+
+# Set the number of databases. The default database is DB 0, you can select
+# a different one on a per-connection basis using SELECT where
+# dbid is a number between 0 and 'databases'-1
+databases 16
+
+################################ SNAPSHOTTING ################################
+#
+# Save the DB on disk:
+#
+# save
+#
+# Will save the DB if both the given number of seconds and the given
+# number of write operations against the DB occurred.
+#
+# In the example below the behaviour will be to save:
+# after 900 sec (15 min) if at least 1 key changed
+# after 300 sec (5 min) if at least 10 keys changed
+# after 60 sec if at least 10000 keys changed
+#
+# Note: you can disable saving completely by commenting out all "save" lines.
+#
+# It is also possible to remove all the previously configured save
+# points by adding a save directive with a single empty string argument
+# like in the following example:
+#
+# save ""
+
+save 900 1
+save 300 10
+save 60 10000
+
+# By default Redis will stop accepting writes if RDB snapshots are enabled
+# (at least one save point) and the latest background save failed.
+# This will make the user aware (in a hard way) that data is not persisting
+# on disk properly, otherwise chances are that no one will notice and some
+# disaster will happen.
+#
+# If the background saving process will start working again Redis will
+# automatically allow writes again.
+#
+# However if you have setup your proper monitoring of the Redis server
+# and persistence, you may want to disable this feature so that Redis will
+# continue to work as usual even if there are problems with disk,
+# permissions, and so forth.
+stop-writes-on-bgsave-error yes
+
+# Compress string objects using LZF when dump .rdb databases?
+# For default that's set to 'yes' as it's almost always a win.
+# If you want to save some CPU in the saving child set it to 'no' but
+# the dataset will likely be bigger if you have compressible values or keys.
+rdbcompression yes
+
+# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
+# This makes the format more resistant to corruption but there is a performance
+# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
+# for maximum performances.
+#
+# RDB files created with checksum disabled have a checksum of zero that will
+# tell the loading code to skip the check.
+rdbchecksum yes
+
+# The filename where to dump the DB
+dbfilename dump.rdb
+
+# The working directory.
+#
+# The DB will be written inside this directory, with the filename specified
+# above using the 'dbfilename' configuration directive.
+#
+# The Append Only File will also be created inside this directory.
+#
+# Note that you must specify a directory here, not a file name.
+dir /var/lib/redis
+
+################################# REPLICATION #################################
+
+# Master-Slave replication. Use slaveof to make a Redis instance a copy of
+# another Redis server. A few things to understand ASAP about Redis replication.
+#
+# 1) Redis replication is asynchronous, but you can configure a master to
+# stop accepting writes if it appears to be not connected with at least
+# a given number of slaves.
+# 2) Redis slaves are able to perform a partial resynchronization with the
+# master if the replication link is lost for a relatively small amount of
+# time. You may want to configure the replication backlog size (see the next
+# sections of this file) with a sensible value depending on your needs.
+# 3) Replication is automatic and does not need user intervention. After a
+# network partition slaves automatically try to reconnect to masters
+# and resynchronize with them.
+#
+# slaveof
+
+# If the master is password protected (using the "requirepass" configuration
+# directive below) it is possible to tell the slave to authenticate before
+# starting the replication synchronization process, otherwise the master will
+# refuse the slave request.
+#
+# masterauth
+
+# When a slave loses its connection with the master, or when the replication
+# is still in progress, the slave can act in two different ways:
+#
+# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will
+# still reply to client requests, possibly with out of date data, or the
+# data set may just be empty if this is the first synchronization.
+#
+# 2) if slave-serve-stale-data is set to 'no' the slave will reply with
+# an error "SYNC with master in progress" to all the kind of commands
+# but to INFO and SLAVEOF.
+#
+slave-serve-stale-data yes
+
+# You can configure a slave instance to accept writes or not. Writing against
+# a slave instance may be useful to store some ephemeral data (because data
+# written on a slave will be easily deleted after resync with the master) but
+# may also cause problems if clients are writing to it because of a
+# misconfiguration.
+#
+# Since Redis 2.6 by default slaves are read-only.
+#
+# Note: read only slaves are not designed to be exposed to untrusted clients
+# on the internet. It's just a protection layer against misuse of the instance.
+# Still a read only slave exports by default all the administrative commands
+# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve
+# security of read only slaves using 'rename-command' to shadow all the
+# administrative / dangerous commands.
+slave-read-only yes
+
+# Replication SYNC strategy: disk or socket.
+#
+# -------------------------------------------------------
+# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY
+# -------------------------------------------------------
+#
+# New slaves and reconnecting slaves that are not able to continue the replication
+# process just receiving differences, need to do what is called a "full
+# synchronization". An RDB file is transmitted from the master to the slaves.
+# The transmission can happen in two different ways:
+#
+# 1) Disk-backed: The Redis master creates a new process that writes the RDB
+# file on disk. Later the file is transferred by the parent
+# process to the slaves incrementally.
+# 2) Diskless: The Redis master creates a new process that directly writes the
+# RDB file to slave sockets, without touching the disk at all.
+#
+# With disk-backed replication, while the RDB file is generated, more slaves
+# can be queued and served with the RDB file as soon as the current child producing
+# the RDB file finishes its work. With diskless replication instead once
+# the transfer starts, new slaves arriving will be queued and a new transfer
+# will start when the current one terminates.
+#
+# When diskless replication is used, the master waits a configurable amount of
+# time (in seconds) before starting the transfer in the hope that multiple slaves
+# will arrive and the transfer can be parallelized.
+#
+# With slow disks and fast (large bandwidth) networks, diskless replication
+# works better.
+repl-diskless-sync no
+
+# When diskless replication is enabled, it is possible to configure the delay
+# the server waits in order to spawn the child that transfers the RDB via socket
+# to the slaves.
+#
+# This is important since once the transfer starts, it is not possible to serve
+# new slaves arriving, that will be queued for the next RDB transfer, so the server
+# waits a delay in order to let more slaves arrive.
+#
+# The delay is specified in seconds, and by default is 5 seconds. To disable
+# it entirely just set it to 0 seconds and the transfer will start ASAP.
+repl-diskless-sync-delay 5
+
+# Slaves send PINGs to server in a predefined interval. It's possible to change
+# this interval with the repl_ping_slave_period option. The default value is 10
+# seconds.
+#
+# repl-ping-slave-period 10
+
+# The following option sets the replication timeout for:
+#
+# 1) Bulk transfer I/O during SYNC, from the point of view of slave.
+# 2) Master timeout from the point of view of slaves (data, pings).
+# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).
+#
+# It is important to make sure that this value is greater than the value
+# specified for repl-ping-slave-period otherwise a timeout will be detected
+# every time there is low traffic between the master and the slave.
+#
+# repl-timeout 60
+
+# Disable TCP_NODELAY on the slave socket after SYNC?
+#
+# If you select "yes" Redis will use a smaller number of TCP packets and
+# less bandwidth to send data to slaves. But this can add a delay for
+# the data to appear on the slave side, up to 40 milliseconds with
+# Linux kernels using a default configuration.
+#
+# If you select "no" the delay for data to appear on the slave side will
+# be reduced but more bandwidth will be used for replication.
+#
+# By default we optimize for low latency, but in very high traffic conditions
+# or when the master and slaves are many hops away, turning this to "yes" may
+# be a good idea.
+repl-disable-tcp-nodelay no
+
+# Set the replication backlog size. The backlog is a buffer that accumulates
+# slave data when slaves are disconnected for some time, so that when a slave
+# wants to reconnect again, often a full resync is not needed, but a partial
+# resync is enough, just passing the portion of data the slave missed while
+# disconnected.
+#
+# The bigger the replication backlog, the longer the time the slave can be
+# disconnected and later be able to perform a partial resynchronization.
+#
+# The backlog is only allocated once there is at least a slave connected.
+#
+# repl-backlog-size 1mb
+
+# After a master has no longer connected slaves for some time, the backlog
+# will be freed. The following option configures the amount of seconds that
+# need to elapse, starting from the time the last slave disconnected, for
+# the backlog buffer to be freed.
+#
+# A value of 0 means to never release the backlog.
+#
+# repl-backlog-ttl 3600
+
+# The slave priority is an integer number published by Redis in the INFO output.
+# It is used by Redis Sentinel in order to select a slave to promote into a
+# master if the master is no longer working correctly.
+#
+# A slave with a low priority number is considered better for promotion, so
+# for instance if there are three slaves with priority 10, 100, 25 Sentinel will
+# pick the one with priority 10, that is the lowest.
+#
+# However a special priority of 0 marks the slave as not able to perform the
+# role of master, so a slave with priority of 0 will never be selected by
+# Redis Sentinel for promotion.
+#
+# By default the priority is 100.
+slave-priority 100
+
+# It is possible for a master to stop accepting writes if there are less than
+# N slaves connected, having a lag less or equal than M seconds.
+#
+# The N slaves need to be in "online" state.
+#
+# The lag in seconds, that must be <= the specified value, is calculated from
+# the last ping received from the slave, that is usually sent every second.
+#
+# This option does not GUARANTEE that N replicas will accept the write, but
+# will limit the window of exposure for lost writes in case not enough slaves
+# are available, to the specified number of seconds.
+#
+# For example to require at least 3 slaves with a lag <= 10 seconds use:
+#
+# min-slaves-to-write 3
+# min-slaves-max-lag 10
+#
+# Setting one or the other to 0 disables the feature.
+#
+# By default min-slaves-to-write is set to 0 (feature disabled) and
+# min-slaves-max-lag is set to 10.
+
+################################## SECURITY ###################################
+
+# Require clients to issue AUTH before processing any other
+# commands. This might be useful in environments in which you do not trust
+# others with access to the host running redis-server.
+#
+# This should stay commented out for backward compatibility and because most
+# people do not need auth (e.g. they run their own servers).
+#
+# Warning: since Redis is pretty fast an outside user can try up to
+# 150k passwords per second against a good box. This means that you should
+# use a very strong password otherwise it will be very easy to break.
+#
+# requirepass foobared
+
+# Command renaming.
+#
+# It is possible to change the name of dangerous commands in a shared
+# environment. For instance the CONFIG command may be renamed into something
+# hard to guess so that it will still be available for internal-use tools
+# but not available for general clients.
+#
+# Example:
+#
+# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
+#
+# It is also possible to completely kill a command by renaming it into
+# an empty string:
+#
+# rename-command CONFIG ""
+#
+# Please note that changing the name of commands that are logged into the
+# AOF file or transmitted to slaves may cause problems.
+
+################################### LIMITS ####################################
+
+# Set the max number of connected clients at the same time. By default
+# this limit is set to 10000 clients, however if the Redis server is not
+# able to configure the process file limit to allow for the specified limit
+# the max number of allowed clients is set to the current file limit
+# minus 32 (as Redis reserves a few file descriptors for internal uses).
+#
+# Once the limit is reached Redis will close all the new connections sending
+# an error 'max number of clients reached'.
+#
+# maxclients 10000
+
+# Don't use more memory than the specified amount of bytes.
+# When the memory limit is reached Redis will try to remove keys
+# according to the eviction policy selected (see maxmemory-policy).
+#
+# If Redis can't remove keys according to the policy, or if the policy is
+# set to 'noeviction', Redis will start to reply with errors to commands
+# that would use more memory, like SET, LPUSH, and so on, and will continue
+# to reply to read-only commands like GET.
+#
+# This option is usually useful when using Redis as an LRU cache, or to set
+# a hard memory limit for an instance (using the 'noeviction' policy).
+#
+# WARNING: If you have slaves attached to an instance with maxmemory on,
+# the size of the output buffers needed to feed the slaves are subtracted
+# from the used memory count, so that network problems / resyncs will
+# not trigger a loop where keys are evicted, and in turn the output
+# buffer of slaves is full with DELs of keys evicted triggering the deletion
+# of more keys, and so forth until the database is completely emptied.
+#
+# In short... if you have slaves attached it is suggested that you set a lower
+# limit for maxmemory so that there is some free RAM on the system for slave
+# output buffers (but this is not needed if the policy is 'noeviction').
+#
+# maxmemory
+
+# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
+# is reached. You can select among five behaviors:
+#
+# volatile-lru -> remove the key with an expire set using an LRU algorithm
+# allkeys-lru -> remove any key according to the LRU algorithm
+# volatile-random -> remove a random key with an expire set
+# allkeys-random -> remove a random key, any key
+# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
+# noeviction -> don't expire at all, just return an error on write operations
+#
+# Note: with any of the above policies, Redis will return an error on write
+# operations, when there are no suitable keys for eviction.
+#
+# At the date of writing these commands are: set setnx setex append
+# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
+# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
+# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
+# getset mset msetnx exec sort
+#
+# The default is:
+#
+# maxmemory-policy noeviction
+
+# LRU and minimal TTL algorithms are not precise algorithms but approximated
+# algorithms (in order to save memory), so you can tune it for speed or
+# accuracy. For default Redis will check five keys and pick the one that was
+# used less recently, you can change the sample size using the following
+# configuration directive.
+#
+# The default of 5 produces good enough results. 10 Approximates very closely
+# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.
+#
+# maxmemory-samples 5
+
+############################## APPEND ONLY MODE ###############################
+
+# By default Redis asynchronously dumps the dataset on disk. This mode is
+# good enough in many applications, but an issue with the Redis process or
+# a power outage may result into a few minutes of writes lost (depending on
+# the configured save points).
+#
+# The Append Only File is an alternative persistence mode that provides
+# much better durability. For instance using the default data fsync policy
+# (see later in the config file) Redis can lose just one second of writes in a
+# dramatic event like a server power outage, or a single write if something
+# wrong with the Redis process itself happens, but the operating system is
+# still running correctly.
+#
+# AOF and RDB persistence can be enabled at the same time without problems.
+# If the AOF is enabled on startup Redis will load the AOF, that is the file
+# with the better durability guarantees.
+#
+# Please check http://redis.io/topics/persistence for more information.
+
+appendonly no
+
+# The name of the append only file (default: "appendonly.aof")
+
+appendfilename "appendonly.aof"
+
+# The fsync() call tells the Operating System to actually write data on disk
+# instead of waiting for more data in the output buffer. Some OS will really flush
+# data on disk, some other OS will just try to do it ASAP.
+#
+# Redis supports three different modes:
+#
+# no: don't fsync, just let the OS flush the data when it wants. Faster.
+# always: fsync after every write to the append only log. Slow, Safest.
+# everysec: fsync only one time every second. Compromise.
+#
+# The default is "everysec", as that's usually the right compromise between
+# speed and data safety. It's up to you to understand if you can relax this to
+# "no" that will let the operating system flush the output buffer when
+# it wants, for better performances (but if you can live with the idea of
+# some data loss consider the default persistence mode that's snapshotting),
+# or on the contrary, use "always" that's very slow but a bit safer than
+# everysec.
+#
+# More details please check the following article:
+# http://antirez.com/post/redis-persistence-demystified.html
+#
+# If unsure, use "everysec".
+
+# appendfsync always
+appendfsync everysec
+# appendfsync no
+
+# When the AOF fsync policy is set to always or everysec, and a background
+# saving process (a background save or AOF log background rewriting) is
+# performing a lot of I/O against the disk, in some Linux configurations
+# Redis may block too long on the fsync() call. Note that there is no fix for
+# this currently, as even performing fsync in a different thread will block
+# our synchronous write(2) call.
+#
+# In order to mitigate this problem it's possible to use the following option
+# that will prevent fsync() from being called in the main process while a
+# BGSAVE or BGREWRITEAOF is in progress.
+#
+# This means that while another child is saving, the durability of Redis is
+# the same as "appendfsync none". In practical terms, this means that it is
+# possible to lose up to 30 seconds of log in the worst scenario (with the
+# default Linux settings).
+#
+# If you have latency problems turn this to "yes". Otherwise leave it as
+# "no" that is the safest pick from the point of view of durability.
+
+no-appendfsync-on-rewrite no
+
+# Automatic rewrite of the append only file.
+# Redis is able to automatically rewrite the log file implicitly calling
+# BGREWRITEAOF when the AOF log size grows by the specified percentage.
+#
+# This is how it works: Redis remembers the size of the AOF file after the
+# latest rewrite (if no rewrite has happened since the restart, the size of
+# the AOF at startup is used).
+#
+# This base size is compared to the current size. If the current size is
+# bigger than the specified percentage, the rewrite is triggered. Also
+# you need to specify a minimal size for the AOF file to be rewritten, this
+# is useful to avoid rewriting the AOF file even if the percentage increase
+# is reached but it is still pretty small.
+#
+# Specify a percentage of zero in order to disable the automatic AOF
+# rewrite feature.
+
+auto-aof-rewrite-percentage 100
+auto-aof-rewrite-min-size 64mb
+
+# An AOF file may be found to be truncated at the end during the Redis
+# startup process, when the AOF data gets loaded back into memory.
+# This may happen when the system where Redis is running
+# crashes, especially when an ext4 filesystem is mounted without the
+# data=ordered option (however this can't happen when Redis itself
+# crashes or aborts but the operating system still works correctly).
+#
+# Redis can either exit with an error when this happens, or load as much
+# data as possible (the default now) and start if the AOF file is found
+# to be truncated at the end. The following option controls this behavior.
+#
+# If aof-load-truncated is set to yes, a truncated AOF file is loaded and
+# the Redis server starts emitting a log to inform the user of the event.
+# Otherwise if the option is set to no, the server aborts with an error
+# and refuses to start. When the option is set to no, the user requires
+# to fix the AOF file using the "redis-check-aof" utility before to restart
+# the server.
+#
+# Note that if the AOF file will be found to be corrupted in the middle
+# the server will still exit with an error. This option only applies when
+# Redis will try to read more data from the AOF file but not enough bytes
+# will be found.
+aof-load-truncated yes
+
+################################ LUA SCRIPTING ###############################
+
+# Max execution time of a Lua script in milliseconds.
+#
+# If the maximum execution time is reached Redis will log that a script is
+# still in execution after the maximum allowed time and will start to
+# reply to queries with an error.
+#
+# When a long running script exceeds the maximum execution time only the
+# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be
+# used to stop a script that did not yet called write commands. The second
+# is the only way to shut down the server in the case a write command was
+# already issued by the script but the user doesn't want to wait for the natural
+# termination of the script.
+#
+# Set it to 0 or a negative value for unlimited execution without warnings.
+lua-time-limit 5000
+
+################################ REDIS CLUSTER ###############################
+#
+# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however
+# in order to mark it as "mature" we need to wait for a non trivial percentage
+# of users to deploy it in production.
+# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#
+# Normal Redis instances can't be part of a Redis Cluster; only nodes that are
+# started as cluster nodes can. In order to start a Redis instance as a
+# cluster node enable the cluster support uncommenting the following:
+#
+# cluster-enabled yes
+
+# Every cluster node has a cluster configuration file. This file is not
+# intended to be edited by hand. It is created and updated by Redis nodes.
+# Every Redis Cluster node requires a different cluster configuration file.
+# Make sure that instances running in the same system do not have
+# overlapping cluster configuration file names.
+#
+# cluster-config-file nodes-6379.conf
+
+# Cluster node timeout is the amount of milliseconds a node must be unreachable
+# for it to be considered in failure state.
+# Most other internal time limits are multiple of the node timeout.
+#
+# cluster-node-timeout 15000
+
+# A slave of a failing master will avoid to start a failover if its data
+# looks too old.
+#
+# There is no simple way for a slave to actually have a exact measure of
+# its "data age", so the following two checks are performed:
+#
+# 1) If there are multiple slaves able to failover, they exchange messages
+# in order to try to give an advantage to the slave with the best
+# replication offset (more data from the master processed).
+# Slaves will try to get their rank by offset, and apply to the start
+# of the failover a delay proportional to their rank.
+#
+# 2) Every single slave computes the time of the last interaction with
+# its master. This can be the last ping or command received (if the master
+# is still in the "connected" state), or the time that elapsed since the
+# disconnection with the master (if the replication link is currently down).
+# If the last interaction is too old, the slave will not try to failover
+# at all.
+#
+# The point "2" can be tuned by user. Specifically a slave will not perform
+# the failover if, since the last interaction with the master, the time
+# elapsed is greater than:
+#
+# (node-timeout * slave-validity-factor) + repl-ping-slave-period
+#
+# So for example if node-timeout is 30 seconds, and the slave-validity-factor
+# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the
+# slave will not try to failover if it was not able to talk with the master
+# for longer than 310 seconds.
+#
+# A large slave-validity-factor may allow slaves with too old data to failover
+# a master, while a too small value may prevent the cluster from being able to
+# elect a slave at all.
+#
+# For maximum availability, it is possible to set the slave-validity-factor
+# to a value of 0, which means, that slaves will always try to failover the
+# master regardless of the last time they interacted with the master.
+# (However they'll always try to apply a delay proportional to their
+# offset rank).
+#
+# Zero is the only value able to guarantee that when all the partitions heal
+# the cluster will always be able to continue.
+#
+# cluster-slave-validity-factor 10
+
+# Cluster slaves are able to migrate to orphaned masters, that are masters
+# that are left without working slaves. This improves the cluster ability
+# to resist to failures as otherwise an orphaned master can't be failed over
+# in case of failure if it has no working slaves.
+#
+# Slaves migrate to orphaned masters only if there are still at least a
+# given number of other working slaves for their old master. This number
+# is the "migration barrier". A migration barrier of 1 means that a slave
+# will migrate only if there is at least 1 other working slave for its master
+# and so forth. It usually reflects the number of slaves you want for every
+# master in your cluster.
+#
+# Default is 1 (slaves migrate only if their masters remain with at least
+# one slave). To disable migration just set it to a very large value.
+# A value of 0 can be set but is useful only for debugging and dangerous
+# in production.
+#
+# cluster-migration-barrier 1
+
+# By default Redis Cluster nodes stop accepting queries if they detect there
+# is at least an hash slot uncovered (no available node is serving it).
+# This way if the cluster is partially down (for example a range of hash slots
+# are no longer covered) all the cluster becomes, eventually, unavailable.
+# It automatically returns available as soon as all the slots are covered again.
+#
+# However sometimes you want the subset of the cluster which is working,
+# to continue to accept queries for the part of the key space that is still
+# covered. In order to do so, just set the cluster-require-full-coverage
+# option to no.
+#
+# cluster-require-full-coverage yes
+
+# In order to setup your cluster make sure to read the documentation
+# available at http://redis.io web site.
+
+################################## SLOW LOG ###################################
+
+# The Redis Slow Log is a system to log queries that exceeded a specified
+# execution time. The execution time does not include the I/O operations
+# like talking with the client, sending the reply and so forth,
+# but just the time needed to actually execute the command (this is the only
+# stage of command execution where the thread is blocked and can not serve
+# other requests in the meantime).
+#
+# You can configure the slow log with two parameters: one tells Redis
+# what is the execution time, in microseconds, to exceed in order for the
+# command to get logged, and the other parameter is the length of the
+# slow log. When a new command is logged the oldest one is removed from the
+# queue of logged commands.
+
+# The following time is expressed in microseconds, so 1000000 is equivalent
+# to one second. Note that a negative number disables the slow log, while
+# a value of zero forces the logging of every command.
+slowlog-log-slower-than 10000
+
+# There is no limit to this length. Just be aware that it will consume memory.
+# You can reclaim memory used by the slow log with SLOWLOG RESET.
+slowlog-max-len 128
+
+################################ LATENCY MONITOR ##############################
+
+# The Redis latency monitoring subsystem samples different operations
+# at runtime in order to collect data related to possible sources of
+# latency of a Redis instance.
+#
+# Via the LATENCY command this information is available to the user that can
+# print graphs and obtain reports.
+#
+# The system only logs operations that were performed in a time equal or
+# greater than the amount of milliseconds specified via the
+# latency-monitor-threshold configuration directive. When its value is set
+# to zero, the latency monitor is turned off.
+#
+# By default latency monitoring is disabled since it is mostly not needed
+# if you don't have latency issues, and collecting data has a performance
+# impact, that while very small, can be measured under big load. Latency
+# monitoring can easily be enabled at runtime using the command
+# "CONFIG SET latency-monitor-threshold " if needed.
+latency-monitor-threshold 0
+
+############################# EVENT NOTIFICATION ##############################
+
+# Redis can notify Pub/Sub clients about events happening in the key space.
+# This feature is documented at http://redis.io/topics/notifications
+#
+# For instance if keyspace events notification is enabled, and a client
+# performs a DEL operation on key "foo" stored in the Database 0, two
+# messages will be published via Pub/Sub:
+#
+# PUBLISH __keyspace@0__:foo del
+# PUBLISH __keyevent@0__:del foo
+#
+# It is possible to select the events that Redis will notify among a set
+# of classes. Every class is identified by a single character:
+#
+# K Keyspace events, published with __keyspace@__ prefix.
+# E Keyevent events, published with __keyevent@__ prefix.
+# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
+# $ String commands
+# l List commands
+# s Set commands
+# h Hash commands
+# z Sorted set commands
+# x Expired events (events generated every time a key expires)
+# e Evicted events (events generated when a key is evicted for maxmemory)
+# A Alias for g$lshzxe, so that the "AKE" string means all the events.
+#
+# The "notify-keyspace-events" takes as argument a string that is composed
+# of zero or multiple characters. The empty string means that notifications
+# are disabled.
+#
+# Example: to enable list and generic events, from the point of view of the
+# event name, use:
+#
+# notify-keyspace-events Elg
+#
+# Example 2: to get the stream of the expired keys subscribing to channel
+# name __keyevent@0__:expired use:
+#
+# notify-keyspace-events Ex
+#
+# By default all notifications are disabled because most users don't need
+# this feature and the feature has some overhead. Note that if you don't
+# specify at least one of K or E, no events will be delivered.
+notify-keyspace-events ""
+
+############################### ADVANCED CONFIG ###############################
+
+# Hashes are encoded using a memory efficient data structure when they have a
+# small number of entries, and the biggest entry does not exceed a given
+# threshold. These thresholds can be configured using the following directives.
+hash-max-ziplist-entries 512
+hash-max-ziplist-value 64
+
+# Similarly to hashes, small lists are also encoded in a special way in order
+# to save a lot of space. The special representation is only used when
+# you are under the following limits:
+list-max-ziplist-entries 512
+list-max-ziplist-value 64
+
+# Sets have a special encoding in just one case: when a set is composed
+# of just strings that happen to be integers in radix 10 in the range
+# of 64 bit signed integers.
+# The following configuration setting sets the limit in the size of the
+# set in order to use this special memory saving encoding.
+set-max-intset-entries 512
+
+# Similarly to hashes and lists, sorted sets are also specially encoded in
+# order to save a lot of space. This encoding is only used when the length and
+# elements of a sorted set are below the following limits:
+zset-max-ziplist-entries 128
+zset-max-ziplist-value 64
+
+# HyperLogLog sparse representation bytes limit. The limit includes the
+# 16 bytes header. When an HyperLogLog using the sparse representation crosses
+# this limit, it is converted into the dense representation.
+#
+# A value greater than 16000 is totally useless, since at that point the
+# dense representation is more memory efficient.
+#
+# The suggested value is ~ 3000 in order to have the benefits of
+# the space efficient encoding without slowing down too much PFADD,
+# which is O(N) with the sparse encoding. The value can be raised to
+# ~ 10000 when CPU is not a concern, but space is, and the data set is
+# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.
+hll-sparse-max-bytes 3000
+
+# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
+# order to help rehashing the main Redis hash table (the one mapping top-level
+# keys to values). The hash table implementation Redis uses (see dict.c)
+# performs a lazy rehashing: the more operation you run into a hash table
+# that is rehashing, the more rehashing "steps" are performed, so if the
+# server is idle the rehashing is never complete and some more memory is used
+# by the hash table.
+#
+# The default is to use this millisecond 10 times every second in order to
+# actively rehash the main dictionaries, freeing memory when possible.
+#
+# If unsure:
+# use "activerehashing no" if you have hard latency requirements and it is
+# not a good thing in your environment that Redis can reply from time to time
+# to queries with 2 milliseconds delay.
+#
+# use "activerehashing yes" if you don't have such hard requirements but
+# want to free memory asap when possible.
+activerehashing yes
+
+# The client output buffer limits can be used to force disconnection of clients
+# that are not reading data from the server fast enough for some reason (a
+# common reason is that a Pub/Sub client can't consume messages as fast as the
+# publisher can produce them).
+#
+# The limit can be set differently for the three different classes of clients:
+#
+# normal -> normal clients including MONITOR clients
+# slave -> slave clients
+# pubsub -> clients subscribed to at least one pubsub channel or pattern
+#
+# The syntax of every client-output-buffer-limit directive is the following:
+#
+# client-output-buffer-limit
+#
+# A client is immediately disconnected once the hard limit is reached, or if
+# the soft limit is reached and remains reached for the specified number of
+# seconds (continuously).
+# So for instance if the hard limit is 32 megabytes and the soft limit is
+# 16 megabytes / 10 seconds, the client will get disconnected immediately
+# if the size of the output buffers reach 32 megabytes, but will also get
+# disconnected if the client reaches 16 megabytes and continuously overcomes
+# the limit for 10 seconds.
+#
+# By default normal clients are not limited because they don't receive data
+# without asking (in a push way), but just after a request, so only
+# asynchronous clients may create a scenario where data is requested faster
+# than it can read.
+#
+# Instead there is a default limit for pubsub and slave clients, since
+# subscribers and slaves receive data in a push fashion.
+#
+# Both the hard or the soft limit can be disabled by setting them to zero.
+client-output-buffer-limit normal 0 0 0
+client-output-buffer-limit slave 256mb 64mb 60
+client-output-buffer-limit pubsub 32mb 8mb 60
+
+# Redis calls an internal function to perform many background tasks, like
+# closing connections of clients in timeout, purging expired keys that are
+# never requested, and so forth.
+#
+# Not all tasks are performed with the same frequency, but Redis checks for
+# tasks to perform according to the specified "hz" value.
+#
+# By default "hz" is set to 10. Raising the value will use more CPU when
+# Redis is idle, but at the same time will make Redis more responsive when
+# there are many keys expiring at the same time, and timeouts may be
+# handled with more precision.
+#
+# The range is between 1 and 500, however a value over 100 is usually not
+# a good idea. Most users should use the default of 10 and raise this up to
+# 100 only in environments where very low latency is required.
+hz 10
+
+# When a child rewrites the AOF file, if the following option is enabled
+# the file will be fsync-ed every 32 MB of data generated. This is useful
+# in order to commit the file to the disk more incrementally and avoid
+# big latency spikes.
+aof-rewrite-incremental-fsync yes
diff --git a/roles/nextcloud/vars/main.yml b/roles/nextcloud/vars/main.yml
new file mode 100644
index 0000000..97bb64e
--- /dev/null
+++ b/roles/nextcloud/vars/main.yml
@@ -0,0 +1,58 @@
+---
+# vars file for nextcloud
+
+php_ver: '8.1'
+
+required_packages:
+ - nginx
+ - imagemagick
+ - php-gd
+ - php-ldap
+ - php-imap
+ - php-json
+ - php-curl
+ - php-intl
+ - php-fpm
+ - php-bcmath
+ - php-gmp
+ - php-imagick
+ - php-mbstring
+ - php-redis
+ - php-xml
+ - php-zip
+ - php-apcu
+ - php-mysql
+
+nextcloud_dl_file_name:
+ latest: "{{['latest', nextcloud_version_major]|reject('undefined')|join('-')}}"
+ releases: "{{['nextcloud', nextcloud_version_full]|reject('undefined')|join('-')}}"
+ prereleases: "nextcloud-{{[nextcloud_version_full, nextcloud_version_special]|reject('undefined')|join()}}"
+ daily: "nextcloud-{{nextcloud_version_major|d('')}}-daily-{{nextcloud_version_special|d('')}}"
+
+mysql_credential_file:
+ debian: '/etc/mysql/debian.cnf'
+
+nextcloud_max_upload_size_in_bytes: "{{ nextcloud_max_upload_size | human_to_bytes }}"
+## finding the major version selected by the user :
+## type : string
+# the user will set either nextcloud_version_major or nextcloud_version_full
+# to pin point a major/specific version.
+# if nextcloud_version_major is set it can have 3 values:
+# - 'master' : we just set an arbitrary high version (99) -- used for daily
+# - a version number [M] : here's what we need. neat !
+# - stable[M] : just remove the 'stable' and here we go !
+# note: There is still a case when the user could use the master branch AND specify a very old date
+# and that whould make the computed major version inconsistent.
+# But I'm sure at 99.99% nobody wants to do that when using the daily channel.
+# if nextcloud_version_full is set, it always have the form [Major.minor.patch] version number. (M.m.p)
+# so the major version is the first element.
+# if both variables are set we exclude the prerelease channel that do not use the major version on the first condition.
+# if none are defined, either the user misconfigured the playbook that's calling the role
+# and the play should fail - so we won't manage this case here -
+# or nextcloud_get_latest is true which is the equivalent for us of using "master"
+nextcloud_computed_major_version: > # type string
+ {%- if nextcloud_version_major is defined and nextcloud_version_channel not in ['prereleases'] -%}
+ {{99 if nextcloud_version_major == 'master' else (nextcloud_version_major|regex_replace('stable')) }}
+ {%- elif nextcloud_version_full is defined -%}
+ {{ (nextcloud_version_full.split('.'))[0] }}
+ {%- else -%}99{%- endif -%}