diff --git a/roles/server/nextcloud/defaults/main.yml b/roles/server/nextcloud/defaults/main.yml new file mode 100644 index 0000000..f5a5406 --- /dev/null +++ b/roles/server/nextcloud/defaults/main.yml @@ -0,0 +1,28 @@ +--- + +domain: "nextcloud.localhost" + +nextcloud_system_user: "nextcloud" +system_user: "{{ nextcloud_system_user }}" + +nextcloud_gpg_fingerprint: "28806A878AE423A28372792ED75899B9A724937A" +nextcloud_gpg_key_remote: "https://nextcloud.com/nextcloud.asc" +nextcloud_release_remote: "https://download.nextcloud.com/server/releases/nextcloud-14.0.12.tar.bz2" +nextcloud_release_remote_checksum: "{{ nextcloud_release_remote }}.sha256" +nextcloud_release_remote_signature: "{{ nextcloud_release_remote }}.asc" + +nextcloud_user_directory: "/var/{{ nextcloud_system_user }}" +nextcloud_installation_directory: "{{ nextcloud_user_directory }}/nextcloud" # directory name of inside downloaded tar zip +nextcloud_data_directory: "{{ nextcloud_user_directory }}/data" + +nextcloud_keyring: "{{ nextcloud_user_directory }}/nextcloud.gpg" +nextcloud_release_file: "{{ nextcloud_user_directory }}/nextcloud.tar.bz2" +nextcloud_release_signature: "{{ nextcloud_release_file }}.asc" +nextcloud_config: "{{ nextcloud_installation_directory }}/config/config.php" + +database_user: "{{ nextcloud_system_user }}" +# database_pass from mysql/database +# database_name from mysql/database + +nextcloud_admin_user: "admin" +nextcloud_admin_pass: "{{ lookup('password', 'credentials/' + inventory_hostname + '/nextcloud/' + nextcloud_admin_user + ' length=80') }}" diff --git a/roles/server/nextcloud/meta/main.yml b/roles/server/nextcloud/meta/main.yml new file mode 100644 index 0000000..d4dc35b --- /dev/null +++ b/roles/server/nextcloud/meta/main.yml @@ -0,0 +1,78 @@ +--- + +dependencies: + - role: mysql/database + # database_user + - role: nginx/php-pool + # system_user + src: "{{ nextcloud_installation_directory }}" + includes: + - "{{ nextcloud_installation_directory }}/apps" + - role: nginx/server + directives: | + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Robots-Tag none; + add_header X-Download-Options noopen; + add_header X-Permitted-Cross-Domain-Policies none; + add_header Referrer-Policy no-referrer; + fastcgi_hide_header X-Powered-By; + root {{ nextcloud_installation_directory }}; + location = /.well-known/carddav { + return 301 $scheme://$host/remote.php/dav; + } + location = /.well-known/caldav { + return 301 $scheme://$host/remote.php/dav; + } + rewrite ^/.well-known/webfinger /public.php?service=webfinger last; + rewrite ^/.well-known/host-meta /public.php?service=host-meta last; + rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last; + client_max_body_size 10240M; + #fastcgi_buffers 64 4K; + location / { + rewrite ^ /index.php$request_uri; + } + location ~ ^/(build|tests|config|lib|3rdparty|templates|data)/ { + deny all; + } + location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { + deny all; + } + #location ~ \.(?:flv|mp4|mov|m4a)$ { + # mp4; + # mp4_buffer_size 100M; + # mp4_max_buffer_size 1024M; + # fastcgi_split_path_info ^(.+?\.php)(/.*)$; + # try_files $uri =404; + # fastcgi_index index.php; + # include fastcgi_params; + # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + # fastcgi_param PATH_INFO $fastcgi_path_info; + # fastcgi_param HTTPS on; + # fastcgi_param modHeadersAvailable true; + # fastcgi_param front_controller_active true; + # fastcgi_pass {{ pool_name }}; + # fastcgi_intercept_errors on; + # fastcgi_request_buffering off; + #} + location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) { + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param HTTPS on; + fastcgi_param modHeadersAvailable true; + fastcgi_param front_controller_active true; + fastcgi_pass {{ pool_name }}; + fastcgi_intercept_errors on; + fastcgi_request_buffering off; + } + location ~ ^/(?:updater|ocs-provider)(?:$|/) { + try_files $uri/ =404; + index index.php; + } + location ~ \.(?:css|js|woff2?|svg|gif|png|html|ttf|ico|jpg|jpeg)$ { + try_files $uri /index.php$request_uri; + access_log off; + } diff --git a/roles/server/nextcloud/tasks/install.yml b/roles/server/nextcloud/tasks/install.yml new file mode 100644 index 0000000..052b298 --- /dev/null +++ b/roles/server/nextcloud/tasks/install.yml @@ -0,0 +1,57 @@ +--- + +- name: Download Nextcloud release + become_user: "{{ nextcloud_system_user }}" + get_url: + url: "{{ nextcloud_release_remote }}" + checksum: "sha256:{{ nextcloud_release_remote_checksum }}" + dest: "{{ nextcloud_release_file }}" + mode: "u=rw,g=r" + validate_certs: yes + +- name: Download signature for Nextcloud release + become_user: "{{ nextcloud_system_user }}" + get_url: + url: "{{ nextcloud_release_remote_signature }}" + dest: "{{ nextcloud_release_signature }}" + mode: "u=rw,g=r" + force: yes + validate_certs: yes + +- name: Receive public key of Nextcloud developers + become_user: "{{ nextcloud_system_user }}" + command: >- + "{{ global_helper_directory }}/gpg_import_url_key.sh" + {{ nextcloud_gpg_key_remote | quote }} + {{ nextcloud_gpg_fingerprint | quote }} + {{ nextcloud_keyring | quote }} + args: + chdir: "{{ nextcloud_user_directory }}" + +- name: Validate signature + become_user: "{{ nextcloud_system_user }}" + command: >- + /usr/bin/gpg2 + --quiet + --no-default-keyring + --keyring "{{ nextcloud_keyring }}" + --verify "{{ nextcloud_release_signature }}" + args: + chdir: "{{ nextcloud_user_directory }}" + +- name: Unpack Nextcloud release + become_user: "{{ nextcloud_system_user }}" + unarchive: + src: "{{ nextcloud_release_file }}" + remote_src: yes + dest: "{{ nextcloud_user_directory }}" + owner: "{{ nextcloud_system_user }}" + group: "{{ nextcloud_system_user }}" + +- name: Remove installation files + file: + state: absent + path: "{{ item }}" + loop: + - "{{ nextcloud_release_file }}" + - "{{ nextcloud_release_signature }}" diff --git a/roles/server/nextcloud/tasks/main.yml b/roles/server/nextcloud/tasks/main.yml new file mode 100644 index 0000000..5a6f12c --- /dev/null +++ b/roles/server/nextcloud/tasks/main.yml @@ -0,0 +1,184 @@ +--- + +- name: Install required dependencies + apt: + state: present + name: + # For Office / Video Previews + - ffmpeg + - libreoffice + # PHP Dependencies + - php-apcu + - php-bz2 + - php-curl +# - php-dom +# - php-fileinfo + - php-gd +# - php-iconv + - php-imagick + - php-intl + - php-json + - php-mbstring + - php-mcrypt + - php-mysql +# - php-posix +# - php-simplexml + - php-xml +# - php-xmlreader +# - php-xmlwriter + - php-zip + +# TODO Redis + +- name: Configure system user + user: + state: present + name: "{{ nextcloud_system_user }}" + system: yes + shell: /bin/false + create_home: yes + move_home: yes + home: "{{ nextcloud_user_directory }}" + +- name: Check if Nextcloud is already downloaded + stat: + path: "{{ nextcloud_installation_directory }}/index.php" + register: nextcloud_installed + check_mode: no + +- name: Download Nextcloud + become_user: "{{ nextcloud_system_user }}" + include_tasks: install.yml + when: not nextcloud_installed.stat.exists + +- name: Create data directory + file: + state: directory + path: "{{ nextcloud_data_directory }}" + owner: "{{ nextcloud_system_user }}" + group: "{{ nextcloud_system_user }}" + mode: "u=rwx,g=rx" + +- name: Install Nextcloud + become_user: "{{ nextcloud_system_user }}" + command: >- + /usr/bin/php occ maintenance:install + --database mysql + --database-name {{ database_name | quote }} + --database-user {{ database_user | quote }} + --database-pass {{ database_pass | quote }} + --database-table-prefix oc_ + --admin-user {{ nextcloud_admin_user | quote }} + --admin-pass {{ nextcloud_admin_pass | quote }} + --data-dir {{ nextcloud_data_directory | quote }} + args: + chdir: "{{ nextcloud_installation_directory }}" + creates: "{{ nextcloud_config }}" + +- name: Configure Nextcloud default domain + become_user: "{{ nextcloud_system_user }}" + lineinfile: + backrefs: yes + path: "{{ nextcloud_config }}" + insertafter: "array \\(" + regexp: "^(\\s*)0 => '.*',$" + line: "\\g<1>0 => '{{ domain }}'," + validate: /usr/bin/php %s + +- name: Configure Nextcloud default domain for cli + become_user: "{{ nextcloud_system_user }}" + lineinfile: + backrefs: yes + path: "{{ nextcloud_config }}" + insertafter: "'version'" + regexp: "^(\\s*)'overwrite.cli.url' => '.*',$" + line: "\\1'overwrite.cli.url' => 'https://{{ domain }}'," + validate: /usr/bin/php %s + +- name: Install Nextcloud apps + become_user: "{{ nextcloud_system_user }}" + command: "/usr/bin/php occ app:install {{ item | quote }}" + args: + chdir: "{{ nextcloud_installation_directory }}" + register: nextcloud_apps_install_results + changed_when: "'already installed' not in nextcloud_apps_install_results.stdout" + failed_when: nextcloud_apps_install_results.rc != 0 and not (nextcloud_apps_install_results.rc == 1 and 'already installed' in nextcloud_apps_install_results.stdout) + with_items: + - accessibility + - activity + - admin_audit + - apporder + - bruteforcesettings + - calendar + - checksum + - cloud_federation_api + - comments + - contacts + - dav + - external + - federatedfilesharing + - federation + - files + - files_automatedtagging + - files_external + - files_pdfviewer + - files_rightclick + - files_sharing + - files_texteditor + - files_trashbin + - files_versions + - files_videoplayer + - firstrunwizard + - gallery + - logreader + - lookup_server_connector + - mail + - metadata + - nextcloud_announcements + - notes + - notifications + - oauth2 + - password_policy + - polls + - provisioning_api + - quota_warning + - serverinfo + - sharebymail + - sharerenamer +# - social + - sociallogin + - socialsharing_email + - spreed + - support + - survey_client + - systemtags + - tasks + - theming + - twofactor_admin + - twofactor_backupcodes + - twofactor_gateway + - twofactor_nextcloud_notification + - twofactor_totp + - twofactor_u2f + - updatenotification + - workflowengine + +- name: Set background job mode to cron + become_user: "{{ nextcloud_system_user }}" + command: /usr/bin/php occ background:cron + args: + chdir: "{{ nextcloud_installation_directory }}" + +#- name: Upgrade Nextcloud +# become_user: "{{ nextcloud_system_user }}" +# command: /usr/bin/php occ upgrade +# args: +# chdir: "{{ nextcloud_installation_directory }}" +# register: nextcloud_upgrade_result +# changed_when: "'already latest version' not in nextcloud_upgrade_result.rc" + +- name: Add background cron job + cron: + name: "nextcloud" + minute: "*/5" + job: "php -f \"{{ nextcloud_installation_directory }}/cron.php\"" diff --git a/roles/server/nextcloud/templates/install_nextcloud.sh b/roles/server/nextcloud/templates/install_nextcloud.sh new file mode 100755 index 0000000..7744a03 --- /dev/null +++ b/roles/server/nextcloud/templates/install_nextcloud.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +readonly CHECKSUM_TYPE="sha256"; +readonly CHECKSUM_APP="${CHECKSUM_TYPE}sum"; +readonly GPG_FINGERPRINT="{{ nextcloud_gpg_fingerprint }}"; +readonly NEXTCLOUD_USER="{{ nextcloud_system_user }}"; +readonly NEXTCLOUD_DIR="{{ nextcloud_installation_directory }}"; +readonly NEXTCLOUD_GIT_REPO="{{ nextcloud_source_repo }}"; + +readonly GIT_REPO="https://github.com/nextcloud/server"; +readonly VERSION_REGEX='v\d+(\.\d+)*'; + +set -e; + +gpg --quiet --keyserver eu.pool.sks-keyservers.net --recv "$GPG_FINGERPRINT"; + +function error() { + echo "$@" >&2; +} + +function as() { + sudo -u "$NEXTCLOUD_USER" "$@"; +} + +cd "$NEXTCLOUD_DIR"; + +version="$(curl --silent "$GIT_REPO/releases.atom" + | grep --only-matching --perl-regexp '(?<=\s)' + | grep --only-matching --perl-regexp '(?<=href="'"$GIT_REPO"'/releases/tag/'"$VERSION_REGEX"'(?="/>)' + | sort --reverse --numeric-sort + | head --lines=1)"; +if g verify-tag --raw "$TAG" 2>&1 | grep --fixed-strings "[GNUPG:] VALIDSIG $GPG_FINGERPRINT " > /dev/null; then + as composer update; +else + error "Invalid or missing signature for $TAG"; + exit 1; +fi + +