From ab013263473a58810f8f08c1607fe582fc7b5a1d Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Fri, 21 Oct 2016 20:27:01 -0400 Subject: [PATCH 1/8] Use the `n` version of node to install instead of system version: It doesn't seem right to use the original node binary to install rocket.chat, especially on systems that use much older versions of node, like on CentOS. --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index f46c4d6..6798af3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -136,7 +136,7 @@ npm: state: present path: "{{ rocket_chat_application_path }}/bundle/programs/server" - executable: "{{ rocket_chat_node_orig_npm }}" + executable: "{{ rocket_chat_node_path }}/npm" become: true become_user: "{{ rocket_chat_service_user }}" tags: build From 474c9a9bd19b9fceff38ba586fdf933fab29cd73 Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Fri, 21 Oct 2016 20:30:27 -0400 Subject: [PATCH 2/8] Replace the use of the file module for permission recursion with chown I've noticed over the course of using the role myself and testing that the use of Ansible's file module to recursively ensure permissions for the bundle directory is quite slow and can significantly impact the time it takes the role to complete. Chown in this instance is much, much faster. I'm commenting out the old functionality for posterity but will probably remove it in the future or revert back to Ansible's way if it improves in speed. --- tasks/main.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 6798af3..1adbfcc 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -153,12 +153,11 @@ - ansible_distribution_major_version == "14" - name: Ensure the Rocket.Chat application data permissions are correct - file: - path: "{{ rocket_chat_application_path }}" - state: directory - owner: "{{ rocket_chat_service_user }}" - group: "{{ rocket_chat_service_user }}" - recurse: true + command: >- + chown {{ rocket_chat_service_user }}.{{ rocket_chat_service_group }} + -R {{ rocket_chat_application_path | quote }} + args: + warn: no tags: build - include_vars: "{{ item }}" From ecd2eb72049978483929a24d8a8f48e050ba4616 Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Sat, 17 Dec 2016 10:27:13 -0500 Subject: [PATCH 3/8] Add self to author list, convert nginx single line 'and' into list --- meta/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index 089c99a..c78ec1b 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,6 +1,8 @@ --- galaxy_info: - author: Calum MacRae + author: + - Calum MacRae + - Michael Goodwin description: Deploy Rocket.Chat #company: your company (optional) # If the issue tracker for your role is not on github, uncomment the From b93ea86f63e103a9da7623a6f806b31585114dac Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Sun, 25 Sep 2016 20:16:21 -0400 Subject: [PATCH 4/8] Let's Encrypt Support! - Add rocket_chat_letsencrypt_* variables to defaults/main.yml - Add tasks/letsencrypt.yml utilizing acme-tiny.py for SSL certs - Inserts cronjob in /etc/cron.monthly/acme-tiny_renew.sh to keep things current (perhaps systemd timer in the future)\ - Set newly generated generic RSA certs to 4096 bits - Add .well-known path for ACME in templates/rocket_chat.conf - Add `cron` to dependencies Resolves: #17 --- defaults/main.yml | 10 +++++++ tasks/letsencrypt.yml | 56 +++++++++++++++++++++++++++++++++++ tasks/main.yml | 4 +++ tasks/nginx.yml | 7 +++-- templates/rocket_chat.conf.j2 | 12 +++++--- vars/Debian.yml | 2 ++ vars/RedHat.yml | 1 + vars/Ubuntu.yml | 1 + 8 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 tasks/letsencrypt.yml diff --git a/defaults/main.yml b/defaults/main.yml index fe8365c..71bb5cc 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -41,3 +41,13 @@ rocket_chat_nginx_generate_pfs_key: true rocket_chat_nginx_pfs_key_numbits: 2048 rocket_chat_nginx_pfs_key_path: /etc/nginx/rocket_chat.pem rocket_chat_nginx_pfs_file: ~ + +# letsencrypt settings +rocket_chat_include_letsencrypt: false +rocket_chat_letsencrypt_email: ~ +rocket_chat_letsencrypt_account_key: /etc/nginx/acme-tiny_account.key +rocket_chat_letsencrypt_csr: /etc/nginx/acme-tiny_{{ rocket_chat_service_host }}.csr +rocket_chat_letsencrypt_domain: "{{ rocket_chat_service_host }}" +rocket_chat_letsencrypt_acmetiny_path: /opt/acme-tiny +rocket_chat_letsencrypt_wellknown_path: /var/www/letsencrypt +rocket_chat_letsencrypt_ca_cert: https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem diff --git a/tasks/letsencrypt.yml b/tasks/letsencrypt.yml new file mode 100644 index 0000000..ce089b2 --- /dev/null +++ b/tasks/letsencrypt.yml @@ -0,0 +1,56 @@ +--- + +# possibly just copy the script into files and include it w/ the role? +- name: Clone acme-tiny to /opt [Let's Encrypt!] + git: + dest: "{{ rocket_chat_letsencrypt_acmetiny_path }}" + repo: https://github.com/diafygi/acme-tiny.git + force: yes + update: yes + +- name: Ensure letsencrypt well-known dir exists [Let's Encrypt!] + file: + path: "{{ rocket_chat_letsencrypt_wellknown_path }}" + state: directory + owner: "{{ rocket_chat_nginx_process_user }}" + +- name: Generate acme-tiny Let's Encrypt account key [Let's Encrypt!] + shell: >- + openssl genrsa -out {{ rocket_chat_letsencrypt_account_key }} 4096 + args: + creates: "{{ rocket_chat_letsencrypt_account_key }}" + +- name: Check if acme-tiny Let's Encrypt CSR exists [Let's Encrypt!] + stat: + path: "{{ rocket_chat_letsencrypt_csr }}" + register: csr_path + +- name: Generate acme-tiny Let's Encrypt CSR [Let's Encrypt!] + shell: >- + openssl req -new -sha256 -key {{ rocket_chat_ssl_key_path }} + -subj "/CN={{ rocket_chat_letsencrypt_domain | default(rocket_chat_service_host) }}" + -out {{ rocket_chat_letsencrypt_csr }} + when: + - (key_gen_result | changed) or + not csr_path.stat.exists + register: csr_gen_result + +- name: Setup script in cron.daily [Let's Encrypt!] + copy: + dest: /etc/cron.monthly/acme-tiny_renew.sh + mode: 0755 + content: | + #!/bin/bash + python {{ rocket_chat_letsencrypt_acmetiny_path }}/acme_tiny.py \ + --account-key {{ rocket_chat_letsencrypt_account_key }} \ + --csr {{ rocket_chat_letsencrypt_csr }} \ + --acme-dir {{ rocket_chat_letsencrypt_wellknown_path }} \ + > {{ rocket_chat_ssl_cert_path }} || exit + curl -s {{ rocket_chat_letsencrypt_ca_cert }} \ + >> {{ rocket_chat_ssl_cert_path }} && + nginx -t && nginx -s reload + +- name: Run acme-tiny_renew.sh (first run cert creation) [Let's Encrypt!] + shell: /etc/cron.monthly/acme-tiny_renew.sh + notify: Reload the Nginx service + when: csr_gen_result | changed diff --git a/tasks/main.yml b/tasks/main.yml index 1adbfcc..bd395c1 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -207,3 +207,7 @@ - include: nginx.yml when: rocket_chat_include_nginx|bool tags: nginx + + - include: letsencrypt.yml + when: rocket_chat_include_letsencrypt|bool + tags: letsencrypt diff --git a/tasks/nginx.yml b/tasks/nginx.yml index 5860a10..defaeeb 100644 --- a/tasks/nginx.yml +++ b/tasks/nginx.yml @@ -36,16 +36,19 @@ - name: Ensure SSL certs have been generated shell: >- - openssl req -x509 -newkey rsa:2048 -nodes + openssl req -x509 -newkey rsa:4096 -nodes -subj "/CN={{ rocket_chat_service_host }}/ /C=NA/ST=NA/L=NA/O=NA/OU=NA" -keyout {{ rocket_chat_ssl_key_path }} -out {{ rocket_chat_ssl_cert_path }} -days 3650 - when: rocket_chat_ssl_generate_certs|bool + when: + - rocket_chat_include_letsencrypt|bool + or rocket_chat_ssl_generate_certs|bool args: creates: "{{ rocket_chat_ssl_key_path }}" notify: Reload the Nginx service + register: key_gen_result - name: Ensure provided PFS key has been deployed copy: diff --git a/templates/rocket_chat.conf.j2 b/templates/rocket_chat.conf.j2 index 8ce677a..5d2e0be 100644 --- a/templates/rocket_chat.conf.j2 +++ b/templates/rocket_chat.conf.j2 @@ -4,10 +4,14 @@ upstream rocket_chat { server { listen 80; server_name {{ rocket_chat_service_host }}; - - # tell users to go to SSL version this time - if ($ssl_protocol = "") { - rewrite ^ https://$server_name$request_uri? permanent; +{% if rocket_chat_include_letsencrypt|bool %} + location /.well-known/acme-challenge/ { + alias /var/www/letsencrypt/; + try_files $uri =404; + } +{% endif %} + location / { + return 301 https://$host$request_uri; } } diff --git a/vars/Debian.yml b/vars/Debian.yml index 79b7159..9ff7861 100644 --- a/vars/Debian.yml +++ b/vars/Debian.yml @@ -6,6 +6,8 @@ rocket_chat_dep_packages: - npm - make - wget + # This seems to install something on Docker that causes a failure in the tests + - cron rocket_chat_mongodb_packages: - mongodb-org-server diff --git a/vars/RedHat.yml b/vars/RedHat.yml index 58671eb..7c1de1c 100644 --- a/vars/RedHat.yml +++ b/vars/RedHat.yml @@ -6,6 +6,7 @@ rocket_chat_dep_packages: - npm - make - wget + - crontabs rocket_chat_mongodb_packages: - mongodb diff --git a/vars/Ubuntu.yml b/vars/Ubuntu.yml index 79b7159..d4a44da 100644 --- a/vars/Ubuntu.yml +++ b/vars/Ubuntu.yml @@ -6,6 +6,7 @@ rocket_chat_dep_packages: - npm - make - wget + - cron rocket_chat_mongodb_packages: - mongodb-org-server From 42be891800e44edfcb2208821c8f60ff6150298f Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Sun, 25 Sep 2016 23:59:17 -0400 Subject: [PATCH 5/8] Installing cron on jessie docker fails the build --- tasks/main.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index bd395c1..ae8afa6 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -40,7 +40,14 @@ - name: Ensure Rocket.Chat dependencies are installed package: - name: "{{ rocket_chat_dep_packages }}" + name: + "{{ + (ansible_virtualization_type != 'docker') | + ternary( + rocket_chat_dep_packages, + rocket_chat_dep_packages | difference('[\"cron\"]') + ) + }}" state: present register: result until: result | succeeded From bfbc164a191427bafd533271acc7bb24665bbfd9 Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Sun, 22 Oct 2017 18:37:34 -0400 Subject: [PATCH 6/8] Major refactoring see changes below: - Change the way NPM and NodeJS are installed for robustness - `rocket_chat_node_path is now `rocket_chat_node_prefix` without the /bin - `rocket_chat_node_orig_npm` is now `rockat_chat_npm_dist` - Add new: - `rocket_chat_node_path`: path to installed node binary - `rocket_chat_npm_version`: Explicit NPM version - `rocket_chat_npm_path`: path to installed npm binary - `rocket_chat_npm_dist`: path to distribution NPM - Add `rocket_chat_letsencrypt_force_renew`: false - SELinux: Restorecon well-known directory for let's encrypt - Re-order instantiation of rocket_chat_service_group,user in order to fix a conflict - Check for privilege escalation rights (i.e. sudo) This is required in order to become a different user than the SSH user - Add Fedora support 24+ - Enable HTTP/2 support if the nginx server supports it - Enhance SSL options to meet current secure standards (HSTS ENABLED!) - Vagrantfile: - Add Fedora 24 and 25 support - Add `gcc-c++` and `policycoreutils-python` for RedHat distros that may need to compile certain dependencies --- README.md | 4 +- defaults/main.yml | 8 ++- tasks/letsencrypt.yml | 8 ++- tasks/main.yml | 96 +++++++++++++++++++++++---------- tasks/mongodb.yml | 6 --- tasks/nginx.yml | 20 ++++++- tasks/upgrade.yml | 2 +- templates/rocket_chat.conf.j2 | 18 +++---- templates/rocketchat.service.j2 | 2 +- templates/rocketchat_upstart.j2 | 2 +- templates/ssl.inc.j2 | 21 ++++++++ tests/Vagrantfile | 29 +++++++--- tests/provision.yml | 12 +++++ vars/Fedora_2x.yml | 6 +++ vars/RedHat.yml | 2 + vars/RedHat_7.yml | 2 +- 16 files changed, 173 insertions(+), 65 deletions(-) create mode 100644 templates/ssl.inc.j2 create mode 100644 vars/Fedora_2x.yml diff --git a/README.md b/README.md index b136ca7..c1c467e 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ All variables have sane defaults set in [`defaults/main.yml`](defaults/main.yml) | `rocket_chat_service_host` | `"{{ ansible_fqdn }}"` | The FQDN of the Rocket.Chat system | | `rocket_chat_service_port` | 3000 | The TCP port Rocket.Chat listens on | | `rocket_chat_node_version` | `4.5.0` | The version of NodeJS to install that `n` understands | -| `rocket_chat_node_path` | `/usr/local/n/versions/node/{{ rocket_chat_node_version }}/bin` | The path to the `node` binary directory that n installs | -| `rocket_chat_node_orig_npm` | `/usr/bin/npm` | The path to the original `npm` binary, before n installs any Node versions | +| `rocket_chat_node_prefix` | `/usr/local/n/versions/node/{{ rocket_chat_node_version }}` | The path to the `node` binary directory that n installs | +| `rocket_chat_npm_dist` | `/usr/bin/npm` | The path to the original `npm` binary, before n installs any Node versions | | `rocket_chat_include_mongodb` | true | A boolean value that determines whether or not to deploy MongoDB | | `rocket_chat_mongodb_keyserver` | keyserver.ubuntu.com | The GPG key server to use when importing the MongoDB repo key | | `rocket_chat_mongodb_gpg_key` | `7F0CEB10` | The GPG key fingerprint to import for the MongoDB repo | diff --git a/defaults/main.yml b/defaults/main.yml index 71bb5cc..563dcbe 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -16,8 +16,11 @@ rocket_chat_service_group: rocketchat rocket_chat_service_host: "{{ ansible_fqdn }}" rocket_chat_service_port: 3000 rocket_chat_node_version: 8.9.4 -rocket_chat_node_path: /usr/local/n/versions/node/{{ rocket_chat_node_version }}/bin -rocket_chat_node_orig_npm: /usr/bin/npm +rocket_chat_node_prefix: /usr/local/n/versions/node/{{ rocket_chat_node_version }} +rocket_chat_node_path: "{{ rocket_chat_node_prefix }}/bin/node" +rocket_chat_npm_version: 3.10.9 +rocket_chat_npm_path: "{{ rocket_chat_node_prefix }}/bin/npm" +rocket_chat_npm_dist: /usr/bin/npm # MongoDB settings rocket_chat_mongodb_packages: mongodb @@ -51,3 +54,4 @@ rocket_chat_letsencrypt_domain: "{{ rocket_chat_service_host }}" rocket_chat_letsencrypt_acmetiny_path: /opt/acme-tiny rocket_chat_letsencrypt_wellknown_path: /var/www/letsencrypt rocket_chat_letsencrypt_ca_cert: https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem +rocket_chat_letsencrypt_force_renew: false diff --git a/tasks/letsencrypt.yml b/tasks/letsencrypt.yml index ce089b2..4295424 100644 --- a/tasks/letsencrypt.yml +++ b/tasks/letsencrypt.yml @@ -10,10 +10,14 @@ - name: Ensure letsencrypt well-known dir exists [Let's Encrypt!] file: - path: "{{ rocket_chat_letsencrypt_wellknown_path }}" + path: "{{ rocket_chat_letsencrypt_wellknown_path }}" state: directory owner: "{{ rocket_chat_nginx_process_user }}" +- name: Restore SELinux contexts for well-know dir [Let's Encrypt!:SELinux] + command: restorecon -R "{{ rocket_chat_letsencrypt_wellknown_path }}" + when: ansible_selinux.status | default(None) | lower == "enabled" + - name: Generate acme-tiny Let's Encrypt account key [Let's Encrypt!] shell: >- openssl genrsa -out {{ rocket_chat_letsencrypt_account_key }} 4096 @@ -53,4 +57,4 @@ - name: Run acme-tiny_renew.sh (first run cert creation) [Let's Encrypt!] shell: /etc/cron.monthly/acme-tiny_renew.sh notify: Reload the Nginx service - when: csr_gen_result | changed + when: (csr_gen_result | changed) or rocket_chat_letsencrypt_force_renew diff --git a/tasks/main.yml b/tasks/main.yml index ae8afa6..d86390d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,14 +1,53 @@ --- # tasks/main.yml: Main tasks for RocketChat.Ansible + - name: Ensure the Rocket.Chat service group is present + group: + name: "{{ rocket_chat_service_group }}" + state: present + system: true + + - name: Ensure the Rocket.Chat service user is present + user: + comment: Rocket.Chat Service User + name: "{{ rocket_chat_service_user }}" + group: "{{ rocket_chat_service_group }}" + home: "{{ rocket_chat_application_path }}" + createhome: true + shell: /bin/false + state: present + system: true + + - name: Check for adequate privilege escalation rights + ping: + become: yes + become_user: "{{ rocket_chat_service_user }}" + register: result + ignore_errors: true + - assert: + that: result|succeeded + msg: > + Check your sudo configuration to ensure that your connecting user + can assume the identities of other users without prompting. + - include_vars: "{{ item }}" with_first_found: - "{{ ansible_distribution }}.yml" - "{{ ansible_os_family }}.yml" tags: vars + - include_vars: "{{ item }}" + with_first_found: + - "{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yml" + # Below is for example: Fedora_2x.yml = 20-29 + - "{{ ansible_distribution }}_{{ ansible_distribution_major_version[:1] ~ 'x' }}.yml" + - "{{ ansible_os_family }}_{{ ansible_distribution_major_version }}.yml" + tags: vars + - include: repo_RedHat.yml - when: ansible_os_family == "RedHat" + when: + - ansible_os_family|lower == "redhat" + - not ansible_distribution|lower == "fedora" tags: repo - name: Ensure APT cache has been updated recently @@ -21,23 +60,6 @@ when: rocket_chat_include_mongodb|bool tags: mongodb - - name: Ensure the Rocket.Chat service group is present - group: - name: "{{ rocket_chat_service_group }}" - state: present - system: true - - - name: Ensure the Rocket.Chat service user is present - user: - comment: Rocket.Chat Service User - name: "{{ rocket_chat_service_user }}" - group: "{{ rocket_chat_service_group }}" - home: "{{ rocket_chat_application_path }}" - createhome: true - shell: /bin/false - state: present - system: true - - name: Ensure Rocket.Chat dependencies are installed package: name: @@ -60,21 +82,36 @@ state: link when: ansible_os_family == "RedHat" - - name: Ensure n (NodeJS) is installed + - name: Ensure n (NodeJS) is installed (bootstrap correct version of NodeJS) npm: name: n global: true - executable: "{{ rocket_chat_node_orig_npm }}" + executable: "{{ rocket_chat_npm_dist }}" - - name: Check to see if n has installed the required 'node' binary + - name: Check to see if n has installed the required binaries in {{ rocket_chat_node_prefix }} stat: - path: "{{ rocket_chat_node_path }}/node" + path: "{{ rocket_chat_node_path }}" register: n_node_bin - - name: Install the supported NodeJS environment via n + - name: "Install the supported NodeJS environment via n [Version: {{ rocket_chat_node_version }}]" shell: n {{ rocket_chat_node_version }} when: not n_node_bin.stat.exists|bool + - name: Check to see if the proper npm version has already been installed + command: "{{ rocket_chat_npm_path }} --version" + changed_when: false + register: current_npm_version + + - name: "Install the supported NPM version via npm [Version: {{ rocket_chat_npm_version }}]" + npm: + name: npm + version: "{{ rocket_chat_npm_version }}" + path: "{{ rocket_chat_node_prefix }}/lib" + executable: "{{ rocket_chat_npm_path }}" + environment: + PATH: "{{ rocket_chat_node_prefix }}/bin:{{ ansible_env.PATH }}" + when: current_npm_version != rocket_chat_npm_version + - name: "Configure /etc/hosts" lineinfile: dest: /etc/hosts @@ -108,11 +145,11 @@ dest: "{{ rocket_chat_application_path }}/rocket.chat-{{ rocket_chat_version }}.tgz" timeout: "{{ rocket_chat_tarball_fetch_timeout }}" validate_certs: "{{ rocket_chat_tarball_validate_remote_cert }}" + owner: "{{ rocket_chat_service_user }}" + group: "{{ rocket_chat_service_group }}" # Temp fix for ansible/ansible#15915 ( Broken include in handlers ) # https://github.com/ansible/ansible/issues/15915 #notify: Upgrade Rocket.Chat - become: true - become_user: "{{ rocket_chat_service_user }}" register: result retries: 2 until: result | succeeded @@ -135,17 +172,20 @@ src: "{{ rocket_chat_application_path }}/rocket.chat-{{ rocket_chat_version }}.tgz" dest: "{{ rocket_chat_application_path }}" creates: "{{ rocket_chat_application_path }}/bundle" - become: true - become_user: "{{ rocket_chat_service_user }}" + owner: "{{ rocket_chat_service_user }}" + group: "{{ rocket_chat_service_group }}" tags: build - name: Install Rocket.Chat via NPM npm: state: present path: "{{ rocket_chat_application_path }}/bundle/programs/server" - executable: "{{ rocket_chat_node_path }}/npm" + executable: "{{ rocket_chat_npm_path }}" + production: true become: true become_user: "{{ rocket_chat_service_user }}" + environment: + PATH: "{{ rocket_chat_node_prefix }}/bin:{{ ansible_env.PATH }}" tags: build - name: Ensure the Rocket.Chat log file symlink is present [Ubuntu 14] diff --git a/tasks/mongodb.yml b/tasks/mongodb.yml index 14ac638..c6ee6e8 100644 --- a/tasks/mongodb.yml +++ b/tasks/mongodb.yml @@ -1,11 +1,5 @@ --- # tasks/mongodb.yml: MongoDB configuration for RocketChat.Ansible - - include_vars: "{{ item }}" - with_first_found: - - "{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yml" - - "{{ ansible_os_family }}_{{ ansible_distribution_major_version }}.yml" - - "{{ ansible_distribution }}.yml" - - "{{ ansible_os_family }}.yml" - name: Ensure the MongoDB repository key has been imported apt_key: diff --git a/tasks/nginx.yml b/tasks/nginx.yml index defaeeb..7ecbf19 100644 --- a/tasks/nginx.yml +++ b/tasks/nginx.yml @@ -11,13 +11,29 @@ name: nginx state: present + - name: Check if Nginx was compiled with the HTTP/2 module + shell: nginx -V 2>&1 | grep -q 'with-http_v2_module' + register: nginx_http2_module + changed_when: false + failed_when: false + + - name: Gather the current Nginx version string + shell: nginx -v 2>&1 | awk 'BEGIN{ FS="/" } { print $2 }' + register: nginx_version_string + changed_when: false + failed_when: false + - name: Deploy Nginx configuration template: src: "{{ item.src }}" dest: "{{ item.dest }}" with_items: - - { src: nginx.conf.j2, dest: /etc/nginx/nginx.conf } - - { src: rocket_chat.conf.j2, dest: /etc/nginx/conf.d/rocket_chat.conf } + - src: nginx.conf.j2 + dest: /etc/nginx/nginx.conf + - src: ssl.inc.j2 + dest: /etc/nginx/conf.d/ssl.inc + - src: rocket_chat.conf.j2 + dest: /etc/nginx/conf.d/rocket_chat.conf notify: Reload the Nginx service - name: Ensure provided SSL certs have been deployed diff --git a/tasks/upgrade.yml b/tasks/upgrade.yml index 21774db..3c97b6f 100644 --- a/tasks/upgrade.yml +++ b/tasks/upgrade.yml @@ -18,7 +18,7 @@ - name: Back up the current Rocket.Chat instance [UPGRADE] shell: >- mv {{ rocket_chat_application_path }}/bundle - {{ rocket_chat_upgrade_backup_path }}/backup_{{ ansible_date_time.date }} + {{ rocket_chat_upgrade_backup_path }}/backup_{{ ansible_date_time.date }}_{{ (1000|random|string|hash)[:8] }} when: rocket_chat_upgrade_backup|bool - name: Delete the current Rocket.Chat instance [UPGRADE] diff --git a/templates/rocket_chat.conf.j2 b/templates/rocket_chat.conf.j2 index 5d2e0be..5e732e4 100644 --- a/templates/rocket_chat.conf.j2 +++ b/templates/rocket_chat.conf.j2 @@ -3,7 +3,7 @@ upstream rocket_chat { } server { listen 80; - server_name {{ rocket_chat_service_host }}; + server_name {{ rocket_chat_service_host }}; {% if rocket_chat_include_letsencrypt|bool %} location /.well-known/acme-challenge/ { alias /var/www/letsencrypt/; @@ -16,18 +16,14 @@ server { } server { - listen 443 ssl; + listen 443 ssl{% if nginx_http2_module.rc == 0 %} http2{% endif %}; server_name {{ rocket_chat_service_host }}; - add_header Strict-Transport-Security "max-age=15768000"; + ssl_certificate {{ rocket_chat_ssl_cert_path }}; ssl_certificate_key {{ rocket_chat_ssl_key_path }}; -{% if rocket_chat_nginx_enable_pfs %} - ssl_dhparam {{ rocket_chat_nginx_pfs_key_path }}; -{% endif %} - ssl_session_cache shared:SSL:10m; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_prefer_server_ciphers on; - ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK"; + + include conf.d/ssl.inc; + error_page 497 https://$host:$server_port$request_uri; location / { proxy_pass http://rocket_chat; @@ -44,7 +40,7 @@ server { proxy_set_header Connection "upgrade"; proxy_redirect off; - + proxy_send_timeout 86400; proxy_read_timeout 86400; } diff --git a/templates/rocketchat.service.j2 b/templates/rocketchat.service.j2 index d99fe24..63315ac 100644 --- a/templates/rocketchat.service.j2 +++ b/templates/rocketchat.service.j2 @@ -15,7 +15,7 @@ Environment=MONGO_OPLOG_URL=mongodb://{{ rocket_chat_mongodb_server }}:{{ rocket Environment=ROOT_URL=https://{{ rocket_chat_service_host }} Environment=PORT={{ rocket_chat_service_port }} WorkingDirectory={{ rocket_chat_application_path }} -ExecStart={{ rocket_chat_node_path }}/node {{ rocket_chat_application_path }}/bundle/main.js +ExecStart={{ rocket_chat_node_path }} {{ rocket_chat_application_path }}/bundle/main.js [Install] WantedBy=multi-user.target diff --git a/templates/rocketchat_upstart.j2 b/templates/rocketchat_upstart.j2 index 173820b..4e2a84a 100644 --- a/templates/rocketchat_upstart.j2 +++ b/templates/rocketchat_upstart.j2 @@ -11,7 +11,7 @@ console log respawn respawn limit 10 5 -env NODE_BIN_DIR="{{ rocket_chat_node_path }}" +env NODE_BIN_DIR="{{ rocket_chat_node_prefix }}/bin" env NODE_PATH="/usr/local/lib/node_modules" env APPLICATION_PATH="{{ rocket_chat_application_path }}/bundle/main.js" diff --git a/templates/ssl.inc.j2 b/templates/ssl.inc.j2 new file mode 100644 index 0000000..ffa8fbf --- /dev/null +++ b/templates/ssl.inc.j2 @@ -0,0 +1,21 @@ + +ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; +{% if nginx_version_string.stdout | version_compare('1.1.0','>=') %} +ssl_ecdh_curve secp384r1; +{% endif %} +ssl_prefer_server_ciphers on; +ssl_protocols TLSv1.2 TLSv1.1; +ssl_session_cache shared:SSL:10M; +{% if nginx_version_string.stdout | version_compare('1.5.9','>=') %} +ssl_session_tickets off; +{% endif %} +{% if rocket_chat_nginx_enable_pfs %} +ssl_dhparam {{ rocket_chat_nginx_pfs_key_path }}; +{% endif %} +ssl_stapling on; +ssl_stapling_verify on; +resolver_timeout 5s; +add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; +add_header X-Frame-Options DENY; +add_header X-Content-Type-Options nosniff; +gzip off; diff --git a/tests/Vagrantfile b/tests/Vagrantfile index 7a5c6a7..990ad1a 100644 --- a/tests/Vagrantfile +++ b/tests/Vagrantfile @@ -1,6 +1,7 @@ -# ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox' +ENV['VAGRANT_NO_PARALLEL'] = 'yes' TYPE_NAME = 'RocketChat' -MEM_SIZE = 2048 +MEM_SIZE = 1024 +LV_CPU_MODE = 'host-passthrough' ANSIBLE_GROUP_NAME = 'chat_servers' SHARED_FOLDER_DISABLED = true @@ -31,16 +32,24 @@ Vagrant.configure('2') do |config| 'ubuntu16' => { 'id' => 1, 'atlas_name' => 'bento/ubuntu-16.04', - 'lv_atlas_name' => 'wholebits/ubuntu-16.04-64' + 'lv_atlas_name' => 'wholebits/ubuntu16.04-64' }, 'ubuntu14' => { 'id' => 2, 'atlas_name' => 'bento/ubuntu-14.04', - 'lv_atlas_name' => 'wholebits/ubuntu-14.04-64' + 'lv_atlas_name' => 'wholebits/ubuntu14.04-64' }, 'centos7' => { 'id' => 3, 'atlas_name' => 'centos/7' + }, + 'Fedora24' => { + 'id' => 4, + 'atlas_name' => 'fedora/24-cloud-base' + }, + 'Fedora25' => { + 'id' => 5, + 'atlas_name' => 'fedora/25-cloud-base' } } @@ -67,19 +76,23 @@ Vagrant.configure('2') do |config| machine.vm.provider :virtualbox do |vb, override| vb.customize ['modifyvm', :id, '--memory', MEM_SIZE.to_s] vb.name = name + '-' + TYPE_NAME - do_ansible(override, boxes) end machine.vm.provider :libvirt do |lv, override| lv.default_prefix = TYPE_NAME lv.memory = MEM_SIZE + lv.cpu_mode = LV_CPU_MODE override.vm.box = box_props['lv_atlas_name'] || box_props['atlas_name'] if box_props['lv_atlas_name'] =~ /wholebits/ override.vm.provision 'shell', - inline: 'apt-get -yqq update &&' \ - 'apt-get -yqq install python-minimal' + inline: 'apt-get -yqq update && apt-get -yqq install python-minimal' + do_ansible(override, boxes) + end + if box_props['atlas_name'] =~ /^fedora/ + override.vm.provision 'shell', + inline: 'dnf -d0 -e0 -y install python2-dnf libselinux-python' + do_ansible(override, boxes) end - do_ansible(override, boxes) end machine.vm.box = box_props['atlas_name'] diff --git a/tests/provision.yml b/tests/provision.yml index 3593795..0f2d104 100644 --- a/tests/provision.yml +++ b/tests/provision.yml @@ -2,6 +2,18 @@ - name: Apply the Rocket.Chat role to all chat_servers hosts: "{{ host_name | default('chat_servers') }}" + become: yes + + pre_tasks: + + - name: "Drop in permissive sudoers file for user: {{ ansible_user }}" + lineinfile: + dest: /etc/sudoers.d/{{ ansible_user }} + state: present + create: yes + regexp: '^{{ ansible_user }}.*' + line: '%{{ ansible_user }} ALL=(ALL) NOPASSWD: ALL' + validate: visudo -cf %s roles: - role: "{{ role_name | default('../../RocketChat.Server') }}" diff --git a/vars/Fedora_2x.yml b/vars/Fedora_2x.yml new file mode 100644 index 0000000..e5deafc --- /dev/null +++ b/vars/Fedora_2x.yml @@ -0,0 +1,6 @@ +--- +rocket_chat_service_update_command: systemctl daemon-reload +rocket_chat_service_template: + src: rocketchat.service.j2 + dest: /usr/lib/systemd/system/rocketchat.service +rocket_chat_tarball_validate_remote_cert: true diff --git a/vars/RedHat.yml b/vars/RedHat.yml index 7c1de1c..7580106 100644 --- a/vars/RedHat.yml +++ b/vars/RedHat.yml @@ -5,8 +5,10 @@ rocket_chat_dep_packages: - nodejs - npm - make + - gcc-c++ - wget - crontabs + - policycoreutils-python rocket_chat_mongodb_packages: - mongodb diff --git a/vars/RedHat_7.yml b/vars/RedHat_7.yml index 8f698b0..e5deafc 100644 --- a/vars/RedHat_7.yml +++ b/vars/RedHat_7.yml @@ -3,4 +3,4 @@ rocket_chat_service_update_command: systemctl daemon-reload rocket_chat_service_template: src: rocketchat.service.j2 dest: /usr/lib/systemd/system/rocketchat.service -rocket_chat_tarball_validate_remote_cert: false +rocket_chat_tarball_validate_remote_cert: true From a27758a729f542d7fc5522ab073c69966e80b6dd Mon Sep 17 00:00:00 2001 From: Sebastian Kral Date: Sat, 18 Feb 2017 23:01:13 -0500 Subject: [PATCH 7/8] Adding httpd_sys_content_t role for selinux to allow traffic to well_known folder --- tasks/letsencrypt.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/letsencrypt.yml b/tasks/letsencrypt.yml index 4295424..3f89f84 100644 --- a/tasks/letsencrypt.yml +++ b/tasks/letsencrypt.yml @@ -13,6 +13,8 @@ path: "{{ rocket_chat_letsencrypt_wellknown_path }}" state: directory owner: "{{ rocket_chat_nginx_process_user }}" + setype: httpd_sys_content_t + recurse: yes - name: Restore SELinux contexts for well-know dir [Let's Encrypt!:SELinux] command: restorecon -R "{{ rocket_chat_letsencrypt_wellknown_path }}" From 2179432c8bc86abe2a4b0a94ec94be83319552ca Mon Sep 17 00:00:00 2001 From: Michael Goodwin Date: Sat, 17 Feb 2018 15:44:45 -0500 Subject: [PATCH 8/8] Update NPM to 5.6.0 --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 563dcbe..d3f256a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -18,7 +18,7 @@ rocket_chat_service_port: 3000 rocket_chat_node_version: 8.9.4 rocket_chat_node_prefix: /usr/local/n/versions/node/{{ rocket_chat_node_version }} rocket_chat_node_path: "{{ rocket_chat_node_prefix }}/bin/node" -rocket_chat_npm_version: 3.10.9 +rocket_chat_npm_version: 5.6.0 rocket_chat_npm_path: "{{ rocket_chat_node_prefix }}/bin/npm" rocket_chat_npm_dist: /usr/bin/npm