From 057295231a50218cc61245c68a960a5d3fb0b97f Mon Sep 17 00:00:00 2001
From: Andrea Dell'Amico <adellam@isti.cnr.it>
Date: Tue, 12 Jun 2018 19:48:21 +0200
Subject: [PATCH] Role that installs owncloud.

---
 nextcloud/defaults/main.yml             |  28 +++++
 nextcloud/meta/main.yml                 |   6 +
 nextcloud/tasks/main.yml                |   3 +
 nextcloud/tasks/nextcloud-install.yml   |  83 +++++++++++++
 nextcloud/tasks/nextcloud-nginx.yml     |  17 +++
 nextcloud/templates/nginx-virthost.conf | 158 ++++++++++++++++++++++++
 nextcloud/vars/main.yml                 |  54 ++++++++
 7 files changed, 349 insertions(+)
 create mode 100644 nextcloud/defaults/main.yml
 create mode 100644 nextcloud/meta/main.yml
 create mode 100644 nextcloud/tasks/main.yml
 create mode 100644 nextcloud/tasks/nextcloud-install.yml
 create mode 100644 nextcloud/tasks/nextcloud-nginx.yml
 create mode 100644 nextcloud/templates/nginx-virthost.conf
 create mode 100644 nextcloud/vars/main.yml

diff --git a/nextcloud/defaults/main.yml b/nextcloud/defaults/main.yml
new file mode 100644
index 0000000..5b84253
--- /dev/null
+++ b/nextcloud/defaults/main.yml
@@ -0,0 +1,28 @@
+---
+nextcloud_version: 13.0.4
+nextcloud_dist_filename: 'nextcloud-{{ nextcloud_version }}.tar.bz2'
+nextcloud_download_url: 'https://download.nextcloud.com/server/releases/{{ nextcloud_dist_filename }}'
+nextcloud_use_redis: True
+nextcloud_use_memcache: False
+nextcloud_web_basedir: /var/www
+nextcloud_web_root: '{{ nextcloud_web_basedir }}/nextcloud'
+nextcloud_data_dir: /srv/nextcloud/data
+nextcloud_oc_dir: /srv/nextcloud/oc_keys
+nextcloud_servername: '{{ ansible_fqdn }}'
+nextcloud_servernames:
+  - { webroot: '{{ nextcloud_web_root }}', id: 1, name: '{{ nextcloud_servername }}' }
+
+nextcloud_user: nextcloud
+
+nextcloud_db: pgsql
+nextcloud_db_host: localhost
+nextcloud_db_name: nextcloud
+nextcloud_db_user: nextcloud_u
+#nextcloud_db_pwd: 'Use a vault file'
+
+nextcloud_admin_user: nc_admin
+#nextcloud_admin_u_pwd: 'Use a vault file'
+
+nextcloud_encryption_enabled: True
+nextcloud_ldap_auth: False
+
diff --git a/nextcloud/meta/main.yml b/nextcloud/meta/main.yml
new file mode 100644
index 0000000..5095747
--- /dev/null
+++ b/nextcloud/meta/main.yml
@@ -0,0 +1,6 @@
+---
+dependencies:
+  - { role: '../../library/roles/php-fpm' }
+  - { role: '../../library/roles/nginx' }
+  - { role: '../../library/roles/redis', when nextcloud_use_redis }
+  - { role: '../../library/roles/memcached', when nextcloud_use_memcache }
diff --git a/nextcloud/tasks/main.yml b/nextcloud/tasks/main.yml
new file mode 100644
index 0000000..53b6fe3
--- /dev/null
+++ b/nextcloud/tasks/main.yml
@@ -0,0 +1,3 @@
+---
+- import_tasks: nextcloud-nginx.yml
+- import_tasks: nextcloud-install.yml
diff --git a/nextcloud/tasks/nextcloud-install.yml b/nextcloud/tasks/nextcloud-install.yml
new file mode 100644
index 0000000..84555a2
--- /dev/null
+++ b/nextcloud/tasks/nextcloud-install.yml
@@ -0,0 +1,83 @@
+---
+- block:
+  - name: Create the nextcloud webroot
+    file: dest={{ nextcloud_web_basedir }} owner=root group=root state=directory
+
+  - name: Create the nextcloud data directory
+    file: dest={{ nextcloud_data_dir }} state=directory owner={{ item.user }} group={{ item.user }}
+    with_items: '{{ phpfpm_pools }}'
+
+  - name: Get nextcloud
+    get_url: url={{ nextcloud_download_url }} dest=/srv/{{ nextcloud_dist_filename }}
+
+  - name: Unpack the nextcloud archive
+    unarchive: remote_src=yes src=/srv/{{ nextcloud_dist_filename }} dest={{ item.doc_root }} owner={{ item.user }} group={{ item.user }}
+    args:
+      creates: '{{ item.doc_root }}/index.php'
+    with_items: '{{ phpfpm_pools }}'
+
+  tags: [ 'nextcloud' ]
+
+- block:
+  - name: Configure the nextcloud instance
+    shell: cd {{ item.doc_root }} ; php occ maintenance:install --database="{{ nextcloud_db }}" --database-host "{{ nextcloud_db_host }}" --database-name "{{ nextcloud_db_name }}" --database-user "{{ nextcloud_db_user }}" --database-pass "{{ nextcloud_db_pwd }}" --admin-user "{{ nextcloud_admin_user }}" --admin-pass "{{ nextcloud_admin_u_pwd }}"  --data-dir={{ nextcloud_data_dir }} ; touch {{ nextcloud_data_dir }}/.ht_nextcloud_setup
+    args:
+      creates: '{{ nextcloud_data_dir }}/.ht_nextcloud_setup'
+    with_items: '{{ phpfpm_pools }}'
+
+  - name: Set the trusted domains list
+    shell: cd {{ item.webroot }} ; php occ config:system:set trusted_domains {{ item.id }} --value={{ item.name }} ; touch {{ nextcloud_data_dir }}/.ht_nextcloud_trusted_domains
+    args:
+      creates: '{{ nextcloud_data_dir }}/.ht_nextcloud_trusted_domains'
+    with_items: '{{ nextcloud_servernames }}'
+
+  - name: Setup the cron configuration
+    shell: cd {{ item.webroot }} ; php occ background:cron ; touch {{ nextcloud_data_dir }}/.ht_nextcloud_cron
+    args:
+      creates: 'touch {{ nextcloud_data_dir }}/.ht_nextcloud_cron'
+    with_items: '{{ nextcloud_servernames }}'
+    tags: [ 'nextcloud', 'nextcloud_config_cron' ]
+
+  - name: Install the nextcloud cron job
+    cron: user={{ item.user }} minute="*/15" job="php -f {{ item.doc_root }}/cron.php" name="NextCloud cron job"
+    with_items: '{{ phpfpm_pools }}'
+    tags: [ 'nextcloud', 'nextcloud_config_cron' ]
+
+  become: True
+  become_user: '{{ nextcloud_user }}'
+  tags: [ 'nextcloud', 'nextcloud_config' ]
+
+- block:
+  - name: Create the nextcloud encryption keys directory
+    become_user: root
+    file: dest={{ nextcloud_oc_dir }} state=directory owner={{ item.user }} group={{ item.user }}
+    with_items: '{{ phpfpm_pools }}'
+
+  - name: Activate global encryption
+    shell: cd {{ item.doc_root }} ; php occ app:enable encryption ; php occ encryption:enable ; php occ encryption:enable-master-key  ; php occ encryption:change-key-storage-root {{ nextcloud_oc_dir }} ; touch {{ nextcloud_oc_dir }}/.ht_nextcloud_oc
+    args:
+      creates: '{{ nextcloud_oc_dir }}/.ht_nextcloud_oc'
+    with_items: '{{ phpfpm_pools }}'
+
+  become: True
+  become_user: '{{ nextcloud_user }}'
+  when: nextcloud_encryption_enabled
+  tags: [ 'nextcloud', 'nextcloud_config', 'nextcloud_config_oc' ]
+
+- block:
+  - name: Enable ldap
+    shell: cd {{ item.doc_root }} ; php occ app:enable user_ldap ; touch {{ item.doc_root }}/.ht_nextcloud_ldap_enabled
+    args:
+      creates: '{{ item.doc_root }}/.ht_nextcloud_ldap_enabled'
+    with_items: '{{ phpfpm_pools }}'
+
+  - name: Configure ldap
+    shell: cd {{ item.doc_root }} ; php occ ldap:create-empty-config ; touch {{ item.doc_root }}/.ht_nextcloud_ldap_configured
+    args:
+      creates: '{{ item.doc_root }}/.ht_nextcloud_ldap_configured'
+    with_items: '{{ phpfpm_pools }}'
+
+  become: True
+  become_user: '{{ nextcloud_user }}'
+  when: nextcloud_ldap_auth
+  tags: [ 'nextcloud', 'nextcloud_config', 'nextcloud_config_ldap' ]
diff --git a/nextcloud/tasks/nextcloud-nginx.yml b/nextcloud/tasks/nextcloud-nginx.yml
new file mode 100644
index 0000000..4c43aa9
--- /dev/null
+++ b/nextcloud/tasks/nextcloud-nginx.yml
@@ -0,0 +1,17 @@
+---
+- block:
+  - name: Install the nginx virtualhosts
+    template: src=nginx-virthost.conf dest=/etc/nginx/sites-available/{{ item.virthost }} owner=root group=root mode=0444
+    with_items: '{{ phpfpm_pools }}'
+    notify: Reload nginx
+
+  - name: Enable the nginx virtualhosts
+    file: src=/etc/nginx/sites-available/{{ item.virthost }} dest=/etc/nginx/sites-enabled/{{ item.virthost }} state=link
+    with_items: '{{ phpfpm_pools }}'
+    notify: Reload nginx
+
+  - name: Create the nginx body temp directory
+    file: dest={{ nginx_client_body_temp_dir }} state=directory owner=www-data group=www-data mode=1700
+    when: nginx_client_body_temp_dir is defined
+
+  tags: [ 'nginx', 'virtualhost', 'nextcloud' ]
diff --git a/nextcloud/templates/nginx-virthost.conf b/nextcloud/templates/nginx-virthost.conf
new file mode 100644
index 0000000..292e319
--- /dev/null
+++ b/nextcloud/templates/nginx-virthost.conf
@@ -0,0 +1,158 @@
+upstream php-handler {
+    server {{ item.listen }};
+    #server unix:/var/run/php5-fpm.sock;
+}
+
+server {
+    listen 80;
+    listen [::]:80;
+    server_name {{ item.nginx_servername }};
+    # enforce https
+    location ~ /\.(?!well-known).* {
+        deny all;
+        access_log off;
+        log_not_found off;
+        return 404;
+    }
+    include /etc/nginx/snippets/letsencrypt-proxy.conf;
+    location / {
+        return 301 https://$server_name$request_uri;
+    }
+}
+
+server {
+    listen 443 ssl http2;
+    listen [::]:443 ssl http2;
+    server_name {{ item.nginx_servername }};
+
+    include /etc/nginx/snippets/nginx-server-ssl.conf;
+    server_tokens off;
+
+    # Add headers to serve security related headers
+    # Before enabling Strict-Transport-Security headers please read into this
+    # topic first.
+    # add_header Strict-Transport-Security "max-age=15768000;
+    # includeSubDomains; preload;";
+    #
+    # WARNING: Only add the preload option once you read about
+    # the consequences in https://hstspreload.org/. This option
+    # will add the domain to a hardcoded list that is shipped
+    # in all major browsers and getting removed from this list
+    # could take several months.
+    add_header X-Content-Type-Options nosniff;
+    add_header X-XSS-Protection "1; mode=block";
+    add_header X-Robots-Tag none;
+    add_header X-Download-Options noopen;
+    add_header X-Permitted-Cross-Domain-Policies none;
+
+    location ~ /\.(?!well-known).* {
+        deny all;
+        access_log off;
+        log_not_found off;
+        return 404;
+    }
+
+    # Path to the root of your installation
+    root {{ item.doc_root }};
+
+    location = /robots.txt {
+        allow all;
+        log_not_found off;
+        access_log off;
+    }
+
+    location = /favicon.ico {
+        log_not_found off;
+        access_log off;
+    }
+    # The following 2 rules are only needed for the user_webfinger app.
+    # Uncomment it if you're planning to use this app.
+    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
+    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
+    # last;
+
+    location = /.well-known/carddav {
+      return 301 $scheme://$host/remote.php/dav;
+    }
+    location = /.well-known/caldav {
+      return 301 $scheme://$host/remote.php/dav;
+    }
+
+    # set max upload size
+    client_max_body_size 512M;
+    fastcgi_buffers 64 4K;
+
+    # 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/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;
+
+    # Uncomment if your server is build with the ngx_pagespeed module
+    # This module is currently not supported.
+    #pagespeed off;
+
+    location / {
+        rewrite ^ /index.php$uri;
+    }
+
+    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
+        deny all;
+    }
+    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
+        deny all;
+    }
+
+    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
+        fastcgi_split_path_info ^(.+\.php)(/.*)$;
+        include fastcgi_params;
+        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+        fastcgi_param PATH_INFO $fastcgi_path_info;
+        fastcgi_param HTTPS on;
+        #Avoid sending the security headers twice
+        fastcgi_param modHeadersAvailable true;
+        fastcgi_param front_controller_active true;
+        fastcgi_pass php-handler;
+        fastcgi_intercept_errors on;
+        fastcgi_request_buffering off;
+    }
+
+    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
+        try_files $uri/ =404;
+        index index.php;
+    }
+
+    # Adding the cache control header for js and css files
+    # Make sure it is BELOW the PHP block
+    location ~ \.(?:css|js|woff|svg|gif)$ {
+        try_files $uri /index.php$uri$is_args$args;
+        add_header Cache-Control "public, max-age=15778463";
+        # Add headers to serve security related headers (It is intended to
+        # have those duplicated to the ones above)
+        # Before enabling Strict-Transport-Security headers please read into
+        # this topic first.
+        # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
+        #
+        # WARNING: Only add the preload option once you read about
+        # the consequences in https://hstspreload.org/. This option
+        # will add the domain to a hardcoded list that is shipped
+        # in all major browsers and getting removed from this list
+        # could take several months.
+        add_header X-Content-Type-Options nosniff;
+        add_header X-XSS-Protection "1; mode=block";
+        add_header X-Robots-Tag none;
+        add_header X-Download-Options noopen;
+        add_header X-Permitted-Cross-Domain-Policies none;
+        # Optional: Don't log access to assets
+        access_log off;
+    }
+
+    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
+        try_files $uri /index.php$uri$is_args$args;
+        # Optional: Don't log access to other assets
+        access_log off;
+    }
+}
+
diff --git a/nextcloud/vars/main.yml b/nextcloud/vars/main.yml
new file mode 100644
index 0000000..e21f911
--- /dev/null
+++ b/nextcloud/vars/main.yml
@@ -0,0 +1,54 @@
+---
+nginx_use_common_virthost: False
+phpfpm_default_user: '{{ nextcloud_user }}'
+phpfpm_default_pool_name: nextcloud
+redis_install: True
+http_port: 80
+https_port: 443
+
+php_version: 7.0
+phpfpm_base_dir: '/etc/php/{{ php_version }}/fpm'
+phpfpm_cli_dir: '/etc/php/{{ php_version }}/cli'
+
+php_fpm_packages:
+  - 'php{{ php_version }}-fpm'
+  - 'php{{ php_version }}-gd'
+  - 'php{{ php_version }}-json'
+  - 'php{{ php_version }}-ldap'
+  - 'php{{ php_version }}-{{ nextcloud_db }}'
+  - 'php{{ php_version }}-mcrypt'
+  - 'php{{ php_version }}-xml'
+  - 'php{{ php_version }}-mbstring'
+  - 'php{{ php_version }}-intl'
+  - 'php{{ php_version }}-curl'
+  - 'php{{ php_version }}-zip'
+  - 'php{{ php_version }}-bz2'
+  - 'php{{ php_version }}-gmp'
+  - 'php-imagick'
+  - 'php-redis'
+  - 'php-apcu'
+
+phpfpm_default_memory_limit: "384M"
+
+php_global_settings:
+  - { option: 'always_populate_raw_post_data', value: '-1' }
+  - { option: 'allow_url_fopen', value: 'off' }
+  - { option: 'max_execution_time', value: '240' }
+  - { option: 'memory_limit', value: '{{ phpfpm_default_memory_limit }}' }
+  - { option: 'max_input_vars', value: '1400' }
+  - { option: 'post_max_size', value: '32M' }
+  - { option: 'upload_max_filesize', value: '32M' }
+  - { option: 'opcache.enable', value: '1' }
+  - { option: 'opcache.enable_cli', value: '1' }
+  - { option: 'opcache.interned_strings_buffer', value: '8' }
+  - { option: 'opcache.max_accelerated_files', value: '10000' }
+  - { option: 'opcache.memory_consumption', value: '128' }
+  - { option: 'opcache.save_comments', value: '1' }
+  - { option: 'opcache.revalidate_freq', value: '1' }
+
+php_cli_global_settings: '{{ php_global_settings }}'
+
+
+phpfpm_pools:
+  - { pool_name: '{{ phpfpm_default_pool_name }}', app_context: '{{ phpfpm_default_context }}', user: '{{ phpfpm_default_user }}', group: '{{ phpfpm_default_group }}', listen: '{{ phpfpm_default_listen }}', allowed_clients: '{{ phpfpm_default_allowed_clients }}', pm: '{{ phpfpm_default_pm }}', pm_max_children: '{{ phpfpm_default_pm_max_children }}', pm_start_servers: '{{ phpfpm_default_pm_start_servers }}', pm_min_spare: '{{ phpfpm_default_pm_min_spare_servers }}', pm_max_spare: '{{ phpfpm_default_pm_max_spare_servers }}', pm_max_requests: '{{ phpfpm_default_pm_max_requests }}', pm_status_enabled: '{{ phpfpm_default_pm_status_enabled }}', pm_status_path: '{{ phpfpm_default_pm_status_path }}', ping_enabled: '{{ phpfpm_default_ping_enabled }}', ping_path: '{{ phpfpm_default_ping_path }}', ping_response: '{{ phpfpm_default_ping_response }}', display_errors: '{{ phpfpm_default_display_errors }}', log_errors: '{{ phpfpm_default_log_errors }}', memory_limit: '{{ phpfpm_default_memory_limit }}', slowlog_timeout: '{{ phpfpm_default_slowlog_timeout }}', rlimit_files: '{{ phpfpm_default_rlimit_files }}', php_extensions: '{{ phpfpm_default_extensions }}', define_custom_variables: '{{ phpfpm_default_define_custom_variables }}', doc_root: '{{ nextcloud_web_root }}', req_term_timeout: '240s', virthost: '{{ nextcloud_servername }}', nginx_servername: '{{ nextcloud_servername }}' }
+