Initial commit

This commit is contained in:
s3lph 2021-04-26 00:07:37 +02:00
commit d8ec69086d
12 changed files with 306 additions and 0 deletions

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# Ansible Collection - s3lph.webserver
WIP

65
galaxy.yml Normal file
View file

@ -0,0 +1,65 @@
### REQUIRED
# The namespace of the collection. This can be a company/brand/organization or product namespace under which all
# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with
# underscores or numbers and cannot contain consecutive underscores
namespace: s3lph
# The name of the collection. Has the same character restrictions as 'namespace'
name: webserver
# The version of the collection. Must be compatible with semantic versioning
version: 0.1
# The path to the Markdown (.md) readme file. This path is relative to the root of the collection
readme: README.md
# A list of the collection's content authors. Can be just the name or in the format 'Full Name <email> (url)
# @nicks:irc/im.site#channel'
authors:
- s3lph <account-gitlab-ideynizv@kernelpanic.lol>
### OPTIONAL but strongly recommended
# A short summary description of the collection
description: Webserver, Apache, Lets Encrypt, ACME, Certbot
# Either a single license or a list of licenses for content inside of a collection. Ansible Galaxy currently only
# accepts L(SPDX,https://spdx.org/licenses/) licenses. This key is mutually exclusive with 'license_file'
license:
- MIT
# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character
# requirements as 'namespace' and 'name'
tags:
- email
- mailserver
- postfix
- dovecot
- postfixadmin
- postsrsd
# Collections that this collection requires to be installed for it to be usable. The key of the dict is the
# collection label 'namespace.name'. The value is a version range
# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version
# range specifiers can be set and are separated by ','
dependencies:
community.general: "2.2.0"
# The URL of the originating SCM repository
repository: https://gitlab.com/s3lph/ansible-collection-webserver
# The URL to any online docs
documentation: https://gitlab.com/s3lph/ansible-collection-webserver
# The URL to the homepage of the collection/project
homepage: https://gitlab.com/s3lph/ansible-collection-webserver
# The URL to the collection issue tracker
issues: https://gitlab.com/s3lph/ansible-collection-webserver/-/issues
# A list of file glob-like patterns used to filter any files or directories that should not be included in the build
# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This
# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry',
# and '.git' are always filtered
build_ignore: []

View file

@ -0,0 +1,31 @@
---
apache2_vhost_serveradmin: root@localhost
apache2_vhost_serveraliases: []
apache2_vhost_documentroot: /var/www/html
apache2_vhost_loglevel: warn
apache2_vhost_errorlog: "${APACHE_LOG_DIR}/error.log"
apache2_vhost_accesslog: "${APACHE_LOG_DIR}/access.log combined"
apache2_vhost_http_enabled: true
apache2_vhost_https_enabled: true
apache2_vhost_http_redirect_to_https: true
apache2_tls_certfile: "/etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem"
apache2_tls_keyfile: "/etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem"
apache2_tls_noacme_fallback_certfile: /etc/ssl/certs/ssl-cert-snakeoil.pem
apache2_tls_noacme_fallback_keyfile: /etc/ssl/private/ssl-cert-snakeoil.key
# generated 2021-04-22, Mozilla Guideline v5.6, Apache 2.4.41, OpenSSL 1.1.1d, intermediate configuration, no OCSP
# https://ssl-config.mozilla.org/#server=apache&version=2.4.41&config=intermediate&openssl=1.1.1d&ocsp=false&guideline=5.6
apache2_tls_protocols: "all -SSLv3 -TLSv1 -TLSv1.1"
apache2_tls_ciphersuite: "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"
apache2_tls_honor_cipher_order: false
apache2_tls_session_tickets: false
apache2_modules:
- ssl
- proxy_http
- headers
- rewrite
apache2_sites: {}

View file

@ -0,0 +1,11 @@
---
- name: restart apache2
service:
name: apache2
state: restarted
- name: reload apache2
service:
name: apache2
state: reloaded

View file

@ -0,0 +1,52 @@
---
- name: enable apache2 modules
community.general.apache2_module:
name: "{{ item }}"
loop: "{{ apache2_modules }}"
notify: restart apache2
- name: flush handlers
meta:
flush_handlers: {}
- name: check for tls keypair existence
stat:
path: "{{ item }}"
follow: yes
loop: |
{%- set files = [] -%}
{%- for name, site in apache2_sites | dict2items -%}
{%- if site.https_enabled | default(apache2_vhost_https_enabled) -%}
{%- endif -%}
{%- set _x = files.append(site.tls_certfile | default(apache2_tls_certfile)) -%}
{%- set _x = files.append(site.tls_keytfile | default(apache2_tls_keyfile)) -%}
{%- endfor -%}
{{- files | unique | list -}}
register: apache2_register_stat_tls_keypairs
- name: render apache site configs
template:
src: etc/apache2/sites-available/site.conf.j2
dest: "/etc/apache2/sites-available/{{ item.key }}.conf"
owner: root
group: root
mode: 0644
vars:
name: "{{ item.key }}"
site: "{{ item.value }}"
certfile_exists: "{{ apache2_register_stat_tls_keypairs[item.value.tls_certfile | default(apache2_tls_certfile)].stat.exists }}"
keyfile_exists: "{{ apache2_register_stat_tls_keypairs[item.value.tls_keyfile | default(apache2_tls_keyfile)].stat.exists }}"
loop: "{{ apache2_sites | dict2items }}"
notify: reload apache2
- name: enable apache2 sites
file:
path: "/etc/apache2/sites-enabled/{{ item }}.conf"
state: link
src: "../sites-available/{{ item }}.conf"
owner: root
group: root
mode: 0777
loop: "{{ apache2_sites }}"
notify: reload apache2

View file

@ -0,0 +1,13 @@
---
- name: install apache2 and related packages
apt:
name:
- apache2
- ssl-cert # snakeoil cert used for optional tls bootstrapping
- name: start and enable apache2
service:
name: apache2
state: started
enabled: yes

View file

@ -0,0 +1,11 @@
---
- import_tasks: install.yml
tags:
- "role::apache2"
- "role::apache2:install"
- import_tasks: config.yml
tags:
- "role::apache2"
- "role::apache2:config"

View file

@ -0,0 +1,55 @@
{{ ansible_managed | comment }}
{% if site.http_enabled | default(apache2_vhost_http_enabled) %}
<VirtualHost *:80>
ServerAdmin {{ site.serveradmin | default(apache2_vhost_serveradmin) }}
ServerName {{ name }}
{% for alias in site.aliases %}
ServerAlias {{ alias }}
{% endfor %}
LogLevel {{ site.loglevel | default(apache2_vhost_loglevel) }}
ErrorLog {{ site.errorlog | default(apache2_vhost_errorlog) }}
CustomLog {{ site.accesslog | default(apache2_vhost_accesslog) }}
{% if site.http_redirect_to_https | default(apache2_vhost_http_redirect_to_https) %}
Redirect permanent / https://{{ name }}/
{% else %}
DocumentRoot {{ site.documentroot | default(apache2_vhost_documentroot) }}
{{ site.additional_config | indent(8) }}
{% endif %}
</VirtualHost>
{% endif %}
{% if site.https_enabled | default(apache2_vhost_https_enabled) %}
<VirtualHost *:443>
ServerAdmin {{ site.serveradmin | default(apache2_vhost_serveradmin) }}
ServerName {{ name }}
{% for alias in site.aliases %}
ServerAlias {{ alias }}
{% endfor %}
LogLevel {{ site.loglevel | default(apache2_vhost_loglevel) }}
ErrorLog {{ site.errorlog | default(apache2_vhost_errorlog) }}
CustomLog {{ site.accesslog | default(apache2_vhost_accesslog) }}
SSLEngine on
{% if certfile_exists and keyfile_exists %}
SSLCertificateFile {{ site.tls_certfile | default(apache2_tls_certfile) }}
SSLCertificateKeyFile {{ site.tls_keyfile | default(apache2_tls_keyfile) }}
{% else %}
SSLCertificateFile {{ apache2_tls_noacme_fallback_certfile }}
SSLCertificateKeyFile {{ apache2_tls_noacme_fallback_keyfile }}
{% endif %}
DocumentRoot {{ site.documentroot | default(apache2_vhost_documentroot) }}
{{ site.additional_config | indent(8) }}
</VirtualHost>
{% endif %}

View file

@ -0,0 +1,9 @@
---
certbot_webroot: /var/www/html
certbot_rsa_key_size: 4096
certbot_email: null
certbot_acme_server: "https://acme-v02.api.letsencrypt.org/directory"
certbot_challenge: webroot
certbot_certificates: {}

View file

@ -0,0 +1,7 @@
---
- name: install certbot
apt:
name:
- certbot

View file

@ -0,0 +1,38 @@
---
- name: issue certificates
command: >-
/usr/bin/certbot certonly
--server {{ cert.server | default(certbot_acme_server) }}
--agree-tos
{% if cert.email | default(certbot_email) is none %}
--register-unsafely-without-email
{% else %}
--email {{ cert.email | default(certbot_email) }}
{% endif %}
--cert-name {{ name }}
--rsa-key-size {{ cert.rsa_key_size | default(certbot_rsa_key_size) }}
{% if cert.challenge | default(certbot_challenge) == 'webroot' %}
--webroot
{% if cert.webroot_map is defined %}
--webroot-map '{{ cert.webroot_map | to_json(width=99999) }}'
{% else %}
--webroot {{ cert.webroot }}
{% for domain in cert.domains | default([name]) %}
--domain {{ domain }}
{% endfor %}
{% endif %}
{% else %}
--{{ cert.challenge | default(certbot_challenge) }}
{{ cert.challenge_freeform_arguments }}
{% endif %}
creates: "/etc/letsencrypt/live/{{ name }}/fullchain.pem"
vars:
name: "{{ item.key }}"
cert: "{{ item.value }}"
loop: "{{ certbot_certificates | dict2items }}"

View file

@ -0,0 +1,11 @@
---
- import_tasks: install.yml
tags:
- "role::certbot"
- "role::certbot:install"
- import_tasks: issue.yml
tags:
- "role::certbot"
- "role::certbot:issue"