Private
Public Access
2
0
This commit is contained in:
2026-01-19 15:06:34 +03:00
parent 278d1785cc
commit 3d9fe37983
59 changed files with 1084 additions and 9684 deletions

View File

@@ -1,19 +0,0 @@
# Defaults
certs_default_country_name: null
certs_default_locality_name: null
certs_default_organization_name: null
certs_default_email_address: null
certs_default_not_after: "+365d" # valid for one year
certs_default_not_before: "-1d" # valid since yesterday
# Required
certs_ca_passphrase: null
certs_list: {}
# - cn: <string>
# domains: <array of strings>
# country_name: <string>
# locality_name: <string>
# organization_name: <string>
# email_address: <string>
# not_after: <string>
# not_before: <string>

View File

@@ -1,42 +0,0 @@
- name: Create private key for new certificate
community.crypto.openssl_privatekey:
path: "/etc/ssl/private/{{ cert.cn }}.key"
mode: "0640"
group: "ssl-cert"
- name: Create CSR for new certificate
community.crypto.openssl_csr:
path: "/etc/ssl/certs/{{ cert.cn }}.csr"
privatekey_path: "/etc/ssl/private/{{ cert.cn }}.key"
common_name: "{{ cert.cn }}"
subject_alt_name: "{{ cert.domains }}"
country_name: "{{ cert.country_name | default(certs_default_country_name) | mandatory }}"
locality_name: "{{ cert.locality_name | default(certs_default_locality_name) | mandatory }}"
organization_name: "{{ cert.organization_name | default(certs_default_organization_name) | mandatory }}"
email_address: "{{ cert.email_address | default(certs_default_email_address) | mandatory }}"
return_content: true
register: certs_csr
- name: Sign certificate with our CA
delegate_to: "localhost"
# noqa: no-handler
when: "certs_csr.changed"
community.crypto.x509_certificate_pipe:
csr_content: "{{ certs_csr.csr }}"
provider: "ownca"
ownca_path: "ca/ca-certificate.crt"
ownca_privatekey_path: "ca/ca-certificate.key"
ownca_privatekey_passphrase: "{{ certs_ca_passphrase }}"
ownca_not_after: "{{ cert.not_after | default(certs_default_not_after) }}"
ownca_not_before: "{{ cert.not_before | default(certs_default_not_before) }}"
register: certs_certificate
- name: Write certificate file on server
# noqa: no-handler
when: "certs_csr.changed"
ansible.builtin.copy:
dest: "/etc/ssl/certs/{{ cert.cn }}.crt"
content: "{{ certs_certificate.certificate }}"
mode: "0644"
notify:
- "Reboot host"

View File

@@ -0,0 +1,2 @@
common_default_packages: []
common_proxy_server: null

View File

@@ -1,2 +1,7 @@
- name: Setup proxy client
when: "common_proxy_server != None"
ansible.builtin.include_tasks: "setup_proxy_client.yml"
- name: Setup packages
when: "common_default_packages | length > 0"
ansible.builtin.include_tasks: "setup_packages.yml"

View File

@@ -0,0 +1,9 @@
- name: Keep packages up to date
ansible.builtin.apt:
update_cache: true
upgrade: "safe"
- name: Install default packages
ansible.builtin.apt:
name: "{{ common_default_packages }}"
autoclean: true

View File

@@ -2,7 +2,11 @@
consul_datacenter: null
consul_domain: null
consul_secret_key: null
consul_nodes: []
consul_server: false
consul_servers: []
# Required for registering services
consul_services: []
# Defaults
consul_version: "1.22.2"
@@ -12,3 +16,5 @@ consul_ca_file: "/etc/ssl/certs/local-ca.crt"
consul_client_addr: "0.0.0.0"
consul_bind_addr: "{{ ansible_default_ipv4.address }}"
consul_advertise_addr: "{{ ansible_default_ipv4.address }}"
consul_default_check_interval: "15s"
consul_default_check_timeout: "2s"

View File

@@ -3,8 +3,3 @@
name: "consul"
state: "restarted"
daemon_reload: true
- name: Reload Consul
ansible.builtin.service:
name: "consul"
state: "reloaded"

View File

@@ -0,0 +1,6 @@
Security:
- Gossip protocol encryption
- Built-in ACL
- Consul agent communication
- mTLS for authentitication and encryption
- Certificate authority

View File

@@ -60,7 +60,7 @@
group: "consul"
mode: "0640"
notify:
- "Reload Consul"
- "Restart Consul"
- name: Deploy Consul service file
ansible.builtin.template:
@@ -76,3 +76,31 @@
state: "started"
enabled: true
daemon_reload: true
- name: Register services to consul
loop: "{{ consul_services }}"
community.general.consul_agent_service:
name: "{{ item.name }}"
service_port: "{{ item.port }}"
tags: ="{{ item.tags | default([]) }}"
- name: Register HTTP checks to consul
loop: "{{ consul_services }}"
when: "item.check_http | default(None) != None"
community.general.consul_agent_check:
name: "{{ item.name }}_check"
service_id: "{{ item.name }}"
interval: "{{ item.check_interval | default(consul_default_check_interval) }}"
timeout: "{{ item.check_timeout | default(consul_default_check_timeout) }}"
http: "{{ item.check_http }}"
scheme: "{{ item.check_scheme | default('http') }}"
- name: Register TCP checks to consul
loop: "{{ consul_services }}"
when: "item.check_tcp | default(None) != None"
community.general.consul_agent_check:
name: "{{ item.name }}_check"
service_id: "{{ item.name }}"
interval: "{{ item.check_interval | default(consul_default_check_interval) }}"
timeout: "{{ item.check_timeout | default(consul_default_check_timeout) }}"
tcp: "{{ item.check_tcp }}"

View File

@@ -1,8 +1,7 @@
{
"log_level": "INFO",
"node_name": "{{ ansible_hostname }}",
"domain": "{{ consul_domain }}",
"server": true,
"datacenter": "{{ consul_datacenter | mandatory }}",
"key_file": "{{ consul_key_file }}",
"cert_file": "{{ consul_cert_file }}",
"ca_file": "{{ consul_ca_file }}",
@@ -10,17 +9,20 @@
"verify_outgoing": true,
"verify_server_hostname": true,
"encrypt": "{{ consul_secret_key }}",
"data_dir": "/opt/consul",
{% if consul_server %}
"node_name": "{{ ansible_hostname }}",
"server": true,
"ui": true,
"leave_on_terminate": true,
"data_dir": "/opt/consul",
"datacenter": "{{ consul_datacenter | mandatory }}",
"client_addr": "{{ consul_client_addr }}",
"bind_addr": "{{ consul_bind_addr }}",
"advertise_addr": "{{ consul_advertise_addr }}",
"bootstrap_expect": {{ consul_nodes | length }},
"retry_join": ["{{ consul_nodes | join('", "') }}"],
"bootstrap_expect": {{ consul_servers | length }},
"enable_syslog": true,
"performance": {
"raft_multiplier": 1
}
},
{% endif %}
"retry_join": ["{{ consul_servers | join('", "') }}"]
}

View File

@@ -10,7 +10,6 @@ Type=notify
User=consul
Group=consul
ExecStart=/usr/local/bin/consul agent -config-file=/etc/consul/config.json
ExecReload=/usr/local/bin/consul reload
KillMode=process
Restart=on-failure
LimitNOFILE=65536

View File

@@ -0,0 +1,16 @@
# Required
keepalived_script_user: null
keepalived_monitored_process: null
keepalived_vrrp_password: null # Max 8 characters
keepalived_vrrp_ips: null
# - master: <string>
# virtual_router_id: <int>
# addr: <string>
# Optionnal
keepalived_alerts_to: []
keepalived_unicast_peers: []
# Required if length keepalived_alerts_to > 0
keepalived_smtp_from: null
keepalived_smtp_relay: null

View File

@@ -0,0 +1,58 @@
# FIXME: NOTICE: setting config option max_auto_priority should result in better keepalived performance
global_defs {
enable_script_security
script_user "{{ keepalived_script_user }}"
{% if keepalived_alerts_to | length > 0 %}
notification_email {
{% for dest in keepalived_alerts_to %}
{{ dest }}
{% endfor %}
}
notification_email_from {{ keepalived_smtp_from }}
smtp_server {{ keepalived_smtp_relay }}
smtp_connect_timeout 30
router_id {{ ansible_hostname }}
{% endif %}
}
vrrp_script chk_{{ keepalived_monitored_process }} {
script "/usr/bin/killall -0 {{ keepalived_monitored_process }}" # Check if process is running
interval 2 # Check every 2 seconds
weight 2 # Weight to influence master election
}
{% for ip in keepalived_vrrp_ips %}
# master: {{ ip.master }}
vrrp_instance VI_{{ ip.virtual_router_id }} {
state {{ (ansible_hostname==ip.master) | ternary('MASTER', 'BACKUP') }}
interface {{ ansible_default_ipv4.interface }}
virtual_router_id {{ ip.virtual_router_id }}
priority {{ (ansible_hostname==ip.master) | ternary('101', '100') }}
advert_int 1
promote_secondaries
{% if keepalived_alerts_to | length > 0 %}
smtp_alert true
{% endif %}
authentication {
auth_type PASS
auth_pass {{ keepalived_vrrp_password }}
}
virtual_ipaddress {
{{ ip.addr }}
}
{% if keepalived_unicast_peers | length > 0 %}
unicast_peer {
{% for peer in keepalived_unicast_peers %}
{% if peer != ansible_default_ipv4.address %}
{{ peer }}
{% endif %}
{% endfor %}
}
{% endif %}
track_script {
chk_{{ keepalived_monitored_process }}
}
}
{% endfor %}

View File

@@ -0,0 +1,19 @@
# Defaults
local_ca_certs_default_country_name: null
local_ca_certs_default_locality_name: null
local_ca_certs_default_organization_name: null
local_ca_certs_default_email_address: null
local_ca_certs_default_not_after: "+365d" # valid for one year
local_ca_certs_default_not_before: "-1d" # valid since yesterday
# Required
local_ca_certs_ca_passphrase: null
local_ca_certs_list: {}
# - cn: <string>
# domains: <array of strings>
# country_name: <string>
# locality_name: <string>
# organization_name: <string>
# email_address: <string>
# not_after: <string>
# not_before: <string>

View File

@@ -0,0 +1,42 @@
- name: Create private key for new certificate
community.crypto.openssl_privatekey:
path: "/etc/ssl/private/{{ cert.cn }}.key"
mode: "0640"
group: "ssl-cert"
- name: Create CSR for new certificate
community.crypto.openssl_csr:
path: "/etc/ssl/certs/{{ cert.cn }}.csr"
privatekey_path: "/etc/ssl/private/{{ cert.cn }}.key"
common_name: "{{ cert.cn }}"
subject_alt_name: "{{ cert.domains }}"
country_name: "{{ cert.country_name | default(local_ca_certs_default_country_name) | mandatory }}"
locality_name: "{{ cert.locality_name | default(local_ca_certs_default_locality_name) | mandatory }}"
organization_name: "{{ cert.organization_name | default(local_ca_certs_default_organization_name) | mandatory }}"
email_address: "{{ cert.email_address | default(local_ca_certs_default_email_address) | mandatory }}"
return_content: true
register: local_ca_certs_csr
- name: Sign certificate with our CA
delegate_to: "localhost"
# noqa: no-handler
when: "local_ca_certs_csr.changed"
community.crypto.x509_certificate_pipe:
csr_content: "{{ local_ca_certs_csr.csr }}"
provider: "ownca"
ownca_path: "ca/ca-certificate.crt"
ownca_privatekey_path: "ca/ca-certificate.key"
ownca_privatekey_passphrase: "{{ local_ca_certs_ca_passphrase }}"
ownca_not_after: "{{ cert.not_after | default(local_ca_certs_default_not_after) }}"
ownca_not_before: "{{ cert.not_before | default(local_ca_certs_default_not_before) }}"
register: local_ca_certs_certificate
- name: Write certificate file on server
# noqa: no-handler
when: "local_ca_certs_csr.changed"
ansible.builtin.copy:
dest: "/etc/ssl/certs/{{ cert.cn }}.crt"
content: "{{ local_ca_certs_certificate.certificate }}"
mode: "0644"
notify:
- "Reboot host"

View File

@@ -10,7 +10,7 @@
mode: "0644"
- name: Create certs
loop: "{{ certs_list }}"
loop: "{{ local_ca_certs_list }}"
loop_control:
loop_var: "cert"
ansible.builtin.include_tasks: "create_cert.yml"

View File

@@ -0,0 +1,6 @@
# Required
mysql_databases: []
mysql_users: []
# - name: <string
# password: <string>
# priv: <string>

View File

@@ -0,0 +1,5 @@
- name: Restart MySQL
ansible.builtin.service:
name: "mysql"
state: "restarted"
daemon_reload: true

View File

@@ -0,0 +1,31 @@
- name: Installation de MySQL
ansible.builtin.apt:
name:
- "mysql-server"
- "python3-pymysql"
notify:
- "Restart MySQL"
- name: Set MySQL bind_address parameter
ansible.builtin.lineinfile:
path: "/etc/mysql/mysql.conf.d/mysqld.cnf"
regexp: "^bind-address\\s+="
line: "bind-address = *"
notify:
- "Restart MySQL"
- name: Création des bases de données MySQL
loop: "{{ mysql_databases }}"
community.mysql.mysql_db:
login_unix_socket: "/var/run/mysqld/mysqld.sock"
name: "{{ item }}"
encoding: "utf8"
- name: Création des utilisateur MySQL
loop: "{{ mysql_users }}"
community.mysql.mysql_user:
login_unix_socket: "/var/run/mysqld/mysqld.sock"
name: "{{ item.name }}"
password: "{{ item.password }}"
priv: "{{ item.priv }}"
host: "{{ item.host }}"

View File

@@ -0,0 +1,6 @@
# Required
ovh_ldp_token: null
ovh_ldp_cluster: null
# Defaults
ovh_ldp_tls_syslog_port: 6514

View File

@@ -0,0 +1,5 @@
- name: Restart syslog-ng
ansible.builtin.service:
name: "syslog-ng"
state: "restarted"
daemon_reload: true

View File

@@ -0,0 +1,13 @@
- name: Install syslog-ng
ansible.builtin.apt:
name:
- "syslog-ng"
- "ca-certificates"
- name: Generate syslog-ng config file for OVH LDP
ansible.builtin.template:
src: "templates/ldp-ovh.conf"
dest: "/etc/syslog-ng/conf.d/ldp-ovh.conf"
mode: "0640"
notify:
- "Restart syslog-ng"

View File

@@ -0,0 +1,22 @@
rewrite ovh-token {
set("{{ ovh_ldp_token }}", value(".SDATA.token@29084.X-OVH-TOKEN"));
};
destination ovhPaaSLogs {
network("{{ ovh_ldp_cluster }}"
port({{ ovh_ldp_tls_syslog_port }})
transport("tls")
flags(syslog-protocol)
ts_format("iso")
frac-digits(6)
tls(peer-verify("required-trusted") ca_dir("/etc/ssl/certs/"))
keep-alive(yes)
so_keepalive(yes)
);
};
log {
source(s_src);
rewrite(ovh-token);
destination(ovhPaaSLogs);
};

View File

@@ -1,2 +0,0 @@
squid_authorized_networks: ["127.0.0.1"]
squid_cache_size: 10240

View File

@@ -1,4 +0,0 @@
- name: Restart squid
ansible.builtin.systemd:
name: "squid"
state: "restarted"

View File

@@ -1,23 +0,0 @@
- name: Install squid package
ansible.builtin.apt:
name: "squid"
notify:
- "Restart squid"
- name: Deploy squid configuration file
ansible.builtin.template:
src: "templates/squid.conf"
dest: "/etc/squid/squid.conf"
owner: "root"
group: "root"
mode: "0644"
notify:
- "Restart squid"
- name: Enable squid
ansible.builtin.systemd:
name: "squid"
enabled: true
daemon_reload: true
notify:
- "Restart squid"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
unbound_listen_interfaces:
- "0.0.0.0"
unbound_access_control:
- "0.0.0.0/0 allow"
unbound_forward_zones:
- name: "."
forward_to: "8.8.8.8"
unbound_stub_zones: []
# - name: <string>
# stub_to: <string>
# no_cache: no (default yes)

View File

@@ -0,0 +1,4 @@
- name: Restart unbound
ansible.builtin.service:
name: "unbound"
state: "restarted"

View File

@@ -0,0 +1,14 @@
- name: Install Unbound
ansible.builtin.apt:
name:
- "unbound"
notify:
- "Restart unbound"
- name: Deploy unbounf config file
ansible.builtin.template:
src: "templates/unbound.conf"
dest: "/etc/unbound/unbound.conf.d/unbound.conf"
mode: "0644"
notify:
- "Restart unbound"

View File

@@ -0,0 +1,21 @@
server:
do-not-query-localhost: no
{% for interface in unbound_listen_interfaces %}
interface: {{ interface }}
{% endfor %}
{% for access in unbound_access_control %}
access-control: {{ access }}
{% endfor %}
{% for zone in unbound_stub_zones %}
stub-zone:
name: "{{ zone.name }}"
stub-addr: {{ zone.stub_to }}
stub-no-cache: {{ zone.no_cache | default('yes') }}
{% endfor %}
{% for zone in unbound_forward_zones %}
forward-zone:
name: "{{ zone.name }}"
forward-addr: {{ zone.forward_to }}
{% endfor %}

