diff --git a/.zuul.yaml b/.zuul.yaml index 6a90bc7..826fe24 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,5 +1,22 @@ -- project: - name: openstack/ara-infra - templates: - - noop-jobs +- nodeset: + name: ara-infra-fedora-28 + nodes: + - name: infra.recordsansible.org + label: fedora-28 +- job: + name: ara-infra-website + parent: base + nodeset: ara-infra-fedora-28 + pre-run: tests/website-pre.yaml + run: playbooks/website.yaml + post-run: tests/website-post.yaml + success-url: logs/build/ + +- project: + check: + jobs: + - ara-infra-website + gate: + jobs: + - ara-infra-website diff --git a/playbooks/roles b/playbooks/roles new file mode 120000 index 0000000..d8c4472 --- /dev/null +++ b/playbooks/roles @@ -0,0 +1 @@ +../roles \ No newline at end of file diff --git a/playbooks/website.yaml b/playbooks/website.yaml new file mode 100644 index 0000000..c68d9cb --- /dev/null +++ b/playbooks/website.yaml @@ -0,0 +1,7 @@ +- name: Set up the ara.recordsansible.org website + hosts: infra.recordsansible.org + gather_facts: yes + tasks: + - name: Include the website role + include_role: + name: website diff --git a/roles/website/defaults/main.yaml b/roles/website/defaults/main.yaml new file mode 100644 index 0000000..33ede98 --- /dev/null +++ b/roles/website/defaults/main.yaml @@ -0,0 +1,22 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +hugo_release: https://github.com/gohugoio/hugo/releases/download/v0.51/hugo_0.51_Linux-64bit.tar.gz +hugo_directory: /opt/hugo +hugo_theme: https://github.com/jpescador/hugo-future-imperfect +hugo_theme_directory: "{{ hugo_directory }}/themes/hugo-future-imperfect" diff --git a/roles/website/files/ara.recordsansible.org.conf b/roles/website/files/ara.recordsansible.org.conf new file mode 100644 index 0000000..7a0e5df --- /dev/null +++ b/roles/website/files/ara.recordsansible.org.conf @@ -0,0 +1,60 @@ +upstream hugo { + server 127.0.0.1:1313; +} + +server { + server_name www.getara.org www.recordsansible.org; + return 301 $scheme://ara.recordsansible.org$request_uri; +} + +server { + listen 80; + server_name www.getara.org getara.org www.recordsansible.org ara.recordsansible.org; + + location / { + return 301 https://ara.recordsansible.org$request_uri; + } +} + +server { + listen 443; + server_name ara.recordsansible.org; + + ssl on; + ssl_certificate /etc/letsencrypt/live/ara.recordsansible.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ara.recordsansible.org/privkey.pem; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + + access_log /var/log/nginx/ara.recordsansible.org_access.log; + error_log /var/log/nginx/ara.recordsansible.org_error.log; + + # Media: images, icons, video, audio, HTC + location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|mp4|ogg|ogv|webm|htc)$ { + access_log off; + add_header Cache-Control "max-age=2592000"; + } + + # CSS and Javascript + location ~* \.(?:css|js)$ { + add_header Cache-Control "max-age=2592000"; + access_log off; + } + + location ^~ { + # checks for static file, if not found proxy to server + try_files $uri @proxy_to_server; + } + + location @proxy_to_server { + # Redefine the header fields that NGINX sends to the upstream server + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # Define the location of the proxy server to send the request to + proxy_pass http://hugo; + } +} diff --git a/roles/website/files/hugo.logrotate b/roles/website/files/hugo.logrotate new file mode 100644 index 0000000..5947a53 --- /dev/null +++ b/roles/website/files/hugo.logrotate @@ -0,0 +1,7 @@ +/var/log/hugo/*.log { + rotate 14 + size 10M + missingok + compress + copytruncate +} diff --git a/roles/website/handlers/main.yaml b/roles/website/handlers/main.yaml new file mode 100644 index 0000000..e3bc54e --- /dev/null +++ b/roles/website/handlers/main.yaml @@ -0,0 +1,23 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +- name: Restart nginx + become: yes + service: + name: nginx + state: restarted diff --git a/roles/website/tasks/hugo.yaml b/roles/website/tasks/hugo.yaml new file mode 100644 index 0000000..1c533c8 --- /dev/null +++ b/roles/website/tasks/hugo.yaml @@ -0,0 +1,94 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +- become: yes + block: + - name: Install git + package: + name: git + state: present + + - name: Create user for Hugo + become: true + user: + name: hugo + comment: User for Hugo + shell: /sbin/nologin + home: "{{ hugo_directory }}" + + - name: Create log directory for Hugo + file: + path: /var/log/hugo + state: directory + owner: hugo + group: hugo + mode: 0750 + + - name: Set up logrotate for Hugo + copy: + src: hugo.logrotate + dest: /etc/logrotate.d/hugo + + - name: Download Hugo release tarball + get_url: + url: "{{ hugo_release }}" + dest: "{{ hugo_directory }}" + register: hugo_download + + - name: Extract Hugo release tarball + unarchive: + src: "{{ hugo_download.dest }}" + dest: "{{ hugo_directory }}" + remote_src: yes + when: hugo_download is changed + + - name: Symlink Hugo in PATH + file: + src: "{{ hugo_directory }}/hugo" + dest: /usr/local/bin/hugo + owner: hugo + group: hugo + state: link + + - name: Clone Hugo theme + become_user: hugo + git: + repo: "{{ hugo_theme }}" + dest: "{{ hugo_theme_directory }}" + force: yes + update: yes + + - name: Configure Hugo server systemd service + template: + src: hugo.service.j2 + dest: /etc/systemd/system/hugo.service + owner: root + group: root + mode: 0644 + register: hugo_systemd + + - when: hugo_systemd is changed + block: + - name: Reload systemctl + systemd: + daemon_reload: yes + + - name: Restart Hugo + service: + name: hugo + state: restarted diff --git a/roles/website/tasks/main.yaml b/roles/website/tasks/main.yaml new file mode 100644 index 0000000..ff28c45 --- /dev/null +++ b/roles/website/tasks/main.yaml @@ -0,0 +1,42 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +# Zuul already prepares the src repository on the remote node and +# Zuul doesn't let you run pipe lookups on executors for security purposes +- name: Symlink ara-infra to persistent location with Zuul + become: yes + file: + src: "{{ ansible_user_dir }}/{{ zuul.project.src_dir }}" + dest: /opt/ara-infra + state: link + when: zuul is defined + +# git rev-parse --show-toplevel returns the root git directory +- name: Copy ara-infra to persistent location + become: yes + synchronize: + src: "{{ lookup('pipe', 'git rev-parse --show-toplevel') }}" + dest: /opt/ + delete: yes + when: zuul is not defined + +- name: Set up Hugo + include_tasks: hugo.yaml + +- name: Set up nginx + include_tasks: nginx.yaml diff --git a/roles/website/tasks/nginx.yaml b/roles/website/tasks/nginx.yaml new file mode 100644 index 0000000..d25a53c --- /dev/null +++ b/roles/website/tasks/nginx.yaml @@ -0,0 +1,43 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +- become: yes + block: + - name: Install nginx + package: + name: nginx + state: present + + - name: Set selinux boolean to allow nginx to reverse proxy + seboolean: + name: httpd_can_network_connect + state: yes + persistent: yes + + - name: Set up nginx vhost + copy: + src: ara.recordsansible.org.conf + dest: /etc/nginx/conf.d/ara.recordsansible.org.conf + notify: + - Restart nginx + + - name: Start and enable nginx + service: + name: nginx + state: started + enabled: yes diff --git a/roles/website/templates/hugo.service.j2 b/roles/website/templates/hugo.service.j2 new file mode 100644 index 0000000..a90d65d --- /dev/null +++ b/roles/website/templates/hugo.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=Hugo internal server +After=network.target + +[Service] +User=hugo +Group=hugo +Type=simple +ExecStart=/usr/local/bin/hugo server --source /opt/ara-infra/website --themesDir {{ hugo_directory }}/themes --log --logFile /var/log/hugo/hugo.log --baseURL "https://ara.recordsansible.org/" --appendPort=false +ProtectSystem=yes +ProtectHome=no +NoNewPrivileges=yes +PrivateTmp=yes + +[Install] +WantedBy=multi-user.target diff --git a/tests/website-post.yaml b/tests/website-post.yaml new file mode 100644 index 0000000..0392c81 --- /dev/null +++ b/tests/website-post.yaml @@ -0,0 +1,42 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +- name: Website post-run + hosts: infra.recordsansible.org + gather_facts: yes + tasks: + - name: Create artifact directories + file: + path: "{{ ansible_user_dir }}/workspace/logs/build" + state: directory + recurse: yes + + - name: Generate static version of the website + become: yes + command: | + /usr/local/bin/hugo \ + --source /opt/ara-infra/website \ + --themesDir /opt/hugo/themes \ + --destination {{ ansible_user_dir }}/workspace/logs/build + + - name: Upload log artifacts + synchronize: + src: "{{ ansible_user_dir }}/workspace/logs" + dest: "{{ zuul.executor.log_root }}" + mode: pull + verify_host: true diff --git a/tests/website-pre.yaml b/tests/website-pre.yaml new file mode 100644 index 0000000..abaf0d9 --- /dev/null +++ b/tests/website-pre.yaml @@ -0,0 +1,53 @@ +--- +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of ARA Records Ansible. +# +# ARA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ARA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ARA. If not, see . + +- name: Website pre-run + hosts: infra.recordsansible.org + vars: + domain: ara.recordsansible.org + ansible_python_interpreter: /usr/bin/python3 + tasks: + - become: true + block: + - name: Install python3-pyOpenSSL + package: + name: python3-pyOpenSSL + state: present + + - name: Create expected letsencrypt directories + file: + path: "/etc/letsencrypt/live/{{ domain }}" + state: directory + recurse: yes + + - name: Generate an OpenSSL private key + openssl_privatekey: + path: "/etc/letsencrypt/live/{{ domain }}/privkey.pem" + + - name: Generate an OpenSSL CSR + openssl_csr: + path: /etc/letsencrypt/live/{{ domain }}/request.csr + privatekey_path: "/etc/letsencrypt/live/{{ domain }}/privkey.pem" + common_name: "{{ domain }}" + + - name: Generate a self signed SSL certificate + openssl_certificate: + path: "/etc/letsencrypt/live/{{ domain }}/fullchain.pem" + privatekey_path: "/etc/letsencrypt/live/{{ domain }}/privkey.pem" + csr_path: /etc/letsencrypt/live/{{ domain }}/request.csr + provider: selfsigned diff --git a/website/config.toml b/website/config.toml index 2619c81..a8304af 100644 --- a/website/config.toml +++ b/website/config.toml @@ -9,8 +9,8 @@ disqusShortname = "" googleAnalytics = "UA-119558821-1" pluralizeListTitles = false enableRobotsTXT = true -canonifyURLs = true enableGitInfo = true +relativeURLs = true [params] # Sets the meta tag description