From abf7a9f76749f944646663163d920299142b6e60 Mon Sep 17 00:00:00 2001 From: Bastian de Byl Date: Tue, 19 Jul 2022 15:10:38 -0400 Subject: [PATCH] added wiki.skudakrennsport.com --- ansible/roles/podman/defaults/main.yml | 2 + .../podman/tasks/configuration-nginx-http.yml | 2 + .../tasks/configuration-nginx-https.yml | 2 + .../podman/tasks/container-bookstack.yml | 80 ++++++++++++++++++ ansible/roles/podman/tasks/firewall.yml | 13 +-- ansible/roles/podman/tasks/main.yml | 1 + .../sites/wiki.skudakrennsport.com.conf.j2 | 13 +++ .../wiki.skudakrennsport.com.https.conf.j2 | 53 ++++++++++++ ansible/roles/ssl/tasks/certbot.yml | 1 + ansible/vars/vault.yml | Bin 5690 -> 6727 bytes 10 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 ansible/roles/podman/tasks/container-bookstack.yml create mode 100644 ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.conf.j2 create mode 100644 ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.https.conf.j2 diff --git a/ansible/roles/podman/defaults/main.yml b/ansible/roles/podman/defaults/main.yml index 8f60c5d..bd5110e 100644 --- a/ansible/roles/podman/defaults/main.yml +++ b/ansible/roles/podman/defaults/main.yml @@ -1,4 +1,5 @@ --- +bookstack_path: "{{ podman_volumes }}/bookstack" drone_path: "{{ podman_volumes }}/drone" graylog_path: "{{ podman_volumes }}/graylog" hass_path: "{{ podman_volumes }}/hass" @@ -13,6 +14,7 @@ drone_runner_capacity: "4" ci_server_name: ci.bdebyl.net pi_server_name: pi.bdebyl.net assistant_server_name: assistant.bdebyl.net +bookstack_server_name: wiki.skudakrennsport.com home_server_name: home.bdebyl.net parts_server_name: parts.bdebyl.net video_server_name: video.bdebyl.net diff --git a/ansible/roles/podman/tasks/configuration-nginx-http.yml b/ansible/roles/podman/tasks/configuration-nginx-http.yml index 7f2f72b..e0b2936 100644 --- a/ansible/roles/podman/tasks/configuration-nginx-http.yml +++ b/ansible/roles/podman/tasks/configuration-nginx-http.yml @@ -65,6 +65,7 @@ - "{{ pi_server_name }}.conf" - "{{ home_server_name }}.conf" - "{{ assistant_server_name }}.conf" + - "{{ bookstack_server_name }}.conf" - "{{ video_server_name }}.conf" - "{{ parts_server_name }}.conf" - "{{ logs_server_name }}.conf" @@ -87,6 +88,7 @@ - "{{ parts_server_name }}.conf" - "{{ home_server_name }}.conf" - "{{ assistant_server_name }}.conf" + - "{{ bookstack_server_name }}.conf" - "{{ video_server_name }}.conf" - "{{ logs_server_name }}.conf" notify: diff --git a/ansible/roles/podman/tasks/configuration-nginx-https.yml b/ansible/roles/podman/tasks/configuration-nginx-https.yml index b307ef3..5189f75 100644 --- a/ansible/roles/podman/tasks/configuration-nginx-https.yml +++ b/ansible/roles/podman/tasks/configuration-nginx-https.yml @@ -36,6 +36,7 @@ loop: - "{{ ci_server_name }}.https.conf" - "{{ parts_server_name }}.https.conf" + - "{{ bookstack_server_name }}.https.conf" notify: - restorecon podman - restart nginx @@ -52,6 +53,7 @@ loop: - "{{ ci_server_name }}.https.conf" - "{{ parts_server_name }}.https.conf" + - "{{ bookstack_server_name }}.https.conf" notify: - restorecon podman - restart nginx diff --git a/ansible/roles/podman/tasks/container-bookstack.yml b/ansible/roles/podman/tasks/container-bookstack.yml new file mode 100644 index 0000000..bd94f14 --- /dev/null +++ b/ansible/roles/podman/tasks/container-bookstack.yml @@ -0,0 +1,80 @@ +--- +- name: create required bookstack volumes + become: true + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: "{{ podman_subuid.stdout }}" + group: "{{ podman_user }}" + mode: 0755 + notify: restorecon podman + loop: + - "{{ bookstack_path }}/mysql" + tags: bookstack + +- name: flush handlers + ansible.builtin.meta: flush_handlers + tags: bookstack + +- name: create bookstack-db container + become: true + become_user: "{{ podman_user }}" + containers.podman.podman_container: + name: bookstack-db + image: docker.io/mysql:5.7.21 + recreate: false + restart: false + restart_policy: on-failure + log_driver: journald + network: + - shared + env: + MYSQL_ROOT_PASSWORD: "{{ bookstack_db_root_pass }}" + TZ: "America/New_York" + MYSQL_DATABASE: bookstack + MYSQL_USER: bookstack + MYSQL_PASSWORD: "{{ bookstack_db_pass }}" + volumes: + - "{{ bookstack_path }}/mysql:/var/lib/mysql" + tags: bookstack + +- name: create systemd startup job for bookstack-db + include_tasks: systemd-generate.yml + vars: + container_name: bookstack-db + tags: bookstack + +- name: create bookstack container + become: true + become_user: "{{ podman_user }}" + containers.podman.podman_container: + name: bookstack + image: docker.io/solidnerd/bookstack:22.04 + recreate: true + restart: false + restart_policy: on-failure + log_driver: journald + network: + - shared + env: + APP_URL: "https://wiki.skudakrennsport.com" + DB_HOST: "bookstack-db" + DB_USERNAME: "bookstack" + DB_DATABASE: "bookstack" + DB_PASSWORD: "{{ bookstack_db_pass }}" + MAIL_DRIVER: "smtp" + MAIL_HOST: "{{ bookstack_mail_host }}" + MAIL_PORT: 465 + MAIL_ENCRYPTION: "ssl" + MAIL_USERNAME: "{{ bookstack_mail_user }}" + MAIL_PASSWORD: "{{ bookstack_mail_pass }}" + MAIL_FROM: "{{ bookstack_mail_user }}" + MAIL_FROM_NAME: "Skudak Wiki" + ports: + - "6875:8080" + tags: bookstack +#- name: create systemd startup job for bookstack +# include_tasks: systemd-generate.yml +# vars: +# container_name: bookstack +# tags: bookstack diff --git a/ansible/roles/podman/tasks/firewall.yml b/ansible/roles/podman/tasks/firewall.yml index 4393564..b1cb4c8 100644 --- a/ansible/roles/podman/tasks/firewall.yml +++ b/ansible/roles/podman/tasks/firewall.yml @@ -8,14 +8,15 @@ zone: "public" state: enabled loop: - - 53/tcp - - 53/udp - - 1153/tcp - - 1153/udp - - 80/tcp - - 443/tcp - "{{ syslog_udp_default }}/udp" - "{{ syslog_udp_error }}/udp" - "{{ syslog_udp_unifi }}/udp" + - 1153/tcp + - 1153/udp + - 443/tcp + - 53/tcp + - 53/udp + - 6875/tcp + - 80/tcp notify: restart firewalld tags: firewall diff --git a/ansible/roles/podman/tasks/main.yml b/ansible/roles/podman/tasks/main.yml index 22d9974..a3468ea 100644 --- a/ansible/roles/podman/tasks/main.yml +++ b/ansible/roles/podman/tasks/main.yml @@ -8,4 +8,5 @@ - import_tasks: container-partkeepr.yml - import_tasks: container-graylog.yml - import_tasks: container-pihole.yml +- import_tasks: container-bookstack.yml - import_tasks: container-nginx.yml diff --git a/ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.conf.j2 b/ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.conf.j2 new file mode 100644 index 0000000..cc0fb4e --- /dev/null +++ b/ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.conf.j2 @@ -0,0 +1,13 @@ +server { + listen 80; + server_name {{ bookstack_server_name }}; + + location '/.well-known/acme-challenge' { + default_type "text/plain"; + root /srv/http/letsencrypt; + } + + location / { + return 301 https://$host$request_uri; + } +} diff --git a/ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.https.conf.j2 b/ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.https.conf.j2 new file mode 100644 index 0000000..c84960e --- /dev/null +++ b/ansible/roles/podman/templates/nginx/sites/wiki.skudakrennsport.com.https.conf.j2 @@ -0,0 +1,53 @@ +upstream bookstack { + server 127.0.0.1:6875; +} + +server { + modsecurity on; + modsecurity_rules_file /etc/nginx/modsec_includes.conf; + + resolver 127.0.0.1 127.0.0.53 9.9.9.9 valid=60s; + + listen 443 ssl http2; + server_name {{ bookstack_server_name }}; + + ssl_certificate /etc/letsencrypt/live/{{ bookstack_server_name }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ bookstack_server_name }}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{{ bookstack_server_name }}/fullchain.pem; + ssl_dhparam /etc/nginx/ssl/dhparam.pem; + + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_session_timeout 1d; + ssl_stapling on; + ssl_stapling_verify on; + + if ($whitelisted = 0) { + return 302 $scheme://skudakrennsport.com$request_uri; + } + + location / { + add_header Referrer-Policy "same-origin" always; + # add_header Strict-Transport-Security "max-age=630720000; includeSubDomains" always; + add_header X-Content-Type-Options "nosniff" always; + + # Sent from upstream: + # add_header X-Frame-Options "SAMEORIGIN"; + # add_header X-XSS-Protection "1; mode=block"; + + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_buffering off; + proxy_http_version 1.1; + proxy_pass http://bookstack; + proxy_redirect off; + + chunked_transfer_encoding off; + } +} + diff --git a/ansible/roles/ssl/tasks/certbot.yml b/ansible/roles/ssl/tasks/certbot.yml index 1ed1fcc..fca95c6 100644 --- a/ansible/roles/ssl/tasks/certbot.yml +++ b/ansible/roles/ssl/tasks/certbot.yml @@ -10,6 +10,7 @@ loop: - "{{ ci_server_name }}" - "{{ parts_server_name }}" + - "{{ bookstack_server_name }}" tags: ssl - name: set group ownership for /etc/letsencrypt/ diff --git a/ansible/vars/vault.yml b/ansible/vars/vault.yml index 666a1309f44960d2199e9cf57def27c2c1971bf3..bc1096ff494907b5233bb3318025504384009628 100644 GIT binary patch literal 6727 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

E3a|UWmuL`ZWEG~+lECSE$nbhD8ZCjH z$&vU6B)b$c(Z&1n|K(+&r;Hz$?g1LLos#)E2ey{eDx#B^-Nv43^hSYoHlB`?f5H^Cl9>{IbP z9HZbi6GEB@;B4~S%b8jMcC*G4zxdv47YGG#V;|wazCf~kmrE)Re8!waf;I`(`AzUB zXrY{HE*jbZm8uv?>JO5Z^`mkKp?;~Rn+m6tmEhNdRtP2I5FGO^bG8s)#Y>t9kxD2_ z2KXaicgCwU`beTZ>vawS72cJdLI!C3K|kW7(=h)}LT z!V(s?33Pvad3csZAzL;ifel-{naICSL||#~69xMnbVezwQjIe*4qJ1jOTMnRZ0@t; zDS2geM^dk3&7+mnmSwV8x?86%l$IeAg46P6#8T+(0osZvDZ009Q62aYy-$(C#khN$ zt101R_Jgh7Wfox@#By@GetTGXvFn$onI0h8epu{OJf@7RA{7L+ zeIl}btiVZs?`0qT=EAHe}-YRR<+wlczck4Ya-m{mh|fvByaC z=Z6Hfp9_3Qm*CL~*^CT|?K=Li@ZP!AY<*XMhGHv4fx#J<2^sLO1G!^&c3W9; zZ2InpvDFRnt>Dt+m7Ht)T^EF^ML=3?1s_R#7R$BOw#uF zo_4RhWZi`2#kA+VaHV3i1B)&6pEG?KSZ!7GTW9PB_$nzf+}?a;njm>rR9qfMPz);U0eE%`a6x z0}OjyXp)3`Nrtx^eQ?SaELT{mi$J|y?%Yj+0iJj^!ve#`$l-a8J`%DqaNh+(xs3cX zmI@-EJ_*zRfq^)CyQhJmyf@z~=h-IXF*GDM^YQanBY}5c?Lce&1cxMVjMw1!BCpD? zAUjipddnPbHDa^%hXzfd2s^-+da?3eE+gsn0C$s+@>8Q7P8Y&LA3>irtdg=u{eRe_ dKmS?0WUI-~>IX%Db{6-yMdhCeK-6frDNu8T0rda? literal 5690 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