View File

@@ -1,16 +0,0 @@
# Required
vip_script_user: null
vip_monitored_process: null
vip_vrrp_password: null # Max 8 characters
vip_vrrp_ips: null
# - master: <string>
# virtual_router_id: <int>
# addr: <string>
# Optionnal
vip_alerts_to: null
# - <string>
# Required if length vip_alerts_to > 0
vip_smtp_from: null
vip_smtp_relay: null

View File

@@ -1,45 +0,0 @@
global_defs {
enable_script_security
script_user "{{ vip_script_user }}"
{% if vip_alerts_to | default([]) | length > 0 %}
notification_email {
{% for dest in vip_alerts_to %}
{{ dest }}
{% endfor %}
}
notification_email_from {{ vip_smtp_from }}
smtp_server {{ vip_smtp_relay }}
smtp_connect_timeout 30
router_id {{ ansible_hostname }}
{% endif %}
}
vrrp_script chk_{{ vip_monitored_process }} {
script "/usr/bin/killall -0 {{ vip_monitored_process }}" # Check if process is running
interval 2 # Check every 2 seconds
weight 2 # Weight to influence master election
}
{% for ip in vip_vrrp_ips %}
# master: {{ ip.master }}
vrrp_instance VI_{{ ip.virtual_router_id }} {
state {{ (ansible_hostname==ip.master) | ternary('MASTER', 'BACKUP') }}
interface eth0
virtual_router_id {{ ip.virtual_router_id }}
priority {{ (ansible_hostname==ip.master) | ternary('101', '100') }}
advert_int 1
promote_secondaries
smtp_alert true
authentication {
auth_type PASS
auth_pass {{ vip_vrrp_password }}
}
virtual_ipaddress {
{{ ip.addr }}
}
track_script {
chk_{{ vip_monitored_process }}
}
}
{% endfor %}

View File

@@ -1,5 +1,5 @@
# Defaults
waf_config_owasp_crs_version: "4.21.0"
waf_config_owasp_crs_version: "4.22.0"
# Required unless not site.custom_cert
waf_config_email: null
@@ -22,8 +22,6 @@ waf_config_sites: []
# - ""
# aliases:
# - ""
# plugins: FIXME:TODO
# - ""
# exceptions:
# before_request:
# - ""
@@ -35,6 +33,7 @@ waf_config_defaults:
custom_cert: true
custom_cert_file: ""
custom_key_file: ""
plugins: []
rate_events: 1000
rate_window: "1m"

View File

@@ -1,4 +1,4 @@
- name: Reload Caddy
- name: Restart Caddy
ansible.builtin.service:
name: "caddy"
state: "reloaded"
state: "restarted"

View File

@@ -1,9 +1,7 @@
- name: Create sites config directories
loop: "{{ waf_config_sites }}"
loop_control:
loop_var: "site"
ansible.builtin.file:
path: "/etc/caddy/sites/{{ site.name }}"
path: "/etc/caddy/sites/{{ item.name }}"
state: "directory"
group: "caddy"
mode: "0750"
@@ -18,7 +16,7 @@
group: "caddy"
mode: "0640"
notify:
- "Reload Caddy"
- "Restart Caddy"
- name: Generate sites crs-setup config file
loop: "{{ waf_config_sites }}"
@@ -30,7 +28,7 @@
group: "caddy"
mode: "0640"
notify:
- "Reload Caddy"
- "Restart Caddy"
- name: Generate sites exclusions before request file
loop: "{{ waf_config_sites }}"
@@ -42,7 +40,7 @@
group: "caddy"
mode: "0640"
notify:
- "Reload Caddy"
- "Restart Caddy"
- name: Generate sites exclusions after response file
loop: "{{ waf_config_sites }}"
@@ -54,7 +52,7 @@
group: "caddy"
mode: "0640"
notify:
- "Reload Caddy"
- "Restart Caddy"
- name: Generate Caddyfile
ansible.builtin.template:
@@ -63,7 +61,7 @@
group: "caddy"
mode: "0640"
notify:
- "Reload Caddy"
- "Restart Caddy"
- name: Copy bot barrier template
ansible.builtin.copy:
@@ -72,4 +70,4 @@
group: "caddy"
mode: "0640"
notify:
- "Reload Caddy"
- "Restart Caddy"

View File

@@ -103,12 +103,16 @@
directives `
Include "/etc/caddy/sites/{{ site.name }}/coraza.conf"
Include "/etc/caddy/sites/{{ site.name }}/crs-setup.conf"
Include "/etc/caddy/plugins/*-config.conf"
Include "/etc/caddy/plugins/*-before.conf"
{% for plugin in site.plugins | default(waf_config_defaults.plugins) %}
Include "/etc/caddy/plugins/{{ plugin }}-config.conf"
Include "/etc/caddy/plugins/{{ plugin }}-before.conf"
{% endfor %}
Include "/etc/caddy/sites/{{ site.name }}/exclusions-request-before.conf"
Include "/etc/caddy/coreruleset-{{ waf_config_owasp_crs_version }}/rules/*.conf"
Include "/etc/caddy/sites/{{ site.name }}/exclusions-response-after.conf"
Include "/etc/caddy/plugins/*-after.conf"
{% for plugin in site.plugins | default(waf_config_defaults.plugins) %}
Include "/etc/caddy/plugins/{{ plugin }}-after.conf"
{% endfor %}
SecRuleEngine On
`
}

View File

@@ -2,10 +2,7 @@ waf_install_go_version: "1.25.5"
waf_install_xcaddy_version: "0.4.5"
waf_install_caddy_version: "2.10.2"
waf_install_coraza_caddy_version: "2.1.0" # Coraza v3.3.3
waf_install_owasp_crs_version: "4.21.0"
# Cluster mode (e.g. with consul)
waf_install_cluster: false
waf_install_owasp_crs_version: "4.22.0"
# Cf.: https://github.com/coreruleset/plugin-registry
waf_install_crs_plugins:
@@ -19,6 +16,7 @@ waf_install_crs_plugins:
version: "1.0.0"
- name: "phpmyadmin-rule-exclusions"
version: "1.0.0"
has_after_config: true
- name: "roundcube-rule-exclusions"
version: "1.0.4"
provider: "EsadCetiner"

View File

@@ -30,7 +30,15 @@
group: "caddy"
remote_src: true
notify:
- "Reload Caddy"
- "Restart Caddy"
- name: Create after config {{ plugin.name }}
when: "not(plugin.has_after_config | default(false))"
ansible.builtin.copy:
content: ""
dest: "/etc/caddy/plugins/{{ plugin.name }}-after.conf"
mode: "0644"
group: "caddy"
# FIXME: bad hack, why is it required?
- name: Adjust /etc/caddy/plugins permissions

View File

@@ -30,20 +30,29 @@
dest: "/usr/local/bin/go"
state: "link"
# FIXME: no .deb
- name: Create xcaddy directory
ansible.builtin.file:
path: "/usr/local/xcaddy-{{ waf_install_xcaddy_version }}"
state: "directory"
mode: "0755"
- name: Install xcaddy
when: |
'xcaddy' not in ansible_facts.packages
or ansible_facts.packages['xcaddy'][0]['version'] != waf_install_xcaddy_version
ansible.builtin.apt:
deb: "{{ waf_install_xcaddy_download }}/v{{ waf_install_xcaddy_version }}/xcaddy_{{ waf_install_xcaddy_version }}_linux_amd64.deb"
force: true
ansible.builtin.unarchive:
src: "{{ waf_install_xcaddy_download }}/v{{ waf_install_xcaddy_version }}/xcaddy_{{ waf_install_xcaddy_version }}_linux_amd64.tar.gz"
dest: "/usr/local/xcaddy-{{ waf_install_xcaddy_version }}"
remote_src: true
- name: Link xcaddy
ansible.builtin.file:
src: "/usr/local/xcaddy-{{ waf_install_xcaddy_version }}/xcaddy"
dest: "/usr/local/bin/xcaddy"
state: "link"
- name: Create Caddy build command
ansible.builtin.set_fact:
waf_install_build_command: >
xcaddy build v{{ waf_install_caddy_version }}
{% if waf_install_cluster %} --with github.com/pteich/caddy-tlsconsul{% endif %}
--with github.com/pteich/caddy-tlsconsul
--with github.com/corazawaf/coraza-caddy/v2@v{{ waf_install_coraza_caddy_version }}
--with github.com/mholt/caddy-ratelimit
--with github.com/steffenbusch/caddy-bot-barrier

View File

@@ -0,0 +1,23 @@
# Required
wordpress_url: null
wordpress_site: null
wordpress_site_title: null
wordpress_admin_user: null
wordpress_admin_password: null
wordpress_admin_email: null
wordpress_db_pass: null
wordpress_themes: []
wordpress_active_theme: null
# Defaults
wordpress_user: "wordpress"
wordpress_plugins: []
wordpress_locale: "fr_FR"
wordpress_db_host: "localhost"
wordpress_db_name: "{{ wordpress_user }}"
wordpress_db_user: "{{ wordpress_user }}"
wordpress_db_prefix: "wp_"
wordpress_db_charset: "utf8mb4"
# Optionnal
wordpress_import_ocdi_indexes: []

View File

@@ -0,0 +1,17 @@
- name: Restart Nginx
ansible.builtin.systemd:
name: "nginx"
state: "restarted"
- name: Flush Wordpress
become: true
become_user: "{{ wordpress_user }}"
ansible.builtin.shell:
executable: "/usr/bin/bash"
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
cmd: |
set -o pipefail
wp cache flush
wp transient delete --all
wp rewrite flush --hard
changed_when: true

View File

@@ -0,0 +1,12 @@
- name: Installation des plugins Wordpress
become: true
become_user: "{{ wordpress_user }}"
loop: "{{ wordpress_plugins_to_install }}"
ansible.builtin.command:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
cmd: "wp plugin install {{ item }} --activate"
creates: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-content/plugins/{{ item | basename | splitext | first }}"
register: "wordpress_out_plugin_install"
changed_when: "'Success: Installed 1 of 1 plugins' in wordpress_out_plugin_install.stdout"
notify:
- "Flush Wordpress"

View File

@@ -0,0 +1,199 @@
- name: Installation des pré-requis
ansible.builtin.apt:
name:
- "nginx"
- "php-fpm"
- "php-mysql"
- "php-curl"
- "php-json"
- "php-xml"
- "php-mbstring"
- "php-zip"
- "zip"
- name: Installation de wp-cli
ansible.builtin.get_url:
url: "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar"
dest: "/usr/local/bin/wp"
owner: "root"
group: "root"
mode: "755"
- name: Création de l'utilisateur système pour Wordpress
ansible.builtin.user:
name: "{{ wordpress_user | mandatory }}"
home: "/var/www/{{ wordpress_user }}"
group: "www-data"
shell: "/usr/bin/bash"
password_lock: true
create_home: true
- name: Création du répertoire de Wordpress
ansible.builtin.file:
path: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
state: "directory"
owner: "{{ wordpress_user }}"
group: "www-data"
mode: "0750"
- name: Installation de Wordpress
become: true
become_user: "{{ wordpress_user }}"
ansible.builtin.command:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
cmd: "wp core download --locale='{{ wordpress_locale }}' --skip-content"
creates: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-config-sample.php"
# TODO: https://make.wordpress.org/cli/handbook/references/config/#config-files
- name: Configuration de Wordpress
become: true
become_user: "{{ wordpress_user }}"
ansible.builtin.shell:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
executable: "/usr/bin/bash"
cmd: |
set -o pipefail
wp config create \
--dbhost='{{ wordpress_db_host }}' \
--dbname='{{ wordpress_db_name }}' \
--dbuser='{{ wordpress_db_user }}' \
--dbpass='{{ wordpress_db_pass }}' \
--dbprefix='{{ wordpress_db_prefix }}' \
--dbcharset='{{ wordpress_db_charset }}' \
--extra-php <<PHP
define('FS_METHOD', 'direct');
define('FORCE_SSL_ADMIN', false);
define('WP_HOME', 'https://{{ wordpress_site }}');
define('WP_SITEURL', 'https://{{ wordpress_site }}');
error_reporting(0);
@ini_set('display_errors', 0);
define('DISALLOW_FILE_EDIT', true);
if (isset(\$_SERVER['HTTP_X_FORWARDED_PROTO']) && \$_SERVER['HTTP_X_FORWARDED_PROTO']=='https')
\$_SERVER['HTTPS'] = 'on';
PHP
creates: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-config.php"
notify:
- "Flush Wordpress"
- name: Create Wordpress database tables
become: true
become_user: "{{ wordpress_user }}"
run_once: true
ansible.builtin.command:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
cmd: >
wp core install
--url='{{ wordpress_url }}'
--title='{{ wordpress_site_title }}'
--admin_user='{{ wordpress_admin_user }}'
--admin_password='{{ wordpress_admin_password }}'
--admin_email='{{ wordpress_admin_email }}'
--locale='{{ wordpress_locale }}'
--skip-email
creates: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-content/uploads/ }}"
register: "wordpress_out_core_install"
changed_when: "'Success: WordPress installed successfully.' in wordpress_out_core_install.stdout"
notify:
- "Flush Wordpress"
- name: Installation des thèmes Wordpress
become: true
become_user: "{{ wordpress_user }}"
loop: "{{ wordpress_themes }}"
ansible.builtin.command:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
cmd: "wp theme install '{{ item }}'"
creates: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-content/themes/{{ item | basename | splitext | first }}"
register: "wordpress_out_theme_install"
changed_when: "'Success: Installed 1 of 1 themes' in wordpress_out_theme_install.stdout"
notify:
- "Flush Wordpress"
- name: Activation du thème Wordpress
become: true
become_user: "{{ wordpress_user }}"
ansible.builtin.command:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
cmd: "wp theme activate '{{ wordpress_active_theme }}'"
register: "wordpress_out_theme_activate"
changed_when: "'Success: Switched to ' in wordpress_out_theme_activate.stdout"
notify:
- "Flush Wordpress"
- name: Installation des plugins wordpress-importer et one-click-demo-import
vars:
wordpress_plugins_to_install:
- "wordpress-importer"
- "one-click-demo-import"
ansible.builtin.include_tasks: "install_plugins.yml"
- name: Importation des plugins OCDI
become: true
become_user: "{{ wordpress_user }}"
loop: "{{ wordpress_import_ocdi_indexes }}"
ansible.builtin.shell:
chdir: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}"
executable: "/usr/bin/bash"
cmd: |
set -o pipefail
wp ocdi import --predefined='{{ item }}' \
&& touch /var/www/{{ wordpress_user }}/{{ wordpress_site }}/.ocdi_index{{ item }}_imported
creates: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/.ocdi_index{{ item }}_imported"
register: "wordpress_out_ocdi_import"
changed_when: "'Success: Content import finished!' in wordpress_out_ocdi_import.stdout"
notify:
- "Flush Wordpress"
- name: Installation des plugins Wordpress
vars:
wordpress_plugins_to_install: "{{ wordpress_plugins }}"
ansible.builtin.include_tasks: "install_plugins.yml"
- name: Création du répertoire cache de Wordpress
ansible.builtin.file:
path: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-content/cache"
state: "directory"
owner: "{{ wordpress_user }}"
group: "www-data"
mode: "0750"
- name: Apply permissions
loop:
- "uploads"
- "cache"
ansible.builtin.file:
path: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-content/{{ item }}/"
owner: "{{ wordpress_user }}"
group: "www-data"
mode: "u=rwX,g=rwX,o=rX"
recurse: true
- name: Configuration de Nginx
ansible.builtin.template:
src: "templates/nginx_vhost.conf"
dest: "/etc/nginx/sites-available/{{ wordpress_site }}.conf"
owner: "root"
group: "root"
mode: "0644"
notify:
- "Restart Nginx"
- name: Link Nginx vhost config
ansible.builtin.file:
src: "/etc/nginx/sites-available/{{ wordpress_site }}.conf"
dest: "/etc/nginx/sites-enabled/{{ wordpress_site }}.conf"
state: "link"
notify:
- "Restart Nginx"
- name: Unlink Nginx default vhost config
ansible.builtin.file:
path: "/etc/nginx/sites-enabled/default"
state: "absent"
notify:
- "Restart Nginx"
# FIXME: php. ini config
# Mainly: upload_max_filesize, post_max_size, max_execution_time

View File

@@ -0,0 +1,50 @@
server {
listen 80;
server_name {{ wordpress_site }} www.{{ wordpress_site }};
root /var/www/{{ wordpress_user }}/{{ wordpress_site }};
index index.html index.htm index.php;
client_max_body_size 50M;
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
location ~ /\.ht {
deny all;
}
location ~ /wp-config\.php\$ {
deny all;
}
location ~ /wp-content/uploads/.*\.php\$ {
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
}
# Réécritures pour WordPress
location ~ ^/index\.php$ { }
location / {
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php last;
break;
}
}
# location / {
# try_files \$uri \$uri/ /index.php?\$args;
# }
# location ~ \.php\$ {
# include snippets/fastcgi-php.conf;
# fastcgi_pass unix:/var/run/php/php-fpm.sock;
# fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
# }
}

View File

@@ -1,4 +0,0 @@
- name: Install Apache 2
ansible.builtin.apt:
name:
- "apache2"