created role to configure multiple apache sites, using ansibleguy.infra_certs role to generate certificates
This commit is contained in:
parent
4875e6ef1f
commit
b0f520c8b5
104
README.md
104
README.md
|
|
@ -1,4 +1,4 @@
|
||||||
# Apache2 Ansible Role
|
# Apache2 Role
|
||||||
Ansible role to install apache2 sites on the target server.
|
Ansible role to install apache2 sites on the target server.
|
||||||
|
|
||||||
**Tested:**
|
**Tested:**
|
||||||
|
|
@ -6,17 +6,44 @@ Ansible role to install apache2 sites on the target server.
|
||||||
|
|
||||||
## Functionality
|
## Functionality
|
||||||
|
|
||||||
* Package installation
|
* **Package installation**
|
||||||
* Ansible dependencies (_minimal_)
|
* Ansible dependencies (_minimal_)
|
||||||
* Apache2
|
* Apache2
|
||||||
* Configuration
|
|
||||||
*
|
|
||||||
* Default opt-in:
|
* **Configuration**
|
||||||
*
|
* Support for multiple sites/servers
|
||||||
* Default opt-outs:
|
* Two **config-modes**:
|
||||||
*
|
* serve (_default_)
|
||||||
* Default config:
|
* redirect
|
||||||
*
|
|
||||||
|
|
||||||
|
* **Default config**:
|
||||||
|
* Disabled: <TLS1.2, unsecure ciphers, autoindex, servertokens/-signature, ServerSideIncludes, CGI
|
||||||
|
* Security headers: HSTS, X-Frame, Referrer-Policy, Content-Type nosniff, X-Domain-Policy, XXS-Protection
|
||||||
|
* Limits to prevent DDoS
|
||||||
|
* Logging to syslog
|
||||||
|
* Using a Self-Signed certificate
|
||||||
|
* Modules: +ssl, headers, rewrite; -autoindex
|
||||||
|
|
||||||
|
|
||||||
|
* **SSL modes** (_for more info see: [CERT ROLE](https://github.com/ansibleguy/infra_certs)_)
|
||||||
|
* **selfsigned** => Generate self-signed ones
|
||||||
|
* **ca** => Generate a minimal Certificate Authority and certificate signed by it
|
||||||
|
* **letsencrypt** => Uses the LetsEncrypt certbot
|
||||||
|
* **existing** => Copy certificate files or use existing ones
|
||||||
|
|
||||||
|
|
||||||
|
* **Default opt-ins**:
|
||||||
|
* restricting methods to POST/GET/HEAD
|
||||||
|
|
||||||
|
|
||||||
|
* **Default opt-outs**:
|
||||||
|
* Include the config file 'site_{{ site_name }}_app.conf' for advanced usage
|
||||||
|
|
||||||
|
|
||||||
|
Options to provide module config will be added in the future!<br>
|
||||||
|
Also some basic mods will get a pre-config added. (_prefork, evasive_)
|
||||||
|
|
||||||
## Info
|
## Info
|
||||||
|
|
||||||
|
|
@ -25,24 +52,65 @@ Ansible role to install apache2 sites on the target server.
|
||||||
|
|
||||||
* **Note:** this role currently only supports debian-based systems
|
* **Note:** this role currently only supports debian-based systems
|
||||||
|
|
||||||
|
|
||||||
|
* **Note:** This role expects that the site's unencrypted 'server' will only redirect to its encrypted connection.
|
||||||
|
|
||||||
|
|
||||||
|
* **Note:** If you want all domain-names to get 'caught' by a site/server you need to add an underline '*' as alias or domain!<br>
|
||||||
|
This will also be done automatically if no domain is supplied.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* Community collection: ```ansible-galaxy install -r requirements.yml```
|
* Community collection and certificate role: ```ansible-galaxy install -r requirements.yml```
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Config
|
||||||
|
|
||||||
|
Define the apache dictionary as needed!
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apache:
|
||||||
|
headers:
|
||||||
|
mySuperCustom: 'headerContent'
|
||||||
|
|
||||||
|
modules:
|
||||||
|
present: ['evasive']
|
||||||
|
|
||||||
|
guys_statics:
|
||||||
|
mode: 'serve'
|
||||||
|
domain: 'static.guy.net'
|
||||||
|
serve:
|
||||||
|
path: '/var/www/static'
|
||||||
|
|
||||||
|
ssl:
|
||||||
|
mode: 'ca' # create minimal ca with signed server-certificate
|
||||||
|
|
||||||
|
config:
|
||||||
|
KeepAliveTimeout: 10
|
||||||
|
|
||||||
|
git_stuff:
|
||||||
|
mode: 'redirect'
|
||||||
|
domain: 'ansibleguy.net'
|
||||||
|
aliases: ['www.ansibleguy.net']
|
||||||
|
redirect:
|
||||||
|
target: 'https://github.com/ansibleguy'
|
||||||
|
|
||||||
|
ssl:
|
||||||
|
mode: 'letsencrypt'
|
||||||
|
|
||||||
|
letsencrypt:
|
||||||
|
email: 'apache@template.ansibleguy.net'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Execution
|
||||||
|
|
||||||
Run the playbook:
|
Run the playbook:
|
||||||
```bash
|
```bash
|
||||||
ansible-playbook -K -D -i inventory/hosts.yml playbook.yml
|
ansible-playbook -K -D -i inventory/hosts.yml playbook.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
You need to define your instances by configuring the 'mariadb' dictionary!
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apache
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
There are also some useful **tags** available:
|
There are also some useful **tags** available:
|
||||||
* base => only configure basics; sites will not be touched
|
* base => only configure basics; sites will not be touched
|
||||||
* sites
|
* sites
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,13 @@ default_apache:
|
||||||
user: 'www-data'
|
user: 'www-data'
|
||||||
group: 'www-data'
|
group: 'www-data'
|
||||||
|
|
||||||
# additions to the main apache config
|
settings:
|
||||||
config: # see: https://httpd.apache.org/docs/2.4/mod/core.html
|
# setting to be set in apache2.conf
|
||||||
ServerTokens: 'Prod'
|
ServerTokens: 'Prod'
|
||||||
ServerSignature: 'Off'
|
ServerSignature: 'Off'
|
||||||
|
|
||||||
|
# additions to the main apache config
|
||||||
|
config: # see: https://httpd.apache.org/docs/2.4/mod/core.html
|
||||||
FileETag: 'None'
|
FileETag: 'None'
|
||||||
KeepAlive: 'On'
|
KeepAlive: 'On'
|
||||||
KeepAliveTimeout: 5
|
KeepAliveTimeout: 5
|
||||||
|
|
@ -45,6 +48,7 @@ default_apache:
|
||||||
SSLCompression: 'off'
|
SSLCompression: 'off'
|
||||||
|
|
||||||
headers: # https://htaccessbook.com/important-security-headers/ | https://geekflare.com/http-header-implementation/
|
headers: # https://htaccessbook.com/important-security-headers/ | https://geekflare.com/http-header-implementation/
|
||||||
|
# if first key does not include 'Header' => prepend 'Header set'
|
||||||
'Header always set Strict-Transport-Security': '"max-age=31536000; includeSubDomains; preload"'
|
'Header always set Strict-Transport-Security': '"max-age=31536000; includeSubDomains; preload"'
|
||||||
'Referrer-Policy': '"same-origin"'
|
'Referrer-Policy': '"same-origin"'
|
||||||
'Content-Security-Policy': "\"default-src 'self';\""
|
'Content-Security-Policy': "\"default-src 'self';\""
|
||||||
|
|
@ -56,6 +60,18 @@ default_apache:
|
||||||
# 'Header set Permissions-Policy': '"none"'
|
# 'Header set Permissions-Policy': '"none"'
|
||||||
# 'Header set Content-Security-Policy': '"default-src https:; font-src https:; img-src https:; script-src https:; style-src https:;"'
|
# 'Header set Content-Security-Policy': '"default-src https:; font-src https:; img-src https:; script-src https:; style-src https:;"'
|
||||||
|
|
||||||
|
ssl:
|
||||||
|
path: '/etc/apache2/ssl'
|
||||||
|
ca:
|
||||||
|
file: # can be used if you want to use an existing ca
|
||||||
|
cn: 'Apache CA Certificate'
|
||||||
|
org: 'AnsibleGuy'
|
||||||
|
ou:
|
||||||
|
country:
|
||||||
|
state:
|
||||||
|
locality:
|
||||||
|
email:
|
||||||
|
pwd: # it's highly recommended setting a passphrase!
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
present: ['ssl', 'headers', 'rewrite']
|
present: ['ssl', 'headers', 'rewrite']
|
||||||
|
|
@ -64,28 +80,32 @@ default_apache:
|
||||||
letsencrypt:
|
letsencrypt:
|
||||||
key_size: 4096
|
key_size: 4096
|
||||||
path: '/etc/letsencrypt'
|
path: '/etc/letsencrypt'
|
||||||
path_key: '/etc/ssl/private'
|
renew_timer: 'Mon *-*-* 03:00:00'
|
||||||
path_cert: '/etc/ssl/certs'
|
|
||||||
renew_timer: 'Mon *-*-* 00:00:00'
|
|
||||||
verbosity: 'v'
|
verbosity: 'v'
|
||||||
|
email:
|
||||||
|
renew: false # if a renewal should be started by the role; the renewal service will auto-renew the certificates otherwise
|
||||||
|
|
||||||
APACHE_CONFIG: "{{ default_apache | combine(apache, recursive=true) }}"
|
APACHE_CONFIG: "{{ default_apache | combine(apache, recursive=true) }}"
|
||||||
|
|
||||||
# site-specific config
|
# site-specific config
|
||||||
default_site_config:
|
default_site_config:
|
||||||
mode: 'serve'
|
mode: 'serve'
|
||||||
|
state: 'present'
|
||||||
admin: 'apache@template.ansibleguy.net'
|
admin: 'apache@template.ansibleguy.net'
|
||||||
port_plain: 80
|
port_plain: 80
|
||||||
port_ssl: 443
|
port_ssl: 443
|
||||||
|
aliases: []
|
||||||
|
ip:
|
||||||
|
|
||||||
config: {} # site-specific setting-value pairs
|
config: {} # site-specific setting-value pairs
|
||||||
config_additions: [] # lines that will 1-to-1 be appended to the site-config
|
config_additions: [] # lines that will 1-to-1 be appended to the site-config
|
||||||
|
app_include: false
|
||||||
|
headers: {}
|
||||||
|
|
||||||
security: # https://www.nixpal.com/apache-httpd-hardening/
|
security: # https://www.nixpal.com/apache-httpd-hardening/
|
||||||
disable_root_index: true
|
disable_root_index: true
|
||||||
disable_directory_access: true
|
|
||||||
disable_ssi_cgi: true
|
disable_ssi_cgi: true
|
||||||
limit_directory_access: true
|
restrict_methods: true
|
||||||
|
|
||||||
redirect:
|
redirect:
|
||||||
target: 'https://github.com/ansibleguy'
|
target: 'https://github.com/ansibleguy'
|
||||||
|
|
@ -95,16 +115,37 @@ default_site_config:
|
||||||
path: '/var/www/html'
|
path: '/var/www/html'
|
||||||
|
|
||||||
ssl:
|
ssl:
|
||||||
mode: 'letsencrypt' # local/selfsigned/letsencrypt
|
mode: 'selfsigned' # existing/selfsigned/ca/letsencrypt
|
||||||
file_pub: '/etc/apache2/ssl/DOMAIN.crt' # should use the certificate chain => top is server cert; bottom root cert
|
# existing:
|
||||||
file_key: '/etc/apache2/ssl/DOMAIN.key'
|
# We expect the certs to be placed in the role's 'files' directory named like the site
|
||||||
file_csr: '/etc/apache2/ssl/DOMAIN.csr'
|
# Example: files/certs/ansibleguy.key and files/certs/ansibleguy.crt
|
||||||
file_ca:
|
# letsencrypt:
|
||||||
csr_data:
|
# Host needs to have a valid public dns record pointed at it
|
||||||
country: 'AT'
|
# Needs to be publicly reachable over port 80/tcp
|
||||||
org: 'AnsibleGuy'
|
cert:
|
||||||
email: 'apache@template.ansibleguy.net'
|
name:
|
||||||
cn: 'Apache Certificate'
|
cn: 'Apache Certificate'
|
||||||
|
org: 'AnsibleGuy'
|
||||||
|
ou:
|
||||||
|
country:
|
||||||
|
state:
|
||||||
|
locality:
|
||||||
|
email:
|
||||||
|
crl_distribution: []
|
||||||
|
ca:
|
||||||
|
file: # can be used if you want to use an existing ca
|
||||||
|
cn:
|
||||||
|
org:
|
||||||
|
ou:
|
||||||
|
country:
|
||||||
|
state:
|
||||||
|
locality:
|
||||||
|
email:
|
||||||
|
pwd: # it's highly recommended setting a passphrase!
|
||||||
|
|
||||||
|
letsencrypt:
|
||||||
|
key_size:
|
||||||
|
email:
|
||||||
|
|
||||||
default_modules:
|
default_modules:
|
||||||
# <IfModule ${MOD}>
|
# <IfModule ${MOD}>
|
||||||
|
|
@ -137,10 +178,6 @@ default_modules:
|
||||||
|
|
||||||
APACHE_MODULES: "{{ default_modules | combine(modules, recursive=true) }}"
|
APACHE_MODULES: "{{ default_modules | combine(modules, recursive=true) }}"
|
||||||
|
|
||||||
packages:
|
|
||||||
apache: ['apache2']
|
|
||||||
letsencrypt: ['python3-certbot-apache']
|
|
||||||
|
|
||||||
apache_config_graylist: [
|
apache_config_graylist: [
|
||||||
'SSLEngine', 'SSLCertificateKeyFile', 'SSLCertificateFile', 'SSLCertificateChainFile', 'ErrorLog', 'CustomLog', 'ServerAdmin',
|
'SSLEngine', 'SSLCertificateKeyFile', 'SSLCertificateFile', 'SSLCertificateChainFile', 'ErrorLog', 'CustomLog', 'ServerAdmin',
|
||||||
'ServerAlias', 'ServerName', 'Redirect'
|
'ServerAlias', 'ServerName', 'Redirect'
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,26 @@ class FilterModule(object):
|
||||||
return {
|
return {
|
||||||
"safe_key": self.safe_key,
|
"safe_key": self.safe_key,
|
||||||
"all_true": self.all_true,
|
"all_true": self.all_true,
|
||||||
|
"prepare_letsencrypt": self.prepare_letsencrypt,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def safe_key(key: str) -> str:
|
def safe_key(key: str) -> str:
|
||||||
return regex_replace('[^0-9a-zA-Z]+', '', key.replace(' ', '_'))
|
return regex_replace(r'[^0-9a-zA-Z\.]+', '', key.replace(' ', '_'))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def all_true(data: list) -> bool:
|
def all_true(data: list) -> bool:
|
||||||
return all(data)
|
return all(data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def prepare_letsencrypt(site: dict, name: str) -> dict:
|
||||||
|
domains = [site['domain']]
|
||||||
|
domains.extend(site['aliases'])
|
||||||
|
return {
|
||||||
|
name: {
|
||||||
|
'domains': domains,
|
||||||
|
'key_size': site['letsencrypt']['key_size'],
|
||||||
|
'email': site['letsencrypt']['email'],
|
||||||
|
'state': site['state'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,8 @@ collections:
|
||||||
|
|
||||||
- name: 'community.general'
|
- name: 'community.general'
|
||||||
source: 'https://galaxy.ansible.com'
|
source: 'https://galaxy.ansible.com'
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- src: 'https://github.com/ansibleguy/infra_certs.git'
|
||||||
|
version: 'stable'
|
||||||
|
name: 'ansibleguy.infra_certs'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: "Apache | Debian | Site '{{ name }}' | Certs | Creating public directory"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ APACHE_CONFIG.ssl.path }}"
|
||||||
|
state: directory
|
||||||
|
mode: 0755
|
||||||
|
|
||||||
|
- name: "Apache | Debian | Site '{{ name }}' | Certs | Creating certificates"
|
||||||
|
ansible.builtin.import_role:
|
||||||
|
name: ansibleguy.infra_certs
|
||||||
|
vars:
|
||||||
|
certs:
|
||||||
|
mode: "{{ site.ssl.mode }}"
|
||||||
|
path: "{{ APACHE_CONFIG.ssl.path }}"
|
||||||
|
owner_key: "{{ APACHE_CONFIG.user }}"
|
||||||
|
group_key: "{{ APACHE_CONFIG.group }}"
|
||||||
|
owner_cert: "{{ APACHE_CONFIG.user }}"
|
||||||
|
group_cert: "{{ APACHE_CONFIG.group }}"
|
||||||
|
cert:
|
||||||
|
name: "{{ name }}"
|
||||||
|
cn: "{{ site.ssl.cert.cn }}"
|
||||||
|
org: "{{ site.ssl.cert.org }}"
|
||||||
|
ou: "{{ site.ssl.cert.ou }}"
|
||||||
|
country: "{{ site.ssl.cert.country }}"
|
||||||
|
state: "{{ site.ssl.cert.state }}"
|
||||||
|
locality: "{{ site.ssl.cert.locality }}"
|
||||||
|
email: "{{ site.ssl.cert.email }}"
|
||||||
|
crl_distribution: "{{ site.ssl.cert.crl_distribution }}"
|
||||||
|
domains: "{{ site.aliases + [site.domain] }}"
|
||||||
|
ips: ["{{ site.ip }}"]
|
||||||
|
ca:
|
||||||
|
path: "{{ APACHE_CONFIG.ssl.path }}"
|
||||||
|
cn: "{{ site.ssl.ca.cn | default(APACHE_CONFIG.ssl.ca.cn, true) }}"
|
||||||
|
org: "{{ site.ssl.ca.org | default(APACHE_CONFIG.ssl.ca.org, true) }}"
|
||||||
|
ou: "{{ site.ssl.ca.ou | default(APACHE_CONFIG.ssl.ca.ou, true) }}"
|
||||||
|
country: "{{ site.ssl.ca.country | default(APACHE_CONFIG.ssl.ca.country, true) }}"
|
||||||
|
state: "{{ site.ssl.ca.state | default(APACHE_CONFIG.ssl.ca.state, true) }}"
|
||||||
|
locality: "{{ site.ssl.ca.locality | default(APACHE_CONFIG.ssl.ca.locality, true) }}"
|
||||||
|
email: "{{ site.ssl.ca.email | default(APACHE_CONFIG.ssl.ca.email, true) }}"
|
||||||
|
pwd: "{{ site.ssl.ca.pwd | default(APACHE_CONFIG.ssl.ca.pwd, true) }}"
|
||||||
|
when: "site.ssl.mode in ['ca', 'selfsigned']"
|
||||||
|
|
||||||
|
- name: "Apache | Debian | Site '{{ name }}' | Certs | Trying to copy cert pub"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ APACHE_CONFIG.ssl.path }}/{{ name }}.crt"
|
||||||
|
src: "files/certs/{{ name }}.crt"
|
||||||
|
mode: 0644
|
||||||
|
owner: "{{ APACHE_CONFIG.user }}"
|
||||||
|
group: "{{ APACHE_CONFIG.group }}"
|
||||||
|
ignore_errors: true
|
||||||
|
register: copy_cert_pub
|
||||||
|
when: site.ssl.mode == 'existing'
|
||||||
|
|
||||||
|
- name: "Apache | Debian | Site '{{ name }}' | Certs | Trying to copy cert pk"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ APACHE_CONFIG.ssl.path }}/{{ name }}.key"
|
||||||
|
src: "files/certs/{{ name }}.key"
|
||||||
|
mode: 0640
|
||||||
|
owner: "{{ APACHE_CONFIG.user }}"
|
||||||
|
group: "{{ APACHE_CONFIG.group }}"
|
||||||
|
no_log: true
|
||||||
|
register: copy_cert_key
|
||||||
|
ignore_errors: true
|
||||||
|
when:
|
||||||
|
- site.ssl.mode == 'existing'
|
||||||
|
- copy_cert_pub.failed is undefined or not copy_cert_pub.failed
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Configuring listen-ports"
|
- name: "Apache | Debian | Site '{{ name }}' | Checking config"
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "The required site-configuration was not provided!
|
||||||
|
Needed: 'domain'"
|
||||||
|
when: site.domain is undefined
|
||||||
|
tags: [config, sites, certs]
|
||||||
|
|
||||||
|
- name: "Apache | Debian | Site '{{ name }}' | Configuring certificates"
|
||||||
|
ansible.builtin.import_tasks: add_certs.yml
|
||||||
|
when: "site.ssl.mode in ['selfsigned', 'existing', 'ca']"
|
||||||
|
tags: [sites, certs]
|
||||||
|
|
||||||
|
- name: "Apache | Debian | Site '{{ name }}' | Configuring listen-ports"
|
||||||
ansible.builtin.blockinfile:
|
ansible.builtin.blockinfile:
|
||||||
path: '/etc/apache2/ports.conf'
|
path: '/etc/apache2/ports.conf'
|
||||||
block: |
|
block: |
|
||||||
|
|
@ -18,8 +30,9 @@
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ site.port_plain }}"
|
- "{{ site.port_plain }}"
|
||||||
- "{{ site.port_ssl }}"
|
- "{{ site.port_ssl }}"
|
||||||
|
tags: [config, sites]
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Create root directory"
|
- name: "Apache | Debian | Site '{{ name }}' | Create root directory"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ site.serve.path }}"
|
path: "{{ site.serve.path }}"
|
||||||
state: directory
|
state: directory
|
||||||
|
|
@ -27,38 +40,18 @@
|
||||||
group: "{{ APACHE_CONFIG.group }}"
|
group: "{{ APACHE_CONFIG.group }}"
|
||||||
mode: 0755
|
mode: 0755
|
||||||
when: site.mode == 'serve'
|
when: site.mode == 'serve'
|
||||||
|
tags: [sites]
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Configuring site"
|
- name: "Apache | Debian | Site '{{ name }}' | Configuring site"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: 'templates/etc/apache2/sites-available/site.conf.j2'
|
src: 'templates/etc/apache2/sites-available/site.conf.j2'
|
||||||
dest: "/etc/apache2/sites-available/site_{{ name }}.conf"
|
dest: "/etc/apache2/sites-available/site_{{ name }}.conf"
|
||||||
owner: 'root'
|
owner: 'root'
|
||||||
group: 'root'
|
group: 'root'
|
||||||
mode: 0644
|
mode: 0644
|
||||||
validate: 'apachectl -t -f %s'
|
tags: [config, sites]
|
||||||
register: apache_config_deployment
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Ask user"
|
- name: "Apache | Debian | Site '{{ name }}' | Enabling site"
|
||||||
ansible.builtin.pause:
|
|
||||||
prompt: "The apache config validation failed! Sometimes this is a false-negative.
|
|
||||||
Do you want to force the deployment? (yes/no)"
|
|
||||||
register: force_deploy
|
|
||||||
when: apache_config_deployment.failed
|
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Configuring site (forced)"
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: 'templates/etc/apache2/sites-available/site.conf.j2'
|
|
||||||
dest: "/etc/apache2/sites-available/site_{{ name }}.conf"
|
|
||||||
owner: 'root'
|
|
||||||
group: 'root'
|
|
||||||
mode: 0644
|
|
||||||
backup: true
|
|
||||||
when:
|
|
||||||
- apache_config_deployment.failed
|
|
||||||
- force_deploy.user_input == 'yes'
|
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Enabling site"
|
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
state: link
|
state: link
|
||||||
src: "/etc/apache2/sites-available/site_{{ name }}.conf"
|
src: "/etc/apache2/sites-available/site_{{ name }}.conf"
|
||||||
|
|
@ -66,3 +59,4 @@
|
||||||
owner: 'root'
|
owner: 'root'
|
||||||
group: 'root'
|
group: 'root'
|
||||||
mode: 0644
|
mode: 0644
|
||||||
|
tags: [sites]
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Cleanup | Disable temporary apache site
|
|
||||||
ansible.builtin.file:
|
|
||||||
state: absent
|
|
||||||
dest: '/etc/apache2/sites-enabled/tmp_le_dummy.conf'
|
|
||||||
register: tmp_site_config
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Cleanup | Reload apache
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: 'apache2.service'
|
|
||||||
state: reloaded
|
|
||||||
when: tmp_site_config.changed
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Dependencies | Deploying temporary apache site
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: 'templates/etc/apache2/sites-available/le_dummy.conf.j2'
|
|
||||||
dest: '/etc/apache2/sites-available/tmp_le_dummy.conf'
|
|
||||||
owner: 'root'
|
|
||||||
group: 'root'
|
|
||||||
mode: 0644
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Dependencies | Enable apache site
|
|
||||||
ansible.builtin.file:
|
|
||||||
state: link
|
|
||||||
src: '/etc/apache2/sites-available/tmp_le_dummy.conf'
|
|
||||||
dest: '/etc/apache2/sites-enabled/tmp_le_dummy.conf'
|
|
||||||
owner: 'root'
|
|
||||||
group: 'root'
|
|
||||||
mode: 0644
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Dependencies | Reload apache
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: 'apache2.service'
|
|
||||||
state: reloaded
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Checking if cert for domain '{{ site.domain }}' exists"
|
|
||||||
ansible.builtin.shell: 'certbot certificates'
|
|
||||||
register: domain_cert
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
# todo: check domains registered in current certificate (certbot certificates) and remove it if there are more than configured before re-configuring it
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Set key/cert paths for domain '{{ site.domain }}'"
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_path_key: "{{ APACHE_CONFIG.letsencrypt.path_key }}/{{ name }}"
|
|
||||||
_path_cert: "{{ APACHE_CONFIG.letsencrypt.path_cert }}/{{ name }}"
|
|
||||||
_path_live: "{{ APACHE_CONFIG.letsencrypt.path }}/live/{{ name }}"
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Creating key/cert directories for domain '{{ site.domain }}'"
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
owner: 'root'
|
|
||||||
group: 'root'
|
|
||||||
mode: 0755
|
|
||||||
with_items:
|
|
||||||
- "{{ _path_key }}"
|
|
||||||
- "{{ _path_cert }}"
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Getting cert
|
|
||||||
ansible.builtin.include_tasks: domain_new.yml
|
|
||||||
when: domain_cert.stdout.find(site.domain) == -1
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Linking certificates for domain '{{ site.domain }}'"
|
|
||||||
ansible.builtin.file:
|
|
||||||
state: link
|
|
||||||
src: "{{ item.value.src }}"
|
|
||||||
dest: "{{ item.value.dst }}"
|
|
||||||
owner: "{{ APACHE_CONFIG.user }}"
|
|
||||||
group: "{{ APACHE_CONFIG.group }}"
|
|
||||||
mode: 0400
|
|
||||||
follow: yes
|
|
||||||
with_dict:
|
|
||||||
- {'config': {'dst': "{{ _path_key }}/privkey.pem", 'src': "{{ _path_live }}/privkey.pem"}}
|
|
||||||
- {'config': {'dst': "{{ _path_cert }}/cert.pem", 'src': "{{ _path_live }}/cert.pem"}}
|
|
||||||
- {'config': {'dst': "{{ _path_cert }}/chain.pem", 'src': "{{ _path_live }}/chain.pem"}}
|
|
||||||
- {'config': {'dst': "{{ _path_cert }}/fullchain.pem", 'src': "{{ _path_live }}/fullchain.pem"}}
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Creating alternative name string (1/3)"
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_aliases: "{{ site.aliases | join(' --domain ') }}"
|
|
||||||
when: apache_aliases | length > 0
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Creating alternative name string (2/3)"
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_apache_aliases: "{{ '--domain ' + _aliases }}"
|
|
||||||
when: apache_aliases | length > 0
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Creating alternative name string (3/3)"
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_apache_aliases: ''
|
|
||||||
when: apache_aliases | length == 0
|
|
||||||
|
|
||||||
- name: debug
|
|
||||||
ansible.builtin.debug:
|
|
||||||
msg: "certbot certonly --apache -{{ APACHE_CONFIG.letsencrypt.verbosity }} --non-interactive --agree-tos --email {{ site.admin }} --cert-name {{ name }}
|
|
||||||
--rsa-key-size {{ APACHE_CONFIG.letsencrypt.key_size }} --no-redirect --domain {{ site.domain }} {{ _apache_aliases }}"
|
|
||||||
|
|
||||||
- name: "Apache | Debian | LetsEncrypt Certbot | Starting certbot for domain '{{ site.domain }}'"
|
|
||||||
ansible.builtin.shell: "certbot certonly --apache -{{ APACHE_CONFIG.letsencrypt.verbosity }} --non-interactive --agree-tos --email {{ site.admin }} --cert-name {{ name }}
|
|
||||||
--rsa-key-size {{ APACHE_CONFIG.letsencrypt.key_size }} --no-redirect --domain {{ site.domain }} {{ _apache_aliases }}"
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Install package
|
|
||||||
ansible.builtin.apt:
|
|
||||||
name: "{{ packages.letsencrypt }}"
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Check if a apache virtualhost is available
|
|
||||||
ansible.builtin.shell: 'ls /etc/apache2/sites-enabled/'
|
|
||||||
register: enabled_apache_sites
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Checking dependencies
|
|
||||||
ansible.builtin.include_tasks: dependencies.yml
|
|
||||||
when: enabled_apache_sites.stdout == ''
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Processing apache sites
|
|
||||||
ansible.builtin.include_tasks: domain.yml
|
|
||||||
vars:
|
|
||||||
site: "{{ default_site_config | combine(site_item, recursive=true) }}"
|
|
||||||
name: "{{ site_item.key | safe_key }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: site_item
|
|
||||||
with_dict: "{{ APACHE_CONFIG.sites }}"
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Cleanup dependencies
|
|
||||||
ansible.builtin.include_tasks: cleanup.yml
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Adding systemd files for certbot renewal
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: "templates/etc/systemd/system/{{ item }}.j2"
|
|
||||||
dest: "/etc/systemd/system/{{ item }}"
|
|
||||||
with_items:
|
|
||||||
- 'ansibleguy.infra_apache.LetsEncryptCertbot.service'
|
|
||||||
- 'ansibleguy.infra_apache.LetsEncryptCertbot.timer'
|
|
||||||
|
|
||||||
- name: Apache | Debian | LetsEncrypt Certbot | Enabling cert-renewal systemd timer
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
daemon_reload: yes
|
|
||||||
name: 'LetsEncryptCertbot.timer'
|
|
||||||
enabled: yes
|
|
||||||
state: started
|
|
||||||
|
|
@ -2,54 +2,101 @@
|
||||||
|
|
||||||
- name: Apache | Debian | Install apache
|
- name: Apache | Debian | Install apache
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
name: "{{ packages.apache }}"
|
name: ['apache2']
|
||||||
state: present
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
tags: [base]
|
||||||
|
|
||||||
- name: Apache | Debian | Checking if all sites exist (1/2)
|
- name: Apache | Debian | Creating service user
|
||||||
ansible.builtin.stat:
|
ansible.builtin.user:
|
||||||
path: "/etc/apache2/sites-available/site_{{ item.key | safe_key }}.conf"
|
name: "{{ APACHE_CONFIG.user }}"
|
||||||
register: sites_exist_raw
|
shell: '/usr/sbin/nologin'
|
||||||
with_dict: "{{ APACHE_CONFIG.sites }}"
|
comment: 'Apache Service User'
|
||||||
|
tags: [base]
|
||||||
|
|
||||||
- name: Apache | Debian | Checking if all sites exist (2/2)
|
- name: Apache | Debian | Setting service user
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.lineinfile:
|
||||||
sites_exist: "{{ sites_exist_raw | json_query('[*].results.stat.exists') | all_true }}"
|
state: present
|
||||||
|
path: '/etc/apache2/envvars'
|
||||||
- name: Apache | Debian | Getting certificate via LetsEncrypt
|
regexp: "{{ item.reg }}"
|
||||||
ansible.builtin.import_tasks: letsencrypt/main.yml
|
line: "{{ item.line }}"
|
||||||
when: >
|
register: apache_user_update_raw
|
||||||
(APACHE_CONFIG.ssl.renew or
|
loop:
|
||||||
not sites_exist) and
|
- {reg: '^export APACHE_RUN_USER=', line: "export APACHE_RUN_USER={{ APACHE_CONFIG.user }}"}
|
||||||
APACHE_CONFIG.ssl.mode == 'letsencrypt'
|
- {reg: '^export APACHE_RUN_GROUP=', line: "export APACHE_RUN_GROUP={{ APACHE_CONFIG.group }}"}
|
||||||
|
tags: [base, config]
|
||||||
|
|
||||||
- name: Apache | Debian | Enabling apache modules
|
- name: Apache | Debian | Enabling apache modules
|
||||||
community.general.apache2_module:
|
community.general.apache2_module:
|
||||||
state: present
|
state: present
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
when: item not in APACHE_CONFIG.modules.absent
|
when: item not in APACHE_CONFIG.modules.absent
|
||||||
|
register: apache_mods_enable_raw
|
||||||
loop: "{{ APACHE_CONFIG.modules.present }}"
|
loop: "{{ APACHE_CONFIG.modules.present }}"
|
||||||
|
tags: [base]
|
||||||
|
|
||||||
- name: Apache | Debian | Disabling apache modules
|
- name: Apache | Debian | Disabling apache modules
|
||||||
community.general.apache2_module:
|
community.general.apache2_module:
|
||||||
state: absent
|
state: absent
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
|
force: True
|
||||||
|
ignore_configcheck: True
|
||||||
|
register: apache_mods_disable_raw
|
||||||
loop: "{{ APACHE_CONFIG.modules.absent }}"
|
loop: "{{ APACHE_CONFIG.modules.absent }}"
|
||||||
|
tags: [base]
|
||||||
|
|
||||||
# todo: configure module settings
|
# todo: configure module settings
|
||||||
|
|
||||||
# todo: check if apache2.conf editing is still needed
|
- name: Apache | Debian | Adding main settings
|
||||||
#- name: Apache | Debian | Adding global config
|
ansible.builtin.lineinfile:
|
||||||
# ansible.builtin.blockinfile:
|
state: present
|
||||||
# path: '/etc/apache2/apache2.conf'
|
path: '/etc/apache2/apache2.conf'
|
||||||
# block: |
|
regexp: "{{ item.key }}\\s"
|
||||||
# {% for setting, value in apache_config_additions_default.items() %}
|
line: "{{ item.key }} {{ item.value }}"
|
||||||
# {{ setting }} {{ value }}
|
validate: "apachectl -t -f %s"
|
||||||
# {% endfor %}
|
register: apache_settings_raw
|
||||||
# {% for setting, value in apache_config_additions.items() %}
|
with_dict: "{{ APACHE_CONFIG.settings }}"
|
||||||
# {{ setting }} {{ value }}
|
tags: [config, base]
|
||||||
# {% endfor %}
|
|
||||||
# marker: "# {mark} ANSIBLE MANAGED BLOCK - global config"
|
- name: Apache | Debian | Restarting apache
|
||||||
# validate: 'apachectl -t -f %s'
|
ansible.builtin.systemd:
|
||||||
|
name: 'apache2.service'
|
||||||
|
state: restarted
|
||||||
|
when: >
|
||||||
|
apache_user_update_raw.changed or
|
||||||
|
apache_mods_enable_raw.changed or
|
||||||
|
apache_mods_disable_raw.changed or
|
||||||
|
apache_settings_raw.changed
|
||||||
|
tags: [base, config]
|
||||||
|
|
||||||
|
# is an additional site-loop since certificates can be pre-/absent
|
||||||
|
- name: Apache | Debian | Getting certificates using LetsEncrypt
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: ansibleguy.infra_certs
|
||||||
|
when: site.ssl.mode == 'letsencrypt'
|
||||||
|
vars:
|
||||||
|
site: "{{ default_site_config | combine(site_item.value, recursive=true) }}"
|
||||||
|
name: "{{ site_item.key | safe_key }}"
|
||||||
|
certs:
|
||||||
|
mode: 'le_certbot'
|
||||||
|
path: "{{ APACHE_CONFIG.ssl.path }}"
|
||||||
|
owner_key: "{{ APACHE_CONFIG.user }}"
|
||||||
|
group_key: "{{ APACHE_CONFIG.group }}"
|
||||||
|
owner_cert: "{{ APACHE_CONFIG.user }}"
|
||||||
|
group_cert: "{{ APACHE_CONFIG.group }}"
|
||||||
|
letsencrypt:
|
||||||
|
certs: "{{ site | prepare_letsencrypt(name) }}"
|
||||||
|
path: "{{ APACHE_CONFIG.letsencrypt.path }}"
|
||||||
|
email: "{{ APACHE_CONFIG.letsencrypt.email }}"
|
||||||
|
renew_timer: "{{ APACHE_CONFIG.letsencrypt.renew_timer }}"
|
||||||
|
verbosity: "{{ APACHE_CONFIG.letsencrypt.verbosity }}"
|
||||||
|
service: 'apache'
|
||||||
|
renew: "{{ APACHE_CONFIG.letsencrypt.renew }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: site_item
|
||||||
|
with_dict: "{{ APACHE_CONFIG.sites }}"
|
||||||
|
no_log: true
|
||||||
|
tags: [certs, sites]
|
||||||
|
|
||||||
- name: Apache | Debian | Disabling default apache sites
|
- name: Apache | Debian | Disabling default apache sites
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|
@ -58,16 +105,19 @@
|
||||||
with_items:
|
with_items:
|
||||||
- '000-default.conf'
|
- '000-default.conf'
|
||||||
- 'default-ssl.conf'
|
- 'default-ssl.conf'
|
||||||
|
tags: [config, base]
|
||||||
|
|
||||||
- name: Apache | Debian | Removing apache site
|
- name: Apache | Debian | Removing site
|
||||||
ansible.builtin.include_tasks: rm_site.yml
|
ansible.builtin.include_tasks: rm_site.yml
|
||||||
|
when: site.state != 'present'
|
||||||
vars:
|
vars:
|
||||||
site: "{{ default_site_config | combine(site_item, recursive=true) }}"
|
site: "{{ default_site_config | combine(site_item.value, recursive=true) }}"
|
||||||
name: "{{ site_item.key | safe_key }}"
|
name: "{{ site_item.key | safe_key }}"
|
||||||
when: site_item.state | default('present') != 'present'
|
|
||||||
loop_control:
|
loop_control:
|
||||||
loop_var: site_item
|
loop_var: site_item
|
||||||
with_dict: "{{ APACHE_CONFIG.sites }}"
|
with_dict: "{{ APACHE_CONFIG.sites }}"
|
||||||
|
no_log: true
|
||||||
|
tags: [config, sites, certs]
|
||||||
|
|
||||||
- name: Apache | Debian | Reloading apache
|
- name: Apache | Debian | Reloading apache
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
|
|
@ -75,15 +125,16 @@
|
||||||
state: reloaded
|
state: reloaded
|
||||||
tags: [base, config, sites, certs]
|
tags: [base, config, sites, certs]
|
||||||
|
|
||||||
- name: Apache | Debian | Adding apache site
|
- name: Apache | Debian | Adding site
|
||||||
ansible.builtin.include_tasks: add_site.yml
|
ansible.builtin.include_tasks: add_site.yml
|
||||||
|
when: site.state == 'present'
|
||||||
vars:
|
vars:
|
||||||
site: "{{ default_site_config | combine(site_item, recursive=true) }}"
|
site: "{{ default_site_config | combine(site_item.value, recursive=true) }}"
|
||||||
name: "{{ site_item.key | safe_key }}"
|
name: "{{ site_item.key | safe_key }}"
|
||||||
when: site_item.state | default('present') == 'present'
|
|
||||||
loop_control:
|
loop_control:
|
||||||
loop_var: site_item
|
loop_var: site_item
|
||||||
with_dict: "{{ APACHE_CONFIG.sites }}"
|
with_dict: "{{ APACHE_CONFIG.sites }}"
|
||||||
|
tags: [config, sites, certs]
|
||||||
|
|
||||||
- name: Apache | Debian | Starting/Enabling apache
|
- name: Apache | Debian | Starting/Enabling apache
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,16 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
# ports will be left configured since I found no clean way to manage them statefully
|
# ports will be left configured since I found no clean way to manage them statefully
|
||||||
|
# also: the web-root will be left as-is
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Removing web-root"
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ site.serve.path }}"
|
|
||||||
state: absent
|
|
||||||
force: yes
|
|
||||||
when: site.mode == 'serve'
|
|
||||||
|
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Removing/Disabling site"
|
- name: "Apache | Debian | Config | Site '{{ name }}' | Removing/Disabling site"
|
||||||
ansible.builtin.template:
|
ansible.builtin.file:
|
||||||
path: "{{ item }}"
|
path: "{{ item }}"
|
||||||
state: absent
|
state: absent
|
||||||
loop:
|
loop:
|
||||||
- "/etc/apache2/sites-available/site_{{ name }}.conf"
|
|
||||||
- "/etc/apache2/sites-enabled/site_{{ name }}.conf"
|
- "/etc/apache2/sites-enabled/site_{{ name }}.conf"
|
||||||
|
- "/etc/apache2/sites-available/site_{{ name }}.conf"
|
||||||
- name: "Apache | Debian | Config | Site '{{ name }}' | Removing certificate from certbot"
|
- "{{ APACHE_CONFIG.ssl.path }}/{{ name }}.key"
|
||||||
ansible.builtin.shell: "certbot certonly --apache -{{ APACHE_LE_CONFIG.verbosity }} --non-interactive --agree-tos --email {{ site.admin }} --cert-name {{ name }}
|
- "{{ APACHE_CONFIG.ssl.path }}/{{ name }}.crt"
|
||||||
--rsa-key-size {{ APACHE_LE_CONFIG.key_size }} --no-redirect --domain {{ site.domain }} {{ _apache_aliases }}"
|
- "{{ APACHE_CONFIG.ssl.path }}/{{ name }}.chain.crt"
|
||||||
ignore_errors: yes
|
- "{{ APACHE_CONFIG.ssl.path }}/{{ name }}.fullchain.crt"
|
||||||
when: site.ssl.mode == 'letsencrypt'
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,14 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- name: Apache | Checking config
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "The required configuration was not provided!
|
||||||
|
Needed: 'apache', 'apache.sites'"
|
||||||
|
when: >
|
||||||
|
apache is undefined or
|
||||||
|
apache.sites is undefined or
|
||||||
|
apache.sites | length == 0
|
||||||
|
|
||||||
- name: Apache | Processing debian config
|
- name: Apache | Processing debian config
|
||||||
ansible.builtin.import_tasks: debian/main.yml
|
ansible.builtin.import_tasks: debian/main.yml
|
||||||
when: "ansible_distribution|lower in ['debian', 'ubuntu']"
|
when: "ansible_distribution|lower in ['debian', 'ubuntu']"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<VirtualHost *:80>
|
|
||||||
ServerName dummy.letsencrypt.localhost
|
|
||||||
ServerAdmin webmaster@localhost
|
|
||||||
ErrorLog {{ APACHE_CONFIG.log.path }}/error.log
|
|
||||||
CustomLog {{ APACHE_CONFIG.log.path }}/access.log combined
|
|
||||||
</VirtualHost>
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
|
# {{ ansible_managed }}
|
||||||
|
# ansibleguy.infra_apache
|
||||||
|
|
||||||
<VirtualHost *:{{ site.port_plain }}>
|
<VirtualHost *:{{ site.port_plain }}>
|
||||||
ServerName {{ site.domain }}
|
ServerName {{ site.domain }}
|
||||||
|
|
||||||
{% if site.aliases | length > 0 %}
|
{% if site.aliases | length > 0 %}
|
||||||
ServerAlias {% for name in site.aliases %} {{ name }} {% endfor %}
|
ServerAlias {% for name in site.aliases %} {{ name }} {% endfor %}{% if site.ip is not none %} {{ site.ip }}{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
ServerAdmin {{ site.admin }}
|
ServerAdmin {{ site.admin }}
|
||||||
|
|
||||||
|
|
@ -30,18 +33,18 @@
|
||||||
ServerName {{ site.domain }}
|
ServerName {{ site.domain }}
|
||||||
|
|
||||||
{% if site.aliases | length > 0 %}
|
{% if site.aliases | length > 0 %}
|
||||||
ServerAlias {% for name in site.aliases %} {{ name }} {% endfor %}
|
ServerAlias {% for alias in site.aliases %} {{ alias }} {% endfor %}{% if site.ip is not none %} {{ site.ip }}{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
ServerAdmin {{ site.admin }}
|
ServerAdmin {{ site.admin }}
|
||||||
|
|
||||||
# log config
|
# log config
|
||||||
{% if APACHE_CONFIG.log.syslog and APACHE_CONFIG.log.syslog_host is not none %}
|
{% if APACHE_CONFIG.log.syslog and APACHE_CONFIG.log.syslog_host is not none %}
|
||||||
ErrorLog "| /usr/bin/logger -n {{ APACHE_CONFIG.log.syslog_host }} -P {{ APACHE_CONFIG.log.syslog_port }} -p local1.error -t {{ APACHE_CONFIG.log.prefix_ue }}{{ name }}"
|
ErrorLog "| /usr/bin/logger -n {{ APACHE_CONFIG.log.syslog_host }} -P {{ APACHE_CONFIG.log.syslog_port }} -p local1.error -t {{ APACHE_CONFIG.log.prefix_ssl }}{{ name }}"
|
||||||
CustomLog "| /usr/bin/logger -n {{ APACHE_CONFIG.log.syslog_host }} -P {{ APACHE_CONFIG.log.syslog_port }} -p local1.info -t {{ APACHE_CONFIG.log.prefix_ue }}{{ name }}" combined
|
CustomLog "| /usr/bin/logger -n {{ APACHE_CONFIG.log.syslog_host }} -P {{ APACHE_CONFIG.log.syslog_port }} -p local1.info -t {{ APACHE_CONFIG.log.prefix_ssl }}{{ name }}" combined
|
||||||
{% elif APACHE_CONFIG.log.syslog %}
|
{% elif APACHE_CONFIG.log.syslog %}
|
||||||
ErrorLog "| /usr/bin/logger -p local1.error -t {{ APACHE_CONFIG.log.prefix_ue }}{{ name }}"
|
ErrorLog "| /usr/bin/logger -p local1.error -t {{ APACHE_CONFIG.log.prefix_ssl }}{{ name }}"
|
||||||
CustomLog "| /usr/bin/logger -p local1.info -t {{ APACHE_CONFIG.log.prefix_ue }}{{ name }}" combined
|
CustomLog "| /usr/bin/logger -p local1.info -t {{ APACHE_CONFIG.log.prefix_ssl }}{{ name }}" combined
|
||||||
{% elif APACHE_CONFIG.log.per_site %}
|
{% elif APACHE_CONFIG.log.per_site %}
|
||||||
ErrorLog {{ APACHE_CONFIG.log.path }}/{{ name }}_error.log
|
ErrorLog {{ APACHE_CONFIG.log.path }}/{{ name }}_error.log
|
||||||
CustomLog {{ APACHE_CONFIG.log.path }}/{{ name }}_access.log combined
|
CustomLog {{ APACHE_CONFIG.log.path }}/{{ name }}_access.log combined
|
||||||
|
|
@ -53,9 +56,11 @@
|
||||||
# ssl config
|
# ssl config
|
||||||
<IfModule mod_ssl.c>
|
<IfModule mod_ssl.c>
|
||||||
SSLEngine on
|
SSLEngine on
|
||||||
SSLCertificateKeyFile /etc/ssl/private/{{ apache_site }}/privkey.pem
|
SSLCertificateKeyFile {{ APACHE_CONFIG.ssl.path }}/{{ name }}.key
|
||||||
SSLCertificateFile /etc/ssl/certs/{{ apache_site }}/cert.pem
|
SSLCertificateFile {{ APACHE_CONFIG.ssl.path }}/{{ name }}.crt
|
||||||
SSLCertificateChainFile /etc/ssl/certs/{{ apache_site }}/fullchain.pem
|
{% if site.ssl.mode != 'selfsigned' %}
|
||||||
|
SSLCertificateChainFile {{ APACHE_CONFIG.ssl.path }}/{{ name }}{% if site.ssl.mode == 'letsencrypt' %}.fullchain{% else %}.chain{% endif %}.crt
|
||||||
|
{% endif %}
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
|
||||||
{% if APACHE_CONFIG.config | length > 0 %}
|
{% if APACHE_CONFIG.config | length > 0 %}
|
||||||
|
|
@ -106,20 +111,15 @@
|
||||||
|
|
||||||
# security config
|
# security config
|
||||||
{% if site.security.restrict_methods %}
|
{% if site.security.restrict_methods %}
|
||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_METHOD} ^(?!{% for method in apache_restricted_methods %}{{ method }}{% if not loop.last %}|{% endif %}{% endfor %})
|
||||||
|
RewriteRule .* - [F]
|
||||||
|
</IfModule>
|
||||||
|
<Directory />
|
||||||
<LimitExcept {% for method in apache_restricted_methods %}{{ method }} {% endfor %}>
|
<LimitExcept {% for method in apache_restricted_methods %}{{ method }} {% endfor %}>
|
||||||
deny from all
|
deny from all
|
||||||
</LimitExcept>
|
</LimitExcept>
|
||||||
{% endif %}
|
|
||||||
{% if site.security.limit_directory_access %}
|
|
||||||
<Directory />
|
|
||||||
Options None
|
|
||||||
Order deny,allow
|
|
||||||
Deny from all
|
|
||||||
</Directory>
|
|
||||||
{% endif %}
|
|
||||||
{% if site.security.disable_directory_access %}
|
|
||||||
<Directory "=">
|
|
||||||
Require all denied
|
|
||||||
</Directory>
|
</Directory>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
@ -158,6 +158,11 @@
|
||||||
{{ line }}
|
{{ line }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if site.app_include %}
|
||||||
|
# additional application config include
|
||||||
|
IncludeOptional site_{{ name }}_app.conf
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
||||||
ServerName {{ site.domain }}
|
ServerName {{ site.domain }}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue