diff --git a/admin-users/defaults/main.yml b/admin-users/defaults/main.yml
deleted file mode 100644
index ad5f42cb..00000000
--- a/admin-users/defaults/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-admin_users: {}
-admin_users_group: adm
diff --git a/admin-users/tasks/admin_user.yml b/admin-users/tasks/admin_user.yml
deleted file mode 100644
index 329ce50e..00000000
--- a/admin-users/tasks/admin_user.yml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-
-- include: user.yml
-
-- include: profile.yml
-
-- include: ssh.yml
-
-- include: sudo.yml
-
-- meta: flush_handlers
diff --git a/admin-users/tasks/main.yml b/admin-users/tasks/main.yml
deleted file mode 100644
index 6a1d1506..00000000
--- a/admin-users/tasks/main.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-
-- fail:
- msg: only compatible with Debian >= 8
- when:
- - ansible_distribution != "Debian" or ansible_distribution_major_version | version_compare('8', '<')
-
-- debug:
- msg: "Warning: empty 'admin_users' variable, tasks will be skipped!"
- when: admin_users == {}
-
-- include: admin_user.yml
- vars:
- user: "{{ item.value }}"
- with_dict: "{{ admin_users }}"
- when: admin_users != {}
diff --git a/admin-users/tasks/profile.yml b/admin-users/tasks/profile.yml
deleted file mode 100644
index 0101d4be..00000000
--- a/admin-users/tasks/profile.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-
-- name: is evomaintenance installed?
- stat:
- path: "/usr/share/scripts/evomaintenance.sh"
- register: evomaintenance_script
- check_mode: no
-
-- name: "Add evomaintenance trap for '{{ user.name }}'"
- lineinfile:
- state: present
- dest: '/home/{{ user.name }}/.profile'
- insertafter: EOF
- line: 'trap "sudo /usr/share/scripts/evomaintenance.sh" 0'
- when: evomaintenance_script.stat.exists
diff --git a/admin-users/tasks/sudo.yml b/admin-users/tasks/sudo.yml
deleted file mode 100644
index e05ac614..00000000
--- a/admin-users/tasks/sudo.yml
+++ /dev/null
@@ -1,48 +0,0 @@
----
-
-- name: "Verify Evolinux sudoers file presence (jessie)"
- template:
- src: sudoers_jessie.j2
- dest: /etc/sudoers.d/evolinux
- force: no
- validate: '/usr/sbin/visudo -cf %s'
- register: copy_sudoers_evolinux
- when: ansible_distribution_release == "jessie"
-
-- name: "Verify Evolinux sudoers file presence (Debian 9 or later)"
- template:
- src: sudoers_stretch.j2
- dest: /etc/sudoers.d/evolinux
- force: no
- validate: '/usr/sbin/visudo -cf %s'
- register: copy_sudoers_evolinux
- when: ansible_distribution_major_version | version_compare('9', '>=')
-
-- name: "Verify Evolinux sudoers file permissions"
- file:
- path: /etc/sudoers.d/evolinux
- mode: "0440"
- state: file
-
-- name: "Add user in sudoers file for '{{ user.name }}' (jessie)"
- replace:
- dest: /etc/sudoers.d/evolinux
- regexp: '^(User_Alias\s+ADMINS\s+=((?!{{ user.name }}).)*)$'
- replace: '\1,{{ user.name }}'
- validate: '/usr/sbin/visudo -cf %s'
- when:
- - ansible_distribution_release == "jessie"
- - not copy_sudoers_evolinux.changed
-
-- name: "Create evolinux-sudo group (Debian 9 or later)"
- group:
- name: evolinux-sudo
- system: yes
- when: ansible_distribution_major_version | version_compare('9', '>=')
-
-- name: "Add user to evolinux-sudo group (Debian 9 or later)"
- user:
- name: '{{ user.name }}'
- groups: 'evolinux-sudo'
- append: yes
- when: ansible_distribution_major_version | version_compare('9', '>=')
diff --git a/amavis/handlers/main.yml b/amavis/handlers/main.yml
new file mode 100644
index 00000000..62049999
--- /dev/null
+++ b/amavis/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart amavis
+ service:
+ name: amavis
+ state: restarted
diff --git a/amavis/tasks/main.yml b/amavis/tasks/main.yml
new file mode 100644
index 00000000..810ba505
--- /dev/null
+++ b/amavis/tasks/main.yml
@@ -0,0 +1,19 @@
+---
+- name: install Amavis
+ apt:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - postgrey
+ - amavisd-new
+ tags:
+ - amavis
+
+- name: configure Amavis
+ template:
+ src: amavis.conf.j2
+ dest: /etc/amavis/conf.d/49-evolinux-defaults.conf
+ mode: "0644"
+ notify: restart amavis
+ tags:
+ - amavis
diff --git a/amavis/templates/amavis.conf.j2 b/amavis/templates/amavis.conf.j2
new file mode 100644
index 00000000..cbe597a2
--- /dev/null
+++ b/amavis/templates/amavis.conf.j2
@@ -0,0 +1,57 @@
+use strict;
+
+## Liste des domaines considérés comme locaux
+#@local_domains_acl = qw(.);
+@local_domains_acl = (".example.net","example.com");
+
+# On customise la ligne ajoutée dans les entêtes
+$X_HEADER_LINE = "by Amavis at $mydomain";
+
+# On precise les FROM pour etre (bugs dans certaines version d'Amavis)
+$mailfrom_notify_admin = "postmaster\@$mydomain";
+$mailfrom_notify_recip = "postmaster\@$mydomain";
+$mailfrom_notify_spamadmin = "postmaster\@$mydomain";
+
+# Notifications de fichiers bannis / virus
+$virus_admin = "postmaster\@$mydomain";
+# Ne pas recevoir des notifications pour les mails UNCHECKED
+delete $admin_maps_by_ccat{&CC_UNCHECKED};
+
+# Que faire avec les messages détectés
+$final_virus_destiny = D_DISCARD;
+$final_banned_destiny = D_BOUNCE;
+$final_spam_destiny = D_BOUNCE;
+$final_bad_header_destiny = D_PASS;
+
+# Pour recevoir des bounces (mails originals) des fichiers bloqués / virus
+#$banned_quarantine_to = "banned\@$mydomain";
+#$virus_quarantine_to = "virus\@$mydomain";
+
+# Note tueuse
+$sa_tag2_level_deflt = 6.31;
+# Pour un comportement "normal" de SA
+$sa_tag_level_deflt = -1999;
+$sa_kill_level_deflt = 1999;
+$sa_dsn_cutoff_level = -99;
+$sa_spam_subject_tag = '[SPAM]';
+
+# log
+$log_level = 2;
+
+# En fonction besoin/ressources, on a juste le nbre de process
+$max_servers = 2;
+
+$enable_ldap = 1;
+$default_ldap = {
+ hostname => '127.0.0.1', tls => 0,
+ base => '{{ ldap_suffix }}', scope => 'sub',
+ query_filter => '(&(mailacceptinggeneralid=%m)(isActive=TRUE))'
+};
+
+# Activer l'antivirus et antivirus
+@bypass_virus_checks_maps = (
+ \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
+@bypass_spam_checks_maps = (
+ \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
+
+1; # ensure a defined return
diff --git a/amazon-ec2/README b/amazon-ec2/README
new file mode 100644
index 00000000..15f8b129
--- /dev/null
+++ b/amazon-ec2/README
@@ -0,0 +1,60 @@
+# amazon-ec2
+
+Manage Amazon EC2 instances.
+
+This role is intended to be called before any other role to setup and start EC2
+instances.
+
+## Dependencies
+
+You should first ensure that you have `python-boto` package installed on your
+machine and an Amazon security access key pair created for your account.
+
+## Tasks
+
+By default, this role does nothing (no `main.yml` file).
+
+* `setup.yml`: create a security group and ssh keys
+* `create-instance.yml`: create new EC2 instances
+* `post-install.yml`: remove admin user created on Debian instances
+
+## Variables
+
+ - `aws_access_key` and `aws_secret_key`: your AWS credentials
+ - `aws_region`: where to create instances. Default: ca-central-1
+ - `ec2_public_ip`: assign public elastic IP address. Default: False
+ - `ec2_instance_count`: how many instance to launch. Default: 1
+ - `ec2_security_group: EC2 security group to use. See
+ ec2_evolinux_security_group in `defaults/main.yml` to define your own.
+ Default: ec2_evolinux_security_group
+ - `ec2_base_ami`: EC2 image to use. Default is to use Debian official ones,
+ depending on the region
+ - `ec2_instance_type`: EC2 instance type to use
+ - `ssh_pubkey_file`: SSH public key file to push to AWS. Do not try to put
+ your ED25519 key here, AWS does not support it. Default: ~/.ssh/id_rsa.pub
+ - `ec2_keyname: a name to give to your public key on AWS. Default is to use
+ $USER environment variable.
+
+## Examples
+
+In your main evolinux playbook put this play before Evolinux one:
+
+```
+---
+- name: Prepare Amazon EC2 instance
+ hosts: localhost
+ gather_facts: False
+
+ vars:
+ aws_access_key:
+ aws_secret_key:
+ # Any other variable you want to set.
+
+ tasks:
+ - include_role:
+ name: amazon-ec2
+ tasks_from: create-instance.yml
+```
+
+See amazon-ec2-evolinux.yml for an almost ready-to-use playbook to set up
+Amazon EC2 instances running Evolinux.
diff --git a/amazon-ec2/amazon-ec2-evolinux.yml b/amazon-ec2/amazon-ec2-evolinux.yml
new file mode 100644
index 00000000..5c7a5e4e
--- /dev/null
+++ b/amazon-ec2/amazon-ec2-evolinux.yml
@@ -0,0 +1,62 @@
+---
+- name: Prepare Amazon EC2 instance
+ hosts: localhost
+ gather_facts: False
+
+ vars:
+ aws_access_key:
+ aws_secret_key:
+ aws_region: ca-central-1
+
+ tasks:
+ - include_role:
+ name: amazon-ec2
+ tasks_from: setup.yml
+ - include_role:
+ name: amazon-ec2
+ tasks_from: create-instance.yml
+
+- name: Install Evolinux
+ hosts: launched-instances
+ become: yes
+
+ vars_files:
+ - 'vars/secrets.yml'
+
+ vars:
+ admin_users: "{{ admin_users }}"
+ minifirewall_trusted_ips: "{{ trusted_ips }}"
+ fail2ban_ignore_ips: "{{ trusted_ips }}"
+ evolinux_hostname:
+ evolinux_domain:
+ evolinux_fqdn:
+ evolinux_internal_hostname:
+ minifirewall_public_ports_tcp: [80, 443]
+ minifirewall_public_ports_udp: []
+ minifirewall_semipublic_ports_tcp: [22]
+ nagios_nrpe_allowed_hosts: "{{ trusted_ips }}"
+
+ roles:
+ - etc-git
+ - evolinux-base
+ - admin-users
+ - munin
+ - minifirewall
+ - fail2ban
+ - nagios-nrpe
+ - listupgrade
+ - evomaintenance
+ - evocheck
+ - packweb-apache
+ - mysql
+
+ post_tasks:
+ - include_role:
+ name: etc-git
+ tasks_from: commit.yml
+ vars:
+ commit_message: "Ansible post-run Evolinux playbook"
+
+ - include_role:
+ name: evocheck
+ tasks_from: exec.yml
diff --git a/amazon-ec2/defaults/main.yml b/amazon-ec2/defaults/main.yml
new file mode 100644
index 00000000..c22b9df4
--- /dev/null
+++ b/amazon-ec2/defaults/main.yml
@@ -0,0 +1,135 @@
+---
+aws_region: ca-central-1
+ec2_public_ip: False
+ec2_instance_count: 1
+ec2_security_group: "{{ ec2_evolinux_security_group }}"
+ec2_base_ami: "{{ ec2_debian_base_ami[aws_region] }}"
+ec2_instance_type: t2.micro
+# Note: Do not try to put your ED25519 key here, AWS does not support it...
+ssh_pubkey_file: ~/.ssh/id_rsa.pub
+ec2_keyname: "{{ lookup('env', 'USER') }}"
+
+# From https://wiki.debian.org/Cloud/AmazonEC2Image/Stretch
+ec2_debian_base_ami:
+ ap-northeast-1: ami-032dd665
+ ap-northeast-2: ami-e174ac8f
+ ap-south-1: ami-6e7a3e01
+ ap-southeast-1: ami-41365b22
+ ap-southeast-2: ami-51f61333
+ ca-central-1: ami-18239d7c
+ eu-central-1: ami-11bb0e7e
+ eu-west-1: ami-d037cda9
+ eu-west-2: ami-ece3f388
+ sa-east-1: ami-a24635ce
+ us-east-1: ami-ac5e55d7
+ us-east-2: ami-9fbb98fa
+ us-west-1: ami-560c3836
+ us-west-2: ami-fa18f282
+
+ec2_evolinux_security_group:
+ name: evolinux-default
+ description: Evolinux default security group
+ rules:
+ - proto: icmp
+ cidr_ip: 0.0.0.0/0
+ from_port: -1
+ to_port: -1
+ - proto: tcp
+ from_port: 22
+ to_port: 22
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 5666
+ to_port: 5666
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 53
+ to_port: 53
+ cidr_ip: 0.0.0.0/0
+ - proto: udp
+ from_port: 53
+ to_port: 53
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 389
+ to_port: 389
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 636
+ to_port: 636
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 143
+ to_port: 143
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 993
+ to_port: 993
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 110
+ to_port: 110
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 995
+ to_port: 995
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 25
+ to_port: 25
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 80
+ to_port: 80
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 443
+ to_port: 443
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 21
+ to_port: 21
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 20
+ to_port: 20
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 5001
+ to_port: 5001
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 465
+ to_port: 465
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 587
+ to_port: 587
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 8181
+ to_port: 8181
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 8282
+ to_port: 8282
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 9091
+ to_port: 9091
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 2222
+ to_port: 2222
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 2223
+ to_port: 2223
+ cidr_ip: 0.0.0.0/0
+ - proto: udp
+ from_port: 123
+ to_port: 123
+ cidr_ip: 0.0.0.0/0
+ rules_egress:
+ - proto: all
+ cidr_ip: 0.0.0.0/0
diff --git a/amazon-ec2/tasks/create-instance.yml b/amazon-ec2/tasks/create-instance.yml
new file mode 100644
index 00000000..470cac72
--- /dev/null
+++ b/amazon-ec2/tasks/create-instance.yml
@@ -0,0 +1,36 @@
+---
+
+- name: Launch new instance(s)
+ ec2:
+ state: present
+ aws_access_key: "{{aws_access_key}}"
+ aws_secret_key: "{{aws_secret_key}}"
+ region: "{{aws_region}}"
+ image: "{{ec2_base_ami}}"
+ instance_type: "{{ec2_instance_type}}"
+ count: "{{ec2_instance_count}}"
+ assign_public_ip: "{{ec2_public_ip}}"
+ group: "{{ec2_security_group.name}}"
+ key_name: "{{ec2_keyname}}"
+ wait: yes
+ register: ec2
+
+- name: Add newly created instance(s) to inventory
+ add_host:
+ hostname: "{{item.public_dns_name}}"
+ groupname: launched-instances
+ ansible_user: admin
+ ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
+ with_items: "{{ec2.instances}}"
+
+- debug:
+ msg: "Your newly created instance is reachable at: {{item.public_dns_name}}"
+ with_items: "{{ec2.instances}}"
+
+- name: Wait for SSH to come up on all instances (give up after 2m)
+ wait_for:
+ state: started
+ host: "{{item.public_dns_name}}"
+ port: 22
+ timeout: 120
+ with_items: "{{ec2.instances}}"
diff --git a/amazon-ec2/tasks/post-install.yml b/amazon-ec2/tasks/post-install.yml
new file mode 100644
index 00000000..369f4941
--- /dev/null
+++ b/amazon-ec2/tasks/post-install.yml
@@ -0,0 +1,5 @@
+---
+- name: Remove admin user
+ user:
+ name: admin
+ state: absent
diff --git a/amazon-ec2/tasks/setup.yml b/amazon-ec2/tasks/setup.yml
new file mode 100644
index 00000000..27a1d8b0
--- /dev/null
+++ b/amazon-ec2/tasks/setup.yml
@@ -0,0 +1,20 @@
+---
+- name: Create default security group
+ ec2_group:
+ name: "{{ec2_security_group.name}}"
+ state: present
+ aws_access_key: "{{aws_access_key}}"
+ aws_secret_key: "{{aws_secret_key}}"
+ region: "{{aws_region}}"
+ description: "{{ec2_security_group.description}}"
+ rules: "{{ec2_security_group.rules}}"
+
+- name: Create key pair
+ ec2_key:
+ name: "{{ec2_keyname}}"
+ state: present
+ aws_access_key: "{{aws_access_key}}"
+ aws_secret_key: "{{aws_secret_key}}"
+ region: "{{aws_region}}"
+ key_material: "{{item}}"
+ with_file: "{{ssh_pubkey_file}}"
diff --git a/apache/README.md b/apache/README.md
index 66804981..40e17499 100644
--- a/apache/README.md
+++ b/apache/README.md
@@ -10,8 +10,8 @@ Everything is in the `tasks/main.yml` file for now.
Main variables are :
-* `apache_private_ipaddr_whitelist_present` : list of IP addresses to have in the private whitelist ;
-* `apache_private_ipaddr_whitelist_absent` : list of IP addresses **not** to have in the whitelist;
+* `apache_ipaddr_whitelist_present` : list of IP addresses to have in the private whitelist ;
+* `apache_ipaddr_whitelist_absent` : list of IP addresses **not** to have in the whitelist;
* `apache_private_htpasswd_present` : list of users to have in the private htpasswd ;
* `apache_private_htpasswd_absent` : list of users to **not** have in the private htpasswd.
* `log2mail_alert_email`: email address to send Log2mail messages to (default: `general_alert_email`).
diff --git a/apache/defaults/main.yml b/apache/defaults/main.yml
index 276f5a38..b21e1d59 100644
--- a/apache/defaults/main.yml
+++ b/apache/defaults/main.yml
@@ -1,6 +1,9 @@
---
-apache_private_ipaddr_whitelist_present: []
-apache_private_ipaddr_whitelist_absent: []
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+apache_ipaddr_whitelist_present: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
+apache_ipaddr_whitelist_absent: []
apache_private_htpasswd_present: []
apache_private_htpasswd_absent: []
diff --git a/apache/files/private_ipaddr_whitelist.conf b/apache/files/ipaddr_whitelist.conf
similarity index 100%
rename from apache/files/private_ipaddr_whitelist.conf
rename to apache/files/ipaddr_whitelist.conf
diff --git a/apache/files/save_apache_status.sh b/apache/files/save_apache_status.sh
new file mode 100644
index 00000000..d65b2e08
--- /dev/null
+++ b/apache/files/save_apache_status.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -e
+
+DIR="/var/log/apache-status"
+URL="http://127.0.0.1/server-status"
+TS=`date +%Y%m%d%H%M%S`
+FILE="${DIR}/${TS}.html"
+
+mkdir -p "${DIR}"
+
+wget -q -O "${FILE}" "${URL}"
+
+chmod 640 "${FILE}"
+
+find "${DIR}" -type f -mtime +1 -delete
+
+exit 0
diff --git a/apache/tasks/auth.yml b/apache/tasks/auth.yml
index 0f550a3c..dff100ce 100644
--- a/apache/tasks/auth.yml
+++ b/apache/tasks/auth.yml
@@ -2,7 +2,7 @@
- name: Init ipaddr_whitelist.conf file
copy:
- src: private_ipaddr_whitelist.conf
+ src: ipaddr_whitelist.conf
dest: /etc/apache2/ipaddr_whitelist.conf
owner: root
group: root
@@ -16,7 +16,7 @@
dest: /etc/apache2/ipaddr_whitelist.conf
line: "Require ip {{ item }}"
state: present
- with_items: "{{ apache_private_ipaddr_whitelist_present }}"
+ with_items: "{{ apache_ipaddr_whitelist_present }}"
notify: reload apache
tags:
- apache
@@ -26,7 +26,7 @@
dest: /etc/apache2/ipaddr_whitelist.conf
line: "Require ip {{ item }}"
state: absent
- with_items: "{{ apache_private_ipaddr_whitelist_absent }}"
+ with_items: "{{ apache_ipaddr_whitelist_absent }}"
notify: reload apache
tags:
- apache
diff --git a/apache/tasks/main.yml b/apache/tasks/main.yml
index 50fb548a..3820fad2 100644
--- a/apache/tasks/main.yml
+++ b/apache/tasks/main.yml
@@ -38,6 +38,10 @@
- expires
- headers
- cgi
+ - ssl
+ - include
+ - negotiation
+ - alias
notify: reload apache
tags:
- apache
@@ -127,30 +131,17 @@
tags:
- apache
-- name: Stat /default index
- stat:
- path: /var/www/index.html
- register: _default_index
- check_mode: no
+- include_role:
+ name: remount-usr
tags:
- apache
-# - block:
-# - name: generate random string for serverstatus suffix
-# command: "apg -a 1 -M N -n 1"
-# changed_when: False
-# register: _random_serverstatus_suffix
-#
-# - name: overwrite apache_serverstatus_suffix
-# set_fact:
-# apache_serverstatus_suffix: "{{ _random_serverstatus_suffix.stdout }}"
-# when: apache_serverstatus_suffix == ""
-#
-# - name: replace server-status suffix in default site index
-# replace:
-# dest: /var/www/index.html
-# regexp: '__SERVERSTATUS_SUFFIX__'
-# replace: "{{ apache_serverstatus_suffix }}"
+- name: "Install save_apache_status.sh"
+ copy:
+ src: save_apache_status.sh
+ dest: /usr/share/scripts/save_apache_status.sh
+ mode: "0755"
+ force: no
- include: log2mail.yml
when: apache_log2mail_include
diff --git a/apache/tasks/munin.yml b/apache/tasks/munin.yml
index 85f0b386..9195ae0f 100644
--- a/apache/tasks/munin.yml
+++ b/apache/tasks/munin.yml
@@ -1,23 +1,55 @@
---
-- name: munin-node and core plugins are installed
+- name: "Install munin-node and core plugins packages"
apt:
name: "{{ item }}"
state: installed
with_items:
- munin-node
- munin-plugins-core
+ tags:
+ - apache
+ - munin
-- name: enable munin plugins
+- name: "Enable Munin plugins"
file:
src: "/usr/share/munin/plugins/{{ item }}"
dest: "/etc/munin/plugins/{{ item }}"
state: link
with_items:
- - apache_accesses
- - apache_processes
- - apache_volume
+ - apache_accesses
+ - apache_processes
+ - apache_volume
notify: restart munin-node
tags:
- - apache
- - munin
+ - apache
+ - munin
+
+- name: "Install fcgi packages for Munin graphs"
+ apt:
+ name: "{{ item }}"
+ state: installed
+ with_items:
+ - libapache2-mod-fcgid
+ - libcgi-fast-perl
+ notify: reload apache
+ tags:
+ - apache
+ - munin
+
+- name: "Enable libapache2-mod-fcgid"
+ command: a2enmod fcgid
+ register: cmd_enable_fcgid
+ changed_when: "'Module fcgid already enabled' not in cmd_enable_fcgid.stdout"
+ notify: restart apache
+ tags:
+ - apache
+ - munin
+
+- name: "Apache has access to /var/log/munin/"
+ file:
+ path: /var/log/munin/
+ group: www-data
+ tags:
+ - apache
+ - munin
diff --git a/apache/templates/evolinux-default.conf.j2 b/apache/templates/evolinux-default.conf.j2
index b50409a8..238665b2 100644
--- a/apache/templates/evolinux-default.conf.j2
+++ b/apache/templates/evolinux-default.conf.j2
@@ -19,11 +19,13 @@
Require all denied
Include /etc/apache2/ipaddr_whitelist.conf
-
- Options -Indexes
+ # munin-cgi-graph, used for zooming on graphs.
+ ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph
+
+ Options +ExecCGI
Require all denied
Include /etc/apache2/ipaddr_whitelist.conf
-
+
# For CGI Scripts. We need to set Directory directive as ScriptAlias take precedence.
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
diff --git a/apt/README.md b/apt/README.md
index ec4da5b6..f3a8b13f 100644
--- a/apt/README.md
+++ b/apt/README.md
@@ -11,6 +11,7 @@ Tasks are extracted in several files, included in `tasks/main.yml` :
## Available variables
+* `apt_config` : customize apt configuration (default: `True`) ;
* `apt_install_basics` : change basic sources components (default: `True`) ;
* `apt_basics_components` : basic sources components (default: `main`) ;
* `apt_install_backports` : install backports sources (default: `False`) ;
diff --git a/apt/defaults/main.yml b/apt/defaults/main.yml
index 4e1cee3d..0960fd16 100644
--- a/apt/defaults/main.yml
+++ b/apt/defaults/main.yml
@@ -1,4 +1,10 @@
---
+apt_config: True
+apt_evolinux_config: True
+apt_hooks: True
+apt_remove_aptitude: True
+apt_upgrade: False
+
apt_install_basics: True
apt_basics_components: "main"
diff --git a/apt/handlers/main.yml b/apt/handlers/main.yml
deleted file mode 100644
index e68f5c28..00000000
--- a/apt/handlers/main.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-- name: apt update
- apt:
- update_cache: yes
diff --git a/apt/tasks/backports.yml b/apt/tasks/backports.yml
index fd459a34..67b193d4 100644
--- a/apt/tasks/backports.yml
+++ b/apt/tasks/backports.yml
@@ -13,7 +13,7 @@
dest: /etc/apt/sources.list.d/backports.list
force: yes
mode: "0640"
- notify: apt update
+ register: apt_backports_list
tags:
- apt
@@ -23,11 +23,13 @@
dest: /etc/apt/preferences.d/0-backports-defaults
force: yes
mode: "0640"
- notify: apt update
+ register: apt_backports_config
tags:
- apt
-- name: Intermediate flush of handlers
- meta: flush_handlers
+- name: Apt update
+ apt:
+ update_cache: yes
+ when: apt_backports_list | changed or apt_backports_config | changed
tags:
- apt
diff --git a/apt/tasks/basics.yml b/apt/tasks/basics.yml
index d68e6063..f615c030 100644
--- a/apt/tasks/basics.yml
+++ b/apt/tasks/basics.yml
@@ -6,7 +6,7 @@
dest: /etc/apt/sources.list
mode: "0644"
force: yes
- notify: apt update
+ register: apt_basic_list
tags:
- apt
@@ -20,7 +20,9 @@
- /etc/apt/sources.list.d/debian-update.list
when: apt_clean_gandi_sourceslist
-- name: Intermediate flush of handlers
- meta: flush_handlers
+- name: Apt update
+ apt:
+ update_cache: yes
+ when: apt_basic_list | changed
tags:
- apt
diff --git a/evolinux-base/tasks/apt.yml b/apt/tasks/config.yml
similarity index 63%
rename from evolinux-base/tasks/apt.yml
rename to apt/tasks/config.yml
index bb0be3fc..264e8dd7 100644
--- a/evolinux-base/tasks/apt.yml
+++ b/apt/tasks/config.yml
@@ -1,24 +1,19 @@
---
-- include_role:
- name: apt
- vars:
- apt_install_basics: "{{ evolinux_apt_replace_default_sources }}"
- apt_install_evolix_public: "{{ evolinux_apt_public_sources }}"
-
-- name: Setting apt config
+- name: Evolinux config for APT
lineinfile:
dest: /etc/apt/apt.conf.d/z-evolinux.conf
- line: "{{ item }}"
+ line: "{{ item.line }}"
+ regexp: "{{ item.regexp }}"
create: yes
state: present
mode: "0640"
with_items:
- - "APT::Install-Recommends \"false\";"
- - "APT::Install-Suggests \"false\";"
- when: evolinux_apt_conf
+ - { line: "APT::Install-Recommends \"false\";", regexp: 'APT::Install-Recommends' }
+ - { line: "APT::Install-Suggests \"false\";", regexp: 'APT::Install-Suggests' }
+ when: apt_evolinux_config
-- name: DPKg invoke hooks
+- name: DPkg invoke hooks
lineinfile:
dest: /etc/apt/apt.conf.d/z-evolinux.conf
line: "{{ item }}"
@@ -30,13 +25,13 @@
- "DPkg::Pre-Invoke { \"df /usr | grep -q /usr && mount -oremount,rw /usr || true\"; };"
- "DPkg::Post-Invoke { \"df /tmp | grep -q /tmp && mount -oremount /tmp || true\"; };"
- "DPkg::Post-Invoke { \"df /usr | grep -q /usr && mount -oremount /usr || true\"; };"
- when: evolinux_apt_hooks
+ when: apt_hooks
- name: Remove Aptitude
apt:
name: aptitude
state: absent
- when: evolinux_apt_remove_aptitude
+ when: apt_remove_aptitude
- name: Updating APT cache
apt:
@@ -46,6 +41,4 @@
- name: Upgrading system
apt:
upgrade: dist
- when: evolinux_apt_upgrade
-
-- meta: flush_handlers
+ when: apt_upgrade
diff --git a/apt/tasks/evolix_public.yml b/apt/tasks/evolix_public.yml
index 5bfb3287..b1db38ab 100644
--- a/apt/tasks/evolix_public.yml
+++ b/apt/tasks/evolix_public.yml
@@ -19,11 +19,13 @@
dest: /etc/apt/sources.list.d/evolix_public.list
force: yes
mode: "0640"
- notify: apt update
+ register: apt_evolix_public
tags:
- apt
-- name: Intermediate flush of handlers
- meta: flush_handlers
+- name: Apt update
+ apt:
+ update_cache: yes
+ when: apt_evolix_public | changed
tags:
- apt
diff --git a/apt/tasks/main.yml b/apt/tasks/main.yml
index 7bb8950e..72960d02 100644
--- a/apt/tasks/main.yml
+++ b/apt/tasks/main.yml
@@ -7,6 +7,12 @@
tags:
- apt
+- name: Custom configuration
+ include: config.yml
+ when: apt_config
+ tags:
+ - apt
+
- name: Install basics repositories
include: basics.yml
when: apt_install_basics
@@ -19,9 +25,6 @@
tags:
- apt
-- debug:
- var: apt_install_evolix_public
-
- name: Install Evolix Public APT repository
include: evolix_public.yml
when: apt_install_evolix_public
diff --git a/clamav/handlers/main.yml b/clamav/handlers/main.yml
new file mode 100644
index 00000000..e053f01a
--- /dev/null
+++ b/clamav/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart clamav
+ service:
+ name: clamav-daemon
+ state: restarted
diff --git a/clamav/meta/main.yml b/clamav/meta/main.yml
new file mode 100644
index 00000000..510b6855
--- /dev/null
+++ b/clamav/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - { role: amavis }
diff --git a/clamav/tasks/main.yml b/clamav/tasks/main.yml
new file mode 100644
index 00000000..6e3058dd
--- /dev/null
+++ b/clamav/tasks/main.yml
@@ -0,0 +1,111 @@
+---
+- name: configure clamav-daemon
+ debconf:
+ name: clamav-daemon
+ question: "{{ item.key }}"
+ value: "{{ item.value }}"
+ vtype: "{{ item.type }}"
+ with_items:
+ - { key: 'clamav-daemon/debconf', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/MaxHTMLNormalize', type: 'string', value: '10M' }
+ - { key: 'clamav-daemon/StatsPEDisabled', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/FollowDirectorySymlinks', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/StreamMaxLength', type: 'string', value: '25' }
+ - { key: 'clamav-daemon/ReadTimeout', type: 'string', value: '180' }
+ - { key: 'clamav-daemon/StatsEnabled', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/MaxConnectionQueueLength', type: 'string', value: '15' }
+ - { key: 'clamav-daemon/LogRotate', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/AllowAllMatchScan', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/ScanOnAccess', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/LogFile', type: 'string', value: '/var/log/clamav/clamav.log' }
+ - { key: 'clamav-daemon/ScanMail', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/BytecodeTimeout', type: 'string', value: '60000' }
+ - { key: 'clamav-daemon/LogTime', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/OnAccessMaxFileSize', type: 'string', value: '5M' }
+ - { key: 'clamav-daemon/TcpOrLocal', type: 'select', value: 'UNIX' }
+ - { key: 'clamav-daemon/MaxEmbeddedPE', type: 'string', value: '10M' }
+ - { key: 'clamav-daemon/FixStaleSocket', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/User', type: 'string', value: 'clamav' }
+ - { key: 'clamav-daemon/BytecodeSecurity', type: 'select', value: 'TrustSigned' }
+ - { key: 'clamav-daemon/ScanSWF', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/MaxDirectoryRecursion', type: 'string', value: '0' }
+ - { key: 'clamav-daemon/MaxThreads', type: 'string', value: '12' }
+ - { key: 'clamav-daemon/LocalSocketGroup', type: 'string', value: 'clamav' }
+ - { key: 'clamav-daemon/MaxScriptNormalize', type: 'string', value: '5M' }
+ - { key: 'clamav-daemon/ForceToDisk', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/StatsHostID', type: 'string', value: 'auto' }
+ - { key: 'clamav-daemon/FollowFileSymlinks', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/TCPSocket', type: 'string', value: '3310' }
+ - { key: 'clamav-daemon/TCPAddr', type: 'string', value: 'any' }
+ - { key: 'clamav-daemon/DisableCertCheck', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/SelfCheck', type: 'string', value: '3600' }
+ - { key: 'clamav-daemon/LocalSocket', type: 'string', value: '/var/run/clamav/clamd.ctl' }
+ - { key: 'clamav-daemon/LocalSocketMode', type: 'string', value: '666' }
+ - { key: 'clamav-daemon/StatsTimeout', type: 'string', value: '10' }
+ - { key: 'clamav-daemon/MaxZipTypeRcg', type: 'string', value: '1M' }
+ - { key: 'clamav-daemon/MaxHTMLNoTags', type: 'string', value: '2M' }
+ - { key: 'clamav-daemon/LogSyslog', type: 'boolean', value: 'false' }
+ - { key: 'clamav-daemon/AddGroups', type: 'string', value: '' }
+ - { key: 'clamav-daemon/Bytecode', type: 'boolean', value: 'true' }
+ - { key: 'clamav-daemon/ScanArchive', type: 'boolean', value: 'true' }
+ tags:
+ - clamav
+
+- name: configure clamav-freshclam
+ debconf:
+ name: clamav-freshclam
+ question: "{{ item.key }}"
+ value: "{{ item.value }}"
+ vtype: "{{ item.type }}"
+ with_items:
+ - { key: 'clamav-freshclam/autoupdate_freshclam', type: 'select', value: 'daemon' }
+ - { key: 'clamav-freshclam/proxy_user', type: 'string', value: '' }
+ - { key: 'clamav-freshclam/NotifyClamd', type: 'boolean', value: 'true' }
+ - { key: 'clamav-freshclam/local_mirror', type: 'select', value: 'db.fr.clamav.net' }
+ - { key: 'clamav-freshclam/http_proxy', type: 'string', value: '' }
+ - { key: 'clamav-freshclam/LogRotate', type: 'boolean', value: 'true' }
+ - { key: 'clamav-freshclam/Bytecode', type: 'boolean', value: 'true' }
+ - { key: 'clamav-freshclam/update_interval', type: 'string', value: '24' }
+ - { key: 'clamav-freshclam/SafeBrowsing', type: 'boolean', value: 'false' }
+ - { key: 'clamav-freshclam/PrivateMirror', type: 'string', value: '' }
+ - { key: 'clamav-freshclam/internet_interface', type: 'string', value: '' }
+ tags:
+ - clamav
+
+- name: install ClamAV
+ apt:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - clamav-daemon
+ - clamav
+ - clamdscan
+ - clamav-freshclam
+ - arc
+ - arj
+ - zoo
+ - pax
+ - bzip2
+ - cabextract
+ - rpm
+ - lzop
+ - razor
+ tags:
+ - clamav
+
+- name: add clamav user to amavis group
+ user:
+ name: clamav
+ groups: amavis
+ append: True
+ tags:
+ - clamav
+
+- name: allow supplementary groups
+ replace:
+ dest: /etc/clamav/clamd.conf
+ regexp: 'AllowSupplementaryGroups false'
+ replace: 'AllowSupplementaryGroups true'
+ notify: restart clamav
+ tags:
+ - clamav
diff --git a/dovecot/.kitchen.yml b/dovecot/.kitchen.yml
new file mode 100644
index 00000000..687c2033
--- /dev/null
+++ b/dovecot/.kitchen.yml
@@ -0,0 +1,36 @@
+---
+driver:
+ name: docker
+ privileged: true
+ use_sudo: false
+
+provisioner:
+ name: ansible_playbook
+ hosts: test-kitchen
+ roles_path: ../
+ ansible_verbose: true
+ require_ansible_source: false
+ require_chef_for_busser: false
+ idempotency_test: true
+
+platforms:
+ - name: debian
+ driver_config:
+ image: evolix/ansible:2.2.1
+
+verifier:
+ name: serverspec
+
+suites:
+ - name: default
+ provisioner:
+ name: ansible_playbook
+ playbook: ./tests/test.yml
+ verifier:
+ patterns:
+ - nginx/tests/spec/memcached_spec.rb
+ bundler_path: '/usr/local/bin'
+ rspec_path: '/usr/local/bin'
+
+transport:
+ max_ssh_sessions: 6
diff --git a/dovecot/README.md b/dovecot/README.md
new file mode 100644
index 00000000..736b95dc
--- /dev/null
+++ b/dovecot/README.md
@@ -0,0 +1,11 @@
+# Dovecot
+
+Installation and basic configuration of dovecot
+
+## Tasks
+
+Minimal configuration is in `tasks/main.yml`
+
+## Available variables
+
+The full list of variables (with default values) can be found in `defaults/main.yml`.
diff --git a/dovecot/defaults/main.yml b/dovecot/defaults/main.yml
new file mode 100644
index 00000000..884bc1ca
--- /dev/null
+++ b/dovecot/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+dovecot_foo: bar
diff --git a/dovecot/files/munin_plugin b/dovecot/files/munin_plugin
new file mode 100755
index 00000000..e5a6d1d1
--- /dev/null
+++ b/dovecot/files/munin_plugin
@@ -0,0 +1,126 @@
+#! /bin/bash
+#
+# Munin Plugin
+# to count logins to your dovecot mailserver
+#
+# Created by Dominik Schulz
+# http://developer.gauner.org/munin/
+# Contributions by:
+# - Stephane Enten
+# - Steve Schnepp
+#
+# Parameters understood:
+#
+# config (required)
+# autoconf (optional - used by munin-config)
+#
+# Config variables:
+#
+# logfile - Where to find the syslog file
+#
+# Add the following line to a file in /etc/munin/plugin-conf.d:
+# env.logfile /var/log/your/logfile.log
+#
+# Magic markers (optional - used by munin-config and installation scripts):
+#
+#%# family=auto
+#%# capabilities=autoconf
+
+######################
+# Configuration
+######################
+EXPR_BIN=/usr/bin/expr
+LOGFILE=${logfile:-/var/log/mail.log}
+######################
+
+if [ "$1" = "autoconf" ]; then
+ echo yes
+ exit 0
+fi
+
+if [ "$1" = "config" ]; then
+ echo 'graph_title Dovecot Logins'
+ echo 'graph_category Mail'
+ echo 'graph_args --base 1000 -l 0'
+ echo 'graph_vlabel Login Counters'
+
+ for t in Total TLS SSL IMAP POP3
+ do
+ field=$(echo $t | tr '[:upper:]' '[:lower:]')
+ echo "login_$field.label $t Logins"
+ echo "login_$field.type DERIVE"
+ echo "login_$field.min 0"
+ done
+
+ echo 'connected.label Connected Users'
+
+ exit 0
+fi
+
+######################
+# Total Logins
+######################
+echo -en "login_total.value "
+VALUE=$(egrep -c '[dovecot]?.*Login' $LOGFILE)
+if [ ! -z "$VALUE" ]; then
+ echo "$VALUE"
+else
+ echo "0"
+fi
+echo -n
+######################
+# Connected Users
+######################
+DISCONNECTS=$(egrep -c '[dovecot]?.*Disconnected' $LOGFILE)
+CONNECTS=$(egrep -c '[dovecot]?.*Login' $LOGFILE)
+VALUE=$($EXPR_BIN $CONNECTS - $DISCONNECTS)
+if [ -z "$VALUE" ] || [ "$VALUE" -lt 0 ]; then
+ VALUE=0
+fi
+echo -en "connected.value "
+echo $VALUE
+echo -n
+######################
+# TLS Logins
+######################
+echo -en "login_tls.value "
+VALUE=$(egrep -c '[dovecot]?.*Login.*TLS' $LOGFILE)
+if [ ! -z "$VALUE" ]; then
+ echo "$VALUE"
+else
+ echo "0"
+fi
+echo -n
+######################
+# SSL Logins
+######################
+echo -en "login_ssl.value "
+VALUE=$(egrep -c '[dovecot]?.*Login.*SSL' $LOGFILE)
+if [ ! -z "$VALUE" ]; then
+ echo "$VALUE"
+else
+ echo "0"
+fi
+echo -n
+######################
+# IMAP Logins
+######################
+echo -en "login_imap.value "
+VALUE=$(egrep -c '[dovecot]?.*imap.*Login' $LOGFILE)
+if [ ! -z "$VALUE" ]; then
+ echo "$VALUE"
+else
+ echo "0"
+fi
+echo -n
+######################
+# POP3 Logins
+######################
+echo -en "login_pop3.value "
+VALUE=$(egrep -c '[dovecot]?.*pop3.*Login' $LOGFILE)
+if [ ! -z "$VALUE" ]; then
+ echo "$VALUE"
+else
+ echo "0"
+fi
+echo -n
diff --git a/dovecot/handlers/main.yml b/dovecot/handlers/main.yml
new file mode 100644
index 00000000..8d1b78d8
--- /dev/null
+++ b/dovecot/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+- name: restart dovecot
+ service:
+ name: dovecot
+ state: restarted
+
+- name: reload dovecot
+ service:
+ name: dovecot
+ state: reloaded
diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml
new file mode 100644
index 00000000..1a835160
--- /dev/null
+++ b/dovecot/tasks/main.yml
@@ -0,0 +1,68 @@
+- name: ensure packages are installed
+ apt:
+ name: '{{ item }}'
+ state: present
+ with_items:
+ - dovecot-ldap
+ - dovecot-imapd
+ - dovecot-pop3d
+ - dovecot-sieve
+ - dovecot-managesieved
+ tags:
+ - dovecot
+
+- name: disable pam auth
+ replace:
+ dest: /etc/dovecot/conf.d/10-auth.conf
+ regexp: "[^#]!include auth-system.conf.ext"
+ replace: "#!include auth-system.conf.ext"
+ tags:
+ - dovecot
+
+- name: update ldap auth
+ lineinfile:
+ dest: /etc/dovecot/dovecot-ldap.conf.ext
+ line: "{{ item.key }} = {{ item.value }}"
+ regexp: "^#*{{ item.key }}"
+ state: present
+ with_items:
+ - { key: 'hosts', value: '127.0.0.1' }
+ - { key: 'auth_bind', value: 'yes' }
+ - { key: 'ldap_version', value: 3 }
+ - { key: 'base', value: "{{ ldap_suffix }}" }
+ - { key: 'user_attrs', value: 'homeDirectory=home' }
+ - { key: 'user_filter', value: '(&(isActive=TRUE)(uid=%u))' }
+ - { key: 'pass_attrs', value: 'uid=user,userPassword=password' }
+ when: ldap_suffix is defined
+ notify: reload dovecot
+ tags:
+ - dovecot
+
+- name: create vmail group
+ group:
+ name: vmail
+ gid: 5000
+ tags:
+ - dovecot
+
+- name: create vmail user
+ user:
+ name: vmail
+ group: vmail
+ uid: 5000
+ shell: /bin/false
+ tags:
+ - dovecot
+
+- name: deploy evolix config
+ template:
+ src: z-evolinux-defaults.conf.j2
+ dest: /etc/dovecot/conf.d/z-evolinux-defaults.conf
+ mode: "0644"
+ notify: reload dovecot
+ tags:
+ - dovecot
+
+- include: munin.yml
+ tags:
+ - dovecot
diff --git a/dovecot/tasks/munin.yml b/dovecot/tasks/munin.yml
new file mode 100644
index 00000000..7f5003f0
--- /dev/null
+++ b/dovecot/tasks/munin.yml
@@ -0,0 +1,20 @@
+---
+
+- name: is Munin present ?
+ stat:
+ path: /etc/munin/plugin-conf.d/munin-node
+ check_mode: no
+ register: munin_node_plugins_config
+
+- block:
+ - name: Install munin plugin
+ copy:
+ src: munin_plugin
+ dest: /etc/munin/plugins/dovecot
+ mode: "0755"
+
+# TODO : add in /etc/munin/plugin-conf.d/munin-node
+# [dovecot]
+# group adm
+
+ when: munin_node_plugins_config.stat.exists
diff --git a/dovecot/templates/z-evolinux-defaults.conf.j2 b/dovecot/templates/z-evolinux-defaults.conf.j2
new file mode 100644
index 00000000..b6d8d5e5
--- /dev/null
+++ b/dovecot/templates/z-evolinux-defaults.conf.j2
@@ -0,0 +1,36 @@
+# {{ ansible_managed }}
+
+# Autorise les mécanismes PLAIN/LOGIN même sans SSL/TLS
+disable_plaintext_auth = no
+auth_mechanisms = plain login
+
+# Authentification LDAP + intégration avec Postfix pour l'auth SMTP
+!include auth-ldap.conf.ext
+service auth {
+ unix_listener auth-userdb {
+ mode = 0600
+ user = vmail
+ group = vmail
+ }
+ unix_listener /var/spool/postfix/private/auth-client {
+ mode = 0666
+ user = postfix
+ group = postfix
+ }
+}
+
+# Stockage des emails dans /home/mail avec UID/GID 5000/5000
+mail_location = maildir:/home/vmail/%d/%n
+mail_uid = 5000
+mail_gid = 5000
+
+# Activation Sieve
+protocol lda {
+ mail_plugins = sieve
+}
+
+# Optimisations
+service login {
+ process_limit = 256
+}
+mail_max_userip_connections = 42
diff --git a/drbd/README.md b/drbd/README.md
index 86ae3aa6..f08d30f4 100644
--- a/drbd/README.md
+++ b/drbd/README.md
@@ -5,23 +5,3 @@ Install tools to setup DRBD replication accross servers.
## Tasks
Everything is in the `tasks/main.yml` file.
-
-## Available variables
-
-The variable `admin_users` must be a "dict" of one or more users :
-
-```
-admin_users:
- foo:
- name: foo
- uid: 1001
- fullname: 'Mr Foo'
- password_hash: 'sdfgsdfgsdfgsdfg'
- ssh_key: 'ssh-rsa AZERTYXYZ'
- bar:
- name: bar
- uid: 1002
- fullname: 'Mr Bar'
- password_hash: 'gsdfgsdfgsdfgsdf'
- ssh_key: 'ssh-rsa QWERTYUIOP'
-```
diff --git a/drbd/tasks/nagios.yml b/drbd/tasks/nagios.yml
index 5ce44d7c..91b06c57 100644
--- a/drbd/tasks/nagios.yml
+++ b/drbd/tasks/nagios.yml
@@ -8,23 +8,8 @@
tags:
- drbd
-- name: Check if /usr is a partition
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- changed_when: False
- failed_when: False
- register: usr_partition
- check_mode: no
- tags:
- - drbd
-
-- name: Mount /usr in rw
- command: mount -o remount,rw /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0 and nagios_plugins_dir.stat.exists
+- include_role:
+ name: remount-usr
tags:
- drbd
diff --git a/elasticsearch/defaults/main.yml b/elasticsearch/defaults/main.yml
index 77e36070..5fce4ef6 100644
--- a/elasticsearch/defaults/main.yml
+++ b/elasticsearch/defaults/main.yml
@@ -8,6 +8,7 @@ elasticsearch_custom_tmpdir: Null
elasticsearch_default_tmpdir: /var/lib/elasticsearch/tmp
elasticsearch_jvm_xms: 2g
elasticsearch_jvm_xmx: 2g
+elasticsearch_log_rotate_days: 365
elasticsearch_curator: False
diff --git a/elasticsearch/meta/main.yml b/elasticsearch/meta/main.yml
index a2f662c3..54156392 100644
--- a/elasticsearch/meta/main.yml
+++ b/elasticsearch/meta/main.yml
@@ -13,6 +13,7 @@ galaxy_info:
- name: Debian
versions:
- jessie
+ - stretch
galaxy_tags: []
# List tags for your role here, one per line. A tag is
@@ -23,4 +24,5 @@ galaxy_info:
# NOTE: A tag is limited to a single word comprised of
# alphanumeric characters. Maximum 20 tags per role.
-dependencies: []
+dependencies:
+ - java8
diff --git a/elasticsearch/tasks/curator.yml b/elasticsearch/tasks/curator.yml
index c1a10658..e2546c7a 100644
--- a/elasticsearch/tasks/curator.yml
+++ b/elasticsearch/tasks/curator.yml
@@ -3,6 +3,7 @@
- name: Curator sources list is available
apt_repository:
repo: "deb http://packages.elastic.co/curator/4/debian stable main"
+ filename: elastic
update_cache: yes
state: present
tags:
diff --git a/elasticsearch/tasks/datadir.yml b/elasticsearch/tasks/datadir.yml
index a0b87ad5..38d2218a 100644
--- a/elasticsearch/tasks/datadir.yml
+++ b/elasticsearch/tasks/datadir.yml
@@ -7,16 +7,16 @@
register: elasticsearch_custom_datadir_test
check_mode: no
-
- name: "read the real datadir"
command: readlink -f /var/lib/elasticsearch
changed_when: false
register: elasticsearch_current_real_datadir_test
check_mode: no
-
tags:
- elasticsearch
- when: elasticsearch_custom_datadir
+ when:
+ - elasticsearch_custom_datadir != ''
+ - elasticsearch_custom_datadir != None
- block:
- name: elasticsearch is stopped
@@ -40,5 +40,9 @@
name: elasticsearch
state: started
tags:
- - elasticsearch
- when: elasticsearch_custom_datadir and elasticsearch_custom_datadir != elasticsearch_current_real_datadir_test.stdout and not elasticsearch_custom_datadir_test.stat.exists
+ - elasticsearch
+ when:
+ - elasticsearch_custom_datadir != ''
+ - elasticsearch_custom_datadir != None
+ - elasticsearch_custom_datadir != elasticsearch_current_real_datadir_test.stdout
+ - not elasticsearch_custom_datadir_test.stat.exists
diff --git a/elasticsearch/tasks/logs.yml b/elasticsearch/tasks/logs.yml
new file mode 100644
index 00000000..ee3d7680
--- /dev/null
+++ b/elasticsearch/tasks/logs.yml
@@ -0,0 +1,9 @@
+---
+
+- name: "log rotation script"
+ template:
+ src: rotate_elasticsearch_logs.j2
+ dest: /etc/cron.daily/rotate_elasticsearch_logs
+ owner: root
+ group: root
+ mode: "0750"
diff --git a/elasticsearch/tasks/main.yml b/elasticsearch/tasks/main.yml
index 00be05ed..bc43bebd 100644
--- a/elasticsearch/tasks/main.yml
+++ b/elasticsearch/tasks/main.yml
@@ -10,6 +10,8 @@
- include: tmpdir.yml
+- include: logs.yml
+
- include: plugin_head.yml
when: elasticsearch_plugin_head
diff --git a/elasticsearch/tasks/packages.yml b/elasticsearch/tasks/packages.yml
index 05d5bf46..ff395cb5 100644
--- a/elasticsearch/tasks/packages.yml
+++ b/elasticsearch/tasks/packages.yml
@@ -1,12 +1,5 @@
---
-- name: install java8
- include_role:
- name: java8
- tags:
- - elasticsearch
- - packages
-
- name: APT https transport is enabled
apt:
name: apt-transport-https
@@ -27,7 +20,7 @@
- name: Elastic sources list is available
apt_repository:
repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
- filename: elastic.list
+ filename: elastic
state: present
update_cache: yes
tags:
diff --git a/elasticsearch/tasks/plugin_head.yml b/elasticsearch/tasks/plugin_head.yml
index c309f185..29b2f1f7 100644
--- a/elasticsearch/tasks/plugin_head.yml
+++ b/elasticsearch/tasks/plugin_head.yml
@@ -11,7 +11,7 @@
- block:
- name: Head repository is checked-out
git:
- repo: "git://github.com/mobz/elasticsearch-head.git"
+ repo: "https://github.com/mobz/elasticsearch-head.git"
dest: "{{ elasticsearch_plugin_head_clone_dir }}"
clone: yes
tags:
@@ -53,3 +53,21 @@
- restart elasticsearch
tags:
- elasticsearch
+
+- name: Install systemd unit
+ template:
+ src: elasticsearch-head.service.j2
+ dest: /etc/systemd/system/elasticsearch-head.service
+ tags:
+ - elasticsearch
+ - systemd
+
+- name: Enable systemd unit
+ systemd:
+ name: elasticsearch-head
+ daemon_reload: yes
+ enabled: yes
+ state: started
+ tags:
+ - elasticsearch
+ - systemd
diff --git a/elasticsearch/tasks/tmpdir.yml b/elasticsearch/tasks/tmpdir.yml
index 380fb190..b6bd445a 100644
--- a/elasticsearch/tasks/tmpdir.yml
+++ b/elasticsearch/tasks/tmpdir.yml
@@ -28,4 +28,4 @@
- restart elasticsearch
tags:
- elasticsearch
- when: elasticsearch_custom_tmpdir or fstab_tmp_noexec | success
+ when: (elasticsearch_custom_tmpdir != '' and elasticsearch_custom_tmpdir != None) or fstab_tmp_noexec | success
diff --git a/elasticsearch/templates/elasticsearch-head.service.j2 b/elasticsearch/templates/elasticsearch-head.service.j2
new file mode 100644
index 00000000..4e409ed0
--- /dev/null
+++ b/elasticsearch/templates/elasticsearch-head.service.j2
@@ -0,0 +1,14 @@
+[Service]
+Type=simple
+ExecStart=/usr/bin/npm run start
+User={{ elasticsearch_plugin_head_owner }}
+Group={{ elasticsearch_plugin_head_group }}
+StandardOutput=syslog
+StandardError=syslog
+SyslogIdentifier=elasticsearch-head
+Restart=always
+WorkingDirectory={{ elasticsearch_plugin_head_clone_dir }}
+Environment=NODE_ENV=production
+
+[Install]
+WantedBy=multi-user.target
diff --git a/elasticsearch/templates/rotate_elasticsearch_logs.j2 b/elasticsearch/templates/rotate_elasticsearch_logs.j2
new file mode 100644
index 00000000..14d2d31d
--- /dev/null
+++ b/elasticsearch/templates/rotate_elasticsearch_logs.j2
@@ -0,0 +1,9 @@
+#!/bin/sh
+# {{ ansible_managed }}
+
+LOG_DIR=/var/log/elasticsearch
+USER=elasticsearch
+MAX_AGE={{ elasticsearch_log_rotate_days | mandatory }}
+
+find ${LOG_DIR} -type f -user ${USER} -name "*.log.????-??-??" -exec gzip --best {} \;
+find ${LOG_DIR} -type f -user ${USER} -name "*.log.????-??-??.gz" -mtime +${MAX_AGE} -delete
diff --git a/evoacme/defaults/main.yml b/evoacme/defaults/main.yml
index 4194b5aa..3d0842bc 100644
--- a/evoacme/defaults/main.yml
+++ b/evoacme/defaults/main.yml
@@ -5,6 +5,7 @@ evoacme_dhparam_size: 2048
evoacme_acme_dir: /var/lib/letsencrypt
evoacme_csr_dir: /etc/ssl/requests
evoacme_crt_dir: /etc/letsencrypt
+evoacme_hooks_dir: "{{ evoacme_crt_dir }}/hooks"
evoacme_log_dir: /var/log/evoacme
evoacme_ssl_minday: 30
evoacme_ssl_ct: 'FR'
diff --git a/evoacme/files/certbot.cron b/evoacme/files/certbot.cron
index a7c4eef2..a16bcf69 100755
--- a/evoacme/files/certbot.cron
+++ b/evoacme/files/certbot.cron
@@ -7,8 +7,8 @@
#
[ -f /etc/default/evoacme ] && . /etc/default/evoacme
-[ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt'
+CRT_DIR="${CRT_DIR:-'/etc/letsencrypt'}"
-find "${CRT_DIR}" -maxdepth 1 -mindepth 1 -type d ! -path "*accounts" -exec basename {} \; | while read vhost; do
- evoacme "$vhost"
-done
+export QUIET=1
+
+find "${CRT_DIR}" -maxdepth 1 -mindepth 1 -type d ! -path "*accounts" ! -path "*hooks" -printf "%f\n" | xargs -n1 evoacme
diff --git a/evoacme/files/evoacme.sh b/evoacme/files/evoacme.sh
index ffbf22ac..e35c97b9 100755
--- a/evoacme/files/evoacme.sh
+++ b/evoacme/files/evoacme.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
# evoacme is a shell script to manage Let's Encrypt certificate with
# certbot tool but with a dedicated user (no-root) and from a csr
@@ -7,78 +7,287 @@
# Licence: AGPLv3
#
+set -e
+set -u
+
usage() {
- echo "Usage: $0 NAME"
- echo ""
- echo "NAME must be correspond to :"
- echo "- a CSR in ${CSR_DIR}/NAME.csr"
- echo "- a KEY in ${SSL_KEY_DIR}/NAME.key"
- echo ""
+ cat </dev/null && service apache2 reload
+log() {
+ if [ "${QUIET}" != "1" ]; then
+ echo "${PROGNAME}: $1"
+ fi
+}
+debug() {
+ if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
+ >&2 echo "${PROGNAME}: $1"
+ fi
+}
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ [ "$1" = "invalid argument(s)" ] && >&2 usage
+ exit 1
}
-mkconf_nginx() {
- [ -f "/etc/nginx/ssl/${vhost}.conf" ] && sed -i "s~^ssl_certificate[^_].*$~ssl_certificate $CRT_DIR/${vhost}/live/fullchain.pem;~" "/etc/nginx/ssl/${vhost}.conf"
- nginx -t 2>/dev/null && service nginx reload
-}
+sed_cert_path_for_apache() {
+ local vhost=$1
+ local vhost_full_path="/etc/apache2/ssl/${vhost}.conf"
+ local cert_path=$2
-mkconf_haproxy() {
- mkdir -p /etc/ssl/haproxy -m 700
- cat "$CRT_DIR/${vhost}/live/fullchain.pem" "$SSL_KEY_DIR/${vhost}.key" > "/etc/ssl/haproxy/${vhost}.pem"
- [ -f "$DH_DIR/${vhost}.pem" ] && cat "$DH_DIR/${vhost}.pem" >> "/etc/ssl/haproxy/${vhost}.pem"
- haproxy -c -f /etc/haproxy/haproxy.cfg >/dev/null && service haproxy reload
+ [ ! -r "${vhost_full_path}" ] && return 0
+
+ local search="^SSLCertificateFile.*$"
+ local replace="SSLCertificateFile ${cert_path}"
+
+ if ! $(grep -qE "${search}" "${vhost_full_path}"); then
+ [ -w "${vhost_full_path}" ] || error "File ${vhost_full_path} is not writable"
+
+ sed -i "s~^${search}~${replace}~" "${vhost_full_path}"
+ debug "Config in ${vhost_full_path} has been updated"
+ $(command -v apache2ctl) -t
+ fi
+}
+sed_cert_path_for_nginx() {
+ local vhost=$1
+ local vhost_full_path="/etc/nginx/ssl/${vhost}.conf"
+ local cert_path=$2
+
+ [ ! -r "${vhost_full_path}" ] && return 0
+
+ local search="^ssl_certificate[^_].*$"
+ local replace="ssl_certificate ${cert_path};"
+
+ if ! $(grep -qE "${search}" "${vhost_full_path}"); then
+ [ -w "${vhost_full_path}" ] || error "File ${vhost_full_path} is not writable"
+
+ sed -i "s~${search}~${replace}~" "${vhost_full_path}"
+ debug "Config in ${vhost_full_path} has been updated"
+ $(command -v nginx) -t
+ fi
+}
+x509_verify() {
+ local file="$1"
+ [ -r "$file" ] || error "File ${file} not found"
+ "${OPENSSL_BIN}" x509 -noout -modulus -in "$file" >/dev/null
+}
+x509_enddate() {
+ local file="$1"
+ [ -r "$file" ] || error "File ${file} not found"
+ "${OPENSSL_BIN}" x509 -noout -enddate -in "$file"
+}
+csr_verify() {
+ local file="$1"
+ [ -r "$file" ] || error "File ${file} not found"
+ "${OPENSSL_BIN}" req -noout -modulus -in "$file" >/dev/null
}
main() {
- [ -f /etc/default/evoacme ] && . /etc/default/evoacme
- [ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR='/etc/ssl/private'
- [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt'
- [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests'
- [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed'
- [ -z "${DH_DIR}" ] && DH_DIR='/etc/ssl/dhparam'
- [ -z "${LOG_DIR}" ] && LOG_DIR='/var/log/evoacme'
-
- [ "$#" -ne 1 ] && usage && exit 1
+ # check arguments
+ [ "$#" -eq 1 ] || error "invalid argument(s)"
- vhost=$(basename "$1" .conf)
+ [ "$1" = "-h" ] || [ "$1" = "--help" ] && usage && exit 0
- # Check master status for evoadmin-cluster
- if [ -f "/home/${vhost}/state" ]; then
- grep -q "STATE=master" "/home/${vhost}/state" || exit 0
- fi
+ mkdir -p "${ACME_DIR}"
+ chown acme: "${ACME_DIR}"
+ [ -w "${ACME_DIR}" ] || error "Directory ${ACME_DIR} is not writable"
- SSL_EMAIL=$(grep emailAddress "${CRT_DIR}/openssl.cnf"|cut -d'=' -f2|xargs)
- if [ -n "$SSL_EMAIL" ]; then
- emailopt="-m $SSL_EMAIL"
- else
- emailopt="--register-unsafely-without-email"
- fi
- DATE=$(date "+%Y%m%d")
-
- if [ -h "$CRT_DIR/${vhost}/live" ]; then
- crt_end_date=$(openssl x509 -noout -enddate -in "$CRT_DIR/${vhost}/live/cert.crt"|sed -e "s/.*=//")
- date_crt=$(date -ud "$crt_end_date" +"%s")
- date_today=$(date +'%s')
- date_diff=$(((date_crt - date_today) / (60*60*24)))
- [ "$date_diff" -ge "$SSL_MINDAY" ] && exit 0
- fi
- rm -rf "$CRT_DIR/${vhost}/${DATE}"
- mkdir -pm 755 "$CRT_DIR/${vhost}/${DATE}"
- chown -R acme: "$CRT_DIR/${vhost}"
- sudo -u acme certbot certonly --quiet --webroot --csr "$CSR_DIR/${vhost}.csr" --webroot-path "$ACME_DIR" -n --agree-tos --cert-path="$CRT_DIR/${vhost}/${DATE}/cert.crt" --fullchain-path="$CRT_DIR/${vhost}/${DATE}/fullchain.pem" --chain-path="$CRT_DIR/${vhost}/${DATE}/chain.pem" "$emailopt" --logs-dir "$LOG_DIR" 2>&1 | grep -v "certbot.crypto_util"
- if [ -f "$CRT_DIR/${vhost}/${DATE}/fullchain.pem" ]; then
- rm -f "$CRT_DIR/${vhost}/live"
- ln -s "$CRT_DIR/${vhost}/${DATE}" "$CRT_DIR/${vhost}/live"
- which apache2ctl >/dev/null && mkconf_apache
- which nginx >/dev/null && mkconf_nginx
- which haproxy >/dev/null && mkconf_haproxy
- else
- rmdir "$CRT_DIR/${vhost}/${DATE}"
- fi
+ [ -d "${CSR_DIR}" ] || error "Directory ${CSR_DIR} is not found"
+
+ mkdir -p "${CRT_DIR}"
+ chown acme: "${CRT_DIR}"
+ [ -w "${CRT_DIR}" ] || error "Directory ${CRT_DIR} is not writable"
+
+ mkdir -p "${LOG_DIR}"
+ chown acme: "${LOG_DIR}"
+ [ -w "${LOG_DIR}" ] || error "Directory ${LOG_DIR} is not writable"
+
+ mkdir -p "${HOOKS_DIR}"
+ chown acme: "${HOOKS_DIR}"
+ [ -d "${HOOKS_DIR}" ] || error "Directory ${HOOKS_DIR} is not found"
+
+ readonly VHOST=$(basename "$1" .conf)
+
+ # check for important programs
+ readonly OPENSSL_BIN=$(command -v openssl) || error "openssl command not installed"
+ readonly CERTBOT_BIN=$(command -v certbot) || error "certbot command not installed"
+
+ # double check for directories
+ [ -d "${ACME_DIR}" ] || error "${ACME_DIR} is not a directory"
+ [ -d "${CSR_DIR}" ] || error "${CSR_DIR} is not a directory"
+ [ -d "${LOG_DIR}" ] || error "${LOG_DIR} is not a directory"
+
+ #### CSR VALIDATION
+
+ # verify .csr file
+ readonly CSR_FILE="${CSR_DIR}/${VHOST}.csr"
+ debug "Using CSR file: ${CSR_FILE}"
+ [ -f "${CSR_FILE}" ] || error "${CSR_FILE} absent"
+ [ -r "${CSR_FILE}" ] || error "${CSR_FILE} is not readable"
+
+ csr_verify "${CSR_FILE}" || error "${CSR_FILE} is invalid"
+
+ # Hook for evoadmin-web in cluster mode : check master status
+ local evoadmin_state_file="/home/${VHOST}/state"
+ [ -r "${evoadmin_state_file}" ] \
+ && grep -q "STATE=slave" "${evoadmin_state_file}" \
+ && debug "We are slave of this evoadmin cluster. Quit!" \
+ && exit 0
+
+ #### INIT OR RENEW?
+
+ readonly LIVE_DIR="${CRT_DIR}/${VHOST}/live"
+ readonly LIVE_CERT="${LIVE_DIR}/cert.crt"
+ readonly LIVE_FULLCHAIN="${LIVE_DIR}/fullchain.pem"
+ readonly LIVE_CHAIN="${LIVE_DIR}/chain.pem"
+
+ # If live symlink already exists, it's not our first time...
+ if [ -h "${LIVE_DIR}" ]; then
+ # we have a live symlink
+ # let's see if there is a cert to renew
+ x509_verify "${LIVE_CERT}" || error "${LIVE_CERT} is invalid"
+
+ # Verify if our certificate will expire
+ crt_end_date=$(x509_enddate "${LIVE_CERT}" | cut -d= -f2)
+ date_renew=$(date -ud "${crt_end_date} - ${SSL_MINDAY} days" +"%s")
+ date_today=$(date +'%s')
+ if [ "${date_today}" -lt "${date_renew}" ]; then
+ debug "Cert ${LIVE_CERT} expires at ${crt_end_date} => more than ${SSL_MINDAY} days: kthxbye."
+ exit 0
+ fi
+ fi
+
+ #### CERTIFICATE CREATION WITH CERTBOT
+
+ local iteration=$(date "+%Y%m%d%H%M%S")
+ [ -n "${iteration}" ] || error "invalid iteration (${iteration})"
+
+ readonly NEW_DIR="${CRT_DIR}/${VHOST}/${iteration}"
+
+ [ -d "${NEW_DIR}" ] && error "${NEW_DIR} directory already exists, remove it manually."
+ mkdir -p "${NEW_DIR}"
+ chmod -R 0700 "${CRT_DIR}"
+ chown -R acme: "${CRT_DIR}"
+ debug "New cert will be created in ${NEW_DIR}"
+
+ readonly NEW_CERT="${NEW_DIR}/cert.crt"
+ readonly NEW_FULLCHAIN="${NEW_DIR}/fullchain.pem"
+ readonly NEW_CHAIN="${NEW_DIR}/chain.pem"
+
+ local CERTBOT_MODE=""
+ [ "${TEST}" = "1" ] && CERTBOT_MODE="${CERTBOT_MODE} --test-cert"
+ [ "${QUIET}" = "1" ] && CERTBOT_MODE="${CERTBOT_MODE} --quiet"
+ [ "${DRY_RUN}" = "1" ] && CERTBOT_MODE="${CERTBOT_MODE} --dry-run"
+
+ local CERTBOT_REGISTRATION="--agree-tos"
+ if [ -n "${SSL_EMAIL}" ]; then
+ debug "Registering at certbot with ${SSL_EMAIL} as email"
+ CERTBOT_REGISTRATION="${CERTBOT_REGISTRATION} -m ${SSL_EMAIL}"
+ else
+ debug "Registering at certbot without email"
+ CERTBOT_REGISTRATION="${CERTBOT_REGISTRATION} --register-unsafely-without-email"
+ fi
+
+ # Permissions checks for acme user
+ sudo -u acme test -r "${CSR_FILE}" || error "File ${CSR_FILE} is not readable by user 'acme'"
+ sudo -u acme test -w "${NEW_DIR}" || error "Directory ${NEW_DIR} is not writable by user 'acme'"
+
+ # create a certificate with certbot
+ sudo -u acme \
+ "${CERTBOT_BIN}" \
+ certonly \
+ ${CERTBOT_MODE} \
+ ${CERTBOT_REGISTRATION} \
+ --non-interactive \
+ --webroot \
+ --csr "${CSR_FILE}" \
+ --webroot-path "${ACME_DIR}" \
+ --cert-path "${NEW_CERT}" \
+ --fullchain-path "${NEW_FULLCHAIN}" \
+ --chain-path "${NEW_CHAIN}" \
+ --logs-dir "$LOG_DIR" \
+ 2>&1 \
+ | grep -v "certbot.crypto_util"
+
+ if [ "${DRY_RUN}" = "1" ]; then
+ debug "In dry-run mode, we stop here. Bye"
+ exit 0
+ fi
+
+ # verify if all is right
+ x509_verify "${NEW_CERT}" || error "${NEW_CERT} is invalid"
+ x509_verify "${NEW_FULLCHAIN}" || error "${NEW_FULLCHAIN} is invalid"
+ x509_verify "${NEW_CHAIN}" || error "${NEW_CHAIN} is invalid"
+
+ log "New certificate available at ${NEW_CERT}"
+
+ #### CERTIFICATE ACTIVATION
+
+ # link dance
+ if [ -h "${LIVE_DIR}" ]; then
+ rm "${LIVE_DIR}"
+ debug "Remove ${LIVE_DIR} link"
+ fi
+ ln -s "${NEW_DIR}" "${LIVE_DIR}"
+ debug "Link ${NEW_DIR} to ${LIVE_DIR}"
+ # verify final path
+ x509_verify "${LIVE_CERT}" || error "${LIVE_CERT} is invalid"
+
+ # update Apache
+ sed_cert_path_for_apache "${VHOST}" "${LIVE_FULLCHAIN}"
+ # update Nginx
+ sed_cert_path_for_nginx "${VHOST}" "${LIVE_FULLCHAIN}"
+
+ #### EXECUTE HOOKS
+ #
+ # executable scripts placed in ${HOOKS_DIR}
+ # are executed, unless their name ends with ".disabled"
+
+ export EVOACME_VHOST_NAME="${VHOST}"
+ export EVOACME_CERT="${LIVE_CERT}"
+ export EVOACME_CHAIN="${LIVE_CHAIN}"
+ export EVOACME_FULLCHAIN="${LIVE_FULLCHAIN}"
+
+ # search for files in hooks directory
+ for hook in $(find ${HOOKS_DIR} -type f); do
+ # keep only executables files, not containing a "."
+ if [ -x "${hook}" ] && (basename "${hook}" | grep -vqF "."); then
+ debug "Executing ${hook}"
+ ${hook}
+ fi
+ done
}
-main "$@"
+readonly PROGNAME=$(basename "$0")
+readonly PROGDIR=$(realpath -m $(dirname "$0"))
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+readonly QUIET=${QUIET:-"0"}
+readonly TEST=${TEST:-"0"}
+readonly DRY_RUN=${DRY_RUN:-"0"}
+
+# Read configuration file, if it exists
+[ -r /etc/default/evoacme ] && . /etc/default/evoacme
+
+# Default value for main variables
+readonly SSL_KEY_DIR=${SSL_KEY_DIR:-"/etc/ssl/private"}
+readonly ACME_DIR=${ACME_DIR:-"/var/lib/letsencrypt"}
+readonly CSR_DIR=${CSR_DIR:-"/etc/ssl/requests"}
+readonly CRT_DIR=${CRT_DIR:-"/etc/letsencrypt"}
+readonly LOG_DIR=${LOG_DIR:-"/var/log/evoacme"}
+readonly HOOKS_DIR=${HOOKS_DIR:-"${CRT_DIR}/hooks"}
+readonly SSL_MINDAY=${SSL_MINDAY:-"30"}
+readonly SSL_EMAIL=${SSL_EMAIL:-""}
+
+main ${ARGS}
diff --git a/evoacme/files/hooks/reload_apache b/evoacme/files/hooks/reload_apache
new file mode 100755
index 00000000..2cceb972
--- /dev/null
+++ b/evoacme/files/hooks/reload_apache
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+readonly PROGNAME=$(basename "$0")
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+readonly QUIET=${QUIET:-"0"}
+
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ exit 1
+}
+debug() {
+ if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
+ >&2 echo "${PROGNAME}: $1"
+ fi
+}
+
+if [ -n "$(pidof apache2)" ]; then
+ if $($(command -v apache2ctl) -t 2> /dev/null); then
+ debug "Apache detected... reloading"
+ service apache2 reload
+ else
+ error " Apache config is broken, you must fix it !"
+ fi
+else
+ debug "Apache is not running. Skip."
+fi
diff --git a/evoacme/files/hooks/reload_dovecot b/evoacme/files/hooks/reload_dovecot
new file mode 100755
index 00000000..31da4fb4
--- /dev/null
+++ b/evoacme/files/hooks/reload_dovecot
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+readonly PROGNAME=$(basename "$0")
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+readonly QUIET=${QUIET:-"0"}
+
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ exit 1
+}
+debug() {
+ if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
+ >&2 echo "${PROGNAME}: $1"
+ fi
+}
+
+if [ -n "$(pidof dovecot)" ]; then
+ if $($(command -v doveconf) > /dev/null); then
+ if $($(command -v doveconf)|grep -E "^ssl_cert[^_]"|grep -q "letsencrypt"); then
+ debug "Dovecot detected... reloading"
+ service dovecot reload
+ else
+ debug "Dovecot doesn't use Let's Encrypt certificate. Skip."
+ fi
+ else
+ error "Dovecot config is broken, you must fix it !"
+ fi
+else
+ debug "Dovecot is not running. Skip."
+fi
diff --git a/evoacme/files/hooks/reload_nginx b/evoacme/files/hooks/reload_nginx
new file mode 100755
index 00000000..35db3787
--- /dev/null
+++ b/evoacme/files/hooks/reload_nginx
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+readonly PROGNAME=$(basename "$0")
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+readonly QUIET=${QUIET:-"0"}
+
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ exit 1
+}
+debug() {
+ if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
+ >&2 echo "${PROGNAME}: $1"
+ fi
+}
+
+if [ -n "$(pidof nginx)" ]; then
+ if $($(command -v nginx) -t 2> /dev/null); then
+ debug "Nginx detected... reloading"
+ service nginx reload
+ else
+ error "Nginx config is broken, you must fix it !"
+ fi
+else
+ debug "Nginx is not running. Skip."
+fi
diff --git a/evoacme/files/hooks/reload_postfix b/evoacme/files/hooks/reload_postfix
new file mode 100755
index 00000000..50ee20ce
--- /dev/null
+++ b/evoacme/files/hooks/reload_postfix
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+readonly PROGNAME=$(basename "$0")
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+readonly QUIET=${QUIET:-"0"}
+
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ exit 1
+}
+debug() {
+ if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
+ >&2 echo "${PROGNAME}: $1"
+ fi
+}
+
+if [ -n "$(pidof master)" ]; then
+ if $($(command -v postconf) > /dev/null); then
+ if $($(command -v postconf)|grep -E "^smtpd_tls_cert_file"|grep -q "letsencrypt"); then
+ debug "Postfix detected... reloading"
+ service postfix reload
+ else
+ debug "Postfix doesn't use Let's Encrypt certificate. Skip."
+ fi
+ else
+ error "Postfix config is broken, you must fix it !"
+ fi
+else
+ debug "Postfix is not running. Skip."
+fi
diff --git a/evoacme/files/make-csr.sh b/evoacme/files/make-csr.sh
index 844847ab..10c0f8e9 100755
--- a/evoacme/files/make-csr.sh
+++ b/evoacme/files/make-csr.sh
@@ -1,151 +1,248 @@
-#!/bin/sh
+#!/bin/bash
#
-# make-csr is a shell script designed to automatically generate a
+# make-csr is a shell script designed to automatically generate a
# certificate signing request (CSR) from an Apache or a Nginx vhost
#
# Author: Victor Laborie
# Licence: AGPLv3
#
-get_domains() {
- echo "$vhostfile"|grep -q nginx
- if [ "$?" -eq 0 ]; then
- domains=$(grep -oE "^( )*[^#]+" "$vhostfile" |grep -oE "[^\$]server_name.*;$"|sed 's/server_name//'|tr -d ';'|sed 's/\s\{1,\}//'|sed 's/\s\{1,\}/\n/g'|sort|uniq)
- fi
-
- echo "$vhostfile" |grep -q apache2
- if [ "$?" -eq 0 ]; then
- domains=$(grep -oE "^( )*[^#]+" "$vhostfile" |grep -oE "(ServerName|ServerAlias).*"|sed 's/ServerName//'|sed 's/ServerAlias//'|sed 's/\s\{1,\}//'|sort|uniq)
- fi
- valid_domains=""
- nb=0
-
- echo "Valid(s) domain(s) in $vhost :"
- for domain in $domains; do
- real_ip=$(dig +short "$domain"|grep -oE "([0-9]+\.){3}[0-9]+")
- for ip in $(echo "$SRV_IP"|xargs -n1); do
- if [ "${ip}" = "${real_ip}" ]; then
- valid_domains="$valid_domains $domain"
- nb=$(( nb + 1 ))
- echo "* $domain -> $real_ip"
- fi
- done
- done
-
- if [ "$nb" -eq 0 ]; then
- nb=$(echo "$domains"|wc -l)
- echo "* No valid domain found"
- echo "All following(s) domain(s) will be used for CSR creation :"
- for domain in $domains; do
- echo "* $domain"
- done
- else
- domains="$valid_domains"
- fi
- domains=$(echo "$domains"|xargs -n1)
+set -u
+
+usage() {
+ cat <&2 echo "${PROGNAME}: $1"
+ fi
+}
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ exit 1
+}
+
+default_key_size() {
+ grep default_bits "${SSL_CONFIG_FILE}" | cut -d'=' -f2 | xargs
+}
+
+sed_selfsigned_cert_path_for_apache() {
+ local apache_ssl_vhost_path="$1"
+
+ mkdir -p $(dirname "${apache_ssl_vhost_path}")
+ if [ ! -f "${apache_ssl_vhost_path}" ]; then
+ cat > "${apache_ssl_vhost_path}" < "${nginx_ssl_vhost_path}" < /dev/null
+
+ [ -r "${crt}" ] || error "Something went wrong, ${crt} has not been generated"
+}
+openssl_key(){
+ local key="$1"
+ local key_dir=$(dirname "${key}")
+ local size="$2"
+
+ [ -w "${key_dir}" ] || error "Directory ${key_dir} is not writable"
+
+ "${OPENSSL_BIN}" genrsa -out "${key}" "${size}" 2> /dev/null
+
+ [ -r "${key}" ] || error "Something went wrong, ${key} has not been generated"
+}
+openssl_csr() {
+ local csr="$1"
+ local csr_dir=$(dirname "${csr}")
+ local key="$2"
+ local cfg="$3"
+
+ [ -w "${csr_dir}" ] || error "Directory ${csr_dir} is not writable"
+
+ if $(grep -q "DNS:" "${cfg}"); then
+ # CSR with SAN
+ "${OPENSSL_BIN}" req -new -sha256 -key "${key}" -reqexts SAN -config "${cfg}" -out "${csr}"
+ else
+ # Single domain CSR
+ "${OPENSSL_BIN}" req -new -sha256 -key "${key}" -config "${cfg}" -out "${csr}"
+ fi
+
+ [ -r "${csr}" ] || error "Something went wrong, ${csr} has not been generated"
}
make_key() {
- openssl genrsa -out "$SSL_KEY_DIR/${vhost}.key" "$SSL_KEY_SIZE" 2>/dev/null
- chown root: "$SSL_KEY_DIR/${vhost}.key"
- chmod 600 "$SSL_KEY_DIR/${vhost}.key"
+ local key="$1"
+ local size="$2"
+
+ openssl_key "${key}" "${size}"
+ debug "Private key stored at ${key}"
+
+ chown root: "${key}"
+ chmod 600 "${key}"
}
make_csr() {
- domains="$1"
- nb=$(echo "$domains"|wc -l)
- config_file="/tmp/make-csr-${vhost}.conf"
+ local domains=$@
+ local nb=$#
+ local config_file="/tmp/make-csr-${VHOST}.conf"
+ local san=""
- mkdir -p "$CSR_DIR" -m 0755
-
- if [ "$nb" -eq 1 ]; then
- cat /etc/letsencrypt/openssl.cnf - > "$config_file" < "${config_file}" < "$config_file" < "${config_file}" < "$CSR_DIR/${vhost}.csr"
- fi
-
- if [ -f "$CSR_DIR/${vhost}.csr" ]; then
- chmod 644 "$CSR_DIR/${vhost}.csr"
- mkdir -p "$SELF_SIGNED_DIR" -m 0755
- openssl x509 -req -sha256 -days 365 -in "$CSR_DIR/${vhost}.csr" -signkey "$SSL_KEY_DIR/${vhost}.key" -out "$SELF_SIGNED_DIR/${vhost}.pem"
- [ -f "$SELF_SIGNED_DIR/${vhost}.pem" ] && chmod 644 "$SELF_SIGNED_DIR/${vhost}.pem"
- fi
-}
+ fi
+ openssl_csr "${CSR_FILE}" "${SSL_KEY_FILE}" "${config_file}"
+ debug "CSR stored at ${CSR_FILE}"
-mkconf_apache() {
- mkdir -p /etc/apache2/ssl
- if [ ! -f "/etc/apache2/ssl/${vhost}.conf" ]; then
- cat > "/etc/apache2/ssl/${vhost}.conf" < "/etc/nginx/ssl/${vhost}.conf" <&2
- exit 1
- fi
- vhost=$(basename "$1" .conf)
- local_ip=$(ip a|grep brd|cut -d'/' -f1|grep -oE "([0-9]+\.){3}[0-9]+")
+ if [ -t 0 ]; then
+ # We have STDIN, so we should have at least 2 arguments
+ if [ "$#" -lt 2 ]; then
+ >&2 echo "invalid arguments"
+ >&2 usage
+ exit 1
+ fi
+ # read VHOST from first argument
+ VHOST="$1"
+ # remove the first argument
+ shift
+ # read domains from remaining arguments
+ DOMAINS=$@
+ else
+ # We don't have STDIN, so we should have only 1 argument
+ if [ "$#" != 1 ]; then
+ >&2 echo "invalid arguments"
+ >&2 usage
+ exit 1
+ fi
+ # read VHOST from first argument
+ VHOST="$1"
+ # read domains from input
+ DOMAINS=
+ while read -r line ; do
+ DOMAINS="${DOMAINS} ${line}"
+ done
+ # trim the string to remove leading/trailing spaces
+ DOMAINS=$(echo "${DOMAINS}" | xargs)
+ fi
+ readonly VHOST
+ readonly DOMAINS
- [ -f /etc/default/evoacme ] && . /etc/default/evoacme
- [ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR='/etc/ssl/private'
- [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests'
- [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt'
- [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed'
- SSL_KEY_SIZE=$(grep default_bits /etc/letsencrypt/openssl.cnf|cut -d'=' -f2|xargs)
- [ -n "${SRV_IP}" ] && SRV_IP="${SRV_IP} $local_ip" || SRV_IP="$local_ip"
-
- vhostfile=$(ls "/etc/nginx/sites-enabled/${vhost}" "/etc/nginx/sites-enabled/${vhost}.conf" "/etc/apache2/sites-enabled/${vhost}" "/etc/apache2/sites-enabled/${vhost}.conf" 2>/dev/null|head -n1)
-
- if [ ! -h "$vhostfile" ]; then
- echo "$vhost is not a valid virtualhost !" >&2
- exit 1
- fi
+ mkdir -p "${CSR_DIR}"
+ chown root: "${CSR_DIR}"
+ [ -w "${CSR_DIR}" ] || error "Directory ${CSR_DIR} is not writable"
- if [ -f "$SSL_KEY_DIR/${vhost}.key" ]; then
- echo "$vhost key already exist, overwrite it ? (y)"
- read REPLY
- [ "$REPLY" = "Y" ] || [ "$REPLY" = "y" ] || exit 0
- rm -f "/etc/apache2/ssl/${vhost}.conf /etc/nginx/ssl/${vhost}.conf"
- [ -h "${CRT_DIR}/${vhost}/live" ] && rm "${CRT_DIR}/${vhost}/live"
- fi
+ mkdir -p "${SELF_SIGNED_DIR}"
+ chown root: "${SELF_SIGNED_DIR}"
+ [ -w "${SELF_SIGNED_DIR}" ] || error "Directory ${SELF_SIGNED_DIR} is not writable"
- get_domains
- make_key
- make_csr "$domains"
- which apache2ctl >/dev/null && mkconf_apache
- which nginx >/dev/null && mkconf_nginx
+ mkdir -p "${SSL_KEY_DIR}"
+ chown root: "${SSL_KEY_DIR}"
+ [ -w "${SSL_KEY_DIR}" ] || error "Directory ${SSL_KEY_DIR} is not writable"
+
+ [ -r "${SSL_CONFIG_FILE}" ] || error "File ${SSL_CONFIG_FILE} is not readable"
+
+ # check for important programs
+ readonly OPENSSL_BIN=$(command -v openssl) || error "openssl command not installed"
+
+ readonly SELF_SIGNED_FILE="${SELF_SIGNED_DIR}/${VHOST}.pem"
+ readonly SSL_KEY_FILE="${SSL_KEY_DIR}/${VHOST}.key"
+ readonly CSR_FILE="${CSR_DIR}/${VHOST}.csr"
+
+ make_key "${SSL_KEY_FILE}" "${SSL_KEY_SIZE}"
+ make_csr ${DOMAINS}
+
+ command -v apache2ctl >/dev/null && sed_selfsigned_cert_path_for_apache "/etc/apache2/ssl/${VHOST}.conf"
+ command -v nginx >/dev/null && sed_selfsigned_cert_path_for_nginx "/etc/nginx/ssl/${VHOST}.conf"
}
-main "$@"
+readonly PROGNAME=$(basename "$0")
+readonly PROGDIR=$(realpath -m $(dirname "$0"))
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+
+# Read configuration file, if it exists
+[ -r /etc/default/evoacme ] && . /etc/default/evoacme
+
+# Default value for main variables
+readonly CSR_DIR=${CSR_DIR:-'/etc/ssl/requests'}
+readonly SSL_CONFIG_FILE=${SSL_CONFIG_FILE:-"/etc/letsencrypt/openssl.cnf"}
+readonly SELF_SIGNED_DIR=${SELF_SIGNED_DIR:-'/etc/ssl/self-signed'}
+readonly SSL_KEY_DIR=${SSL_KEY_DIR:-'/etc/ssl/private'}
+readonly SSL_KEY_SIZE=${SSL_KEY_SIZE:-$(default_key_size)}
+
+main ${ARGS}
diff --git a/evoacme/files/vhost-domains.sh b/evoacme/files/vhost-domains.sh
new file mode 100755
index 00000000..fd25ce86
--- /dev/null
+++ b/evoacme/files/vhost-domains.sh
@@ -0,0 +1,153 @@
+#!/bin/bash
+#
+# make-csr is a shell script designed to automatically generate a
+# certificate signing request (CSR) from an Apache or a Nginx vhost
+#
+# Author: Victor Laborie
+# Licence: AGPLv3
+#
+
+set -u
+
+usage() {
+ cat <&2 echo "${PROGNAME}: $1"
+ fi
+}
+error() {
+ >&2 echo "${PROGNAME}: $1"
+ exit 1
+}
+
+real_ip_for_domain() {
+ dig +short "$1" | grep -oE "([0-9]+\.){3}[0-9]+"
+}
+local_ip() {
+ ip a | grep brd | cut -d'/' -f1 | grep -oE "([0-9]+\.){3}[0-9]+"
+}
+
+nginx_domains() {
+ local vhost_file="$1"
+
+ grep -oE "^( )*[^#]+" "${vhost_file}" \
+ | grep -oE "[^\$]server_name.*;$" \
+ | sed 's/server_name//' \
+ | tr -d ';' \
+ | sed 's/\s\{1,\}//' \
+ | sed 's/\s\{1,\}/\n/g' \
+ | sort \
+ | uniq
+}
+
+apache_domains() {
+ local vhost_file="$1"
+
+ grep -oE "^( )*[^#]+" "${vhost_file}" \
+ | grep -oE "(ServerName|ServerAlias).*" \
+ | sed 's/ServerName//' \
+ | sed 's/ServerAlias//' \
+ | sed 's/\s\{1,\}//' \
+ | sort \
+ | uniq
+}
+
+get_domains() {
+ local vhost_file="$1"
+ local ips="$2"
+ local domains=""
+ local valid_domains=""
+ local nb=0
+
+ if $(echo "${vhost_file}" | grep -q nginx); then
+ debug "Nginx vhost file used"
+ domains=$(nginx_domains "${vhost_file}")
+ fi
+ if $(echo "${vhost_file}" | grep -q apache2); then
+ debug "Apache vhost file used"
+ domains=$(apache_domains "${vhost_file}")
+ fi
+
+ debug "Valid(s) domain(s) in ${vhost_file} :"
+ for domain in ${domains}; do
+ real_ip=$(real_ip_for_domain "${domain}")
+ for ip in $(echo "${ips}" | xargs -n1); do
+ if [ "${ip}" = "${real_ip}" ]; then
+ valid_domains="${valid_domains} ${domain}"
+ nb=$(( nb + 1 ))
+ debug "* ${domain} -> ${real_ip}"
+ fi
+ done
+ done
+
+ if [ "${nb}" -eq 0 ]; then
+ nb=$(echo "${domains}" | wc -l)
+ debug "* No valid domain found"
+ debug "All following(s) domain(s) will be used for CSR creation :"
+ for domain in ${domains}; do
+ debug "* ${domain}"
+ done
+ else
+ domains="${valid_domains}"
+ fi
+
+ echo "${domains}" | xargs -n 1
+}
+
+first_vhost_file_found() {
+ local vhost_name="$1"
+
+ ls "/etc/nginx/sites-enabled/${vhost_name}" \
+ "/etc/nginx/sites-enabled/${vhost_name}.conf" \
+ "/etc/apache2/sites-enabled/${vhost_name}.conf" \
+ 2>/dev/null \
+ | head -n 1
+}
+
+main() {
+ if [ "$#" != 1 ]; then
+ >&2 usage
+ exit 1
+ fi
+ if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
+ usage
+ exit 0
+ fi
+
+ local vhost_name=$(basename "$1" .conf)
+ local vhost_file=$(first_vhost_file_found "${vhost_name}")
+
+ if [ ! -h "${vhost_file}" ]; then
+ >&2 echo "No virtualhost has been found for '${vhost_name}'."
+ exit 1
+ fi
+
+ local ips=$(local_ip)
+ if [ -n "${SRV_IP}" ]; then
+ ips="${ips} ${SRV_IP}"
+ fi
+
+ get_domains "${vhost_file}" "${ips}"
+}
+
+readonly PROGNAME=$(basename "$0")
+readonly PROGDIR=$(realpath -m $(dirname "$0"))
+readonly ARGS=$@
+
+readonly VERBOSE=${VERBOSE:-"0"}
+readonly SRV_IP=${SRV_IP:-""}
+
+main $ARGS
diff --git a/evoacme/tasks/acme.yml b/evoacme/tasks/acme.yml
index e28b3b12..16417ca6 100644
--- a/evoacme/tasks/acme.yml
+++ b/evoacme/tasks/acme.yml
@@ -22,6 +22,14 @@
group: acme
state: directory
+- name: "Fix hooks directory permissions"
+ file:
+ path: "{{ evoacme_hooks_dir }}"
+ mode: "0700"
+ owner: acme
+ group: acme
+ state: directory
+
- name: Fix log dir's right
file:
path: "{{ evoacme_log_dir }}"
diff --git a/evoacme/tasks/certbot.yml b/evoacme/tasks/certbot.yml
index 20658ec2..f01cc668 100644
--- a/evoacme/tasks/certbot.yml
+++ b/evoacme/tasks/certbot.yml
@@ -20,28 +20,26 @@
name: certbot
state: latest
-- name: Check if /usr is a partition
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- changed_when: False
- failed_when: False
- check_mode: no
-
- register: usr_partition
-
-- name: Mount /usr in rw
- command: mount -o remount,rw /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0
+- include_role:
+ name: remount-usr
- name: Remove certbot symlink for apt install
file:
path: /usr/local/bin/certbot
state: absent
+- name: stat /etc/cron.d/certbot
+ stat:
+ path: /etc/cron.d/certbot
+ register: etc_cron_d_certbot
+
+- name: Rename certbot dpkg cron to .disabled
+ copy:
+ remote_src: True
+ src: /etc/cron.d/certbot
+ dest: /etc/cron.d/certbot.disabled
+ when: etc_cron_d_certbot.stat.exists
+
- name: Remove certbot dpkg cron
file:
path: /etc/cron.d/certbot
diff --git a/evoacme/tasks/conf.yml b/evoacme/tasks/conf.yml
index b39b5384..4d9f6704 100644
--- a/evoacme/tasks/conf.yml
+++ b/evoacme/tasks/conf.yml
@@ -1,6 +1,6 @@
---
- ini_file:
- dest: /etc/letsencrypt/openssl.cnf
+ dest: "{{ evoacme_crt_dir }}/openssl.cnf"
section: 'req'
option: "{{ item.name }}"
value: "{{ item.var }}"
diff --git a/evoacme/tasks/evoacme_hook.yml b/evoacme/tasks/evoacme_hook.yml
new file mode 100644
index 00000000..200bcbc4
--- /dev/null
+++ b/evoacme/tasks/evoacme_hook.yml
@@ -0,0 +1,14 @@
+---
+
+- name: "Search for {{ hook_name }} hook"
+ command: "find {{ evoacme_hooks_dir }} -type f \\( -name '{{ hook_name }}' -o -name '{{ hook_name }}.*' \\)"
+ check_mode: no
+ changed_when: False
+ register: _find_hook
+
+- name: "Copy {{ hook_name }} hook if missing"
+ copy:
+ src: "hooks/{{ hook_name }}"
+ dest: "{{ evoacme_hooks_dir }}/{{ hook_name }}"
+ mode: "0750"
+ when: _find_hook.stdout == ""
diff --git a/evoacme/tasks/main.yml b/evoacme/tasks/main.yml
index beac178e..08bb980a 100644
--- a/evoacme/tasks/main.yml
+++ b/evoacme/tasks/main.yml
@@ -9,11 +9,30 @@
- include: acme.yml
+- include: evoacme_hook.yml
+ vars:
+ hook_name: "{{ item }}"
+ with_items:
+ - reload_apache
+ - reload_nginx
+ - reload_dovecot
+ - reload_postfix
+
- include: conf.yml
- include: scripts.yml
-- include: webserver.yml
+- name: Determine Apache presence
+ stat:
+ path: /etc/apache2/apache2.conf
+ check_mode: no
+ register: sta
+
+- name: Determine Nginx presence
+ stat:
+ path: /etc/nginx/nginx.conf
+ check_mode: no
+ register: stn
- include: apache.yml
when: sta.stat.isreg is defined and sta.stat.isreg
diff --git a/evoacme/tasks/scripts.yml b/evoacme/tasks/scripts.yml
index 01e61fdb..77e7b75a 100644
--- a/evoacme/tasks/scripts.yml
+++ b/evoacme/tasks/scripts.yml
@@ -9,15 +9,23 @@
- name: Copy make-csr.sh script
copy:
- src: files/make-csr.sh
+ src: make-csr.sh
dest: /usr/local/sbin/make-csr
owner: root
group: root
mode: "0755"
+- name: Copy vhost-domains.sh script
+ copy:
+ src: vhost-domains.sh
+ dest: /usr/local/sbin/vhost-domains
+ owner: root
+ group: root
+ mode: "0755"
+
- name: Copy evoacme script
copy:
- src: files/evoacme.sh
+ src: evoacme.sh
dest: /usr/local/sbin/evoacme
owner: root
group: root
diff --git a/evoacme/tasks/webserver.yml b/evoacme/tasks/webserver.yml
deleted file mode 100644
index 8092aa98..00000000
--- a/evoacme/tasks/webserver.yml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-- name: Determine Nginx presence
- stat:
- path: /etc/nginx/nginx.conf
- check_mode: no
- register: stn
-
-- name: Determine Apache presence
- stat:
- path: /etc/apache2/apache2.conf
- check_mode: no
- register: sta
diff --git a/evoacme/templates/nginx.conf.j2 b/evoacme/templates/nginx.conf.j2
index dbb8a769..378d37cb 100644
--- a/evoacme/templates/nginx.conf.j2
+++ b/evoacme/templates/nginx.conf.j2
@@ -1,5 +1,9 @@
location ~ /.well-known/acme-challenge {
+{% if ansible_distribution_major_version > 8 %}
+ alias {{ evoacme_acme_dir }}/;
+{% else %}
alias {{ evoacme_acme_dir }}/.well-known/acme-challenge;
+{% endif %}
try_files $uri =404;
allow all;
}
diff --git a/evocheck/tasks/install_local.yml b/evocheck/tasks/install_local.yml
index d98ce0ae..7c0580c1 100644
--- a/evocheck/tasks/install_local.yml
+++ b/evocheck/tasks/install_local.yml
@@ -1,5 +1,6 @@
---
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
when: evocheck_bin_dir | search ("/usr")
- name: Scripts dir is present
diff --git a/evocheck/tasks/remount_usr_rw.yml b/evocheck/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/evocheck/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/evolinux-base/README.md b/evolinux-base/README.md
index 8ef7a70e..dbcf7762 100644
--- a/evolinux-base/README.md
+++ b/evolinux-base/README.md
@@ -36,6 +36,7 @@ Main variables are:
* `evolinux_additional_packages`: optional additional packages to install (default: `[]`)
* `evolinux_postfix_purge_exim`: purge Exim packages (default: `True`) ;
* `evolinux_ssh_password_auth_addresses`: list of addresses that can authenticate with a password (default: `[]`)
-* `evolinux_ssh_disable_root`: disable SSH access for root (default: `True`)
+* `evolinux_ssh_disable_root`: disable SSH access for root (default: `False`)
+* `evolinux_ssh_allow_current_user`: don't lock yourself out (default: `False`)
The full list of variables (with default values) can be found in `defaults/main.yml`.
diff --git a/evolinux-base/defaults/main.yml b/evolinux-base/defaults/main.yml
index e0c91fd1..54e5d85c 100644
--- a/evolinux-base/defaults/main.yml
+++ b/evolinux-base/defaults/main.yml
@@ -10,6 +10,21 @@ logcheck_alert_email: Null
raid_alert_email: Null
postfix_alias_email: Null
+# apt
+
+evolinux_apt_include: True
+
+evolinux_apt_conf: True
+evolinux_apt_hooks: True
+evolinux_apt_replace_default_sources: True
+evolinux_apt_public_sources: True
+evolinux_apt_upgrade: True
+evolinux_apt_remove_aptitude: True
+
+# etc-git
+
+evolinux_etcgit_include: True
+
# hostname
evolinux_hostname_include: True
@@ -31,17 +46,6 @@ evolinux_kernel_disable_tcp_timestamps: True
evolinux_kernel_reduce_swapiness: True
evolinux_kernel_cve20165696: True
-# apt
-
-evolinux_apt_include: True
-
-evolinux_apt_conf: True
-evolinux_apt_hooks: True
-evolinux_apt_replace_default_sources: True
-evolinux_apt_public_sources: True
-evolinux_apt_upgrade: True
-evolinux_apt_remove_aptitude: True
-
# fstab
evolinux_fstab_include: True
@@ -96,6 +100,27 @@ evolinux_system_alert5_init: True
evolinux_system_alert5_enable: True
evolinux_system_eni_auto: True
+# evomaintenance
+
+evolinux_evomaintenance_include: True
+
+# ssh
+
+evolinux_ssh_include: True
+
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+evolinux_ssh_password_auth_addresses: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
+evolinux_ssh_match_address: True
+evolinux_ssh_disable_acceptenv: True
+evolinux_ssh_allow_current_user: False
+
+### disabled because of a memory leak
+# # evolinux users
+#
+# evolinux_users_include: True
+
# root
evolinux_root_include: True
@@ -108,15 +133,7 @@ evolinux_root_gitconfig: True
evolinux_root_bash_history_appendonly: True
evolinux_root_vim_default: True
evolinux_root_vim_conf: True
-
-# ssh
-
-evolinux_ssh_include: True
-
-evolinux_ssh_password_auth_addresses: []
-evolinux_ssh_match_address: True
-evolinux_ssh_disable_root: True
-evolinux_ssh_disable_acceptenv: True
+evolinux_root_disable_ssh: False
# postfix
@@ -152,3 +169,31 @@ evolinux_hardware_include: True
evolinux_provider_online_include: False
evolinux_provider_orange_fce_include: False
+
+# log2mail
+
+evolinux_log2mail_include: True
+
+# Minifirewall
+
+evolinux_minifirewall_include: True
+
+# Munin
+
+evolinux_munin_include: True
+
+# Nagios/NRPE
+
+evolinux_nagios_nrpe_include: True
+
+# fail2ban
+
+evolinux_fail2ban_include: True
+
+# Listupgrade
+
+evolinux_listupgrade_include: True
+
+# Generate ldif
+
+evolinux_generateldif_include: True
diff --git a/evolinux-base/files/alert5.service b/evolinux-base/files/alert5.service
new file mode 100644
index 00000000..ea560a51
--- /dev/null
+++ b/evolinux-base/files/alert5.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Evolix alert5 script
+
+[Service]
+Type=oneshot
+ExecStart=/usr/share/scripts/alert5.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/evolinux-base/files/hwraid.le-vert.net.gpg.key b/evolinux-base/files/hwraid.le-vert.net.gpg.key
new file mode 100644
index 00000000..6d2f49d3
--- /dev/null
+++ b/evolinux-base/files/hwraid.le-vert.net.gpg.key
@@ -0,0 +1,31 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.12 (GNU/Linux)
+
+mQENBFHwGLoBCADGXHFostxbz4UzGFYtmox4pvyN1gMhq2KCuQ6f+FESa4HTd9L6
+XVhXWPCad3cdxBIls+41+AdZTWxWMu7DUdy8nMU1Ikfw6JeHcSx97G5BdxBVMjK4
+iMGfPdLfDgWf4BQ2h0dnTEWobt31WaqgNiNjNrKktqbymmF94pwYkwL53ydIA4zl
+8ZQRZooFigkS9WdoKjh30Pv/SWakILSLcSQFHK0dvSkeGd1NxT9dMNPAXXqLom4+
+7kCc0s04sS+0DwW16b0Hpb46mtsR9kzOnrE/Smj24uOGzNZen0oCc2Y7bfZlyaN+
+RlTkWEze7lemc4Byup/QWkhT0Er8F8uxexy5ABEBAAG0PEhXUmFpZCAoaHR0cDov
+L2h3cmFpZC5sZS12ZXJ0Lm5ldCkgPHJvb3RAaHdyYWlkLmxlLXZlcnQubmV0PokB
+OAQTAQIAIgUCUfAYugIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQYAUh
+DiOz07Rc4Af+N3dEZZHzLNVTjQ0+fCyeg8/flWOkR8DhP10cyoJhSHFTZRdXVshn
+kP4VmmUycVeURh76DmrIRe/9Oyca6aGXccRMqvq+HMgBPVwD5qNhcJPIuzqEvmlO
+6UIeW2ydil/v1pWu740fGntyFRQcsfqjReVPXw9K588F7MDMyL+31vLm6aorLSzR
+hvLhOmGisTs0wg2Oz9f4muauRy6cpQPw/Zi/P/F4WkQYscbHrSbhszj6OIg/vftR
+UbZ7QB26/+40B0ag4JzLpmj3scFxf/WdUl5LXazqhsbkurk7huV41BNKXi1+BS3c
+x6pFzWEHpiuG1j7U/nScGzEQpsMlUW9D+rkBDQRR8Bi6AQgAuhH1H0VLwcROI/5n
+9yTxSbTIZbyhUan3raAbit3pgo0zLagfUtp3vULVnm5ISqQcYFGLZoE1MUkmjGOL
+38W0lsIiZTaKOKXxBbLlPhhrvlXnNWAG/S1wnq7K+DV179KCTkUzaLRDbHvv999j
+9odBRtAkiTnCfHTMCN4AhydEejNxtlzJo4E5FecH4reimLI5euUdTltgCjixrbsa
+KbQftYpSMdXnLy2+00QZoXu0U/h4WZcMhOSEEiyGP9BY6m5G76n03HIeQ6eALDFu
+ryAgO+SB9rBrm/VN0kR/TZq0iA3uzLHC7zCw2aImipkr+rIuJOku0wH9MyowBbia
+bQtnCQARAQABiQEfBBgBAgAJBQJR8Bi6AhsMAAoJEGAFIQ4js9O0d5YH/3fNQgsC
+LvD0g2wdoksv5bG9CUOi9Bs0JHqI0LhXmPvMsbDojZ+zZle7KWNfK2227mWhmoG1
+WLujJSmTtxhEO1fXIdYjlDfk2uLJKuFi2wQX9n8dFDUmKY3CUJgeVZof1uQ/5C3D
+O06CcuOtf2d/+iijuW112aV1q1hoQqw71ojTET0iIV6lD/0i1eEBSSe1Ohb9yTGR
+VxTVrB78zU9hih4/Oq8wJT/Fv25aO1MDSc26CXAg0JA6IWvKal3BSPNhtz4L4FIg
+lXleArf9oJqxDO3TsV5zcLyxsIuRuxyP0+AKdSQUqv0dFi4Jf79OmvOmgwydhHjY
++f7quLbwiiDmPbU=
+=Yv6D
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/evolinux-base/meta/main.yml b/evolinux-base/meta/main.yml
index 2d640995..2b6aed3c 100644
--- a/evolinux-base/meta/main.yml
+++ b/evolinux-base/meta/main.yml
@@ -12,6 +12,7 @@ galaxy_info:
- name: Debian
versions:
- jessie
+ - stretch
dependencies: []
# List your role dependencies here, one per line.
diff --git a/evolinux-base/tasks/fstab.yml b/evolinux-base/tasks/fstab.yml
index 6c8b122a..9baa8a70 100644
--- a/evolinux-base/tasks/fstab.yml
+++ b/evolinux-base/tasks/fstab.yml
@@ -16,7 +16,7 @@
replace: '\1{{ evolinux_fstab_home_options | mandatory }}\3'
notify: remount /home
when:
- - "' /home ' in fstab_content.stdout"
+ - fstab_content.stdout | regex_search('\s/home\s')
- evolinux_fstab_home
- name: /tmp partition is customized
@@ -25,7 +25,7 @@
regexp: '([^#]\s+/tmp\s+\S+\s+)([a-z,]+)(\s+)'
replace: '\1{{ evolinux_fstab_tmp_options | mandatory }}\3'
when:
- - "' /tmp ' in fstab_content.stdout"
+ - fstab_content.stdout | regex_search('\s/tmp\s')
- evolinux_fstab_tmp
- name: /usr partition is customized
@@ -34,7 +34,7 @@
regexp: '([^#]\s+/usr\s+\S+\s+)([a-z,]+)(\s+)'
replace: '\1{{ evolinux_fstab_usr_options | mandatory }}\3'
when:
- - "' /usr ' in fstab_content.stdout"
+ - fstab_content.stdout | regex_search('\s/usr\s')
- evolinux_fstab_usr
- name: /var partition is customized
@@ -44,7 +44,7 @@
replace: '\1{{ evolinux_fstab_var_options | mandatory }}\3'
notify: remount /var
when:
- - "' /var ' in fstab_content.stdout"
+ - fstab_content.stdout | regex_search('\s/var\s')
- evolinux_fstab_var
- name: /var/tmp is created
diff --git a/evolinux-base/tasks/hardware.yml b/evolinux-base/tasks/hardware.yml
index 69ab0889..8607a586 100644
--- a/evolinux-base/tasks/hardware.yml
+++ b/evolinux-base/tasks/hardware.yml
@@ -9,7 +9,7 @@
- name: Check if Broadcom NetXtreme II device is present
shell: "lspci | grep -q 'NetXtreme II'"
check_mode: no
- register: broadcom
+ register: broadcom_netextreme_search
failed_when: False
changed_when: False
@@ -22,7 +22,7 @@
tasks_from: basics.yml
vars:
apt_basics_components: "main contrib non-free"
- when: broadcom|success
+ when: broadcom_netextreme_search.rc == 0
## RAID
@@ -53,6 +53,18 @@
when: "'Hewlett-Packard Company Smart Array' in raidmodel.stdout"
- block:
+ - name: Add HW tool GPG key
+ apt_key:
+ # url: https://hwraid.le-vert.net/debian/hwraid.le-vert.net.gpg.key
+ data: "{{ lookup('file', 'hwraid.le-vert.net.gpg.key') }}"
+ when: ansible_distribution_release == "stretch"
+
+ - name: Add HW tool repository
+ apt_repository:
+ repo: 'deb http://hwraid.le-vert.net/debian stretch main'
+ state: present
+ when: ansible_distribution_release == "stretch"
+
- name: Install packages for DELL/LSI hardware
apt:
name: "{{ item }}"
diff --git a/evolinux-base/tasks/main.yml b/evolinux-base/tasks/main.yml
index 5c1ad594..4784b084 100644
--- a/evolinux-base/tasks/main.yml
+++ b/evolinux-base/tasks/main.yml
@@ -5,6 +5,19 @@
when:
- ansible_distribution != "Debian" or ansible_distribution_major_version | version_compare('8', '<')
+- name: Apt configuration
+ include_role:
+ name: apt
+ vars:
+ apt_install_basics: "{{ evolinux_apt_replace_default_sources }}"
+ apt_install_evolix_public: "{{ evolinux_apt_public_sources }}"
+ when: evolinux_apt_include
+
+- name: /etc versioning with Git
+ include_role:
+ name: etc-git
+ when: evolinux_etcgit_include
+
- name: Hostname
include: hostname.yml
when: evolinux_hostname_include
@@ -13,10 +26,6 @@
include: kernel.yml
when: evolinux_kernel_include
-- name: Apt configuration and packages install
- include: apt.yml
- when: evolinux_apt_include
-
- name: Fstab configuration
include: fstab.yml
when: evolinux_fstab_include
@@ -29,14 +38,25 @@
include: system.yml
when: evolinux_system_include
-- name: Root user configuration
- include: root.yml
- when: evolinux_root_include
+- name: Evomaintenance
+ include_role:
+ name: evomaintenance
+ when: evolinux_evomaintenance_include
- name: SSH configuration
include: ssh.yml
when: evolinux_ssh_include
+### disabled because of a memory leak
+# - name: Create evolinux users
+# include_role:
+# name: evolinux-users
+# when: evolinux_users_include
+
+- name: Root user configuration
+ include: root.yml
+ when: evolinux_root_include
+
- name: Postfix
include: postfix.yml
when: evolinux_postfix_include
@@ -63,4 +83,34 @@
- name: Override Logmail service
include: log2mail.yml
- when: evolinux_packages_serveur_base
+ when: evolinux_log2mail_include
+
+- name: Minifirewall
+ include_role:
+ name: minifirewall
+ when: evolinux_minifirewall_include
+
+- name: Munin
+ include_role:
+ name: munin
+ when: evolinux_munin_include
+
+- name: Nagios/NRPE
+ include_role:
+ name: nagios-nrpe
+ when: evolinux_nagios_nrpe_include
+
+- name: fail2ban
+ include_role:
+ name: fail2ban
+ when: evolinux_fail2ban_include
+
+- name: Listupgrade
+ include_role:
+ name: listupgrade
+ when: evolinux_listupgrade_include
+
+- name: Generate ldif script
+ include_role:
+ name: generate-ldif
+ when: evolinux_generateldif_include
diff --git a/evolinux-base/tasks/packages.yml b/evolinux-base/tasks/packages.yml
index bb1f81c9..effa7c0c 100644
--- a/evolinux-base/tasks/packages.yml
+++ b/evolinux-base/tasks/packages.yml
@@ -13,6 +13,7 @@
- apg
- conntrack
- logrotate
+ - bash-completion
- ssl-cert
- ca-certificates
when: evolinux_packages_system
diff --git a/evolinux-base/tasks/postfix.yml b/evolinux-base/tasks/postfix.yml
index 9aad67e4..84bb06a2 100644
--- a/evolinux-base/tasks/postfix.yml
+++ b/evolinux-base/tasks/postfix.yml
@@ -1,6 +1,6 @@
---
-- name: packages are installed
+- name: Postfix packages are installed
apt:
name: "{{ item }}"
state: present
diff --git a/evolinux-base/tasks/remount_usr_rw.yml b/evolinux-base/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/evolinux-base/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/evolinux-base/tasks/root.yml b/evolinux-base/tasks/root.yml
index ffe64fe1..8fb2d113 100644
--- a/evolinux-base/tasks/root.yml
+++ b/evolinux-base/tasks/root.yml
@@ -80,4 +80,23 @@
- "set shiftwidth=4"
when: evolinux_root_vim_conf
+- name: disable SSH access for root
+ replace:
+ dest: /etc/ssh/sshd_config
+ regexp: '^PermitRootLogin (yes|without-password|prohibit-password)'
+ replace: "PermitRootLogin no"
+ validate: '/usr/sbin/sshd -T -f %s'
+ notify: reload sshd
+ when: evolinux_root_disable_ssh
+
+### Disabled : it seems useless and too dangerous for now
+# - name: remove root from AllowUsers directive
+# replace:
+# dest: /etc/ssh/sshd_config
+# regexp: '^(AllowUsers ((?!root(?:@\S+)?).)*)(\sroot(?:@\S+)?|root(?:@\S+)?\s)(.*)$'
+# replace: '\1\4'
+# validate: '/usr/sbin/sshd -T -f %s'
+# notify: reload sshd
+# when: evolinux_root_disable_ssh
+
- meta: flush_handlers
diff --git a/evolinux-base/tasks/ssh.yml b/evolinux-base/tasks/ssh.yml
index 2b7273b5..e4f51a81 100644
--- a/evolinux-base/tasks/ssh.yml
+++ b/evolinux-base/tasks/ssh.yml
@@ -3,61 +3,45 @@
msg: "Warning: empty 'evolinux_ssh_password_auth_addresses' variable, tasks will be skipped!"
when: evolinux_ssh_password_auth_addresses == []
-- name: Security directives for Evolinux
+# From 'man sshd_config' :
+# « If all of the criteria on the Match line are satisfied, the keywords
+# on the following lines override those set in the global section of the config
+# file, until either another Match line or the end of the file.
+# If a keyword appears in multiple Match blocks that are satisfied,
+# only the first instance of the keyword is applied. »
+#
+# We want to allow any user from a list of IP addresses to login with password,
+# but users of the "evolix" group can't login with password from other IP addresses
+
+- name: Security directives for Evolinux (Debian 9 or later)"
blockinfile:
dest: /etc/ssh/sshd_config
block: |
- Match Group evolinux-sudo
- PasswordAuthentication no
Match Address {{ evolinux_ssh_password_auth_addresses | join(',') }}
PasswordAuthentication yes
+ Match Group evolix
+ PasswordAuthentication no
marker: "# {mark} EVOLINUX PASSWORD RESTRICTIONS"
insertafter: EOF
validate: '/usr/sbin/sshd -T -f %s'
notify: reload sshd
- when: not evolinux_ssh_password_auth_addresses == []
+ when:
+ - evolinux_ssh_password_auth_addresses != []
+ - ansible_distribution_major_version | version_compare('9', '>=')
-# - name: verify Match Address directive
-# command: "grep 'Match Address' /etc/ssh/sshd_config"
-# changed_when: False
-# failed_when: False
-# check_mode: no
-# register: grep_matchaddress_ssh
-#
-# - name: Add Match Address sshd directive
-# lineinfile:
-# dest: /etc/ssh/sshd_config
-# line: "\nMatch Address {{ evolinux_ssh_password_auth_addresses | join(',') }}\n PasswordAuthentication yes"
-# insertafter: '# +ForceCommand cvs server'
-# validate: '/usr/sbin/sshd -T -f %s'
-# notify: reload sshd
-# when: evolinux_ssh_match_address and grep_matchaddress_ssh.rc != 0 and evolinux_ssh_password_auth_addresses != []
-#
-# - name: Modify Match Address sshd directive
-# replace:
-# dest: /etc/ssh/sshd_config
-# regexp: '^(Match Address ((?!{{ item }}).)*)$'
-# replace: '\1,{{ item }}'
-# validate: '/usr/sbin/sshd -T -f %s'
-# with_items: "{{ evolinux_ssh_password_auth_addresses }}"
-# notify: reload sshd
-# when: evolinux_ssh_match_address and grep_matchaddress_ssh.rc == 0
-#
-# - name: Add Match Group sudo without password
-# lineinfile:
-# dest: /etc/ssh/sshd_config
-# line: "\nMatch Group sudo\n PasswordAuthentication no"
-# insertbefore: '^Match Address'
-# validate: '/usr/sbin/sshd -T -f %s'
-# notify: reload sshd
-
-- name: disable SSH access for root
- replace:
+- name: Security directives for Evolinux (Jessie)
+ blockinfile:
dest: /etc/ssh/sshd_config
- regexp: '^PermitRootLogin (yes|without-password)'
- replace: "PermitRootLogin no"
+ block: |
+ Match Address {{ evolinux_ssh_password_auth_addresses | join(',') }}
+ PasswordAuthentication yes
+ marker: "# {mark} EVOLINUX PASSWORD RESTRICTIONS BY ADDRESS"
+ insertafter: EOF
+ validate: '/usr/sbin/sshd -T -f %s'
notify: reload sshd
- when: evolinux_ssh_disable_root
+ when:
+ - evolinux_ssh_password_auth_addresses != []
+ - ansible_distribution_release == "jessie"
# We disable AcceptEnv because it can be a security issue, but also because we
# do not want clients to push their environment variables like LANG.
@@ -77,4 +61,38 @@
notify: reload sshd
when: ansible_distribution_major_version | version_compare('9', '>=')
+- name: "Get current user"
+ command: logname
+ register: logname
+ check_mode: no
+ changed_when: False
+ when: evolinux_ssh_allow_current_user
+
+# we must double-escape caracters, because python
+- name: verify AllowUsers directive
+ shell: "grep -E '^AllowUsers' /etc/ssh/sshd_config"
+ changed_when: False
+ failed_when: False
+ register: grep_allowusers_ssh
+ check_mode: no
+ when: evolinux_ssh_allow_current_user
+
+- name: "Add AllowUsers sshd directive for current user"
+ lineinfile:
+ dest: /etc/ssh/sshd_config
+ line: "\nAllowUsers {{ logname.stdout }}"
+ insertafter: 'Subsystem'
+ validate: '/usr/sbin/sshd -T -f %s'
+ notify: reload sshd
+ when: evolinux_ssh_allow_current_user and grep_allowusers_ssh.rc != 0
+
+- name: "Modify AllowUsers sshd directive for current user"
+ replace:
+ dest: /etc/ssh/sshd_config
+ regexp: '^(AllowUsers ((?!{{ logname.stdout }}).)*)$'
+ replace: '\1 {{ logname.stdout }}'
+ validate: '/usr/sbin/sshd -T -f %s'
+ notify: reload sshd
+ when: evolinux_ssh_allow_current_user and grep_allowusers_ssh.rc == 0
+
- meta: flush_handlers
diff --git a/evolinux-base/tasks/system.yml b/evolinux-base/tasks/system.yml
index 261ef1a9..4ef08fa3 100644
--- a/evolinux-base/tasks/system.yml
+++ b/evolinux-base/tasks/system.yml
@@ -33,7 +33,8 @@
# TODO : find a way to force the console-data configuration
# non-interactively (like tzdata ↑)
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
- name: Ensure automagic vim conf is disabled
lineinfile:
@@ -59,7 +60,7 @@
- name: Set /etc/adduser.conf DIR_MODE to 0700
replace:
dest: /etc/adduser.conf
- regexp: "^DIR_MODE=.*$"
+ regexp: "^DIR_MODE=0755$"
replace: "DIR_MODE=0700"
when: evolinux_system_dirmode_adduser
@@ -116,29 +117,56 @@
## alert5
-- name: Install alert5 init script
+- name: Install alert5 init script (jessie/stretch)
template:
- src: system/init_alert5.j2
+ src: system/alert5.sysvinit.j2
dest: /etc/init.d/alert5
force: no
mode: "0755"
- when: evolinux_system_alert5_init
+ when:
+ - evolinux_system_alert5_init
+ - ansible_distribution_release == "jessie" or ansible_distribution_release == "stretch"
-
-#TODO: switch service/systemd modules with Ansible 2.2+
-
-- name: Enable alert5 init script
+- name: Enable alert5 init script (jessie/stretch)
service:
name: alert5
enabled: yes
- when: evolinux_system_alert5_init and evolinux_system_alert5_enable
+ when:
+ - evolinux_system_alert5_init
+ - evolinux_system_alert5_enable
+ - ansible_distribution_release == "jessie" or ansible_distribution_release == "stretch"
-# - name: Enable alert5 init script
-# systemd:
-# name: alert5
-# daemon_reload: yes
-# enabled: yes
-# when: evolinux_system_alert5_init and evolinux_system_alert5_enable
+
+
+- name: Install alert5 init script (buster)
+ template:
+ src: system/alert5.sh.j2
+ dest: /usr/share/scripts/alert5.sh
+ force: no
+ mode: "0755"
+ when:
+ - evolinux_system_alert5_init
+ - ansible_distribution_major_version | version_compare('10', '>=')
+
+- name: Install alert5 service (buster)
+ copy:
+ src: alert5.service
+ dest: /etc/systemd/system/alert5.service
+ force: yes
+ mode: "0755"
+ when:
+ - evolinux_system_alert5_init
+ - ansible_distribution_major_version | version_compare('10', '>=')
+
+- name: Enable alert5 init script (buster)
+ systemd:
+ name: alert5
+ daemon_reload: yes
+ enabled: yes
+ when:
+ - evolinux_system_alert5_init
+ - evolinux_system_alert5_enable
+ - ansible_distribution_major_version | version_compare('10', '>=')
## network interfaces
diff --git a/evolinux-base/templates/system/alert5.sh.j2 b/evolinux-base/templates/system/alert5.sh.j2
new file mode 100644
index 00000000..7949af28
--- /dev/null
+++ b/evolinux-base/templates/system/alert5.sh.j2
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+## sends a mail when booting
+date | mail -s'boot/reboot' {{ reboot_alert_email or general_alert_email | mandatory }}
+
+## starts the firewall
+#/etc/init.d/minifirewall start
diff --git a/evolinux-base/templates/system/init_alert5.j2 b/evolinux-base/templates/system/alert5.sysvinit.j2
similarity index 100%
rename from evolinux-base/templates/system/init_alert5.j2
rename to evolinux-base/templates/system/alert5.sysvinit.j2
diff --git a/admin-users/.kitchen.yml b/evolinux-users/.kitchen.yml
similarity index 92%
rename from admin-users/.kitchen.yml
rename to evolinux-users/.kitchen.yml
index f9ea107a..0c97cc85 100644
--- a/admin-users/.kitchen.yml
+++ b/evolinux-users/.kitchen.yml
@@ -31,7 +31,7 @@ suites:
playbook: ./tests/test.yml
verifier:
patterns:
- - admin-users/tests/spec/admin-users_spec.rb
+ - evolinux-users/tests/spec/evolinux-users_spec.rb
bundler_path: '/usr/local/bin'
rspec_path: '/usr/local/bin'
diff --git a/admin-users/README.md b/evolinux-users/README.md
similarity index 50%
rename from admin-users/README.md
rename to evolinux-users/README.md
index 68b0044d..439bd898 100644
--- a/admin-users/README.md
+++ b/evolinux-users/README.md
@@ -1,6 +1,6 @@
-# admin-users
+# evolinux-users
-Creates admin users accounts, based on a configuration data structure.
+Creates evolinux users accounts, based on a configuration data structure.
## Tasks
@@ -8,20 +8,26 @@ Everything is in the `tasks/main.yml` file.
## Available variables
-The variable `admin_users` must be a "dict" of one or more users :
+The variable `evolinux_users` must be a "dict" of one or more users :
```
-admin_users:
+evolinux_users:
foo:
name: foo
uid: 1001
fullname: 'Mr Foo'
+ groups: "baz"
password_hash: 'sdfgsdfgsdfgsdfg'
ssh_key: 'ssh-rsa AZERTYXYZ'
bar:
name: bar
uid: 1002
fullname: 'Mr Bar'
+ groups:
+ - "baz"
+ - "qux"
password_hash: 'gsdfgsdfgsdfgsdf'
- ssh_key: 'ssh-rsa QWERTYUIOP'
+ ssh_keys:
+ - 'ssh-rsa QWERTYUIOP'
+ - 'ssh-ed25519 QWERTYUIOP'
```
diff --git a/evolinux-users/defaults/main.yml b/evolinux-users/defaults/main.yml
new file mode 100644
index 00000000..d7d6f958
--- /dev/null
+++ b/evolinux-users/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+evolinux_users: {}
+evolinux_sudo_group: "evolinux-sudo"
+evolinux_root_disable_ssh: True
diff --git a/admin-users/handlers/main.yml b/evolinux-users/handlers/main.yml
similarity index 100%
rename from admin-users/handlers/main.yml
rename to evolinux-users/handlers/main.yml
diff --git a/admin-users/meta/main.yml b/evolinux-users/meta/main.yml
similarity index 88%
rename from admin-users/meta/main.yml
rename to evolinux-users/meta/main.yml
index 006768d3..9bae9e73 100644
--- a/admin-users/meta/main.yml
+++ b/evolinux-users/meta/main.yml
@@ -1,6 +1,6 @@
galaxy_info:
author: Evolix
- description: Creates admin users accounts.
+ description: Creates evolinux users accounts.
issue_tracker_url: https://forge.evolix.org/projects/ansible-roles/issues
diff --git a/admin-users/tasks/user.yml b/evolinux-users/tasks/account.yml
similarity index 72%
rename from admin-users/tasks/user.yml
rename to evolinux-users/tasks/account.yml
index 94f1a0c3..1ed142f9 100644
--- a/admin-users/tasks/user.yml
+++ b/evolinux-users/tasks/account.yml
@@ -35,19 +35,22 @@
update_password: on_create
when: loginisbusy.rc != 0 and uidisbusy.rc == 0
-- name: "Create {{ admin_users_group }} group (Debian 9 or later)"
+- name: "Create secondary groups"
group:
- name: "{{ admin_users_group }}"
- when: ansible_distribution_major_version | version_compare('9', '>=')
+ name: "{{ group }}"
+ with_items: "{{ user.groups }}"
+ loop_control:
+ loop_var: group
+ when: user.groups is defined
-- name: "Add user to {{ admin_users_group }} group (Debian 9 or later)"
+- name: "Add user '{{ user.name }}' to secondary groups"
user:
name: '{{ user.name }}'
- groups: '{{ admin_users_group }}'
+ groups: "{{ user.groups }}"
append: yes
- when: ansible_distribution_major_version | version_compare('9', '>=')
+ when: user.groups is defined
-- name: "Fix perms on homedirectory for '{{ user.name }}'"
+- name: "Fix perms on home directory for '{{ user.name }}'"
file:
name: '/home/{{ user.name }}'
mode: "0700"
diff --git a/evolinux-users/tasks/main.yml b/evolinux-users/tasks/main.yml
new file mode 100644
index 00000000..ec1400bd
--- /dev/null
+++ b/evolinux-users/tasks/main.yml
@@ -0,0 +1,20 @@
+---
+
+- fail:
+ msg: only compatible with Debian >= 8
+ when:
+ - ansible_distribution != "Debian" or ansible_distribution_major_version | version_compare('8', '<')
+
+- debug:
+ msg: "Warning: empty 'evolinux_users' variable, tasks will be skipped!"
+ when: evolinux_users == {}
+
+- name: Create user accounts
+ include: user.yml
+ vars:
+ user: "{{ item.value }}"
+ with_dict: "{{ evolinux_users }}"
+ when: evolinux_users != {}
+
+- include: root_disable_ssh.yml
+ when: evolinux_root_disable_ssh
diff --git a/evolinux-users/tasks/profile.yml b/evolinux-users/tasks/profile.yml
new file mode 100644
index 00000000..99af2512
--- /dev/null
+++ b/evolinux-users/tasks/profile.yml
@@ -0,0 +1,16 @@
+---
+
+- name: search profile for presence of evomaintenance
+ command: 'grep -q "trap.*sudo.*evomaintenance.sh"'
+ changed_when: False
+ failed_when: False
+ register: grep_profile_evomaintenance
+
+# Don't add the trap if it is present or commented
+- name: "Add evomaintenance trap for '{{ user.name }}'"
+ lineinfile:
+ state: present
+ dest: '/home/{{ user.name }}/.profile'
+ insertafter: EOF
+ line: 'trap "sudo /usr/share/scripts/evomaintenance.sh" 0'
+ when: grep_profile_evomaintenance.rc != 0
diff --git a/evolinux-users/tasks/root_disable_ssh.yml b/evolinux-users/tasks/root_disable_ssh.yml
new file mode 100644
index 00000000..7906307f
--- /dev/null
+++ b/evolinux-users/tasks/root_disable_ssh.yml
@@ -0,0 +1,17 @@
+---
+
+- name: disable root login
+ replace:
+ dest: /etc/ssh/sshd_config
+ regexp: '^PermitRootLogin (yes|without-password|prohibit-password)'
+ replace: "PermitRootLogin no"
+ notify: reload sshd
+
+### Disabled : it seems useless and too dangerous for now
+# - name: remove root from AllowUsers directive
+# replace:
+# dest: /etc/ssh/sshd_config
+# regexp: '^(AllowUsers ((?!root(?:@\S+)?).)*)(\sroot(?:@\S+)?|root(?:@\S+)?\s)(.*)$'
+# replace: '\1\4'
+# validate: '/usr/sbin/sshd -T -f %s'
+# notify: reload sshd
diff --git a/admin-users/tasks/ssh.yml b/evolinux-users/tasks/ssh.yml
similarity index 68%
rename from admin-users/tasks/ssh.yml
rename to evolinux-users/tasks/ssh.yml
index d74a51f2..8982dd6c 100644
--- a/admin-users/tasks/ssh.yml
+++ b/evolinux-users/tasks/ssh.yml
@@ -14,10 +14,21 @@
user: "{{ user.name }}"
key: "{{ user.ssh_key }}"
state: present
+ when: user.ssh_key is defined
+
+- name: "Add user's SSH public keys for '{{ user.name }}'"
+ authorized_key:
+ user: "{{ user.name }}"
+ key: "{{ ssk_key }}"
+ state: present
+ with_items: "{{ user.ssh_keys }}"
+ loop_control:
+ loop_var: ssk_key
+ when: user.ssh_keys is defined
# we must double-escape caracters, because python
- name: verify AllowUsers directive
- shell: "egrep '^AllowUsers' /etc/ssh/sshd_config"
+ shell: "grep -E '^AllowUsers' /etc/ssh/sshd_config"
changed_when: False
failed_when: False
register: grep_allowusers_ssh
@@ -35,32 +46,37 @@
- name: "Modify AllowUsers sshd directive for '{{ user.name }}'"
replace:
dest: /etc/ssh/sshd_config
- regexp: '^(AllowUsers ((?!{{ user.name }}).)*)$'
+ regexp: '^(AllowUsers ((?!\b{{ user.name }}\b).)*)$'
replace: '\1 {{ user.name }}'
validate: '/usr/sbin/sshd -T -f %s'
notify: reload sshd
when: grep_allowusers_ssh.rc == 0
-- name: verify Match User directive
+- name: "verify Match User directive"
command: "grep 'Match User' /etc/ssh/sshd_config"
changed_when: False
failed_when: False
register: grep_matchuser_ssh
check_mode: no
-- name: "Add Match User sshd directive for '{{ user.name }}'"
+- name: "Add Match User sshd directive for '{{ user.name }}' (Jessie)"
lineinfile:
dest: /etc/ssh/sshd_config
line: "\nMatch User {{ user.name }}\n PasswordAuthentication no"
+ insertafter: "# END EVOLINUX PASSWORD RESTRICTIONS BY ADDRESS"
validate: '/usr/sbin/sshd -T -f %s'
notify: reload sshd
- when: grep_matchuser_ssh.rc != 0
+ when:
+ - ansible_distribution_release == "jessie"
+ - grep_matchuser_ssh.rc != 0
-- name: "Modify Match User's sshd directive for '{{ user.name }}'"
+- name: "Modify Match User's sshd directive for '{{ user.name }}' (Jessie)"
replace:
dest: /etc/ssh/sshd_config
regexp: '^(Match User ((?!{{ user.name }}).)*)$'
replace: '\1,{{ user.name }}'
validate: '/usr/sbin/sshd -T -f %s'
notify: reload sshd
- when: grep_matchuser_ssh.rc == 0
+ when:
+ - ansible_distribution_release == "jessie"
+ - grep_matchuser_ssh.rc == 0
diff --git a/evolinux-users/tasks/sudo_jessie.yml b/evolinux-users/tasks/sudo_jessie.yml
new file mode 100644
index 00000000..f675954e
--- /dev/null
+++ b/evolinux-users/tasks/sudo_jessie.yml
@@ -0,0 +1,18 @@
+---
+
+- name: "Verify Evolinux sudoers file presence (jessie)"
+ template:
+ src: sudoers_jessie.j2
+ dest: /etc/sudoers.d/evolinux
+ force: no
+ mode: "0440"
+ validate: '/usr/sbin/visudo -cf %s'
+ register: copy_sudoers_evolinux
+
+- name: "Add user in sudoers file for '{{ user.name }}' (jessie)"
+ replace:
+ dest: /etc/sudoers.d/evolinux
+ regexp: '^(User_Alias\s+ADMINS\s+=((?!{{ user.name }}).)*)$'
+ replace: '\1,{{ user.name }}'
+ validate: '/usr/sbin/visudo -cf %s'
+ when: not copy_sudoers_evolinux.changed
diff --git a/evolinux-users/tasks/sudo_stretch.yml b/evolinux-users/tasks/sudo_stretch.yml
new file mode 100644
index 00000000..f77ae484
--- /dev/null
+++ b/evolinux-users/tasks/sudo_stretch.yml
@@ -0,0 +1,20 @@
+---
+
+- name: "Verify Evolinux sudoers file presence (Debian 9 or later)"
+ template:
+ src: sudoers_stretch.j2
+ dest: /etc/sudoers.d/evolinux
+ force: no
+ validate: '/usr/sbin/visudo -cf %s'
+ register: copy_sudoers_evolinux
+
+- name: "Create evolinux-sudo group (Debian 9 or later)"
+ group:
+ name: "{{ evolinux_sudo_group }}"
+ system: yes
+
+- name: "Add user to evolinux-sudo group (Debian 9 or later)"
+ user:
+ name: '{{ user.name }}'
+ groups: "{{ evolinux_sudo_group }}"
+ append: yes
diff --git a/evolinux-users/tasks/user.yml b/evolinux-users/tasks/user.yml
new file mode 100644
index 00000000..73fea728
--- /dev/null
+++ b/evolinux-users/tasks/user.yml
@@ -0,0 +1,15 @@
+---
+
+- include: account.yml
+
+- include: profile.yml
+
+- include: ssh.yml
+
+- include: sudo_jessie.yml
+ when: ansible_distribution_release == "jessie"
+
+- include: sudo_stretch.yml
+ when: ansible_distribution_major_version | version_compare('9', '>=')
+
+- meta: flush_handlers
diff --git a/admin-users/templates/sudoers_jessie.j2 b/evolinux-users/templates/sudoers_jessie.j2
similarity index 100%
rename from admin-users/templates/sudoers_jessie.j2
rename to evolinux-users/templates/sudoers_jessie.j2
diff --git a/admin-users/templates/sudoers_stretch.j2 b/evolinux-users/templates/sudoers_stretch.j2
similarity index 75%
rename from admin-users/templates/sudoers_stretch.j2
rename to evolinux-users/templates/sudoers_stretch.j2
index 8de1bbc6..289a65ee 100644
--- a/admin-users/templates/sudoers_stretch.j2
+++ b/evolinux-users/templates/sudoers_stretch.j2
@@ -5,5 +5,5 @@ Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh, /usr/share/scripts
nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_procs
nagios ALL = (clamav) NOPASSWD: /usr/bin/clamscan /tmp/safe.txt
-%evolinux-sudo ALL=(ALL:ALL) ALL
-%evolinux-sudo ALL = NOPASSWD: MAINT
+%{{ evolinux_sudo_group }} ALL=(ALL:ALL) ALL
+%{{ evolinux_sudo_group }} ALL = NOPASSWD: MAINT
diff --git a/admin-users/tests/spec/admin-users_spec.rb b/evolinux-users/tests/spec/evolinux-users_spec.rb
similarity index 100%
rename from admin-users/tests/spec/admin-users_spec.rb
rename to evolinux-users/tests/spec/evolinux-users_spec.rb
diff --git a/admin-users/tests/test.yml b/evolinux-users/tests/test.yml
similarity index 94%
rename from admin-users/tests/test.yml
rename to evolinux-users/tests/test.yml
index 06c29643..f622eebf 100644
--- a/admin-users/tests/test.yml
+++ b/evolinux-users/tests/test.yml
@@ -2,7 +2,7 @@
- hosts: test-kitchen
vars:
- admin_users:
+ evolinux_users:
foo:
name: foo
uid: 1001
@@ -20,4 +20,4 @@
# state: directory
roles:
- - role: admin-users
+ - role: evolinux-users
diff --git a/evomaintenance/defaults/main.yml b/evomaintenance/defaults/main.yml
index fc584481..2d0bf1b6 100644
--- a/evomaintenance/defaults/main.yml
+++ b/evomaintenance/defaults/main.yml
@@ -17,4 +17,7 @@ evomaintenance_urgency_tel: "06.00.00.00.00"
evomaintenance_realm: "{{ ansible_domain }}"
-evomaintenance_hosts: []
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+evomaintenance_hosts: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
diff --git a/fail2ban/defaults/main.yml b/fail2ban/defaults/main.yml
index 2fe40951..73cd46cb 100644
--- a/fail2ban/defaults/main.yml
+++ b/fail2ban/defaults/main.yml
@@ -1,4 +1,11 @@
---
general_alert_email: "root@localhost"
fail2ban_alert_email: Null
-fail2ban_ignore_ips: []
+
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+fail2ban_ignore_ips: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
+
+fail2ban_wordpress: False
+fail2ban_roundcube: False
diff --git a/fail2ban/files/roundcube.conf b/fail2ban/files/roundcube.conf
new file mode 100644
index 00000000..d4ad016a
--- /dev/null
+++ b/fail2ban/files/roundcube.conf
@@ -0,0 +1,2 @@
+[Definition]
+failregex = Login failed for .*. from
diff --git a/fail2ban/files/wordpress-hard.conf b/fail2ban/files/wordpress-hard.conf
new file mode 100644
index 00000000..0eba3cf0
--- /dev/null
+++ b/fail2ban/files/wordpress-hard.conf
@@ -0,0 +1,31 @@
+# Fail2Ban configuration file soft
+#
+# Author: Charles Lecklider
+#
+
+[INCLUDES]
+
+# Read common prefixes. If any customizations available -- read them from
+# common.local
+before = common.conf
+
+
+[Definition]
+
+_daemon = (?:wordpress|wp)
+
+# Option: failregex
+# Notes.: regex to match the password failures messages in the logfile. The
+# host must be matched by a group named "host". The tag "" can
+# be used for standard IP/hostname matching and is only an alias for
+# (?:::f{4,6}:)?(?P[\w\-.^_]+)
+# Values: TEXT
+#
+failregex = ^%(__prefix_line)sAuthentication failure for .* from $
+ ^%(__prefix_line)sXML-RPC authentication failure from $
+
+# Option: ignoreregex
+# Notes.: regex to ignore. If this regex matches, the line is ignored.
+# Values: TEXT
+#
+ignoreregex =
diff --git a/fail2ban/files/wordpress-soft.conf b/fail2ban/files/wordpress-soft.conf
new file mode 100644
index 00000000..345aab68
--- /dev/null
+++ b/fail2ban/files/wordpress-soft.conf
@@ -0,0 +1,33 @@
+# Fail2Ban configuration file hard
+#
+# Author: Charles Lecklider
+#
+
+[INCLUDES]
+
+# Read common prefixes. If any customizations available -- read them from
+# common.local
+before = common.conf
+
+
+[Definition]
+
+_daemon = (?:wordpress|wp)
+
+# Option: failregex
+# Notes.: regex to match the password failures messages in the logfile. The
+# host must be matched by a group named "host". The tag "" can
+# be used for standard IP/hostname matching and is only an alias for
+# (?:::f{4,6}:)?(?P[\w\-.^_]+)
+# Values: TEXT
+#
+failregex = ^%(__prefix_line)sAuthentication attempt for unknown user .* from ( via XML-RPC)?$
+ ^%(__prefix_line)sBlocked authentication attempt for .* from ( via XML-RPC)?$
+ ^%(__prefix_line)sBlocked user enumeration attempt from $
+ ^%(__prefix_line)sPingback error .* generated from $
+
+# Option: ignoreregex
+# Notes.: regex to ignore. If this regex matches, the line is ignored.
+# Values: TEXT
+#
+ignoreregex =
diff --git a/fail2ban/tasks/main.yml b/fail2ban/tasks/main.yml
index 7a47a0ce..579e143d 100644
--- a/fail2ban/tasks/main.yml
+++ b/fail2ban/tasks/main.yml
@@ -2,13 +2,16 @@
# We have to copy the local jail before installing the package
# or we risk being jailed by fail2ban
-- name: Prepare /etc/fail2ban
+- name: Prepare fail2ban hierarchy
file:
- path: /etc/fail2ban
+ path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0755"
+ with_items:
+ - "/etc/fail2ban"
+ - "/etc/fail2ban/filter.d"
tags:
- fail2ban
@@ -22,14 +25,6 @@
tags:
- fail2ban
-- name: package is installed
- apt:
- name: fail2ban
- state: present
- tags:
- - fail2ban
- - packages
-
- name: custom filters are installed
copy:
src: "{{ item }}"
@@ -38,6 +33,17 @@
with_items:
- dovecot-evolix.conf
- sasl-evolix.conf
+ - wordpress-soft.conf
+ - wordpress-hard.conf
+ - roundcube.conf
notify: restart fail2ban
tags:
- fail2ban
+
+- name: package is installed
+ apt:
+ name: fail2ban
+ state: present
+ tags:
+ - fail2ban
+ - packages
diff --git a/fail2ban/templates/jail.local.j2 b/fail2ban/templates/jail.local.j2
index 2f4d6bc3..73b5f21f 100644
--- a/fail2ban/templates/jail.local.j2
+++ b/fail2ban/templates/jail.local.j2
@@ -26,3 +26,30 @@ action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(proto
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
action = %(action_mwl)s
+
+{% if fail2ban_wordpress %}
+[wordpress-hard]
+enabled = true
+port = http,https
+filter = wordpress-hard
+logpath = /var/log/auth.log
+maxretry = 1
+findtime = 300
+
+[wordpress-soft]
+enabled = true
+port = http,https
+filter = wordpress-soft
+logpath = /var/log/auth.log
+maxretry = 5
+findtime = 300
+{% endif %}
+
+{% if fail2ban_roundcube %}
+[roundcube]
+enabled = true
+port = http,https
+filter = roundcube
+logpath = /var/lib/roundcube/logs/errors
+maxretry = 5
+{% endif %}
diff --git a/filebeat/meta/main.yml b/filebeat/meta/main.yml
index 4e6139af..37aa6319 100644
--- a/filebeat/meta/main.yml
+++ b/filebeat/meta/main.yml
@@ -12,6 +12,7 @@ galaxy_info:
- name: Debian
versions:
- jessie
+ - stretch
dependencies: []
# List your role dependencies here, one per line.
diff --git a/filebeat/tasks/main.yml b/filebeat/tasks/main.yml
index bc038b93..75f4bc2b 100644
--- a/filebeat/tasks/main.yml
+++ b/filebeat/tasks/main.yml
@@ -20,7 +20,7 @@
- name: Elastic sources list is available
apt_repository:
repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
- filename: elastic.list
+ filename: elastic
state: present
update_cache: yes
tags:
@@ -36,7 +36,7 @@
- packages
- name: Filebeat service is enabled
- service:
+ systemd:
name: filebeat
enabled: yes
@@ -59,31 +59,11 @@
when: filebeat_logstash_plugin and logstash_plugin.stat.exists
- block:
- - name: Check if /usr is a partition
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- changed_when: False
- failed_when: False
- check_mode: no
- register: usr_partition
-
- - name: Mount /usr in rw
- command: mount -o remount,rw /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0
+ - include_role:
+ name: remount-usr
- name: Logstash plugin is installed
command: /usr/share/logstash/bin/logstash-plugin install logstash-input-beats
-
- - name: /usr is remounted
- command: mount -oremount /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0
when:
- filebeat_logstash_plugin
- logstash_plugin.stat.exists
diff --git a/generate-ldif/README.md b/generate-ldif/README.md
new file mode 100644
index 00000000..a71be619
--- /dev/null
+++ b/generate-ldif/README.md
@@ -0,0 +1,22 @@
+# generate-ldif
+
+Install generateldif ; a script for building an ldif file, ready to import into LDAP.
+
+## Tasks
+
+The roles install the script, but doesn't run it.
+
+A separate `exec.yml` task file can be played manually in playbooks or roles to execute the script. Example :
+
+```
+- include_role:
+ name: generate-ldif
+ tasks_from: exec.yml
+```
+## Variables
+
+* `general_scripts_dir` : parent directory for the script
+* `client_number` : client number (default: `XXX`)
+* `monitoring_mode` : `everytime` or `worktime` (default: `everytime`)
+* `monitoring_type` : `icmp` or `nrpe` (default: `icmp`)
+* `monitoring_timeout` : timeout for nrpe checks, in seconds (default: `10`)
diff --git a/generate-ldif/defaults/main.yml b/generate-ldif/defaults/main.yml
new file mode 100644
index 00000000..48bd19fc
--- /dev/null
+++ b/generate-ldif/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+general_scripts_dir: "/usr/share/scripts"
+
+client_number: XXX
+monitoring_mode: "everytime"
+monitoring_type: "icmp"
+monitoring_timeout: "10"
diff --git a/generate-ldif/tasks/exec.yml b/generate-ldif/tasks/exec.yml
new file mode 100644
index 00000000..6450c6bc
--- /dev/null
+++ b/generate-ldif/tasks/exec.yml
@@ -0,0 +1,15 @@
+---
+- name: run generateldif
+ command: '{{ general_scripts_dir }}/generateldif.sh'
+ register: generateldif_run
+ changed_when: False
+ failed_when: False
+ check_mode: no
+ tags:
+ - generateldif-exec
+
+- debug:
+ var: generateldif_run.stdout_lines
+ verbosity: 1
+ tags:
+ - generateldif-exec
diff --git a/generate-ldif/tasks/main.yml b/generate-ldif/tasks/main.yml
new file mode 100644
index 00000000..35da06be
--- /dev/null
+++ b/generate-ldif/tasks/main.yml
@@ -0,0 +1,12 @@
+---
+- include_role:
+ name: remount-usr
+ when: general_scripts_dir | search("/usr")
+
+- name: "copy generateldif.sh"
+ template:
+ src: templates/generateldif.sh.j2
+ dest: '{{ general_scripts_dir }}/generateldif.sh'
+ owner: root
+ group: root
+ mode: "0750"
diff --git a/generate-ldif/templates/generateldif.sh.j2 b/generate-ldif/templates/generateldif.sh.j2
new file mode 100755
index 00000000..0f3abcf2
--- /dev/null
+++ b/generate-ldif/templates/generateldif.sh.j2
@@ -0,0 +1,542 @@
+#!/bin/sh
+
+if [ $(id -u) != 0 ]; then
+ echo "You must be root" 2>&1
+ exit 1
+fi
+
+is_pkg_installed() {
+ dpkg -l "$1" 2>/dev/null | grep -q '^ii'
+}
+
+get_pkg_version() {
+ dpkg-query -W -f='${Version}\n' "$1" | \
+ sed 's/[~+-].\+//' | sed 's/.\+://' | sed 's/p.*//' | cut -d'.' -f1,2
+}
+
+clientNumber="{{ client_number | mandatory }}"
+monitoringMode="{{ monitoring_mode | mandatory }}"
+monitoringType="{{ monitoring_type | mandatory }}"
+monitoringTimeout="{{ monitoring_timeout | mandatory }}"
+isActive="TRUE"
+NagiosEnabled="TRUE"
+
+EvoComputerName=$(hostname -s)
+dnsPTRrecord=$(hostname -f)
+HardwareMark=$(dmidecode -s system-manufacturer | grep -v '^#')
+computerIP=$(hostname -i | cut -d' ' -f1)
+computerOS=$(lsb_release -s -d | sed 's#\..##')
+computerKernel=$(uname -r)
+HardwareSerial=$(dmidecode -s system-serial-number | grep -v '^#')
+
+type="baremetal"
+lscpu | grep -q KVM && type="kvm"
+lscpu | grep -q Oracle && type="virtualbox"
+
+if [ "$type" = "kvm" ]; then
+ HardwareMark="KVM"
+ HardwareModel="Virtual Machine"
+
+ cpuMark=$(lscpu | grep Vendor | tr -s '\t' ' ' | cut -d' ' -f3)
+ cpuModel="Virtual $(lscpu | grep "Model name" | tr -s '\t' ' ' | cut -d' ' -f3-), $(nproc) vCPU"
+ cpuFreq="$(lscpu | grep "CPU MHz" | tr -s '\t' ' ' | cut -d' ' -f3-)MHz"
+elif [ "$type" = "virtualbox" ]; then
+ HardwareMark="VirtualBox"
+ HardwareModel="Virtual Machine"
+
+ cpuMark=$(lscpu | grep Vendor | tr -s '\t' ' ' | cut -d' ' -f3)
+ cpuModel="Virtual $(lscpu | grep "Model name" | tr -s '\t' ' ' | cut -d' ' -f3-), $(nproc) vCPU"
+ cpuFreq="$(lscpu | grep "CPU MHz" | tr -s '\t' ' ' | cut -d' ' -f3-)MHz"
+else
+ HardwareModel=$(dmidecode -s system-product-name | grep -v '^#')
+
+ cpuMark=$(dmidecode -s processor-manufacturer | grep -v '^#' | head -1)
+ cpuModel=$(dmidecode -s processor-version | grep -v '^#' | head -1)
+ cpuFreq=$(dmidecode -s processor-frequency | grep -v '^#' | head -1)
+fi
+
+# lspci is not available on OpenVZ container.
+if ( test -d /proc/vz && ! test -d /proc/bc ); then
+ screen0Mark="No screen on OpenVZ container"
+ screen0Model="No screen on OpenVZ container"
+ sdaSize="Total SIMFS $(df -h -t simfs --total | tail -1 | tr -s '\t' ' ' | cut -d' ' -f2)"
+else
+ screen0Mark=$(lspci -q -vm | grep VGA -A3 | grep Vendor | tr -d '\t' | cut -d':' -f2 | head -1)
+ screen0Model=$(lspci -q -vm | grep VGA -A3 | grep Device | tr -d '\t' | cut -d':' -f2 | head -1)
+ sdaSize=$(lsblk -d -r -n -o TYPE,SIZE | grep disk | sed 's/^disk //'| xargs | sed 's/ / + /g')
+ raidModel=$(lspci -q -vm | grep RAID -A3 | grep Device | tr -d '\t' | cut -d':' -f2 | head -1)
+fi
+
+if (test -b /dev/vda); then
+ sdaModel="Virtual VirtIO Disk"
+elif [ -d /proc/vz ] && [ ! -d /proc/bc ]; then
+ sdaModel="OpenVZ SIMFS disk"
+else
+ hdparm -I /dev/sda 2>&1 | grep -q bad
+ if [ $? -eq 0 ]; then
+ if (test -n "${raidModel}"); then
+ sdaModel=${raidModel}
+ else
+ sdaModel="Model unknown, RAID HW?"
+ fi
+ else
+ sdaModel=$(hdparm -I /dev/sda | grep Model | tr -s '\t' ' ' | cut -d' ' -f4-)
+ fi
+fi
+
+ldif_file="/root/${EvoComputerName}.$(date +"%Y%m%d%H%M%S").ldif"
+
+computer_dn="EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net"
+
+# Generic services.
+cat < "${ldif_file}"
+## Generated on $(date --iso-8601=seconds)
+## Can be injected in LDAP with this command:
+# ldapvi --profile evolix --add --in ${EvoComputerName}.ldif
+
+dn: ${computer_dn}
+dnsArecord: ${EvoComputerName}
+EvoComputerName: ${EvoComputerName}
+HardwareMark: ${HardwareMark}
+HardwareModel: ${HardwareModel}
+dnsZone: evolix.net
+objectClass: EvoComputer
+objectClass: top
+computerIP: ${computerIP}
+dnsPTRrecord: ${dnsPTRrecord}
+computerOS: ${computerOS}
+computerKernel: Linux ${computerKernel}
+isActive: ${isActive}
+NagiosEnabled: ${NagiosEnabled}
+NagiosComments: ${monitoringType},${monitoringMode},${monitoringTimeout}
+HardwareSerial: ${HardwareSerial}
+clientNumber: ${clientNumber}
+EOT
+
+# CPU
+if [ -n "${cpuMark}" ]; then
+ cat <> "${ldif_file}"
+
+dn: HardwareName=cpu0,${computer_dn}
+HardwareMark: ${cpuMark}
+objectClass: EvoHardware
+HardwareName: cpu0
+HardwareSize: ${cpuFreq}
+HardwareType: CPU
+HardwareModel: ${cpuModel}
+EOT
+fi
+
+# Memory
+mem=$(free -h | grep Mem: | tr -s ' ' | cut -d ' ' -f2)
+if [ -n "${mem}" ]; then
+ cat <> "${ldif_file}"
+
+dn: HardwareName=ram0,${computer_dn}
+HardwareName: ram0
+objectClass: EvoHardware
+HardwareSize: ${mem}
+HardwareType: mem
+NagiosEnabled: TRUE
+EOT
+fi
+
+# Screen
+swap=$(free -h | grep Swap: | tr -s ' ' | cut -d ' ' -f2)
+if [ -n "${screen0Mark}" ]; then
+ cat <> "${ldif_file}"
+
+dn: HardwareName=screen0,${computer_dn}
+HardwareMark: ${screen0Mark}
+HardwareName: screen0
+objectClass: EvoHardware
+HardwareModel: ${screen0Model}
+HardwareType: video
+EOT
+fi
+
+# /dev/sda
+if [ -n "${sdaModel}" ]; then
+ cat <> "${ldif_file}"
+
+dn: HardwareName=sda,${computer_dn}
+objectClass: EvoHardware
+HardwareName: sda
+HardwareSize: ${sdaSize}
+HardwareType: disk
+HardwareModel: ${sdaModel}
+HardwarePartitioncount: 1
+NagiosEnabled: TRUE
+EOT
+fi
+
+# Swap
+swap=$(free -h | grep Swap: | tr -s ' ' | cut -d ' ' -f2)
+if [ -n "${swap}" ]; then
+ cat <> "${ldif_file}"
+
+dn: HardwareName=swap,${computer_dn}
+objectClass: EvoHardware
+HardwareName: swap
+HardwareSize: ${swap}
+HardwareType: mem
+NagiosEnabled: TRUE
+EOT
+fi
+
+# NRPE
+nrpe_version=$(get_pkg_version nagios-nrpe-server)
+if [ -n "${nrpe_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=nrpe,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: TCP
+ServiceVersion: NRPE ${nrpe_version}
+objectClass: EvoService
+ServiceName: nrpe
+ipServicePort: 5666
+ServiceType: monitoring
+EOT
+fi
+
+# Postfix
+postfix_version=$(get_pkg_version postfix)
+if [ -n "${postfix_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=postfix,${computer_dn}
+ipServiceProtocol: tcp
+NagiosEnabled: TRUE
+objectClass: EvoService
+ServiceName: postfix
+ipServicePort: 25
+ServiceType: smtp
+ServiceVersion: Postfix ${postfix_version}
+EOT
+fi
+
+# OpenSSH
+openssh_version=$(get_pkg_version openssh-server)
+if [ -n "${openssh_version}" ]; then
+ opensshFingerprintRSA=$(ssh-keyscan -t rsa localhost 2>/dev/null\
+ | sed -e 's/localhost //' -e 's/ssh-rsa /ssh-rsa,/')
+ opensshFingerprintED25519=$(ssh-keyscan -t ed25519 localhost 2>/dev/null\
+ | sed -e 's/localhost //' -e 's/ssh-ed25519 /ssh-ed25519,/')
+ opensshFingerprintECDSA=$(ssh-keyscan -t ecdsa-sha2-nistp256 localhost 2>/dev/null\
+ | sed -e 's/localhost //' -e 's/ecdsa-sha2-nistp256 /ecdsa-sha2-nistp256,/')
+ opensshFingerprint="${opensshFingerprintRSA}${opensshFingerprintRSA:+;}${opensshFingerprintED25519}${opensshFingerprintED25519:+;}${opensshFingerprintECDSA}"
+
+ cat <> "${ldif_file}"
+
+dn: ServiceName=openssh,${computer_dn}
+ipServiceProtocol: tcp
+NagiosEnabled: TRUE
+objectClass: EvoService
+ipServicePort: 22
+ServiceName: openssh
+ServiceType: ssh
+ServiceVersion: OpenSSH ${openssh_version}
+ServiceFingerprint: ${opensshFingerprint}
+EOT
+fi
+
+# NTP
+ntp_version=$(get_pkg_version ntp)
+if [ -n "${ntp_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=ntp,${computer_dn}
+NagiosEnabled: TRUE
+objectClass: EvoService
+ServiceName: ntp
+ServiceType: ntp
+ServiceVersion: NTP ${ntp_version}
+EOT
+fi
+
+for net in $(ls /sys/class/net); do
+ path=$(readlink -e /sys/class/net/${net})
+ echo $path | grep -q virtual
+ if [ $? -ne 0 ]; then
+ hw=$(cat ${path}/address)
+ vendor_id=$(cat ${path}/device/vendor)
+ dev_id=$(cat ${path}/device/device)
+ [ "${dev_id}" = "0x0001" ] && dev_id="0x1000"
+ dev=$(lspci -d "${vendor_id}:${dev_id}" -vm)
+ vendor=$(echo "${dev}" | grep -E "^Vendor" | cut -d':' -f2 | xargs)
+ model=$(echo "${dev}" | grep -E "^Vendor" -A1 | grep -E "^Device" | cut -d':' -f2 | xargs)
+ size=$(cat ${path}/tx_queue_len)
+ ips=$(ip -o addr show "${net}" | grep "global" | awk '{print $4 }' | xargs | cut -d'/' -f1)
+ cat <> "${ldif_file}"
+
+dn: HardwareName=$net,EvoComputerName=$(hostname),ou=computer,dc=evolix,dc=net
+objectClass: EvoHardware
+HardwareAddress: ${hw}
+EOT
+ [ -n "$ips" ] && echo "HardwareIP: ${ips}" >> "${ldif_file}"
+ cat <> "${ldif_file}"
+HardwareMark: ${vendor}
+HardwareModel: ${model}
+HardwareName: ${net}
+HardwareSize: ${size}
+HardwareType: netcard
+EOT
+ fi
+done
+
+# Apache
+if is_pkg_installed apache2-data; then
+ apache_version=$(get_pkg_version apache2-data)
+fi
+if [ -n "${apache_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=apache,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: apache
+ipServicePort: 80
+ServiceType: http
+ServiceVersion: Apache ${apache_version}
+
+dn: ServiceName=apache-ssl,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: apache-ssl
+ipServicePort: 443
+ServiceType: http
+ServiceVersion: Apache ${apache_version}
+EOT
+fi
+
+# Nginx
+if is_pkg_installed nginx-common; then
+ nginx_version=$(get_pkg_version nginx-common)
+fi
+if [ -n "${nginx_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=nginx,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: nginx
+ipServicePort: 80
+ServiceType: http
+ServiceVersion: Nginx ${nginx_version}
+
+dn: ServiceName=nginx-ssl,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ipServicePort: 443
+ServiceName: nginx-ssl
+ServiceType: https
+ServiceVersion: Nginx ${nginx_version}
+EOT
+fi
+
+# MySQL
+if is_pkg_installed mysql-server-5.5; then
+ mysql_version=$(get_pkg_version mysql-server-5.5)
+elif is_pkg_installed mysql-server-5.7; then
+ mysql_version=$(get_pkg_version mysql-server-5.7)
+fi
+if [ -n "${mysql_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=mysql,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: mysql
+ipServicePort: 3306
+ServiceType: sql
+ServiceVersion: MySQL ${mysql_version}
+EOT
+fi
+
+# MariaDB
+if is_pkg_installed mariadb-server-10.1; then
+ mariadb_version=$(get_pkg_version mariadb-server-10.1)
+elif is_pkg_installed mariadb-server-10.0; then
+ mariadb_version=$(get_pkg_version mariadb-server-10.0)
+fi
+if [ -n "${mariadb_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=mysql,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: mysql
+ipServicePort: 3306
+ServiceType: sql
+ServiceVersion: MariaDB ${mariadb_version}
+EOT
+fi
+
+# Squid
+if is_pkg_installed squid; then
+ # squid on Debian 9+
+ squid_version=$(get_pkg_version squid)
+elif is_pkg_installed squid3-common; then
+ # squid on Debian 8
+ squid_version=$(get_pkg_version squid3-common)
+fi
+if [ -n "${squid_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=squid,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: squid
+ipServicePort: 3128
+ServiceType: proxy
+ServiceVersion: Squid ${squid_version}
+EOT
+fi
+
+# ProFTPD
+if is_pkg_installed proftpd-basic; then
+ proftpd_version=$(get_pkg_version proftpd-basic)
+fi
+if [ -n "${proftpd_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=proftpd,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: proftpd
+ipServicePort: 3128
+ServiceType: ftp
+ServiceVersion: ProFTPD ${proftpd_version}
+EOT
+fi
+
+# OpenLDAP
+if is_pkg_installed slapd; then
+ ldap_version=$(get_pkg_version slapd)
+fi
+if [ -n "${ldap_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=openldap,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: openldap
+ipServicePort: 389
+ServiceType: ldap
+ServiceVersion: OpenLDAP ${ldap_version}
+EOT
+fi
+
+# Dovecot
+if is_pkg_installed dovecot-common; then
+ dovecot_version=$(get_pkg_version dovecot-common)
+fi
+if [ -n "${dovecot_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=dovecot-pop,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: dovecot-pop
+ipServicePort: 110
+ServiceType: pop
+ServiceVersion: Dovecot ${dovecot_version}
+
+dn: ServiceName=dovecot-pop-ssl,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: dovecot-pop-ssl
+ipServicePort: 995
+ServiceType: pop
+ServiceVersion: Dovecot ${dovecot_version}
+
+dn: ServiceName=dovecot-imap,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: dovecot-imap
+ipServicePort: 143
+ServiceType: imap
+ServiceVersion: Dovecot ${dovecot_version}
+
+dn: ServiceName=dovecot-imap-ssl,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: dovecot-imap-ssl
+ipServicePort: 993
+ServiceType: imap
+ServiceVersion: Dovecot ${dovecot_version}
+EOT
+fi
+
+# Amavis
+if is_pkg_installed amavisd-new; then
+ amavis_version=$(get_pkg_version amavisd-new)
+fi
+if [ -n "${amavis_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=amavisd-new,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: amavisd-new
+ipServicePort: 10024
+ServiceType: smtp
+ServiceVersion: amavisd-new ${amavis_version}
+EOT
+fi
+
+# ClamAV
+if is_pkg_installed clamav-daemon; then
+ clamav_version=$(get_pkg_version clamav-daemon)
+fi
+if [ -n "${clamav_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=clamav_db,${computer_dn}
+NagiosEnabled: TRUE
+objectClass: EvoService
+ServiceName: clamav_db
+ServiceType: antivirus
+ServiceVersion: ClamAV ${clamav_version}
+EOT
+fi
+
+# Elasticsearch
+if is_pkg_installed elasticsearch; then
+ elasticsearch_version=$(get_pkg_version elasticsearch)
+fi
+if [ -n "${elasticsearch_version}" ]; then
+ cat <> "${ldif_file}"
+
+dn: ServiceName=elasticsearch,${computer_dn}
+NagiosEnabled: TRUE
+ipServiceProtocol: tcp
+objectClass: EvoService
+ServiceName: elasticsearch
+ipServicePort: 9200
+ServiceType: http
+ServiceVersion: Elasticsearch ${elasticsearch_version}
+EOT
+fi
+
+# test if we have a stdout
+if [ -t 1 ]; then
+ echo "Output is in ${ldif_file}"
+fi
+
+exit 0
diff --git a/java8/tasks/main.yml b/java8/tasks/main.yml
index 22107bd5..8e24def3 100644
--- a/java8/tasks/main.yml
+++ b/java8/tasks/main.yml
@@ -11,7 +11,7 @@
- name: Java 8 is installed
apt:
- name: openjdk-8-jre
+ name: openjdk-8-jre-headless
default_release: "{{ java8_apt_release }}"
state: present
tags:
diff --git a/jenkins/meta/main.yml b/jenkins/meta/main.yml
new file mode 100644
index 00000000..eda76a17
--- /dev/null
+++ b/jenkins/meta/main.yml
@@ -0,0 +1,27 @@
+---
+galaxy_info:
+ author: Evolix
+ description: Install Jenkins
+
+ issue_tracker_url: https://forge.evolix.org/projects/ansible-roles/issues
+
+ license: GPLv2
+
+ min_ansible_version: 2.2
+
+ platforms:
+ - name: Debian
+ versions:
+ - jessie
+
+ galaxy_tags: []
+ # List tags for your role here, one per line. A tag is
+ # a keyword that describes and categorizes the role.
+ # Users find roles by searching for tags. Be sure to
+ # remove the '[]' above if you add tags to this list.
+ #
+ # NOTE: A tag is limited to a single word comprised of
+ # alphanumeric characters. Maximum 20 tags per role.
+
+dependencies:
+ - java8
diff --git a/jenkins/tasks/main.yml b/jenkins/tasks/main.yml
index 88db3b90..19496958 100644
--- a/jenkins/tasks/main.yml
+++ b/jenkins/tasks/main.yml
@@ -1,9 +1,5 @@
---
-- name: Include java8 role
- include_role:
- name: java8
-
- name: Add jenkins GPG key
apt_key:
# url: https://jenkins-ci.org/debian/jenkins-ci.org.key
diff --git a/kibana/README.md b/kibana/README.md
index 5d95b5a7..7239adf7 100644
--- a/kibana/README.md
+++ b/kibana/README.md
@@ -8,6 +8,8 @@ Everything is in the `tasks/main.yml` file.
## Available variables
+* `kibana_server_host` : Specifies the address to which the Kibana server will bind (default: `127.0.0.1`) ;
+* `kibana_server_basepath` : where to mount the application (default: empty) ;
* `kibana_proxy_nginx` : configure an Nginx proxy (not enabled) for Kibana (default: `False`) ;
* `kibana_proxy_domain` : domain to use for the proxy ;
* `kibana_proxy_ssl_cert` : certificate to use for the proxy ;
diff --git a/kibana/defaults/main.yml b/kibana/defaults/main.yml
index 7e7555f1..6fd7e16f 100644
--- a/kibana/defaults/main.yml
+++ b/kibana/defaults/main.yml
@@ -1,4 +1,8 @@
---
+
+kibana_server_host: "127.0.0.1"
+kibana_server_basepath: ""
+
kibana_proxy_nginx: False
kibana_proxy_domain: "kibana.{{ ansible_fqdn }}"
diff --git a/kibana/meta/main.yml b/kibana/meta/main.yml
index d0e7a891..dce2560a 100644
--- a/kibana/meta/main.yml
+++ b/kibana/meta/main.yml
@@ -12,6 +12,7 @@ galaxy_info:
- name: Debian
versions:
- jessie
+ - stretch
dependencies: []
# List your role dependencies here, one per line.
diff --git a/kibana/tasks/main.yml b/kibana/tasks/main.yml
index 9cf74638..6803568a 100644
--- a/kibana/tasks/main.yml
+++ b/kibana/tasks/main.yml
@@ -1,9 +1,5 @@
---
-- name: Install java8
- include_role:
- name: java8
-
- name: APT https transport is enabled
apt:
name: apt-transport-https
@@ -24,7 +20,7 @@
- name: Elastic sources list is available
apt_repository:
repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
- filename: elastic.list
+ filename: elastic
state: present
update_cache: yes
tags:
@@ -38,8 +34,24 @@
tags:
- packages
+- name: kibana server host configuration
+ lineinfile:
+ dest: /etc/kibana/kibana.yml
+ line: "server.host: \"{{ kibana_server_host }}\""
+ regexp: '^server.host:'
+ insertafter: '^#server.host:'
+ notify: restart kibana
+
+- name: kibana server basepath configuration
+ lineinfile:
+ dest: /etc/kibana/kibana.yml
+ line: "server.basePath: \"{{ kibana_server_basepath }}\""
+ regexp: '^server.basePath:'
+ insertafter: '^#server.basePath:'
+ notify: restart kibana
+
- name: Kibana service is enabled and started
- service:
+ systemd:
name: kibana
enabled: yes
state: started
@@ -62,22 +74,17 @@
when: not ansible_check_mode
- block:
- - name: Remount /usr as writable
- command: "mount -o remount,rw /usr"
- args:
- warn: no
+ - include_role:
+ name: remount-usr
- name: Move kibana optimize directory
- shell: "mv /usr/share/kibana/optimize /var/lib/kibana/optimize && ln -s /var/lib/kibana/optimize /usr/share/kibana/optimize"
+ shell: "mv /usr/share/kibana/{{ item }} /var/lib/kibana/{{ item }} && ln -s /var/lib/kibana/{{ item }} /usr/share/kibana/{{ item }}"
args:
- creates: /var/lib/kibana/optimize
+ creates: "/var/lib/kibana/{{ item }}"
notify: restart kibana
-
- - name: Remount /usr as read-only
- command: "mount -o remount /usr"
- args:
- warn: no
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
+ with_items:
+ - optimize
+ - data
- include: proxy_nginx.yml
when: kibana_proxy_nginx
diff --git a/kibana/tasks/remount_usr_rw.yml b/kibana/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/kibana/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/kibana/templates/nginx_proxy_kibana_nossl.j2 b/kibana/templates/nginx_proxy_kibana_nossl.j2
index 1540b841..3c674317 100644
--- a/kibana/templates/nginx_proxy_kibana_nossl.j2
+++ b/kibana/templates/nginx_proxy_kibana_nossl.j2
@@ -9,7 +9,7 @@ server {
server_name {{ kibana_proxy_domain }};
# Auth.
- include /etc/nginx/snippets/private_ipaddr_whitelist;
+ include /etc/nginx/snippets/ipaddr_whitelist;
deny all;
auth_basic "Reserved {{ kibana_proxy_domain }}";
auth_basic_user_file /etc/nginx/snippets/private_htpasswd;
diff --git a/kibana/templates/nginx_proxy_kibana_ssl.j2 b/kibana/templates/nginx_proxy_kibana_ssl.j2
index ea2e06c9..c72db251 100644
--- a/kibana/templates/nginx_proxy_kibana_ssl.j2
+++ b/kibana/templates/nginx_proxy_kibana_ssl.j2
@@ -19,7 +19,7 @@ server {
ssl_certificate_key {{ kibana_proxy_ssl_key }};
# Auth.
- include /etc/nginx/snippets/private_ipaddr_whitelist;
+ include /etc/nginx/snippets/ipaddr_whitelist;
deny all;
auth_basic "Reserved {{ kibana_proxy_domain }}";
auth_basic_user_file /etc/nginx/snippets/private_htpasswd;
diff --git a/kvm-host/tasks/main.yml b/kvm-host/tasks/main.yml
index a3ee3556..9fc73e93 100644
--- a/kvm-host/tasks/main.yml
+++ b/kvm-host/tasks/main.yml
@@ -5,21 +5,14 @@
- include: packages.yml
-- name: Check if /usr is a partition
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- changed_when: False
- failed_when: False
- check_mode: no
- register: usr_partition
+- include_role:
+ name: remount-usr
-- name: Mount /usr in rw
- command: mount -o remount,rw /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0
+- name: Copy add-vm script
+ get_url:
+ url: https://forge.evolix.org/projects/kvm-tools/repository/revisions/master/raw/add-vm.sh
+ dest: /usr/share/scripts/add-vm.sh
+ mode: "0750"
- include: munin.yml
diff --git a/ldap/defaults/main.yml b/ldap/defaults/main.yml
index 1e90583f..88631a11 100644
--- a/ldap/defaults/main.yml
+++ b/ldap/defaults/main.yml
@@ -1,4 +1,4 @@
---
-ldap_domain: "{{ ansible_fqdn }}"
-ldap_organization: "{{ ansible_domain }}"
-#ldap_password=$(apg -n1 -m 12 -c cl_seed)
+ldap_hostname: "{{ ansible_hostname }}"
+ldap_domain: "{{ ansible_domain }}"
+ldap_suffix: "dc={{ ldap_hostname }},dc={{ ldap_domain.split('.')[-2] }},dc={{ ldap_domain.split('.')[-1] }}"
diff --git a/ldap/tasks/main.yml b/ldap/tasks/main.yml
index c28c01fe..84bed58d 100644
--- a/ldap/tasks/main.yml
+++ b/ldap/tasks/main.yml
@@ -6,8 +6,82 @@
- slapd
- ldap-utils
- ldapvi
+ - shelldap
+
+- name: "Is /root/.ldapvirc present ?"
+ stat:
+ path: /root/.ldapvirc
+ check_mode: no
+ register: root_ldapvirc_path
- name: apg package is installed
apt:
name: apg
state: present
+ when: not root_ldapvirc_path.stat.exists
+
+- name: create a password for cn=admin
+ command: "apg -n 1 -m 16 -M lcN"
+ register: ldap_admin_password
+ changed_when: False
+ when: not root_ldapvirc_path.stat.exists
+
+- name: create a password for cn=nagios
+ command: "apg -n 1 -m 16 -M lcN"
+ register: ldap_nagios_password
+ changed_when: False
+ when: not root_ldapvirc_path.stat.exists
+
+- name: hash password for cn=admin
+ command: "slappasswd -s {{ ldap_admin_password.stdout }}"
+ register: ldap_admin_password_ssha
+ changed_when: False
+ when: not root_ldapvirc_path.stat.exists
+
+- name: hash password for cn=nagios
+ command: "slappasswd -s {{ ldap_nagios_password.stdout }}"
+ register: ldap_nagios_password_ssha
+ changed_when: False
+ when: not root_ldapvirc_path.stat.exists
+
+- name: create ldapvirc config
+ template:
+ src: ldapvirc.j2
+ dest: /root/.ldapvirc
+ mode: "0640"
+ when: not root_ldapvirc_path.stat.exists
+
+- name: upload ldap initial config
+ template:
+ src: config_ldapvi.j2
+ dest: /root/evolinux_ldap_config.ldapvi
+ mode: "0640"
+ when: not root_ldapvirc_path.stat.exists
+
+- name: upload ldap initial entries
+ template:
+ src: first-entries.ldif.j2
+ dest: /root/evolinux_ldap_first-entries.ldif
+ mode: "0640"
+ when: not root_ldapvirc_path.stat.exists
+
+- name: inject config
+ command: ldapvi -Y EXTERNAL -h ldapi:// --ldapmodify /root/evolinux_ldap_config.ldapvi
+ environment:
+ TERM: xterm
+ when: not root_ldapvirc_path.stat.exists
+
+- name: inject first entries
+ command: slapadd -l /root/evolinux_ldap_first-entries.ldif
+ when: not root_ldapvirc_path.stat.exists
+
+- name: upload custom schema
+ copy:
+ src: "{{ ldap_schema }}"
+ dest: "/root/{{ ldap_schema }}"
+ mode: "0640"
+ when: not root_ldapvirc_path.stat.exists and ldap_schema is defined
+
+- name: inject custom schema
+ command: "ldapadd -Y EXTERNAL -H ldapi:/// -f /root/{{ ldap_schema }}"
+ when: not root_ldapvirc_path.stat.exists and ldap_schema is defined
diff --git a/ldap/templates/config_ldapvi.j2 b/ldap/templates/config_ldapvi.j2
new file mode 100644
index 00000000..9be8044c
--- /dev/null
+++ b/ldap/templates/config_ldapvi.j2
@@ -0,0 +1,8 @@
+modify: olcDatabase={1}mdb,cn=config
+olcSuffix: {{ ldap_suffix }}
+olcRootDN: cn=admin,{{ ldap_suffix }}
+olcRootPW: {{ ldap_admin_password_ssha.stdout }}
+olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
+olcAccess: {1}to attrs=userPassword by self write by anonymous auth by dn="cn=admin,{{ ldap_suffix }}" write by dn="cn=perl,ou=ldapusers,{{ ldap_suffix }}" write by * none
+olcAccess: {2}to attrs=shadowLastChange by self write by dn="cn=admin,{{ ldap_suffix }}" write by dn="cn=perl,ou=ldapusers,{{ ldap_suffix }}" write by * read
+olcAccess: {3}to * by self write by dn="cn=admin,{{ ldap_suffix }}" write by dn="cn=perl,ou=ldapusers,{{ ldap_suffix }}" write by * read
diff --git a/ldap/templates/first-entries.ldif.j2 b/ldap/templates/first-entries.ldif.j2
new file mode 100644
index 00000000..0e82ddbc
--- /dev/null
+++ b/ldap/templates/first-entries.ldif.j2
@@ -0,0 +1,30 @@
+dn: {{ ldap_suffix }}
+objectClass: top
+objectClass: dcObject
+objectClass: organization
+o: {{ ldap_domain }}
+dc: {{ ldap_hostname }}
+
+dn: cn=admin,{{ ldap_suffix }}
+objectClass: simpleSecurityObject
+objectClass: organizationalRole
+cn: admin
+description: LDAP administrator
+userPassword: {{ ldap_admin_password_ssha.stdout }}
+
+dn: ou=ldapusers,{{ ldap_suffix }}
+objectClass: top
+objectClass: organizationalUnit
+ou: ldapusers
+
+dn: cn=perl,ou=ldapusers,{{ ldap_suffix }}
+objectClass: simpleSecurityObject
+objectClass: organizationalRole
+cn: perl
+userPassword: {{ ldap_admin_password_ssha.stdout }}
+
+dn: cn=nagios,ou=ldapusers,{{ ldap_suffix }}
+objectClass: simpleSecurityObject
+objectClass: organizationalRole
+cn: nagios
+userPassword: {{ ldap_nagios_password_ssha.stdout }}
diff --git a/ldap/templates/ldapvirc.j2 b/ldap/templates/ldapvirc.j2
new file mode 100644
index 00000000..e61a7524
--- /dev/null
+++ b/ldap/templates/ldapvirc.j2
@@ -0,0 +1,6 @@
+profile default
+host: ldap://127.0.0.1
+base: {{ ldap_suffix }}
+user: cn=admin,{{ ldap_suffix }}
+bind: simple
+password: {{ ldap_admin_password.stdout }}
diff --git a/listupgrade/tasks/main.yml b/listupgrade/tasks/main.yml
index 74944eca..de9fdb2c 100644
--- a/listupgrade/tasks/main.yml
+++ b/listupgrade/tasks/main.yml
@@ -22,7 +22,7 @@
state: directory
owner: root
group: root
- mode: "0600"
+ mode: "0700"
- name: Copy listupgrade config
template:
diff --git a/logstash/defaults/main.yml b/logstash/defaults/main.yml
index 2d3c7b40..e563f517 100644
--- a/logstash/defaults/main.yml
+++ b/logstash/defaults/main.yml
@@ -1,3 +1,4 @@
---
logstash_jvm_xms: 256m
logstash_jvm_xmx: 1g
+logstash_log_rotate_days: 365
diff --git a/logstash/meta/main.yml b/logstash/meta/main.yml
index 629e9f67..c74021e7 100644
--- a/logstash/meta/main.yml
+++ b/logstash/meta/main.yml
@@ -13,7 +13,5 @@ galaxy_info:
versions:
- jessie
-dependencies: []
- # List your role dependencies here, one per line.
- # Be sure to remove the '[]' above if you add dependencies
- # to this list.
+dependencies:
+ - java8
diff --git a/logstash/tasks/logs.yml b/logstash/tasks/logs.yml
new file mode 100644
index 00000000..9d5b5023
--- /dev/null
+++ b/logstash/tasks/logs.yml
@@ -0,0 +1,9 @@
+---
+
+- name: "log rotation script"
+ template:
+ src: rotate_logstash_logs.j2
+ dest: /etc/cron.daily/rotate_logstash_logs
+ owner: root
+ group: root
+ mode: "0750"
diff --git a/logstash/tasks/main.yml b/logstash/tasks/main.yml
index 16e9ae79..71be5614 100644
--- a/logstash/tasks/main.yml
+++ b/logstash/tasks/main.yml
@@ -1,11 +1,5 @@
---
-- name: Install java8
- include_role:
- name: java8
- tags:
- - packages
-
- name: APT https transport is enabled
apt:
name: apt-transport-https
@@ -26,7 +20,7 @@
- name: Elastic sources list is available
apt_repository:
repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
- filename: elastic.list
+ filename: elastic
state: present
update_cache: yes
tags:
@@ -41,7 +35,7 @@
- packages
- name: Logstash service is enabled
- service:
+ systemd:
name: logstash
enabled: yes
@@ -76,3 +70,5 @@
- debug:
var: logstash_template
verbosity: 1
+
+- include: logs.yml
diff --git a/logstash/templates/rotate_logstash_logs.j2 b/logstash/templates/rotate_logstash_logs.j2
new file mode 100644
index 00000000..40155506
--- /dev/null
+++ b/logstash/templates/rotate_logstash_logs.j2
@@ -0,0 +1,9 @@
+#!/bin/sh
+# {{ ansible_managed }}
+
+LOG_DIR=/var/log/logstash
+MAX_AGE={{ logstash_log_rotate_days | mandatory }}
+
+find ${LOG_DIR} -type f -user logstash -name "logstash.log.*.gz" -mtime +${MAX_AGE} -delete
+find ${LOG_DIR} -type f -user root -name "logstash.err.*.gz" -mtime +${MAX_AGE} -delete
+find ${LOG_DIR} -type f -user root -name "logstash.stdout.*.gz" -mtime +${MAX_AGE} -delete
diff --git a/memcached/README.md b/memcached/README.md
index 3c571029..38e5f89d 100644
--- a/memcached/README.md
+++ b/memcached/README.md
@@ -1,4 +1,4 @@
-# PHP-FPM
+# Memcached
Installation and basic configuration of memcached
diff --git a/meta/main.yml b/meta/main.yml
new file mode 100644
index 00000000..b32a44cf
--- /dev/null
+++ b/meta/main.yml
@@ -0,0 +1,2 @@
+---
+galaxy_info:
diff --git a/minifirewall/defaults/main.yml b/minifirewall/defaults/main.yml
index 69e1e8fe..4c8498cf 100644
--- a/minifirewall/defaults/main.yml
+++ b/minifirewall/defaults/main.yml
@@ -6,16 +6,23 @@ minifirewall_checkout_path: "/tmp/minifirewall"
minifirewall_int: "{{ ansible_default_ipv4.interface }}"
minifirewall_ipv6: "on"
minifirewall_intlan: "{{ ansible_default_ipv4.address }}/32"
-minifirewall_trusted_ips: ["0.0.0.0/0"]
+
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+# and default to ['0.0.0.0/0'] if the result is still empty
+minifirewall_trusted_ips: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique | default(['0.0.0.0/0'], true) }}"
minifirewall_privilegied_ips: []
minifirewall_protected_ports_tcp: [22]
minifirewall_protected_ports_udp: []
-minifirewall_public_ports_tcp: [22, 80, 443]
-minifirewall_public_ports_udp: []
-minifirewall_semipublic_ports_tcp: [20, 21, 25]
+minifirewall_public_ports_tcp: [25, 53, 443, 993, 995, 2222]
+minifirewall_public_ports_udp: [53]
+minifirewall_semipublic_ports_tcp: [20, 21, 22, 80, 110, 143]
minifirewall_semipublic_ports_udp: []
minifirewall_private_ports_tcp: [5666]
minifirewall_private_ports_udp: []
minifirewall_autostart: "no"
+
+evomaintenance_hosts: []
diff --git a/minifirewall/tasks/config.yml b/minifirewall/tasks/config.yml
index 80acf5d0..ea6b1a9e 100644
--- a/minifirewall/tasks/config.yml
+++ b/minifirewall/tasks/config.yml
@@ -94,6 +94,20 @@
SERVICESUDP3='{{ minifirewall_private_ports_udp | join(' ') }}'
register: minifirewall_config_ports
+- name: evomaintenance
+ lineinfile:
+ dest: /etc/default/minifirewall
+ line: "/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s {{ item }} -m state --state ESTABLISHED,RELATED -j ACCEPT"
+ insertafter: "^# EvoMaintenance"
+ with_items: "{{ evomaintenance_hosts }}"
+
+- name: remove minifirewall example rule for the evomaintenance
+ lineinfile:
+ dest: /etc/default/minifirewall
+ regexp: '^#.*(--sport 5432).*(-s X\.X\.X\.X)'
+ state: absent
+ when: evomaintenance_hosts != []
+
- name: restart minifirewall
# service:
# name: minifirewall
diff --git a/minifirewall/tasks/install.yml b/minifirewall/tasks/install.yml
index 47d72b44..5efdd585 100644
--- a/minifirewall/tasks/install.yml
+++ b/minifirewall/tasks/install.yml
@@ -1,5 +1,12 @@
---
+- name: dependencies are satisfied
+ apt:
+ name: '{{ item }}'
+ state: present
+ with_items:
+ - iptables
+
- name: init script is copied
copy:
src: minifirewall
diff --git a/minifirewall/tasks/main.yml b/minifirewall/tasks/main.yml
index 0208313a..851d1917 100644
--- a/minifirewall/tasks/main.yml
+++ b/minifirewall/tasks/main.yml
@@ -1,12 +1,5 @@
---
-- name: packages are installed
- apt:
- name: '{{ item }}'
- state: present
- with_items:
- - iptables
-
- include: install.yml
- include: config.yml
diff --git a/mysql/tasks/munin.yml b/mysql/tasks/munin.yml
index 0903def1..52b6eed4 100644
--- a/mysql/tasks/munin.yml
+++ b/mysql/tasks/munin.yml
@@ -36,18 +36,25 @@
dest: '/etc/munin/plugins/mysql_{{ item }}'
state: link
with_items:
+ - commands
- connections
- files_tables
- innodb_bpool
- innodb_bpool_act
+ - innodb_insert_buf
- innodb_io
+ - innodb_io_pend
- innodb_log
- innodb_rows
- innodb_semaphores
- myisam_indexes
+ - network_traffic
- qcache
- qcache_mem
+ - select_types
+ - slow
- sorts
+ - table_locks
- tmp_tables
notify: restart munin-node
diff --git a/mysql/tasks/remount_usr_rw.yml b/mysql/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/mysql/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/mysql/tasks/users_jessie.yml b/mysql/tasks/users_jessie.yml
index a8c22cf8..e1a02130 100644
--- a/mysql/tasks/users_jessie.yml
+++ b/mysql/tasks/users_jessie.yml
@@ -13,6 +13,7 @@
command: "apg -n 1 -m 16 -M lcN"
register: mysql_admin_password
changed_when: False
+ check_mode: no
tags:
- mysql
diff --git a/mysql/tasks/utils.yml b/mysql/tasks/utils.yml
index d0fe71a8..a6fc307c 100644
--- a/mysql/tasks/utils.yml
+++ b/mysql/tasks/utils.yml
@@ -30,9 +30,10 @@
when: ansible_distribution_major_version | version_compare('9', '>=')
- name: Read debian-sys-maint password
- shell: cat /etc/mysql/debian.cnf | grep -m1 "password = .*" | cut -d" " -f3
+ shell: 'cat /etc/mysql/debian.cnf | grep -m1 "password = .*" | cut -d" " -f3'
register: mysql_debian_password
changed_when: False
+ check_mode: no
tags:
- mysql
@@ -48,7 +49,8 @@
# mysqltuner
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
when: (mysql_scripts_dir or general_scripts_dir) | search ("/usr")
- name: Install mysqltuner
@@ -71,7 +73,8 @@
# automatic optimizations
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
when: (mysql_scripts_dir or general_scripts_dir) | search ("/usr")
- name: Optimize script for MySQL
@@ -133,7 +136,8 @@
# my-add.sh
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
when: (mysql_scripts_dir or general_scripts_dir) | search ("/usr")
- name: Install my-add.sh
diff --git a/nagios-nrpe/defaults/main.yml b/nagios-nrpe/defaults/main.yml
index c9ee2603..96c3ddd3 100644
--- a/nagios-nrpe/defaults/main.yml
+++ b/nagios-nrpe/defaults/main.yml
@@ -1,5 +1,8 @@
---
-nagios_nrpe_allowed_hosts: []
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+nagios_nrpe_allowed_hosts: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
nagios_nrpe_ldap_dc: "dc=DOMAIN,dc=EXT"
nagios_nrpe_ldap_passwd: LDAP_PASSWD
nagios_nrpe_pgsql_passwd: PGSQL_PASSWD
diff --git a/nagios-nrpe/files/plugins/check_amavis b/nagios-nrpe/files/plugins/check_amavis
index 43e69bcb..d364dba3 100755
--- a/nagios-nrpe/files/plugins/check_amavis
+++ b/nagios-nrpe/files/plugins/check_amavis
@@ -3,12 +3,14 @@
use Getopt::Long;
use MIME::Entity;
use Net::SMTP;
+use POSIX qw(strftime);
my $server = '';
my $port = 10024;
my $from = '';
my $to = '';
my $debug = 0;
+my $date = strftime "%a, %d %b %g %X %z", localtime;
$result = GetOptions (
"server|s=s" => \$server,
@@ -32,6 +34,7 @@ my $top = MIME::Entity->build(
Type =>"multipart/mixed",
From => $from,
To => $to,
+ Date => $date,
Subject => "EICAR test",
Data => "This is a test",
);
@@ -62,7 +65,7 @@ $smtp->close();
print "$result\n";
-if ($result =~/2.7.0 Ok, discarded/) {
+if ($result =~/2.5.0 Ok, id=[^,]+, BOUNCE/) {
print "OK - All fine\n";
exit 0;
} else {
diff --git a/nagios-nrpe/files/plugins_bsd/check_free_mem.sh b/nagios-nrpe/files/plugins_bsd/check_free_mem.sh
index f2261ea9..f0b79c8a 100755
--- a/nagios-nrpe/files/plugins_bsd/check_free_mem.sh
+++ b/nagios-nrpe/files/plugins_bsd/check_free_mem.sh
@@ -64,7 +64,7 @@ __EOT
# Total memory size (in MB)
tot_mem=$(( `/sbin/sysctl -n hw.physmem` / BYTES_IN_MB))
# Free memory size (in MB)
-free_mem=$(( `/usr/bin/vmstat | /usr/bin/tail -1 | /usr/bin/awk '{ print $5 }'` / KB_IN_MB ))
+free_mem=$(/usr/bin/vmstat | /usr/bin/tail -1 | /usr/bin/awk '{ print $4 }' | tr -d 'M')
# Free memory size (in percentage)
free_mem_perc=$(( free_mem * 100 / tot_mem ))
diff --git a/nagios-nrpe/tasks/main.yml b/nagios-nrpe/tasks/main.yml
index dbb73903..d0298c6c 100644
--- a/nagios-nrpe/tasks/main.yml
+++ b/nagios-nrpe/tasks/main.yml
@@ -17,6 +17,7 @@
dest: /etc/nagios/nrpe.d/evolix.cfg
group: nagios
mode: "0640"
+ force: no
notify: restart nagios-nrpe-server
- name: Nagios config is secured
@@ -27,7 +28,8 @@
state: directory
notify: restart nagios-nrpe-server
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
when: nagios_plugins_directory | search ("/usr")
tags:
- nagios-plugins
diff --git a/nagios-nrpe/tasks/remount_usr_rw.yml b/nagios-nrpe/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/nagios-nrpe/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/nagios-nrpe/templates/evolix.cfg.j2 b/nagios-nrpe/templates/evolix.cfg.j2
index 45223167..38e29b27 100644
--- a/nagios-nrpe/templates/evolix.cfg.j2
+++ b/nagios-nrpe/templates/evolix.cfg.j2
@@ -28,6 +28,7 @@ command[check_ldap]=/usr/lib/nagios/plugins/check_ldap -3 -H localhost -D cn=nag
command[check_ldaps]=/usr/lib/nagios/plugins/check_ldaps -3 -H localhost -b {{ nagios_nrpe_ldap_dc }}
command[check_imap]=/usr/lib/nagios/plugins/check_imap -H localhost
command[check_imaps]=/usr/lib/nagios/plugins/check_imap -S -H localhost -p 993
+command[check_imapproxy]=/usr/lib/nagios/plugins/check_imap -H localhost -p 1143
command[check_pop]=/usr/lib/nagios/plugins/check_pop -H localhost
command[check_pops]=/usr/lib/nagios/plugins/check_pop -S -H localhost -p 995
command[check_ftp]=/usr/lib/nagios/plugins/check_ftp -H localhost
@@ -48,6 +49,7 @@ command[check_clamav_db]=/usr/lib/nagios/plugins/check_file_age -w 86400 -c 1728
command[check_ssl]=/usr/lib/nagios/plugins/check_http -f follow -I 127.0.0.1 -S -p 443 -H ssl.evolix.net -C 15,5
command[check_elasticsearch]=/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -u /_cat/health?h=st -p 9200 -r 'red' --invert-regex
command[check_memcached]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 11211
+command[check_opendkim]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 54321
# Local checks (not packaged)
command[check_mem]={{ nagios_plugins_directory }}/check_mem -f -C -w 20 -c 10
diff --git a/nginx/README.md b/nginx/README.md
index d519608b..73ede527 100644
--- a/nginx/README.md
+++ b/nginx/README.md
@@ -18,8 +18,8 @@ Main variables are :
* `nginx_minimal` : very basic install and config (default: `False`) ;
* `nginx_jessie_backports` : on Debian Jessie, we can prefer v1.10 from backports (default: `False`) ;
-* `nginx_private_ipaddr_whitelist_present` : list of IP addresses to have in the private whitelist ;
-* `nginx_private_ipaddr_whitelist_absent` : list of IP addresses **not** to have in the whitelist ;
+* `nginx_ipaddr_whitelist_present` : list of IP addresses to have in the private whitelist ;
+* `nginx_ipaddr_whitelist_absent` : list of IP addresses **not** to have in the whitelist ;
* `nginx_private_htpasswd_present` : list of users to have in the private htpasswd ;
* `nginx_private_htpasswd_absent` : list of users to **not** have in the private htpasswd.
diff --git a/nginx/defaults/main.yml b/nginx/defaults/main.yml
index 16398ee4..38dcbb89 100644
--- a/nginx/defaults/main.yml
+++ b/nginx/defaults/main.yml
@@ -3,8 +3,11 @@
nginx_minimal: False
nginx_jessie_backports: False
-nginx_private_ipaddr_whitelist_present: []
-nginx_private_ipaddr_whitelist_absent: []
+evolix_trusted_ips: []
+additional_trusted_ips: []
+# Let's merge evolix_trusted_ips with additional_trusted_ips
+nginx_ipaddr_whitelist_present: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
+nginx_ipaddr_whitelist_absent: []
nginx_private_htpasswd_present: []
nginx_private_htpasswd_absent: []
diff --git a/nginx/files/nginx/snippets/private_ipaddr_whitelist b/nginx/files/nginx/snippets/ipaddr_whitelist
similarity index 100%
rename from nginx/files/nginx/snippets/private_ipaddr_whitelist
rename to nginx/files/nginx/snippets/ipaddr_whitelist
diff --git a/nginx/tasks/main_regular.yml b/nginx/tasks/main_regular.yml
index 74580972..f6563b76 100644
--- a/nginx/tasks/main_regular.yml
+++ b/nginx/tasks/main_regular.yml
@@ -38,13 +38,13 @@
- nginx
# TODO: verify that those permissions are correct :
-# not too strict for private_ipaddr_whitelist
+# not too strict for ipaddr_whitelist
# and not too loose for private_htpasswd
-- name: Copy private_ipaddr_whitelist
+- name: Copy ipaddr_whitelist
copy:
- src: nginx/snippets/private_ipaddr_whitelist
- dest: /etc/nginx/snippets/private_ipaddr_whitelist
+ src: nginx/snippets/ipaddr_whitelist
+ dest: /etc/nginx/snippets/ipaddr_whitelist
owner: www-data
group: www-data
directory_mode: "0640"
@@ -56,20 +56,20 @@
- name: add IP addresses to private IP whitelist
lineinfile:
- dest: /etc/nginx/snippets/private_ipaddr_whitelist
+ dest: /etc/nginx/snippets/ipaddr_whitelist
line: "allow {{ item }};"
state: present
- with_items: "{{ nginx_private_ipaddr_whitelist_present }}"
+ with_items: "{{ nginx_ipaddr_whitelist_present }}"
notify: reload nginx
tags:
- nginx
- name: remove IP addresses from private IP whitelist
lineinfile:
- dest: /etc/nginx/snippets/private_ipaddr_whitelist
+ dest: /etc/nginx/snippets/ipaddr_whitelist
line: "allow {{ item }};"
state: absent
- with_items: "{{ nginx_private_ipaddr_whitelist_absent }}"
+ with_items: "{{ nginx_ipaddr_whitelist_absent }}"
notify: reload nginx
tags:
- nginx
@@ -112,6 +112,7 @@
src: evolinux-default.conf.j2
dest: /etc/nginx/sites-available/evolinux-default.conf
mode: "0640"
+ force: no
notify: reload nginx
tags:
- nginx
diff --git a/nginx/templates/evolinux-default.conf.j2 b/nginx/templates/evolinux-default.conf.j2
index 165f39f8..cc2d7f46 100644
--- a/nginx/templates/evolinux-default.conf.j2
+++ b/nginx/templates/evolinux-default.conf.j2
@@ -23,8 +23,7 @@ server {
root /var/www;
# Auth.
- include /etc/nginx/snippets/private_ipaddr_whitelist;
- deny all;
+ include /etc/nginx/snippets/ipaddr_whitelist;
auth_basic "Reserved {{ ansible_fqdn }}";
auth_basic_user_file /etc/nginx/snippets/private_htpasswd;
satisfy any;
diff --git a/opendkim/files/opendkim-add.sh b/opendkim/files/opendkim-add.sh
new file mode 100644
index 00000000..a7da1ce0
--- /dev/null
+++ b/opendkim/files/opendkim-add.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+if [ "$#" -ne 1 ]; then
+ echo "Usage : $0 example.com" >&2
+ exit 1
+fi
+
+domain="$(echo "$1"|xargs)"
+
+mkdir -pm 0750 "/etc/opendkim/keys/${domain}"
+chown opendkim:opendkim "/etc/opendkim/keys/${domain}"
+
+if [ ! -f "/etc/opendkim/keys/${domain}/default.private" ]; then
+ cd "/etc/opendkim/keys/${domain}"
+ echo "Generate DKIM keys ..."
+ sudo -u opendkim opendkim-genkey -r -d "${domain}"
+ chmod 640 /etc/opendkim/keys/${domain}/*
+fi
+
+grep -q "${domain}" /etc/opendkim/TrustedHosts
+if [ "$?" -ne 0 ]; then
+ echo "Add ${domain} to TrustedHosts ..."
+ echo "${domain}" >> /etc/opendkim/TrustedHosts
+fi
+
+grep -q "${domain}" /etc/opendkim/KeyTable
+if [ "$?" -ne 0 ]; then
+ echo "Add ${domain} to KeyTable ..."
+ echo "default._domainkey.${domain} ${domain}:default:/etc/opendkim/keys/${domain}/default.private" >> /etc/opendkim/KeyTable
+fi
+
+grep -q "${domain}" /etc/opendkim/SigningTable
+if [ "$?" -ne 0 ]; then
+ echo "Add ${domain} to SigningTable ..."
+ echo "*@${domain} default._domainkey.${domain}" >> /etc/opendkim/SigningTable
+fi
+
+systemctl reload opendkim
+if [ "$?" -eq 0 ]; then
+ echo "OpenDKIM successfully reloaded"
+ echo "Public key is in : /etc/opendkim/keys/${domain}/default.txt"
+ exit 0
+else
+ echo "An error has occurred while opendkim reload, please FIX configuration !" >&2
+ exit 1
+fi
diff --git a/opendkim/files/opendkim.conf b/opendkim/files/opendkim.conf
new file mode 100644
index 00000000..c8c4d385
--- /dev/null
+++ b/opendkim/files/opendkim.conf
@@ -0,0 +1,18 @@
+UserID opendkim:opendkim
+Socket inet:54321@127.0.0.1
+PidFile /var/run/opendkim/opendkim.pid
+OversignHeaders From
+TrustAnchorFile /usr/share/dns/root.key
+Selector default
+Canonicalization relaxed/relaxed
+ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
+InternalHosts refile:/etc/opendkim/TrustedHosts
+KeyTable refile:/etc/opendkim/KeyTable
+LogResults Yes
+LogWhy Yes
+Mode sv
+SigningTable refile:/etc/opendkim/SigningTable
+Syslog Yes
+SyslogSuccess Yes
+TemporaryDirectory /var/tmp
+UMask 007
diff --git a/opendkim/handlers/main.yml b/opendkim/handlers/main.yml
new file mode 100644
index 00000000..ccf166a8
--- /dev/null
+++ b/opendkim/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+- name: reload opendkim
+ systemd:
+ name: opendkim
+ state: reloaded
+
+- name: restart opendkim
+ systemd:
+ name: opendkim
+ state: restarted
diff --git a/opendkim/tasks/main.yml b/opendkim/tasks/main.yml
new file mode 100644
index 00000000..8c81b686
--- /dev/null
+++ b/opendkim/tasks/main.yml
@@ -0,0 +1,78 @@
+---
+- name: install OpenDKIM
+ apt:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - opendkim
+ - opendkim-tools
+ tags:
+ - opendkim
+
+- name: create keys directory
+ file:
+ name: "{{ item }}"
+ state: directory
+ owner: opendkim
+ group: opendkim
+ mode: "0750"
+ with_items:
+ - '/etc/opendkim'
+ - '/etc/opendkim/keys'
+ tags:
+ - opendkim
+
+- name: add 127.0.0.1 to TrustedHosts
+ lineinfile:
+ dest: '/etc/opendkim/TrustedHosts'
+ line: '127.0.0.1'
+ create: True
+ owner: opendkim
+ group: opendkim
+ mode: "0640"
+ notify: reload opendkim
+ tags:
+ - opendkim
+
+- name: create config files
+ file:
+ name: "/etc/opendkim/{{ item }}"
+ state: touch
+ owner: opendkim
+ group: opendkim
+ mode: "0640"
+ with_items:
+ - 'KeyTable'
+ - 'SigningTable'
+ changed_when: False
+ tags:
+ - opendkim
+
+- name: copy OpenDKIM config
+ copy:
+ src: opendkim.conf
+ dest: /etc/opendkim.conf
+ mode: "0644"
+ force: yes
+ notify: restart opendkim
+ tags:
+ - opendkim
+
+- name: ensure opendkim is started and enabled
+ systemd:
+ name: opendkim
+ state: started
+ enabled: True
+ tags:
+ - opendkim
+
+- include_role:
+ name: remount-usr
+
+- name: deploy opendkim-add.sh script
+ copy:
+ src: opendkim-add.sh
+ dest: /usr/share/scripts/opendkim-add.sh
+ mode: "0750"
+ tags:
+ - opendkim
diff --git a/packweb-apache/README.md b/packweb-apache/README.md
index d3f3f5b6..99e25da1 100644
--- a/packweb-apache/README.md
+++ b/packweb-apache/README.md
@@ -4,7 +4,7 @@ Install the web pack, with Apache.
## Tasks
-Everything is in the `tasks/main.yml` file for now.
+See `tasks/main.yml`.
## Available variables
diff --git a/packweb-apache/meta/main.yml b/packweb-apache/meta/main.yml
new file mode 100644
index 00000000..914dbebb
--- /dev/null
+++ b/packweb-apache/meta/main.yml
@@ -0,0 +1,19 @@
+galaxy_info:
+ author: Evolix
+ description: Installation of Evolix "Pack Web" meta-role
+
+ issue_tracker_url: https://forge.evolix.org/projects/ansible-roles/issues
+
+ license: GPLv2
+
+ min_ansible_version: 2.2
+
+ platforms:
+ - name: Debian
+ versions:
+ - jessie
+ - stretch
+
+dependencies:
+ - { role: squid, squid_localproxy_enable: True }
+ - mysql
diff --git a/packweb-apache/tasks/awstats.yml b/packweb-apache/tasks/awstats.yml
index 1919b17d..5ea0fa57 100644
--- a/packweb-apache/tasks/awstats.yml
+++ b/packweb-apache/tasks/awstats.yml
@@ -46,3 +46,11 @@
create: yes
regexp: '-config=awstats'
line: "10 */6 * * * root umask 033; [ -x /usr/lib/cgi-bin/awstats.pl -a -f /etc/awstats/awstats.conf -a -r /var/log/apache2/access.log ] && /usr/lib/cgi-bin/awstats.pl -config=awstats -update >/dev/null"
+
+- name: Comment default awstat cron's tasks
+ lineinfile:
+ dest: /etc/cron.d/awstats
+ regexp: "(?i)^([^#]*update\\.sh.*)"
+ line: '#\1'
+ backrefs: yes
+ state: present
diff --git a/php/defaults/main.yml b/php/defaults/main.yml
index ca243024..d12014b2 100644
--- a/php/defaults/main.yml
+++ b/php/defaults/main.yml
@@ -1,5 +1,6 @@
---
+php_sury_enable: False
php_fpm_enable: False
php_apache_enable: False
php_symfony_requirements: False
diff --git a/php/files/sury.preferences b/php/files/sury.preferences
new file mode 100644
index 00000000..9c644b5d
--- /dev/null
+++ b/php/files/sury.preferences
@@ -0,0 +1,7 @@
+Package: php* libapache2-mod-php*
+Pin: origin packages.sury.org
+Pin-Priority: 999
+
+Package: *
+Pin: origin packages.sury.org
+Pin-Priority: 50
diff --git a/php/tasks/apache.yml b/php/tasks/apache.yml
index df352848..cefeb95c 100644
--- a/php/tasks/apache.yml
+++ b/php/tasks/apache.yml
@@ -52,6 +52,7 @@
section: PHP
option: disable_functions
value: "exec,shell-exec,system,passthru,putenv,popen"
+ mode: "0644"
- name: Custom php.ini
copy:
@@ -59,6 +60,7 @@
content: |
; Put customized values here.
; default_charset = "ISO-8859-1"
+ mode: "0644"
force: no
- name: "Set custom values for PHP to enable Symfony"
diff --git a/php/tasks/main.yml b/php/tasks/main.yml
index 7ea4269c..9b1d3375 100644
--- a/php/tasks/main.yml
+++ b/php/tasks/main.yml
@@ -8,6 +8,9 @@
- include: php_jessie.yml
when: ansible_distribution_release == "jessie"
+- include: php_stretch_sury.yml
+ when: ansible_distribution_major_version | version_compare('9', '>=') and php_sury_enable
+
- include: php_stretch.yml
when: ansible_distribution_major_version | version_compare('9', '>=')
diff --git a/php/tasks/php_stretch_sury.yml b/php/tasks/php_stretch_sury.yml
new file mode 100644
index 00000000..be549804
--- /dev/null
+++ b/php/tasks/php_stretch_sury.yml
@@ -0,0 +1,23 @@
+---
+
+- name: Setup deb.sury.org repository - Add GPG key
+ get_url:
+ url: https://packages.sury.org/php/apt.gpg
+ dest: /etc/apt/trusted.gpg.d/sury.gpg
+ mode: "0644"
+
+- name: Setup deb.sury.org repository - Install apt-transport-https
+ apt:
+ state: present
+ name: apt-transport-https
+
+- name: Setup deb.sury.org repository - Add preferences file
+ copy:
+ src: sury.preferences
+ dest: /etc/apt/preferences.d/z-sury
+
+- name: Setup deb.sury.org repository - Add source list
+ apt_repository:
+ repo: "deb https://packages.sury.org/php/ stretch main"
+ filename: sury
+ state: present
diff --git a/postfix/README.md b/postfix/README.md
index 67f56298..04bf879a 100644
--- a/postfix/README.md
+++ b/postfix/README.md
@@ -4,9 +4,10 @@ Installation and basic configuration of Postfix.
## Tasks
-Minimal configuration is in `tasks/main.yml` and optional customization in :
+Minimal configuration is in `tasks/minimal.yml` and optional customization in :
* `slow_transport.yml` : slow transport to specific destination.
+* `packmail.yml` : config for virtual mail accounts with OpenLDAP
## Available variables
@@ -14,5 +15,7 @@ Main variables are :
* `postfix_hostname` : hostname for Postfix ;
* `postfix_slow_transport` : enable customization for delivrability.
+* `postfix_force_main_cf` : force copy of main.cf
+* `postfix_packmail` : install an Evolix Packmail instead of lite postfix config
The full list of variables (with default values) can be found in `defaults/main.yml`.
diff --git a/postfix/defaults/main.yml b/postfix/defaults/main.yml
index f0673d65..55ab72cd 100644
--- a/postfix/defaults/main.yml
+++ b/postfix/defaults/main.yml
@@ -1,3 +1,5 @@
---
postfix_hostname: "{{ ansible_fqdn }}"
-postfix_slow_transport_include: False
+postfix_force_main_cf: False
+postfix_packmail: False
+postfix_slow_transport_include: "{{ postfix_packmail }}"
diff --git a/postfix/files/cn4evolix.ldif b/postfix/files/cn4evolix.ldif
new file mode 100644
index 00000000..a17532ad
--- /dev/null
+++ b/postfix/files/cn4evolix.ldif
@@ -0,0 +1,63 @@
+dn: cn={4}evolix,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: {4}evolix
+olcAttributeTypes: {0}( 1.3.6.1.4.1.24331.22.1.1 NAME 'maildrop' DESC 'mail fo
+ rward' SUP mail )
+olcAttributeTypes: {1}( 1.3.6.1.4.1.24331.22.1.2 NAME 'mailacceptinggeneralid'
+ DESC 'mail alias' SUP mail )
+olcAttributeTypes: {2}( 1.3.6.1.4.1.24331.22.1.3 NAME 'isActive' DESC 'boolean
+ to verify an global account is active or not' EQUALITY booleanMatch SYNTAX 1
+ .3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {3}( 1.3.6.1.4.1.24331.22.1.4 NAME 'accountActive' DESC 'bo
+ olean to verify if an mail account is active' EQUALITY booleanMatch SYNTAX 1.
+ 3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {4}( 1.3.6.1.4.1.24331.22.1.5 NAME 'authsmtpActive' DESC 'b
+ oolean to verify if SMTP-AUTH is enabled for entry' EQUALITY booleanMatch SYN
+ TAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {5}( 1.3.6.1.4.1.24331.22.1.6 NAME 'courierActive' DESC 'bo
+ olean to verify if Courier POP/IMAP is enabled for entry' EQUALITY booleanMat
+ ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {6}( 1.3.6.1.4.1.24331.22.1.7 NAME 'webmailActive' DESC 'bo
+ olean to verify if webmail is enabled for entry' EQUALITY booleanMatch SYNTAX
+ 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {7}( 1.3.6.1.4.1.24331.22.1.8 NAME 'isAdmin' DESC 'boolean
+ to verify if entry is admin for entry' EQUALITY booleanMatch SYNTAX 1.3.6.1.4
+ .1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {8}( 1.3.6.1.4.1.24331.22.1.9 NAME 'postfixTransport' DESC
+ 'transport for Postfix' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.11
+ 5.121.1.26{20} SINGLE-VALUE )
+olcAttributeTypes: {9}( 1.3.6.1.4.1.24331.22.1.10 NAME 'domain' DESC 'Postfix
+ domain' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTA
+ X 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+olcAttributeTypes: {10}( 1.3.6.1.4.1.24331.22.1.11 NAME 'quota' DESC 'Courier
+ maildir quota' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.
+ 26 SINGLE-VALUE )
+olcAttributeTypes: {11}( 1.3.6.1.4.1.24331.22.1.16 NAME 'vacationActive' DESC
+ 'A flag, for marking the user as being away' EQUALITY booleanMatch SYNTAX 1.3
+ .6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcAttributeTypes: {12}( 1.3.6.1.4.1.24331.22.1.17 NAME 'vacationInfo' DESC 'A
+ bsentee note to leave behind, while on vacation' EQUALITY octetStringMatch SY
+ NTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )
+olcAttributeTypes: {13}( 1.3.6.1.4.1.24331.22.1.18 NAME 'vacationStart' DESC '
+ Beginning of vacation' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.
+ 121.1.40 SINGLE-VALUE )
+olcAttributeTypes: {14}( 1.3.6.1.4.1.24331.22.1.19 NAME 'vacationEnd' DESC 'En
+ d of vacation' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+ SINGLE-VALUE )
+olcAttributeTypes: {15}( 1.3.6.1.4.1.24331.22.1.20 NAME 'vacationForward' DESC
+ 'Where to forward mails to, while on vacation' EQUALITY caseIgnoreIA5Match S
+ UBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
+ )
+olcAttributeTypes: {16}( 1.3.6.1.4.1.24331.22.1.21 NAME 'smbActive' DESC 'bool
+ ean to verify if an Samba account is active' EQUALITY booleanMatch SYNTAX 1.3
+ .6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+olcObjectClasses: {0}( 1.3.6.1.4.1.24331.22.2.1 NAME 'mailAccount' DESC 'LDAP/
+ Unix mail account or virtual account' SUP top AUXILIARY MUST ( uid $ mailacce
+ ptinggeneralid ) MAY ( accountActive $ authsmtpActive $ quota $ isActive $ co
+ urierActive $ webmailActive $ isAdmin $ vacationActive $ vacationInfo $ vacat
+ ionStart $ vacationEnd $ vacationForward $ maildrop ) )
+olcObjectClasses: {1}( 1.3.6.1.4.1.24331.22.2.2 NAME 'mailAlias' DESC 'Mail al
+ iasing/forwarding entry' SUP top STRUCTURAL MUST ( mailacceptinggeneralid $ m
+ aildrop ) MAY ( cn $ isActive ) )
+olcObjectClasses: {2}( 1.3.6.1.4.1.24331.22.2.4 NAME 'postfixDomain' DESC 'Pos
+ tfix domain' SUP posixGroup STRUCTURAL MAY ( postfixTransport $ isActive ) )
diff --git a/postfix/files/filter b/postfix/files/filter
new file mode 100644
index 00000000..586574a1
--- /dev/null
+++ b/postfix/files/filter
@@ -0,0 +1 @@
+# Default empty file
diff --git a/postfix/files/spam.sh b/postfix/files/spam.sh
new file mode 100644
index 00000000..10d5e62a
--- /dev/null
+++ b/postfix/files/spam.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+#set -x
+
+umask 022
+
+tmp_file=$(mktemp)
+
+tmp=$(mktemp -d)
+
+if [ -f $tmp_file ] ;
+ then rm $tmp_file ;
+fi
+
+sleep $[ $RANDOM / 1024 ]
+
+# Postfix
+cd $tmp
+
+wget -q -t 3 http://antispam00.evolix.org/spam/client.access -O $tmp_file
+cp $tmp_file /etc/postfix/client.access
+rm $tmp_file
+
+wget -q -t 3 http://antispam00.evolix.org/spam/sender.access -O $tmp_file
+cp $tmp_file /etc/postfix/sender.access
+rm $tmp_file
+
+wget -q -t 3 http://antispam00.evolix.org/spam/recipient.access -O $tmp_file
+cp $tmp_file /etc/postfix/recipient.access
+rm $tmp_file
+
+wget -q -t 3 http://antispam00.evolix.org/spam/header_kill -O $tmp_file
+cp $tmp_file /etc/postfix/header_kill
+rm $tmp_file
+
+wget -q -t 3 http://antispam00.evolix.org/spam/sa-blacklist.access -O sa-blacklist.access
+wget -q -t 3 http://antispam00.evolix.org/spam/sa-blacklist.access.md5 -O $tmp_file
+if md5sum -c $tmp_file > /dev/null && [ -s sa-blacklist.access ] ; then
+ cp sa-blacklist.access /etc/postfix/sa-blacklist.access
+fi
+rm sa-blacklist.access
+rm $tmp_file
+
+/usr/sbin/postmap hash:/etc/postfix/client.access
+/usr/sbin/postmap hash:/etc/postfix/sender.access
+/usr/sbin/postmap hash:/etc/postfix/recipient.access
+/usr/sbin/postmap -r hash:/etc/postfix/sa-blacklist.access
+
+wget -q -t 3 http://antispam00.evolix.org/spam/spamd.cidr -O spamd.cidr
+wget -q -t 3 http://antispam00.evolix.org/spam/spamd.cidr.md5 -O $tmp_file
+if md5sum -c $tmp_file > /dev/null && [ -s spamd.cidr ] ; then
+ cp spamd.cidr /etc/postfix/spamd.cidr
+fi
+rm spamd.cidr
+rm $tmp_file
+
+
+# SpamAssassin
+cd $tmp
+wget -q -t 3 http://antispam00.evolix.org/spam/evolix_rules.cf -O evolix_rules.cf
+wget -q -t 3 http://antispam00.evolix.org/spam/evolix_rules.cf.md5 -O $tmp_file
+if md5sum -c $tmp_file > /dev/null && [ -s evolix_rules.cf ] ; then
+ dpkg -l spamassassin 2>&1 | grep -v "no packages found matching" | grep -q ^ii && cp evolix_rules.cf /etc/spamassassin
+ dpkg -l spamassassin 2>&1 | grep -v "no packages found matching" | grep -q ^ii && /etc/init.d/spamassassin reload > /dev/null
+ if [ -d /etc/spamassassin/sa-update-hooks.d ]; then
+ run-parts --lsbsysinit /etc/spamassassin/sa-update-hooks.d
+ fi
+fi
+
+# ClamAV
+cd $tmp
+wget -q -t 3 http://antispam00.evolix.org/spam/evolix.ndb -O evolix.ndb
+wget -q -t 3 http://antispam00.evolix.org/spam/evolix.ndb.md5 -O $tmp_file
+dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && chown clamav: evolix.ndb
+if md5sum -c $tmp_file > /dev/null && [ -s evolix.ndb ] ; then
+ dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && cp -a evolix.ndb /var/lib/clamav/
+fi
+wget -q -t 3 http://antispam00.evolix.org/spam/evolix.hsb -O evolix.hsb
+wget -q -t 3 http://antispam00.evolix.org/spam/evolix.hsb.md5 -O $tmp_file
+dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && chown clamav: evolix.hsb
+if md5sum -c $tmp_file > /dev/null && [ -s evolix.hsb ] ; then
+ dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && cp -a evolix.hsb /var/lib/clamav/
+fi
+dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && /etc/init.d/clamav-daemon reload-database > /dev/null
+rm $tmp_file
+
+rm -rf $tmp
diff --git a/postfix/meta/main.yml b/postfix/meta/main.yml
index a4cc6bd0..3c7b219a 100644
--- a/postfix/meta/main.yml
+++ b/postfix/meta/main.yml
@@ -13,7 +13,9 @@ galaxy_info:
versions:
- jessie
-dependencies: []
- # List your role dependencies here, one per line.
- # Be sure to remove the '[]' above if you add dependencies
- # to this list.
+dependencies:
+ - { role: ldap, ldap_schema: 'cn4evolix.ldif', when: postfix_packmail == True }
+ - { role: spamassasin, when: postfix_packmail == True }
+ - { role: clamav, when: postfix_packmail == True }
+ - { role: opendkim, when: postfix_packmail == True }
+ - { role: dovecot, when: postfix_packmail == True }
diff --git a/postfix/tasks/main.yml b/postfix/tasks/main.yml
index 49ccb2ac..a1b5a424 100644
--- a/postfix/tasks/main.yml
+++ b/postfix/tasks/main.yml
@@ -1,30 +1,17 @@
-- name: ensure packages are installed
- apt:
- name: '{{ item }}'
- state: present
- with_items:
- - postfix
- - mailgraph
-
+---
- name: check if main.cf is default
- shell: egrep -v "^(myhostname|mydestination|mailbox_command)" /etc/postfix/main.cf | md5sum -
+ shell: 'grep -v -E "^(myhostname|mydestination|mailbox_command)" /etc/postfix/main.cf | md5sum -'
changed_when: False
check_mode: no
register: default_main_cf
+ tags:
+ - postfix
-- name: create minimal main.cf
- template:
- src: evolinux_main.cf.j2
- dest: /etc/postfix/main.cf
- owner: root
- group: root
- mode: "0644"
- force: yes
- when: default_main_cf.stdout == "5450c05d65878e99dad696c7c722e511 -" or
- default_main_cf.stdout == "30022953f1f61f002bfb72e163ecb27e -"
- notify: restart postfix
+- include: minimal.yml
+ when: postfix_packmail == False
-- meta: flush_handlers
+- include: packmail.yml
+ when: postfix_packmail == True
- include: slow_transport.yml
when: postfix_slow_transport_include
diff --git a/postfix/tasks/minimal.yml b/postfix/tasks/minimal.yml
new file mode 100644
index 00000000..d1e4b4c5
--- /dev/null
+++ b/postfix/tasks/minimal.yml
@@ -0,0 +1,24 @@
+---
+- name: ensure packages are installed
+ apt:
+ name: '{{ item }}'
+ state: present
+ with_items:
+ - postfix
+ tags:
+ - postfix
+
+- name: create minimal main.cf
+ template:
+ src: evolinux_main.cf.j2
+ dest: /etc/postfix/main.cf
+ owner: root
+ group: root
+ mode: "0644"
+ force: yes
+ notify: restart postfix
+ when: postfix_force_main_cf == True or
+ postfix_maincf_md5_jessie in default_main_cf.stdout or
+ postfix_maincf_md5_stretch in default_main_cf.stdout
+ tags:
+ - postfix
diff --git a/postfix/tasks/packmail.yml b/postfix/tasks/packmail.yml
new file mode 100644
index 00000000..de9ee7ad
--- /dev/null
+++ b/postfix/tasks/packmail.yml
@@ -0,0 +1,117 @@
+---
+- name: ensure packages are installed
+ apt:
+ name: '{{ item }}'
+ state: present
+ with_items:
+ - postfix
+ - postfix-ldap
+ - postfix-policyd-spf-python
+ - mailgraph
+ tags:
+ - postfix
+
+- name: create packmail main.cf
+ template:
+ src: packmail_main.cf.j2
+ dest: /etc/postfix/main.cf
+ owner: root
+ group: root
+ mode: "0644"
+ force: yes
+ notify: restart postfix
+ when: postfix_force_main_cf == True or
+ postfix_maincf_md5_jessie in default_main_cf.stdout or
+ postfix_maincf_md5_stretch in default_main_cf.stdout
+ tags:
+ - postfix
+
+- name: deploy packmail master.cf
+ template:
+ src: packmail_master.cf.j2
+ dest: /etc/postfix/master.cf
+ mode: "0644"
+ notify: restart postfix
+ tags:
+ - postfix
+
+- name: copy default filter files
+ copy:
+ src: filter
+ dest: "/etc/postfix/{{ item }}"
+ force: no
+ with_items:
+ - virtual
+ - client.access
+ - client.access_local
+ - header_kill
+ - header_kill_local
+ - recipient.access
+ - recipient.access_local
+ - sa-blacklist.access
+ - sender.access
+ - sender.access_local
+ - spamd.cidr
+ register: postfix_copy_filter
+ tags:
+ - postfix
+
+- name: postmap filter files
+ command: "postmap /etc/postfix/{{ item }}"
+ with_items:
+ - virtual
+ - client.access
+ - client.access_local
+ - header_kill
+ - header_kill_local
+ - recipient.access
+ - recipient.access_local
+ - sa-blacklist.access
+ - sender.access
+ - sender.access_local
+ - spamd.cidr
+ when: postfix_copy_filter.changed
+ tags:
+ - postfix
+
+- name: deploy ldap postfix config
+ template:
+ src: "{{ item }}.j2"
+ dest: "/etc/postfix/{{ item }}"
+ mode: "0644"
+ with_items:
+ - virtual_aliases.cf
+ - virtual_domains.cf
+ - virtual_mailboxes.cf
+ notify: restart postfix
+ tags:
+ - postfix
+
+- include_role:
+ name: remount-usr
+ tags:
+ - postfix
+
+- name: copy spam.sh script
+ copy:
+ src: spam.sh
+ dest: /usr/share/scripts/spam.sh
+ mode: "0700"
+ tags:
+ - postfix
+
+- name: enable spam.sh cron
+ lineinfile:
+ dest: /etc/cron.d/spam
+ line: "42 * * * * /usr/share/scripts/spam.sh"
+ create: yes
+ state: present
+ mode: "0640"
+ tags:
+ - postfix
+
+- name: update antispam list
+ command: /usr/share/scripts/spam.sh
+ changed_when: false
+ tags:
+ - postfix
diff --git a/postfix/tasks/slow_transport.yml b/postfix/tasks/slow_transport.yml
index 3bf8ae6d..2f4cab1e 100644
--- a/postfix/tasks/slow_transport.yml
+++ b/postfix/tasks/slow_transport.yml
@@ -1,10 +1,12 @@
---
-
- name: slow transport is defined in master.cf
lineinfile:
dest: /etc/postfix/master.cf
regexp: "^slow "
line: "slow unix - - n - - smtp"
+ notify: restart postfix
+ tags:
+ - postfix
- name: list of providers for slow transport
lineinfile:
@@ -21,24 +23,5 @@
- "hotmail.fr slow:"
- "hotmail.com slow:"
notify: postmap transport
-
-- name: main.cf is configured for slow transports
- blockinfile:
- dest: /etc/postfix/main.cf
- marker: "# {mark} Slow transports configuration (installed by Ansible)"
- block: |
- minimal_backoff_time = 2h
- maximal_backoff_time = 6h
- maximal_queue_lifetime = 4d
- queue_run_delay = 100s
- bounce_queue_lifetime = 1d
- initial_destination_concurrency = 5
- default_destination_concurrency_limit = 20
- slow_destination_rate_delay = 0
- slow_destination_concurrency_limit = 1
- slow_destination_concurrency_failed_cohort_limit = 100
- slow_destination_recipient_limit = 25
- transport_maps = hash:$config_directory/transport
- notify: restart postfix
-
-- meta: flush_handlers
+ tags:
+ - postfix
diff --git a/postfix/templates/evolinux_main.cf.j2 b/postfix/templates/evolinux_main.cf.j2
index 429e6602..e42a413f 100644
--- a/postfix/templates/evolinux_main.cf.j2
+++ b/postfix/templates/evolinux_main.cf.j2
@@ -13,3 +13,19 @@ recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
disable_vrfy_command = yes
+
+{% if postfix_slow_transport_include == True %}
+# Slow transports configuration
+minimal_backoff_time = 2h
+maximal_backoff_time = 6h
+maximal_queue_lifetime = 4d
+queue_run_delay = 100s
+bounce_queue_lifetime = 1d
+initial_destination_concurrency = 5
+default_destination_concurrency_limit = 20
+slow_destination_rate_delay = 0
+slow_destination_concurrency_limit = 1
+slow_destination_concurrency_failed_cohort_limit = 100
+slow_destination_recipient_limit = 25
+transport_maps = hash:$config_directory/transport
+{% endif %}
diff --git a/postfix/templates/packmail_main.cf.j2 b/postfix/templates/packmail_main.cf.j2
new file mode 100644
index 00000000..9f14ec50
--- /dev/null
+++ b/postfix/templates/packmail_main.cf.j2
@@ -0,0 +1,423 @@
+## fichier principal de configuration de Postfix
+## commentaires de Gregory Colpart reg AT evolix DOT fr
+## version 1.0 : 1ere version publique (05.04.2010)
+
+########################
+# Section : Emplacements
+########################
+
+# Repertoire ou se trouvent les commandes de postfix [OBLIGATOIRE]
+#par defaut, = $program_directory
+command_directory = /usr/sbin
+
+# Repertoire ou se trouvent les demons de postfix [OBLIGATOIRE]
+#par defaut, = $program_directory
+daemon_directory = /usr/lib/postfix/sbin
+
+# Variable pour indiquer les emplacements des commandes et demons de postfix
+#program_directory = /usr/lib/postfix
+
+# Repertoire contenant les fichiers de boites aux lettres
+#par defaut, = /var/mail
+#mail_spool_directory =
+
+# Repertoire de la file d'attente de postfix
+#par defaut, = /var/spool/postfix
+#queue_directory =
+
+# Boites aux lettres
+#par defaut, =
+home_mailbox = Maildir/
+
+# Transmettre les mails a un MDA
+#par defaut, =
+#mailbox_command = /usr/bin/procmail
+
+# Separateur entre noms d'utilisateur et extensions d'adresse
+# mettre + pour integration avec amavis
+#par defaut, =
+recipient_delimiter = +
+
+# Controle si le repertoire existe (souvent pour les systemes de fichiers montes)
+#par defaut, = no
+#require_home_directory =
+
+# Commande pour transmettre le courrier a un MDA
+#par defaut, =
+#mailbox_command = /usr/bin/procmail
+
+# Banniere SMTP affichee
+#par default, = $myhostname ESMTP $mail_name
+smtpd_banner = $myhostname ESMTP mail server
+
+# Groupe des commandes set-gid ayant des acces en ecriture
+#par defaut, = postdrop
+# setgid_group = postdrop
+
+# Produire des "biff notifications" aux utilisateurs pour
+# prevenir de l'arrivee de nouveaux mails
+# par default, = yes
+#biff = no
+
+
+####################
+# Section : domaines
+####################
+
+# Indique le nom d'hote pleinement qualifie ou se trouve postfix [OBLIGATOIRE]
+#par defaut, = [retour de la commande Unix hostname]
+myhostname = {{ ansible_fqdn }}
+
+# Variable indiquant le domaine dans lequel se trouve la machine
+#par defaut, = [partie domain de la variable $myhostname]
+#mydomain =
+
+# Liste des noms de domaine (ou IP) consideres comme local
+#par defaut, = $myhostname, localhost.$mydomain, localhost
+mydestination = $myhostname
+
+# Indique le domaine apparaissant dans le courrier envoye
+#par defaut, = $myhostname
+myorigin = {{ ansible_fqdn }}
+
+# Liste de domaine fonctionnant UNIQUEMENT avec des alias virtuels
+#par defaut, = $virtual_alias_maps
+#virtual_alias_domains = [ domaines avec alias virtuels ]
+
+# Liste de domaine fonctionnant avec des comptes virtuels
+#par defaut, = $virtual_mailbox_maps
+virtual_mailbox_domains = ldap:$config_directory/virtual_domains.cf
+
+# Repertoire de base de l'espace de stockage
+#par defaut, =
+virtual_mailbox_base = /
+
+# Ajoute $mydomain aux adresse ne compoirtant que la partie hote sans le domaine
+#par defaut, = yes
+#append_dot_mydomain = no
+
+# Ajoute $myorigin aux adresses ne comportant pas de composante de domaine
+#par defaut, = yes
+#append_at_myorigin = no
+
+# Liste de domaines cachant des sous-domaines internes
+#par defaut, =
+#masquerade_domains =
+
+# A l'exception de certains comptes :
+#par defaut, =
+#masquerade_exceptions = root, admin
+
+# Champs d'application de la reecriture des sous-domaines caches
+#par defaut, = envelope_sender, header_sender, header_recipient
+#masquerade_classes =
+
+# Sites eligibles pour un vidage rapide (postqueue -s [domain.tld])
+#par defaut, = $relay_domains
+#fast_flush_domains =
+
+# Interfaces sur lesquelles ecoutent postfix
+#par defaut, = all
+#inet_interfaces = all
+
+# Adresse IP externe du firewall/proxy si derriere NAT ou proxy
+# evite principalement les boucles si MX secondaire et MX primaire indisponible
+#par defaut, =
+#proxy_interfaces = [adresse IP]
+
+# Domaines acceptes pour faire relai (MX 2aire)
+#relay_domains = [domaine a relayer]
+
+
+###########################
+# Section : base de donnees
+###########################
+
+# Liste des bases de donnees utilisees par l'agent de distribution locale
+# Pour regenerer une base de donnees : postalias /etc/aliases (par ex)
+#par defaut, = hash:/etc/aliases, nis:mail.aliases
+alias_maps = hash:/etc/aliases
+
+# Liste des bases de donnees locales
+# Pour regenerer avec newaliases
+#par defaut, = hash:/etc/aliases
+alias_database = hash:/etc/aliases
+
+# Chemin vers la commande newaliases
+#par defaut, = /usr/bin/newaliases
+#newaliases_path =
+
+# Base de donnes d'alias virtuels
+# ne pas oublier : postmap /etc/postfix/virtual
+#par defaut, = $virtual_maps
+virtual_alias_maps = hash:$config_directory/virtual, ldap:$config_directory/virtual_aliases.cf
+
+# Base de donners des boites virtuelles
+# ne pas oublier : postmap /etc/postfix/vmailbox
+#par defaut, =
+virtual_mailbox_maps = ldap:$config_directory/virtual_mailboxes.cf
+
+virtual_uid_maps = static:5000
+virtual_gid_maps = static:5000
+virtual_transport = dovecot
+dovecot_destination_recipient_limit = 1
+
+# Reecriture des adresses
+#par defaut, =
+#canonical_maps = hash:/etc/postfix/canonical
+
+# Reecriture des adresses a l'arrivee (ecrase $canonical_maps)
+#par defaut, =
+#recipient_canonical_maps = hash:/etc/postfix/canonical
+
+# Reecriture des adresses au depart
+#par defaut, =
+#sender_canonical_maps = hash:/etc/postfix/canonical
+
+# Adresses changees
+#relocated_maps = hash:/etc/postfix/relocated
+
+# Boite pour receptionner tous les utilisateurs inconnus
+#luser_relay = spam
+
+# Liste de base de donnees contenant les adresses locales permettant de rejeter les messages aux utilisateurs inconnus
+# (sera nulle pour recuperer les courriels vers les utilisateurs inconnus)
+#par defaut, = proxy:unix:passwd.byname $alias_maps
+#local_recipient_maps =
+
+# MAILING-LIST nommee xx
+# dans le fichier /etc/aliases :
+# xx: user1@domain1 user2@domain2 etc.
+# owner-xx: admin@domain
+# Utiliser ou non l'alias xx-owner comme adresse d'enveloppe d'expedition
+#par defaut, = yes
+#owner_request_special =
+
+# Utiliser l'adresse relle de l'admin au lieu de xx-owner
+#par defaut, = no
+#expand_owner_alias =
+
+
+###########################################
+# Section : parametres de la file d'attente
+###########################################
+
+# Lorsqu'un message n'a pas ete delivre, Postfix adjoint une marque indiquant le moment ou la prochaine tentaive pourra avoir lieu
+
+# Delai au-dela duquel les messages non delivres seront renvoyes a l'expediteur
+#par defaut, = 5d
+#maximal_queue_lifetime =
+
+# Delai au-dela duquel les *bounces* non delivres ne seront plus envoyes
+#par defaut, = 5d
+bounce_queue_lifetime = 1d
+
+# Intervalle de temps ou postfix examinera la file
+# Il examine notamment la file deferred pour voir si de NOUVEAUX messages sont arrives
+# Il faut aussi que la marque indique qu'ils soient prets
+#par defaut, = 1000s
+#queue_run_delay =
+
+# A chaque echec, le delai de la prochaine distribution double, avec les restrictions suivantes :
+# Delai minimal
+#par defaut, = 1000s
+#minimal_backoff_time =
+# Delai maximal
+#par defaut, = 4000s
+#maximal_backoff_time =
+
+# Si maxproc est vide (master.cf), nombre maximal est :
+#par defaut, = 100
+#default_process_limit =
+
+# Nombre maximal de destinataires stockes en memoire par qmgr pour un transport particulier
+#par defaut, = 10000
+#default_recipient_limit =
+
+# Nombre limitant de messages envoyes simultanement INITIALEMENT pour une destination particuliere
+# (forcement majoree par maxproc du master.cf ou $default_process_limit)
+#par defaut, = 5
+#initial_destination_concurrency =
+
+# Une fois ces messages distribues, si il reste des messages dans la file d'attente pour cette destination
+# particuliere, postfix augmente le nombre de tentative tant qu'il ne detecte pas de probleme avec
+# la destination, avec la limite suivante :
+#par defaut, = 20
+#default_destination_concurrency_limit =
+
+# Cette limite peut etre differente selon le type de transport utilise :
+#par defaut, = $default_destination_concurrency_limit
+#lmtp_destination_concurrency_limit =
+#par defaut, = 2
+#local_destination_concurrency_limit =
+#par defaut, = $default_destination_concurrency_limit
+#relay_destination_concurrency_limit =
+#par defaut, = $default_destination_concurrency_limit
+#smtp_destination_concurrency_limit =
+#par defaut, = $default_destination_concurrency_limit
+#virtual_destination_concurrency_limit =
+
+# On peut aussi limiter le nombre maximum de destinataire pour un meme message
+# Si le nombre de destinataire depasse la limite, postfix divise en groupe d'adresses plus petites et envoie des copies distinctes du message
+#par defaut, = 10000
+#default_destination_recipient_limit =
+#par defaut, = $default_destination_recipient_limit
+#lmtp_destination_recipient_limit =
+#par defaut, = 1
+#local_destination_recipient_limit =
+#par defaut, = 20000
+#qmgr_message_recipient_limit =
+#par defaut, = $default_destination_recipient_limit
+#relay_destination_recipient_limit =
+#par defaut, = $default_destination_recipient_limit
+#smtp_destination_recipient_limit =
+#par defaut, = 1000
+#smtpd_recipient_limit =
+#par defaut, = $default_destination_recipient_limit
+#virtual_destination_recipient_limit =
+
+# Nombre maximum de destinataires pour un transport lorsque priorite superieure de transport
+#par defaut, = 1000
+#default_extra_recipient_limit =
+
+slow_destination_rate_delay = 0
+slow_destination_concurrency_limit = 1
+slow_destination_recipient_limit = 25
+slow_destination_concurrency_failed_cohort_limit = 100
+
+# Types d'incidents a rapporter
+# resource : message non delivre pour probleme de ressource
+# software : message non delivre pour probleme de logiciels
+# policy : envoie le transcription smtp d'un message rejete par restrictions
+# protocol : envoie toute transcription smtp erronee
+# delay : envoie les entetes de messages differes
+# bounce : envoie les entetes de tous les message renvoyes
+# 2bounce : envoie les entetes de tous les messages renvoyes non delivres
+#par defaut, = resource, software
+notify_classes = resource, software, bounce, 2bounce, delay, policy, protocol
+
+# A qui les reporter ?
+#Pour delay
+#par defaut, = postmaster
+delay_notice_recipient = delay
+#Pour policy, protocol, resource, software
+#par defaut, = postmaster
+error_notice_recipient = error
+#Pour bounce
+#par defaut, = postmaster
+bounce_notice_recipient = bounce
+#Pour 2bounce
+#par defaut, = postmaster
+2bounce_notice_recipient = bounce
+
+
+########################
+# Section : restrictions
+########################
+
+# Restrictions au depart de la conversation
+#par defaut, =
+smtpd_client_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ cidr:$config_directory/spamd.cidr,
+
+# Restrictions au niveau de la commande HELO/EHLO
+#par defaut, =
+smtpd_helo_restrictions =
+ reject_invalid_hostname
+
+# Restrictions au niveau de la commande MAIL FROM
+#par defaut, =
+smtpd_sender_restrictions =
+ permit_mynetworks,
+ check_sender_access hash:$config_directory/sa-blacklist.access
+
+# Restrictions au niveau de la commande MAIL FROM
+#par defaut, = permit_mynetworks, reject_unauth_destination
+smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination,
+ check_policy_service unix:private/policyd-spf,
+ check_client_access hash:$config_directory/client.access_local,
+ check_client_access hash:$config_directory/client.access,
+ check_sender_access hash:$config_directory/sender.access_local,
+ check_sender_access hash:$config_directory/sender.access,
+ check_recipient_access hash:$config_directory/recipient.access_local,
+ check_recipient_access hash:$config_directory/recipient.access,
+ reject_unlisted_recipient,
+ reject_unknown_sender_domain,
+ reject_non_fqdn_sender,
+ reject_unauth_pipelining,
+
+policyd-spf_time_limit = 3600
+
+header_checks =
+ regexp:$config_directory/header_kill_local,
+ regexp:$config_directory/header_kill
+
+transport_maps = hash:$config_directory/transport
+
+# Attendre la commande 'RCPT TO' avant d'evaluer les restrictions ?
+# (peut poser pb avec certains clients et permet d'avoir renseignements suppl)
+#par defaut, = yes
+#smtpd_delay_reject =
+
+# Definition des plages IP appartenant a mynetworks
+#par defaut, toutes les plages d'adresses IPv4 (et IPv6) des interfaces
+mynetworks = 127.0.0.0/8,[::1]/128,10.0.0.0/16
+
+# Exiger la commande HELO/EHLO
+#par defaut, = no
+smtpd_helo_required = yes
+
+# Exiger syntaxe conforme dans les commandes MAIL FROM ou RCPT TO
+#par defaut, = no
+strict_rfc821_envelopes = yes
+
+# Rejeter le courrier provenant d'une adresse inexistante ?
+#par defaut, = no
+#smtpd_reject_unlisted_sender =
+
+# Rejeter le courrier a destination d'une adresse inexistante ?
+#par defaut, = yes
+#smtpd_reject_unlisted_recipient =
+
+
+#######################
+# Section : Chiffrement
+#######################
+
+smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
+smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
+smtpd_use_tls=yes
+smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
+smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
+
+# SASL
+smtpd_sasl_auth_enable = yes
+broken_sasl_auth_clients = yes
+smtpd_sasl_type = dovecot
+smtpd_sasl_path = private/auth-client
+
+# Amavis and OpenDKIM
+content_filter = smtp-amavis:[127.0.0.1]:10024
+smtpd_milters = inet:[127.0.0.1]:54321
+non_smtpd_milters = inet:[127.0.0.1]:54321
+
+{% if postfix_slow_transport_include == True %}
+# Slow transports configuration
+minimal_backoff_time = 2h
+maximal_backoff_time = 6h
+maximal_queue_lifetime = 4d
+queue_run_delay = 100s
+bounce_queue_lifetime = 1d
+initial_destination_concurrency = 5
+default_destination_concurrency_limit = 20
+slow_destination_rate_delay = 0
+slow_destination_concurrency_limit = 1
+slow_destination_concurrency_failed_cohort_limit = 100
+slow_destination_recipient_limit = 25
+transport_maps = hash:$config_directory/transport
+{% endif %}
diff --git a/postfix/templates/packmail_master.cf.j2 b/postfix/templates/packmail_master.cf.j2
new file mode 100644
index 00000000..7326cb35
--- /dev/null
+++ b/postfix/templates/packmail_master.cf.j2
@@ -0,0 +1,171 @@
+#
+# Postfix master process configuration file. For details on the format
+# of the file, see the master(5) manual page (command: "man 5 master" or
+# on-line: http://www.postfix.org/master.5.html).
+#
+# Do not forget to execute "postfix reload" after editing this file.
+#
+# ==========================================================================
+# service type private unpriv chroot wakeup maxproc command + args
+# (yes) (yes) (no) (never) (100)
+# ==========================================================================
+smtp inet n - y - - smtpd
+#smtp inet n - y - 1 postscreen
+#smtpd pass - - y - - smtpd
+#dnsblog unix - - y - 0 dnsblog
+#tlsproxy unix - - y - 0 tlsproxy
+submission inet n - y - - smtpd
+ -o syslog_name=postfix/submission
+ -o smtpd_tls_security_level=encrypt
+ -o smtpd_sasl_auth_enable=yes
+ -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+ -o milter_macro_daemon_name=ORIGINATING
+smtps inet n - y - - smtpd
+ -o syslog_name=postfix/smtps
+ -o smtpd_tls_wrappermode=yes
+ -o smtpd_sasl_auth_enable=yes
+ -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+ -o milter_macro_daemon_name=ORIGINATING
+#628 inet n - y - - qmqpd
+pickup unix n - y 60 1 pickup
+cleanup unix n - y - 0 cleanup
+qmgr unix n - n 300 1 qmgr
+#qmgr unix n - n 300 1 oqmgr
+tlsmgr unix - - y 1000? 1 tlsmgr
+rewrite unix - - y - - trivial-rewrite
+bounce unix - - y - 0 bounce
+defer unix - - y - 0 bounce
+trace unix - - y - 0 bounce
+verify unix - - y - 1 verify
+flush unix n - y 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - y - - smtp
+# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
+relay unix - - y - - smtp
+ -o smtp_fallback_relay=
+# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+showq unix n - y - - showq
+error unix - - y - - error
+retry unix - - y - - error
+discard unix - - y - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - y - - lmtp
+anvil unix - - y - 1 anvil
+scache unix - - y - 1 scache
+#
+# ====================================================================
+# Interfaces to non-Postfix software. Be sure to examine the manual
+# pages of the non-Postfix software to find out what options it wants.
+#
+# Many of the following services use the Postfix pipe(8) delivery
+# agent. See the pipe(8) man page for information about ${recipient}
+# and other message envelope options.
+# ====================================================================
+#
+# maildrop. See the Postfix MAILDROP_README file for details.
+# Also specify in main.cf: maildrop_destination_recipient_limit=1
+#
+maildrop unix - n n - - pipe
+ flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
+#
+# ====================================================================
+#
+# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
+#
+# Specify in cyrus.conf:
+# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
+#
+# Specify in main.cf one or more of the following:
+# mailbox_transport = lmtp:inet:localhost
+# virtual_transport = lmtp:inet:localhost
+#
+# ====================================================================
+#
+# Cyrus 2.1.5 (Amos Gouaux)
+# Also specify in main.cf: cyrus_destination_recipient_limit=1
+#
+#cyrus unix - n n - - pipe
+# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
+#
+# ====================================================================
+# Old example of delivery via Cyrus.
+#
+#old-cyrus unix - n n - - pipe
+# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
+#
+# ====================================================================
+#
+# See the Postfix UUCP_README file for configuration details.
+#
+uucp unix - n n - - pipe
+ flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
+#
+# Other external delivery methods.
+#
+ifmail unix - n n - - pipe
+ flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
+bsmtp unix - n n - - pipe
+ flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
+scalemail-backend unix - n n - 2 pipe
+ flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
+mailman unix - n n - - pipe
+ flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
+ ${nexthop} ${user}
+
+slow unix - - n - - smtp
+
+policyd-spf unix - n n - 0 spawn
+ user=policyd-spf argv=/usr/bin/policyd-spf
+
+dovecot unix - n n - - pipe
+ flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
+
+scan unix - - y - 10 smtp
+localhost:10026 inet n - y - 10 smtpd
+ -o content_filter=
+ -o local_recipient_maps=
+ -o relay_recipient_maps=
+ -o myhostname=filter.mynetwork.local
+ -o smtpd_helo_restrictions=
+ -o smtpd_client_restrictions=
+ -o smtpd_sender_restrictions=
+ -o smtpd_recipient_restrictions=permit_mynetworks,reject
+ -o mynetworks=127.0.0.0/8
+
+smtp-amavis unix - - y - 2 lmtp
+ -o lmtp_data_done_timeout=1200
+ -o lmtp_send_xforward_command=yes
+
+127.0.0.1:10025 inet n - y - - smtpd
+ -o content_filter=
+ -o smtpd_milters=
+ -o local_recipient_maps=
+ -o relay_recipient_maps=
+ -o smtpd_restriction_classes=
+ -o smtpd_delay_reject=no
+ -o smtpd_client_restrictions=permit_mynetworks,reject
+ -o smtpd_helo_restrictions=
+ -o smtpd_sender_restrictions=
+ -o smtpd_recipient_restrictions=permit_mynetworks,reject
+ -o smtpd_data_restrictions=reject_unauth_pipelining
+ -o smtpd_end_of_data_restrictions=
+ -o mynetworks=127.0.0.0/8
+ -o strict_rfc821_envelopes=yes
+ -o smtpd_error_sleep_time=0
+ -o smtpd_soft_error_limit=1001
+ -o smtpd_hard_error_limit=1000
+ -o smtpd_client_connection_count_limit=0
+ -o smtpd_client_connection_rate_limit=0
+ -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
+
+pre-cleanup unix n - n - 0 cleanup
+ -o virtual_alias_maps=
+ -o canonical_maps=
+ -o sender_canonical_maps=
+ -o recipient_canonical_maps=
+ -o masquerade_domains=
+ -o always_bcc=
+ -o sender_bcc_maps=
+ -o recipient_bcc_maps=
diff --git a/postfix/templates/virtual_aliases.cf.j2 b/postfix/templates/virtual_aliases.cf.j2
new file mode 100644
index 00000000..1a6e5f9c
--- /dev/null
+++ b/postfix/templates/virtual_aliases.cf.j2
@@ -0,0 +1,5 @@
+search_base = {{ ldap_suffix }}
+query_filter = (&(mailacceptinggeneralid=%u@%d)(isActive=TRUE))
+result_attribute = maildrop
+version = 3
+aliases_scope = sub
diff --git a/postfix/templates/virtual_domains.cf.j2 b/postfix/templates/virtual_domains.cf.j2
new file mode 100644
index 00000000..97e9ebb3
--- /dev/null
+++ b/postfix/templates/virtual_domains.cf.j2
@@ -0,0 +1,5 @@
+search_base = {{ ldap_suffix }}
+query_filter = (&(cn=%s)(objectClass=postfixDomain)(isActive=TRUE))
+result_attribute = cn
+scope = sub
+version = 3
diff --git a/postfix/templates/virtual_mailboxes.cf.j2 b/postfix/templates/virtual_mailboxes.cf.j2
new file mode 100644
index 00000000..0796bdf6
--- /dev/null
+++ b/postfix/templates/virtual_mailboxes.cf.j2
@@ -0,0 +1,5 @@
+search_base = {{ ldap_suffix }}
+query_filter = (&(mailacceptinggeneralid=%s)(objectClass=mailAccount)(isActive=TRUE)(accountActive=TRUE))
+result_attribute = homeDirectory
+scope = sub
+version = 3
diff --git a/postfix/vars/main.yml b/postfix/vars/main.yml
new file mode 100644
index 00000000..e8a773c9
--- /dev/null
+++ b/postfix/vars/main.yml
@@ -0,0 +1,5 @@
+---
+## MD5 hash of default main.cf filter, obtained with this command :
+# grep -v -E "^(myhostname|mydestination|mailbox_command)" /etc/postfix/main.cf | md5sum -
+postfix_maincf_md5_jessie: "5450c05d65878e99dad696c7c722e511"
+postfix_maincf_md5_stretch: "30022953f1f61f002bfb72e163ecb27e"
diff --git a/postgresql/defaults/main.yml b/postgresql/defaults/main.yml
index 543f1707..6ee57747 100644
--- a/postgresql/defaults/main.yml
+++ b/postgresql/defaults/main.yml
@@ -9,4 +9,4 @@ postgresql_random_page_cost: 1.5
postgresql_effective_cache_size: "{{ (ansible_memtotal_mb * 0.5) | int }}MB"
# PostgreSQL version
-postgresql_version: '9.4'
+postgresql_version: '9.6'
diff --git a/postgresql/tasks/main.yml b/postgresql/tasks/main.yml
index b090b09d..3bc1f904 100644
--- a/postgresql/tasks/main.yml
+++ b/postgresql/tasks/main.yml
@@ -1,9 +1,10 @@
---
-- include: pgdg-repo.yml
- when: postgresql_version != '9.4'
+- include: packages_jessie.yml
+ when: ansible_distribution_release == "jessie"
-- include: packages.yml
+- include: packages_stretch.yml
+ when: ansible_distribution_major_version | version_compare('9', '>=')
- include: config.yml
diff --git a/postgresql/tasks/packages_jessie.yml b/postgresql/tasks/packages_jessie.yml
new file mode 100644
index 00000000..abf0ad08
--- /dev/null
+++ b/postgresql/tasks/packages_jessie.yml
@@ -0,0 +1,12 @@
+---
+
+- include: pgdg-repo.yml
+ when: postgresql_version != '9.4'
+
+- name: Install postgresql package
+ apt:
+ name: '{{item}}'
+ with_items:
+ - "postgresql-{{postgresql_version}}"
+ - ptop
+ - libdbd-pg-perl
diff --git a/postgresql/tasks/packages.yml b/postgresql/tasks/packages_stretch.yml
similarity index 69%
rename from postgresql/tasks/packages.yml
rename to postgresql/tasks/packages_stretch.yml
index cd4f3efa..334a1dff 100644
--- a/postgresql/tasks/packages.yml
+++ b/postgresql/tasks/packages_stretch.yml
@@ -4,5 +4,6 @@
apt:
name: '{{item}}'
with_items:
- - "postgresql-{{postgresql_version}}"
+ - postgresql
- ptop
+ - libdbd-pg-perl
diff --git a/postgresql/templates/postgresql.conf b/postgresql/templates/postgresql.conf
index eafadeb9..ebb6dde2 100644
--- a/postgresql/templates/postgresql.conf
+++ b/postgresql/templates/postgresql.conf
@@ -3,7 +3,7 @@ shared_buffers = {{ postgresql_shared_buffers }}
work_mem = {{ postgresql_work_mem }}
#shared_preload_libraries = 'pg_stat_statements'
#synchronous_commit = off
-{% if postgresql_version |version_compare('9.5', '<') %}
+{% if postgresql_version | version_compare('9.5', '<') %}
checkpoint_segments = 30
{% else %}
max_wal_size = 15GB
diff --git a/proftpd/README.md b/proftpd/README.md
index 4b2faa95..1fcb4910 100644
--- a/proftpd/README.md
+++ b/proftpd/README.md
@@ -12,5 +12,7 @@ Main variables are :
* `proftpd_hostname`: hostname (default: `ansible_hostname`)
* `proftpd_fqdn`: fully qualified domain name (default: `ansible_fqdn`)
+* `proftpd_default_address` : address for the server to listen on (default: `[]`)
+* `proftpd_port` : port for the control socket (default: `21`)
The full list of variables (with default values) can be found in `defaults/main.yml`.
diff --git a/proftpd/defaults/main.yml b/proftpd/defaults/main.yml
index 5355ea43..3dc9511c 100644
--- a/proftpd/defaults/main.yml
+++ b/proftpd/defaults/main.yml
@@ -1,3 +1,5 @@
---
proftpd_hostname: "{{ ansible_hostname }}"
proftpd_fqdn: "{{ ansible_fqdn }}"
+proftpd_default_address: []
+proftpd_port: "21"
diff --git a/proftpd/files/vpasswd b/proftpd/files/vpasswd
new file mode 100644
index 00000000..c7f074ae
--- /dev/null
+++ b/proftpd/files/vpasswd
@@ -0,0 +1 @@
+# username:password:uid:gid:gecos:homedir:shell
diff --git a/proftpd/meta/main.yml b/proftpd/meta/main.yml
index 7b590850..d08211b1 100644
--- a/proftpd/meta/main.yml
+++ b/proftpd/meta/main.yml
@@ -12,6 +12,7 @@ galaxy_info:
- name: Debian
versions:
- jessie
+ - stretch
dependencies: []
# List your role dependencies here, one per line.
diff --git a/proftpd/tasks/main.yml b/proftpd/tasks/main.yml
index 3f6b3abe..a0c5fbb2 100644
--- a/proftpd/tasks/main.yml
+++ b/proftpd/tasks/main.yml
@@ -20,6 +20,7 @@
src: evolinux.conf.j2
dest: /etc/proftpd/conf.d/z-evolinux.conf
mode: "0644"
+ force: no
notify: restart proftpd
tags:
- proftpd
@@ -32,3 +33,25 @@
notify: restart proftpd
tags:
- proftpd
+
+- name: Put empty vpasswd file if missing
+ copy:
+ src: vpasswd
+ dest: /etc/proftpd/vpasswd
+ force: no
+ notify: restart proftpd
+ tags:
+ - proftpd
+
+# Why 440? Because should be edited with ftpasswd.
+# So, readonly when opened with vim.
+# Then readable by group.
+- name: Enforce permissions on password file
+ file:
+ path: /etc/proftpd/vpasswd
+ mode: "0440"
+ owner: root
+ group: root
+ notify: restart proftpd
+ tags:
+ - proftpd
diff --git a/proftpd/templates/evolinux.conf.j2 b/proftpd/templates/evolinux.conf.j2
index d6e8b565..8a810a99 100644
--- a/proftpd/templates/evolinux.conf.j2
+++ b/proftpd/templates/evolinux.conf.j2
@@ -15,6 +15,10 @@ PassivePorts 60000 61000
UseReverseDNS off
IdentLookups off
TimesGMT off
+Port {{ proftpd_port }}
+{% if proftpd_default_address != [] %}
+DefaultAddress {{ proftpd_default_address | join(' ') }}
+{% endif %}
# Local permissions
DefaultRoot ~
diff --git a/redis/README.md b/redis/README.md
index 29ff132f..5a7168b7 100644
--- a/redis/README.md
+++ b/redis/README.md
@@ -16,6 +16,7 @@ Main variables are :
* `redis_conf_path`: config file location ;
* `redis_port`: listening TCP port ;
* `redis_bind_interface`: listening IP address ;
+* `redis_password`: password for redis. Empty means no password ;
* `redis_unixsocket`: Unix socket ;
* `redis_loglevel`: log verbosity ;
* `redis_logfile`: log file location.
diff --git a/redis/defaults/main.yml b/redis/defaults/main.yml
index cf4e5fef..6526c887 100644
--- a/redis/defaults/main.yml
+++ b/redis/defaults/main.yml
@@ -7,6 +7,8 @@ redis_bind_interface: 127.0.0.1
redis_unixsocket: '/var/run/redis/redis.sock'
redis_timeout: 300
+redis_password: NULL
+
redis_loglevel: "notice"
redis_logfile: /var/log/redis/redis-server.log
diff --git a/redis/handlers/main.yml b/redis/handlers/main.yml
index 8a416b0e..49b906a1 100644
--- a/redis/handlers/main.yml
+++ b/redis/handlers/main.yml
@@ -8,3 +8,8 @@
service:
name: munin-node
state: restarted
+
+- name: restart nagios-nrpe-server
+ service:
+ name: nagios-nrpe-server
+ state: restarted
diff --git a/redis/tasks/main.yml b/redis/tasks/main.yml
index 1b0545fa..33a70797 100644
--- a/redis/tasks/main.yml
+++ b/redis/tasks/main.yml
@@ -1,8 +1,11 @@
---
- name: Redis is installed.
apt:
- name: redis-server
+ name: "{{ item }}"
state: present
+ with_items:
+ - redis-server
+ - redis-tools
tags:
- redis
- packages
@@ -31,3 +34,12 @@
- include: munin.yml
when: _munin_installed.stat.exists and _munin_installed.stat.isdir
+
+- name: is NRPE present ?
+ stat:
+ path: /etc/nagios/nrpe.d/evolix.cfg
+ check_mode: no
+ register: nrpe_evolix_config
+
+- include: nrpe_stretch.yml
+ when: ansible_distribution_release == "stretch" and nrpe_evolix_config.stat.exists == true
diff --git a/redis/tasks/munin.yml b/redis/tasks/munin.yml
index 07473e2f..0d8a27f6 100644
--- a/redis/tasks/munin.yml
+++ b/redis/tasks/munin.yml
@@ -6,23 +6,10 @@
tags:
- redis
-- name: Check if /usr is a partition
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- changed_when: False
- failed_when: False
- check_mode: no
- register: usr_partition
- tags: redis
-
-- name: Mount /usr in rw
- command: mount -o remount,rw /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0
- tags: redis
+- include_role:
+ name: remount-usr
+ tags:
+ - redis
- name: Create plugin directory
file:
@@ -60,3 +47,26 @@
- used_memory
notify: restart munin-node
tags: redis
+
+- name: Count redis condif blocks in munin-node configuration
+ command: grep -c "\[redis_" /etc/munin/plugin-conf.d/munin-node
+ register: munin_redis_blocs_in_config
+ failed_when: False
+ changed_when: False
+ check_mode: no
+
+- name: Add redis password for munin (if no more than 1 config block)
+ ini_file:
+ dest: /etc/munin/plugin-conf.d/munin-node
+ section: 'redis_*'
+ option: env.password
+ value: '{{ redis_password }}'
+ notify: restart munin-node
+ when: "redis_password != '' and redis_password != None and {{munin_redis_blocs_in_config.stdout | int}} <= 1"
+ tags: redis
+
+
+- name: Warn if multiple instance in munin-plugins configuration
+ debug:
+ msg: "WARNING - It seems you have multiple redis sections in your munin-node configuration - Munin config NOT changed"
+ when: "redis_password != '' and redis_password != None and {{munin_redis_blocs_in_config.stdout | int}} > 1 "
diff --git a/redis/tasks/nrpe_stretch.yml b/redis/tasks/nrpe_stretch.yml
new file mode 100644
index 00000000..c78e5a28
--- /dev/null
+++ b/redis/tasks/nrpe_stretch.yml
@@ -0,0 +1,18 @@
+---
+- name: Install perl lib-redis (needed by check_redis)
+ apt:
+ name: libredis-perl
+ state: present
+ tags:
+ - redis
+ - nrpe
+
+- name: Replace check_tcp by check_redis for NRPE
+ replace:
+ dest: /etc/nagios/nrpe.d/evolix.cfg
+ regexp: '^command\[check_redis\]=.+'
+ replace: 'command[check_redis]=/usr/lib/nagios/plugins/check_redis -H 127.0.0.1'
+ notify: restart nagios-nrpe-server
+ tags:
+ - redis
+ - nrpe
diff --git a/redis/templates/redis.conf.j2 b/redis/templates/redis.conf.j2
index f7a7c5f0..78dd0c8c 100644
--- a/redis/templates/redis.conf.j2
+++ b/redis/templates/redis.conf.j2
@@ -7,6 +7,10 @@ bind {{ redis_bind_interface }}
unixsocket {{ redis_unixsocket }}
{% endif %}
+{% if redis_password %}
+requirepass {{ redis_password }}
+{% endif %}
+
timeout {{ redis_timeout }}
loglevel {{ redis_loglevel }}
diff --git a/redmine/files/puma.service b/redmine/files/puma.service
index 65aab8fb..6e993607 100644
--- a/redmine/files/puma.service
+++ b/redmine/files/puma.service
@@ -13,5 +13,5 @@ KillMode=process
#Restart=on-failure
[Install]
-WantedBy=multi-user.target
+WantedBy=default.target
Alias=puma.service
diff --git a/redmine/templates/additional_environment.rb.j2 b/redmine/templates/additional_environment.rb.j2
index b1211a2e..b6065a57 100644
--- a/redmine/templates/additional_environment.rb.j2
+++ b/redmine/templates/additional_environment.rb.j2
@@ -1 +1,2 @@
config.paths['log'] = "/home/{{ redmine_user }}/log/redmine.log"
+config.log_level = :warn
diff --git a/remount-usr/handlers/main.yml b/remount-usr/handlers/main.yml
new file mode 100644
index 00000000..5f197e78
--- /dev/null
+++ b/remount-usr/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+- name: remount usr
+ command: "mount -o remount /usr"
+ failed_when: false
+ args:
+ warn: no
diff --git a/remount-usr/tasks/main.yml b/remount-usr/tasks/main.yml
new file mode 100644
index 00000000..cdc7e10e
--- /dev/null
+++ b/remount-usr/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: "check if /usr is a read-only partition"
+ command: 'grep -E " /usr.*ro" /proc/mounts'
+ args:
+ warn: no
+ changed_when: False
+ failed_when: False
+ check_mode: no
+ register: usr_partition
+
+- name: "mount /usr in rw"
+ command: 'mount -o remount,rw /usr'
+ args:
+ warn: no
+ when: usr_partition.rc == 0
+ notify: remount usr
diff --git a/spamassasin/files/sa-update.sh b/spamassasin/files/sa-update.sh
new file mode 100644
index 00000000..b138c285
--- /dev/null
+++ b/spamassasin/files/sa-update.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+# Evolix sa-update, based on:
+# Duncan Findlay
+# duncf@debian.org
+
+mail=$(grep EVOMAINTMAIL /etc/evomaintenance.cf | cut -d'=' -f2)
+test -x /usr/bin/sa-update || exit 0
+test -x /etc/init.d/spamassassin || exit 0
+
+# If there's a problem with the ruleset or configs, print the output
+# of spamassassin --lint (which will typically get emailed to root)
+# and abort.
+die_with_lint() {
+ su debian-spamd -c "spamassassin --lint -D 2>&1"
+ exit 1
+}
+
+do_compile() {
+# Compile, if rules have previously been compiled, and it's possible
+ if [ -x /usr/bin/re2c -a -x /usr/bin/sa-compile \
+ -a -d /var/lib/spamassassin/compiled ]; then
+ su debian-spamd -c "sa-compile --quiet"
+ # Fixup perms -- group and other should be able to
+ # read and execute, but never write. Works around
+ # sa-compile's failure to obey umask.
+ chmod -R go-w,go+rX /var/lib/spamassassin/compiled
+ fi
+}
+
+# Tell a running spamd to reload its configs and rules.
+reload() {
+ # Reload
+ if which invoke-rc.d >/dev/null 2>&1; then
+ invoke-rc.d spamassassin reload > /dev/null
+ else
+ /etc/init.d/spamassassin reload > /dev/null
+ fi
+ if [ -d /etc/spamassassin/sa-update-hooks.d ]; then
+ run-parts --lsbsysinit /etc/spamassassin/sa-update-hooks.d
+ fi
+}
+
+# Update
+umask 022
+su debian-spamd -c "sa-update --gpghomedir /var/lib/spamassassin/sa-update-keys"
+
+case $? in
+ 0)
+ # got updates!
+ su debian-spamd -c "spamassassin --lint" || die_with_lint
+ do_compile
+ reload
+ echo -e "Les règles SpamAsassin ont été mises à jour. Merci de reporter toute anomalie." | \
+ mail -s "SpamAsassin's rules updated." $mail
+ ;;
+ 1)
+ # no updates
+ exit 0
+ ;;
+ 2)
+ # lint failed!
+ die_with_lint
+ ;;
+ *)
+ echo "sa-update failed for unknown reasons" 1>&2
+ ;;
+esac
diff --git a/spamassasin/files/spamassassin.cf b/spamassasin/files/spamassassin.cf
new file mode 100644
index 00000000..821f51d4
--- /dev/null
+++ b/spamassasin/files/spamassassin.cf
@@ -0,0 +1,117 @@
+#required_score 5 -> assure par Amavis
+report_safe 0
+#rewrite_header Subject [SPAM] -> assure par Amavis
+add_header all Report _REPORT_
+
+# filtre bayesien
+# mkdir -p /var/spool/spam/ && chown amavis /var/spool/spam/
+use_bayes 1
+bayes_auto_learn 1
+bayes_path /var/spool/spam/bayes
+bayes_file_mode 0777
+
+# AWL : AutoWhitelist
+# mkdir -p /var/spool/spam/ && chown amavis /var/spool/spam/
+loadplugin Mail::SpamAssassin::Plugin::AWL
+use_auto_whitelist 1
+auto_whitelist_path /var/spool/spam/auto_whitelist
+auto_whitelist_file_mode 0666
+
+# LANG TESTS
+loadplugin Mail::SpamAssassin::Plugin::TextCat
+ok_languages en fr es it
+ok_locales en fr es it
+
+score BODY_8BITS 1.500
+score CHARSET_FARAWAY 3.200
+score CHARSET_FARAWAY_HEADER 3.200
+score HTML_CHARSET_FARAWAY 0.500
+score MIME_CHARSET_FARAWAY 2.450
+score UNWANTED_LANGUAGE_BODY 2.800
+
+# DCC
+# use_dcc 1 => un plugin maintenant...
+score DCC_CHECK 2.9
+
+# RAZOR : http://razor.sourceforge.net
+use_razor2 1
+score RAZOR2_CHECK 2.9
+score RAZOR2_CF_RANGE_51_100 1.3
+
+# pyzor : http://pyzor.sourceforge.net/
+use_pyzor 0
+
+# RBL (Realtime Blackhole List)
+skip_rbl_checks 0
+score RCVD_IN_BL_SPAMCOP_NET 3
+
+# misc
+score HELO_DYNAMIC_IPADDR 0.3
+score BIZ_TLD 0.1
+score PRIORITY_NO_NAME 0.2
+
+# disable HTML tests
+
+score HTML_MESSAGE 0
+score HTML_00_10 0
+score HTML_10_20 0
+score HTML_20_30 0
+score HTML_30_40 0
+score HTML_40_50 0
+score HTML_50_60 0
+score HTML_60_70 0
+score HTML_70_80 0
+score HTML_80_90 0
+score HTML_90_100 0
+#score HTML_COMMENT_8BITS 0
+score UPPERCASE_25_50 0
+score UPPERCASE_50_75 0
+score UPPERCASE_75_100 0
+score MIME_HTML_ONLY 0.1
+# From http://maxime.ritter.eu.org/Spam/user_prefs
+# Trop de faux negatifs avec BAYES_(0|1|2|3|4)*
+score BAYES_00 0 0 -0.01 -0.01
+score BAYES_01 0 0 -0.01 -0.01
+score BAYES_10 0 0 -0.01 -0.01
+score BAYES_20 0 0 -0.01 -0.01
+score BAYES_30 0 0 -0.01 -0.01
+score BAYES_40 0 0 -0.01 -0.01
+score BAYES_44 0 0 -0.01 -0.01
+score BAYES_50 0 0 0.1 0.1
+score BAYES_56 0 0 0.5 0.5
+score BAYES_60 0 0 1.0 1.0
+score BAYES_70 0 0 2.5 2.5
+score BAYES_80 0 0 3.5 3.5
+score BAYES_90 0 0 4.5 4.5
+score BAYES_99 0 0 8.0 8.0
+
+score RCVD_IN_SORBS_DUL 0.3
+score SUBJ_ILLEGAL_CHARS 0
+score RCVD_IN_NJABL_DUL 0.3
+
+score ADDRESS_IN_SUBJECT 0.1
+
+score HELO_LH_HOME 1.0
+
+#internal_networks 192.168.XXX/24
+trusted_networks 62.212.111.216 88.179.18.233 85.118.59.50 31.170.8.0/21
+#score ALL_TRUSTED 0.3
+score HELO_DYNAMIC_IPADDR 0.3
+
+score FORGED_MUA_OUTLOOK 0.5
+
+# Eudora sucks
+score EXTRA_MPART_TYPE 0.1
+score MIME_BOUND_EQ_REL 0.1
+score MIME_QP_LONG_LINE 0.1
+
+# SMTP senders *have* dynamic IP addresses
+# A.B.C.D.dnsbl.sorbs.net -> 127.0.0.10
+score RCVD_IN_DYNABLOCK 0
+score HELO_DYNAMIC_IPADDR 0.3
+score RCVD_IN_SORBS 0.1
+score RCVD_IN_PBL 0.1
+score RCVD_IN_SORBS_DUL 0
+
+# old bug...
+score FH_DATE_PAST_20XX 0.0
diff --git a/spamassasin/handlers/main.yml b/spamassasin/handlers/main.yml
new file mode 100644
index 00000000..7479d736
--- /dev/null
+++ b/spamassasin/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart spamassassin
+ service:
+ name: spamassassin
+ state: restarted
diff --git a/spamassasin/meta/main.yml b/spamassasin/meta/main.yml
new file mode 100644
index 00000000..510b6855
--- /dev/null
+++ b/spamassasin/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - { role: amavis }
diff --git a/spamassasin/tasks/main.yml b/spamassasin/tasks/main.yml
new file mode 100644
index 00000000..cfcfa09b
--- /dev/null
+++ b/spamassasin/tasks/main.yml
@@ -0,0 +1,57 @@
+---
+- name: install SpamAssasin
+ apt:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - spamassassin
+ - evomaintenance
+ tags:
+ - spamassassin
+
+- name: configure SpamAssasin
+ copy:
+ src: spamassassin.cf
+ dest: /etc/spamassassin/local_evolix.cf
+ mode: "0644"
+ notify: restart spamassassin
+ tags:
+ - spamassassin
+
+- name: enable SpamAssasin
+ replace:
+ dest: /etc/default/spamassassin
+ regexp: 'ENABLED=0'
+ replace: 'ENABLED=1'
+ notify: restart spamassassin
+ tags:
+ - spamassassin
+
+- include_role:
+ name: remount-usr
+ tags:
+ - spamassassin
+
+- name: copy sa-update.sh script
+ copy:
+ src: sa-update.sh
+ dest: /usr/share/scripts/sa-update.sh
+ mode: "0750"
+ tags:
+ - spamassassin
+
+- name: enable sa-update.sh cron
+ lineinfile:
+ dest: /etc/cron.d/sa-update
+ line: "42 6 5 1,4,7,10 * /usr/share/scripts/sa-update.sh"
+ create: yes
+ state: present
+ mode: "0640"
+ tags:
+ - spamassassin
+
+- name: update SpamAssasin's rules
+ command: "/usr/share/scripts/sa-update.sh"
+ changed_when: false
+ tags:
+ - spamassassin
diff --git a/supervisord/handlers/main.yml b/supervisord/handlers/main.yml
index 3bf89428..be10ba0a 100644
--- a/supervisord/handlers/main.yml
+++ b/supervisord/handlers/main.yml
@@ -1,5 +1,5 @@
---
-- name: Restart supervisord
+- name: restart supervisor
service:
name: supervisor
state: restarted
diff --git a/supervisord/tasks/main.yml b/supervisord/tasks/main.yml
index 500c5d68..17d7737a 100644
--- a/supervisord/tasks/main.yml
+++ b/supervisord/tasks/main.yml
@@ -1,13 +1,17 @@
---
-- name: Install supervisord
+- name: Install Supervisor
apt:
name: supervisor
+ tags:
+ - supervisord
-- name: Add http configuration for supvervisord
+- name: Add http configuration for Supervisor
copy:
src: http.conf
dest: /etc/supervisor/conf.d/
mode: "0644"
force: no
- notify: Restart supervisord
+ notify: restart supervisor
when: supervisord_enable_http
+ tags:
+ - supervisord
diff --git a/tomcat/tasks/nagios.yml b/tomcat/tasks/nagios.yml
index 01de5348..69c99810 100644
--- a/tomcat/tasks/nagios.yml
+++ b/tomcat/tasks/nagios.yml
@@ -4,21 +4,8 @@
name: monitoring-plugins
state: present
-- name: Check if /usr is a partition
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- changed_when: False
- failed_when: False
- check_mode: no
- register: usr_partition
-
-- name: Mount /usr in rw
- command: mount -o remount,rw /usr
- args:
- warn: no
- changed_when: False
- when: usr_partition.rc == 0
+- include_role:
+ name: remount-usr
- name: Create Nagios plugins dir
file:
diff --git a/varnish/tasks/munin.yml b/varnish/tasks/munin.yml
index 1c2ad790..552c8a34 100644
--- a/varnish/tasks/munin.yml
+++ b/varnish/tasks/munin.yml
@@ -4,7 +4,9 @@
name: libxml-parser-perl
tags: varnish
-- include: remount_usr_rw.yml
+- include_role:
+ name: remount-usr
+ tags: varnish
- name: Create plugin directory
file:
diff --git a/varnish/tasks/remount_usr_rw.yml b/varnish/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/varnish/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/webapps/README.md b/webapps/README.md
deleted file mode 100644
index 2c74fa01..00000000
--- a/webapps/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# webapps
-
-Install popular webapps
-
-## Tasks
-
-Tasks are extracted in several files, included in `tasks/main.yml` :
-
-* `wordpress.yml` : wordpress installation
-
-## Available variables
-
-* `webapp_wordpress_install` : enable wordpress installation
diff --git a/webapps/defaults/main.yml b/webapps/defaults/main.yml
deleted file mode 100644
index 1c25888f..00000000
--- a/webapps/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-webapps_wordpress_install: False
-webapps_wordpress_version: 4.7-branch
-webapps_wordpress_upstream: https://github.com/WordPress/WordPress
-webapps_wordpress_upstream_default_title: "new blog Evolix SaaS"
-
diff --git a/webapps/evoadmin-mail/defaults/main.yml b/webapps/evoadmin-mail/defaults/main.yml
new file mode 100644
index 00000000..000be699
--- /dev/null
+++ b/webapps/evoadmin-mail/defaults/main.yml
@@ -0,0 +1,23 @@
+---
+general_alert_email: "root@localhost"
+evoadminmail_contact_email: Null
+evoadminmail_bounce_email: "{{ evoadminmail_contact_email }}"
+
+evoadminmail_username: evoadmin-mail
+evoadminmail_home_dir: "/home/{{ evoadminmail_username }}"
+evoadminmail_document_root: "{{ evoadminmail_home_dir }}/www"
+evoadminmail_log_dir: "{{ evoadminmail_home_dir }}/log"
+evoadminmail_scripts_dir: /usr/share/scripts/
+evoadminmail_host: "evoadminmail.{{ ansible_fqdn }}"
+
+evoadminmail_enable_vhost: True
+
+evoadminmail_tpl_servername: "{{ ansible_fqdn }}"
+evoadminmail_tpl_address: "{{ ansible_default_ipv4.address }}"
+evoadminmail_tpl_phpmyadmin_url: Null
+evoadminmail_tpl_cgi_suffix: Null
+evoadminmail_tpl_signature: evoadmin
+evoadminmail_tpl_mail_from: root@localhost
+evoadminmail_tpl_mail_bcc: Null
+evoadminmail_tpl_mail_standard: "{{ general_alert_email }}"
+evoadminmail_tpl_mail_urgent: "{{ general_alert_email }}"
diff --git a/webapps/evoadmin-mail/handlers/main.yml b/webapps/evoadmin-mail/handlers/main.yml
new file mode 100644
index 00000000..6866dc8b
--- /dev/null
+++ b/webapps/evoadmin-mail/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: reload apache2
+ service:
+ name: apache2
+ state: reloaded
diff --git a/webapps/evoadmin-mail/tasks/config.yml b/webapps/evoadmin-mail/tasks/config.yml
new file mode 100644
index 00000000..00e342f3
--- /dev/null
+++ b/webapps/evoadmin-mail/tasks/config.yml
@@ -0,0 +1,17 @@
+---
+
+- name: "Create /etc/evolinux"
+ file:
+ dest: "/etc/evolinux"
+ recurse: yes
+ state: directory
+
+#- name: Configure web-add config file
+# template:
+# src: web-add.conf.j2
+# dest: /etc/evolinux/web-add.conf
+#
+#- name: Configure web-add template file for mail
+# template:
+# src: web-mail.tpl.j2
+# dest: "{{ evoadminmail_scripts_dir }}/web-mail.tpl"
diff --git a/webapps/evoadmin-mail/tasks/main.yml b/webapps/evoadmin-mail/tasks/main.yml
new file mode 100644
index 00000000..0647bbcb
--- /dev/null
+++ b/webapps/evoadmin-mail/tasks/main.yml
@@ -0,0 +1,19 @@
+---
+
+- include: packages.yml
+
+- include: user.yml
+
+- include: config.yml
+
+- include: ssl.yml
+
+- include: web.yml
+
+- name: enable evoadmin-mail link in default site index
+ lineinfile:
+ dest: /var/www/index.html
+ state: present
+ regexp: "EvoAdmin-mail"
+ line: ' Interface admin mail (EvoAdmin-mail)'
+ insertbefore: ""
diff --git a/webapps/evoadmin-mail/tasks/packages.yml b/webapps/evoadmin-mail/tasks/packages.yml
new file mode 100644
index 00000000..b1b8a1dd
--- /dev/null
+++ b/webapps/evoadmin-mail/tasks/packages.yml
@@ -0,0 +1,14 @@
+---
+
+- include_role:
+ name: apt
+ tasks_from: evolix_public.yml
+
+- name: Install PHP packages
+ apt:
+ name: '{{ item }}'
+ state: present
+ with_items:
+ - php-pear
+ - php-log
+ - php-crypt-chap
diff --git a/webapps/evoadmin-mail/tasks/ssl.yml b/webapps/evoadmin-mail/tasks/ssl.yml
new file mode 100644
index 00000000..3dd91590
--- /dev/null
+++ b/webapps/evoadmin-mail/tasks/ssl.yml
@@ -0,0 +1,24 @@
+---
+
+
+- name: ssl-cert package is installed
+ apt:
+ name: ssl-cert
+ state: present
+
+- name: Create private key and csr for default site ({{ ansible_fqdn }})
+ command: openssl req -newkey rsa:2048 -sha256 -nodes -keyout /etc/ssl/private/{{ evoadminmail_host }}.key -out /etc/ssl/{{ evoadminmail_host }}.csr -batch -subj "/CN={{ evoadminmail_host }}"
+ args:
+ creates: "/etc/ssl/private/{{ evoadminmail_host }}.key"
+
+- name: Adjust rights on private key
+ file:
+ path: /etc/ssl/private/{{ evoadminmail_host }}.key
+ owner: root
+ group: ssl-cert
+ mode: "0640"
+
+- name: Create certificate for default site
+ command: openssl x509 -req -days 3650 -sha256 -in /etc/ssl/{{ evoadminmail_host }}.csr -signkey /etc/ssl/private/{{ evoadminmail_host }}.key -out /etc/ssl/certs/{{ evoadminmail_host }}.crt
+ args:
+ creates: "/etc/ssl/certs/{{ evoadminmail_host }}.crt"
diff --git a/webapps/evoadmin-mail/tasks/user.yml b/webapps/evoadmin-mail/tasks/user.yml
new file mode 100644
index 00000000..5b267e72
--- /dev/null
+++ b/webapps/evoadmin-mail/tasks/user.yml
@@ -0,0 +1,114 @@
+---
+
+- name: Create evoadmin account
+ user:
+ name: "{{ evoadminmail_username }}"
+ comment: "Evoadmin Web Account"
+ home: "{{ evoadminmail_home_dir}}"
+ shell: /bin/bash
+ password: "!"
+
+- name: Create log/ directory
+ file:
+ path: "{{ evoadminmail_home_dir}}/log"
+ state: directory
+ owner: "{{ evoadminmail_username }}"
+ group: "{{ evoadminmail_username }}"
+ mode: "0750"
+
+- name: Create www-evoadminmail group
+ group:
+ name: "www-{{ evoadminmail_username }}"
+ state: present
+
+- name: "Create www-evoadmin (Debian 9 or later)"
+ user:
+ name: "www-{{ evoadminmail_username }}"
+ home: "{{ evoadminmail_home_dir}}/www"
+ shell: /bin/bash
+ createhome: no
+ when: ansible_distribution_major_version | version_compare('9', '>=')
+
+- name: Install Git
+ apt:
+ name: git
+ state: present
+
+- name: "Clone evoadmin repository (Debian 9 or later)"
+ git:
+ repo: https://forge.evolix.org/evoadmin-mail.git
+ dest: "{{ evoadminmail_document_root}}"
+ version: master
+ update: yes
+ when: ansible_distribution_major_version | version_compare('9', '>=')
+
+- name: "Change perms on evoadminmail document root"
+ file:
+ dest: "{{ evoadminmail_document_root }}"
+ owner: "www-{{ evoadminmail_username }}"
+ group: "{{ evoadminmail_username }}"
+ recurse: yes
+
+- name: "Copy connect.php"
+ template:
+ src: connect.php.j2
+ dest: "{{ evoadminmail_document_root }}/htdocs/config/connect.php"
+ owner: "www-{{ evoadminmail_username }}"
+ group: "{{ evoadminmail_username }}"
+ when: ldap_admin_password is defined
+
+- name: "Copy conf.php"
+ template:
+ src: conf.php.j2
+ dest: "{{ evoadminmail_document_root }}/htdocs/config/conf.php"
+ owner: "www-{{ evoadminmail_username }}"
+ group: "{{ evoadminmail_username }}"
+
+- name: create a password for evoadmin user
+ command: "apg -n 1 -m 16 -M lcN"
+ register: evoadminmail_admin_password
+ changed_when: False
+
+- name: upload ldif for evoadmin user
+ template:
+ src: evoadmin.ldif.j2
+ dest: /root/evolinux_evoadminmail_admin.ldif
+ mode: "0640"
+
+- name: inject config
+ command: slapadd -l /root/evolinux_evoadminmail_admin.ldif
+
+- name: create log file
+ file:
+ dest: /var/log/evoadmin-mail.log
+ state: touch
+ owner: "www-{{ evoadminmail_username }}"
+ group: "adm"
+ mode: "0640"
+
+- include_role:
+ name: remount-usr
+ when: evoadminmail_scripts_dir | search ("/usr")
+
+- name: "Create {{ evoadminmail_scripts_dir }}"
+ file:
+ dest: "{{ evoadminmail_scripts_dir }}"
+ # recurse: yes
+ mode: "0700"
+ state: directory
+
+# we use a shell command to have a "changed" thet really reflects the result.
+- name: Fix permissions
+ shell: "chmod -R --verbose u=rwX,g=rX,o= {{ item }}"
+ register: command_result
+ changed_when: "'changed' in command_result.stdout"
+ # failed_when: False
+ with_items:
+ - "{{ evoadminmail_home_dir}}/www"
+
+#- name: Add evoadmin sudoers file
+# template:
+# src: sudoers.j2
+# dest: /etc/sudoers.d/evoadmin
+# mode: "0600"
+# validate: "visudo -cf %s"
diff --git a/webapps/evoadmin-mail/tasks/web.yml b/webapps/evoadmin-mail/tasks/web.yml
new file mode 100644
index 00000000..e7d915a3
--- /dev/null
+++ b/webapps/evoadmin-mail/tasks/web.yml
@@ -0,0 +1,30 @@
+---
+
+- name: "Set custom values for PHP config (Debian 9 or later)"
+ ini_file:
+ dest: /etc/php/7.0/apache2/conf.d/zzz-evolinux-custom.ini
+ section: PHP
+ option: "disable_functions"
+ value: "shell-exec,system,passthru,putenv,popen,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority"
+ notify: reload apache2
+ when: ansible_distribution_major_version | version_compare('9', '>=')
+
+- name: Install evoadminmail VHost
+ template:
+ src: evoadminmail.conf.j2
+ dest: /etc/apache2/sites-available/evoadminmail.conf
+ notify: reload apache2
+
+- name: Enable evoadminmail vhost
+ command: "a2ensite evoadminmail.conf"
+ register: cmd_a2ensite
+ changed_when: "'Enabling site' in cmd_a2ensite.stdout"
+ notify: reload apache2
+ when: evoadminmail_enable_vhost
+
+- name: Disable evoadminmail vhost
+ command: "a2dissite evoadminmail.conf"
+ register: cmd_a2dissite
+ changed_when: "'Disabling site' in cmd_a2dissite.stdout"
+ notify: reload apache2
+ when: not evoadminmail_enable_vhost
diff --git a/webapps/evoadmin-mail/templates/conf.php.j2 b/webapps/evoadmin-mail/templates/conf.php.j2
new file mode 100644
index 00000000..bac22bfd
--- /dev/null
+++ b/webapps/evoadmin-mail/templates/conf.php.j2
@@ -0,0 +1,56 @@
+
+ * @version 1.0
+ */
+
+define("LDAP_URI","ldap://127.0.0.1");
+$ldap_servers = array('ldap://127.0.0.1');
+define("LDAP_BASE","{{ ldap_suffix }}");
+define("LDAP_ADMIN_DN","cn=admin,{{ ldap_suffix }}");
+define("LDAP_ADMIN_PASS","{{ ldap_admin_password.stdout }}");
+
+define("SUDOBIN","/usr/bin/sudo");
+define("SUDOSCRIPT","/usr/share/scripts/evoadmin.sh");
+define("SUDOPASS","xxxxxx");
+
+define('SERVEUR','localhost');
+define('SERVEURPORT',3306);
+define('BASE','horde');
+define('NOM', 'horde');
+define('PASSE', 'xxxx');
+
+?>
diff --git a/webapps/evoadmin-mail/templates/evoadmin.ldif.j2 b/webapps/evoadmin-mail/templates/evoadmin.ldif.j2
new file mode 100644
index 00000000..389fdff9
--- /dev/null
+++ b/webapps/evoadmin-mail/templates/evoadmin.ldif.j2
@@ -0,0 +1,12 @@
+dn: uid=evoadmin,{{ ldap_suffix }}
+uid: evoadmin
+cn: Evoadmin ADM
+uidNumber: 4242
+gidNumber: 4242
+homeDirectory: /dev/null
+isAdmin: TRUE
+mailacceptinggeneralid: evoadmin@{{ ansible_fqdn }}
+objectClass: mailAccount
+objectClass: organizationalRole
+objectClass: posixAccount
+userPassword: {{ evoadminmail_admin_password.stdout }}
diff --git a/webapps/evoadmin-mail/templates/evoadminmail.conf.j2 b/webapps/evoadmin-mail/templates/evoadminmail.conf.j2
new file mode 100644
index 00000000..026fe00d
--- /dev/null
+++ b/webapps/evoadmin-mail/templates/evoadminmail.conf.j2
@@ -0,0 +1,58 @@
+
+ ServerName {{ evoadminmail_host }}
+ Redirect permanent / https://{{ evoadminmail_host }}/
+
+
+
+
+ # FQDN principal
+ ServerName {{ evoadminmail_host }}
+ #ServerAlias {{ evoadminmail_host }}
+
+ # Repertoire principal
+ DocumentRoot {{ evoadminmail_document_root }}/htdocs/
+
+ # SSL
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/{{ evoadminmail_host }}.crt
+ SSLCertificateKeyFile /etc/ssl/private/{{ evoadminmail_host }}.key
+ SSLProtocol all -SSLv2 -SSLv3
+
+ # Propriete du repertoire
+
+ #Options Indexes SymLinksIfOwnerMatch
+ Options SymLinksIfOwnerMatch
+ AllowOverride AuthConfig Limit FileInfo
+ Require all granted
+
+
+ # user - group (thanks to sesse@debian.org)
+ AssignUserID www-{{ evoadminmail_username }} {{ evoadminmail_username }}
+
+ # LOG
+ CustomLog /var/log/apache2/access.log combined
+ CustomLog {{ evoadminmail_log_dir }}/access.log combined
+ ErrorLog {{ evoadminmail_log_dir }}/error.log
+
+ # AWSTATS
+ SetEnv AWSTATS_FORCE_CONFIG {{ evoadminmail_username }}
+
+ # REWRITE
+ UseCanonicalName On
+ RewriteEngine On
+ RewriteCond %{HTTP_HOST} !^{{ evoadminmail_host }}$
+ RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [L,R]
+
+ # PHP
+ #php_admin_flag engine off
+ #AddType text/html .html
+ #php_admin_flag display_errors On
+ #php_flag short_open_tag On
+ #php_flag register_globals On
+ #php_admin_value memory_limit 256M
+ #php_admin_value max_execution_time 60
+ #php_admin_value upload_max_filesize 8M
+ #php_admin_flag allow_url_fopen Off
+ php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f www-{{ evoadminmail_username }}"
+ php_admin_value open_basedir "none"
+
diff --git a/webapps/evoadmin-mail/templates/sudoers.j2 b/webapps/evoadmin-mail/templates/sudoers.j2
new file mode 100644
index 00000000..4dfd71c1
--- /dev/null
+++ b/webapps/evoadmin-mail/templates/sudoers.j2
@@ -0,0 +1,3 @@
+User_Alias EVOADMIN = www-evoadmin
+Cmnd_Alias EVOADMIN_WEB = {{ evoadmin_scripts_dir | mandatory }}/web-*.sh, {{ evoadmin_scripts_dir | mandatory }}/ftpadmin.sh
+EVOADMIN ALL=NOPASSWD: EVOADMIN_WEB
diff --git a/webapps/evoadmin-mail/templates/web-add.conf.j2 b/webapps/evoadmin-mail/templates/web-add.conf.j2
new file mode 100644
index 00000000..86eabd29
--- /dev/null
+++ b/webapps/evoadmin-mail/templates/web-add.conf.j2
@@ -0,0 +1,2 @@
+CONTACT_MAIL="{{ evoadmin_contact_email or general_alert_email | mandatory }}"
+WWWBOUNCE_MAIL="{{ evoadmin_bounce_email or general_alert_email | mandatory }}"
diff --git a/webapps/evoadmin-mail/templates/web-mail.tpl.j2 b/webapps/evoadmin-mail/templates/web-mail.tpl.j2
new file mode 100644
index 00000000..262995c3
--- /dev/null
+++ b/webapps/evoadmin-mail/templates/web-mail.tpl.j2
@@ -0,0 +1,86 @@
+From: {{ evoadmin_tpl_mail_from }}
+To: RCPTTO
+Bcc: {{ evoadmin_tpl_mail_bcc }}
+Subject: Parametres hebergement web : LOGIN
+
+Bonjour,
+
+Votre compte d'hebergement web a ete cree.
+
+**********************************
+* CONNEXION SFTP/SSH
+**********************************
+
+NOM DU SERVEUR : {{ evoadmin_tpl_servername }}
+USER : LOGIN
+PASSWORD : PASSE1
+
+*****************************************
+* Details sur l'environnement Apache/PHP
+*****************************************
+
+URL du site :
+http://{{ evoadmin_tpl_servername }}
+
+URL des stats :
+http://{{ evoadmin_tpl_servername }}/cgi-RANDOM/awstats.pl
+(acces par IP ou login a demander !)
+
+Repertoire de connexion : HOME_DIR/LOGIN/
+Repertoire pour site web : HOME_DIR/LOGIN/www/
+
+Apache/PHP tourne en www-LOGIN:LOGIN c'est-a-dire qu'il a acces
+uniquement *en lecture* aux differents fichiers/repertoires
+(a condition d'avoir 'g=rx' sur les repertoires et 'g=r' sur les
+fichiers ce qui est le comportement par defaut).
+
+Lorsqu'on a besoin d'autoriser *l'ecriture* pour certains
+fichiers/repertoires, il suffit d'ajouter le droit 'g+w'.
+
+***********************************
+* MySQL
+***********************************
+
+SERVEUR : 127.0.0.1
+PORT DU SERVEUR : 3306
+USER : LOGIN
+PASSWORD : PASSE2
+NOM BASE : DBNAME
+URL interface d'admin :
+{{ evoadmin_tpl_phpmyadmin_url }}
+
+***********************************
+* Rappels divers
+***********************************
+
+Votre nom de domaine doit etre configure pour pointer
+sur l'adresse IP {{ evoadmin_tpl_address }} (enregistrement DNS A)
+ou etre un alias de {{ evoadmin_tpl_servername }} (enregistrement DNS CNAME).
+
+Si vous avez besoin de faire des tests, vous devez
+ajouter la ligne suivante au fichier "/etc/hosts" sous Linux/Unix
+ou au fichier "system32\drivers\etc\hosts" sous Windows NT/XP :
+{{ evoadmin_tpl_address }} {{ evoadmin_tpl_servername }}
+
+Attention, par defaut, toutes les connexions vers l'exterieur
+sont bloquees. Si vous avez besoin de recuperer des donnees
+a l'exterieur (flux RSS, BDD externe, etc.), contactez nous
+afin de mettre en oeuvre les autorisations necessaires.
+
+Afin de securiser au maximum le serveur, certaines URL
+particulieres sont non autorisees pour eviter diverses
+attaques (XSS, robots, trojans, injections, etc.).
+Exemple d'URL refusee :
+http://{{ evoadmin_tpl_servername }}/cmd32.exe
+En cas de soucis avec votre application, prevenez-nous.
+
+Si vous desirez mettre en place des parametres particuliers
+pour votre site (PHP, etc.) ou pour tout autre demande (scripts en crontab,
+etc.), n'hesitez pas a nous contacter a l'adresse
+{{ evoadmin_tpl_mail_standard }} (ou {{ evoadmin_tpl_mail_urgent }} si votre demande est
+urgente).
+
+
+Cordialement,
+--
+{{ evoadmin_tpl_signature }}
diff --git a/webapps/evoadmin-web/defaults/main.yml b/webapps/evoadmin-web/defaults/main.yml
index 58200cf1..c57c3b54 100644
--- a/webapps/evoadmin-web/defaults/main.yml
+++ b/webapps/evoadmin-web/defaults/main.yml
@@ -6,7 +6,7 @@ evoadmin_bounce_email: "{{ evoadmin_contact_email }}"
evoadmin_home_dir: "/home/{{ evoadmin_username }}"
evoadmin_document_root: "{{ evoadmin_home_dir }}/www"
evoadmin_log_dir: "{{ evoadmin_home_dir }}/log"
-evoadmin_scripts_dir: /usr/share/scripts/evoadmin/
+evoadmin_scripts_dir: /usr/share/scripts/evoadmin
evoadmin_host: "evoadmin.{{ ansible_fqdn }}"
evoadmin_username: evoadmin
diff --git a/webapps/evoadmin-web/files/evolinux.conf.diff b/webapps/evoadmin-web/files/ftp/evolinux.conf.diff
similarity index 100%
rename from webapps/evoadmin-web/files/evolinux.conf.diff
rename to webapps/evoadmin-web/files/ftp/evolinux.conf.diff
diff --git a/webapps/evoadmin-web/meta/main.yml b/webapps/evoadmin-web/meta/main.yml
new file mode 100644
index 00000000..82440b08
--- /dev/null
+++ b/webapps/evoadmin-web/meta/main.yml
@@ -0,0 +1,18 @@
+galaxy_info:
+ author: Evolix
+ description: Installation of evoadmin-web
+
+ issue_tracker_url: https://forge.evolix.org/projects/ansible-roles/issues
+
+ license: GPLv2
+
+ min_ansible_version: 2.2
+
+ platforms:
+ - name: Debian
+ versions:
+ - jessie
+ - stretch
+
+dependencies:
+ - proftpd
diff --git a/webapps/evoadmin-web/tasks/ftp.yml b/webapps/evoadmin-web/tasks/ftp.yml
index 83913d01..a78150a1 100644
--- a/webapps/evoadmin-web/tasks/ftp.yml
+++ b/webapps/evoadmin-web/tasks/ftp.yml
@@ -1,25 +1,12 @@
---
-- name: Verify if proftpd has evolinux config file
- stat:
- path: /etc/proftpd/conf.d/z-evolinux.conf
- register: proftpd_config
+- name: patch must be installed
+ apt:
+ name: patch
+ state: installed
-- block:
- - name: Patch ProFTPd config file
- patch:
- remote_src: no
- src: evolinux.conf.diff
- dest: /etc/proftpd/conf.d/z-evolinux.conf
-
- # Why 440? Because should be edited with ftpasswd.
- # So, readonly when opened with vim.
- # Then readable by group.
- - name: Create /etc/proftpd/vpasswd file in 0440 mode
- file:
- state: touch
- path: /etc/proftpd/vpasswd
- mode: "0440"
- owner: root
- group: root
- when: proftpd_config.stat.exists
+- name: Patch ProFTPd config file
+ patch:
+ remote_src: no
+ src: ftp/evolinux.conf.diff
+ dest: /etc/proftpd/conf.d/z-evolinux.conf
diff --git a/webapps/evoadmin-web/tasks/packages.yml b/webapps/evoadmin-web/tasks/packages.yml
index e0b1fe05..79d1e312 100644
--- a/webapps/evoadmin-web/tasks/packages.yml
+++ b/webapps/evoadmin-web/tasks/packages.yml
@@ -4,8 +4,6 @@
name: apt
tasks_from: evolix_public.yml
-- meta: flush_handlers
-
- name: Install PHP packages
apt:
name: '{{ item }}'
diff --git a/webapps/evoadmin-web/tasks/remount_usr_rw.yml b/webapps/evoadmin-web/tasks/remount_usr_rw.yml
deleted file mode 100644
index 8c51aee2..00000000
--- a/webapps/evoadmin-web/tasks/remount_usr_rw.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Get mount options for partitions
- shell: "mount | grep 'on /usr type'"
- args:
- warn: no
- register: mount
- changed_when: False
- failed_when: False
- when: not ansible_check_mode
-
-- name: Remount /usr if it is a partition and it is not mounted in rw
- command: "mount -o remount,rw /usr"
- when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw")
- args:
- warn: no
diff --git a/webapps/evoadmin-web/tasks/user.yml b/webapps/evoadmin-web/tasks/user.yml
index c5e5a35b..4070a52a 100644
--- a/webapps/evoadmin-web/tasks/user.yml
+++ b/webapps/evoadmin-web/tasks/user.yml
@@ -24,7 +24,7 @@
name: www-evoadmin
when: ansible_distribution_major_version | version_compare('9', '>=')
-- name: Install Git
+- name: Git is needed to clone the evoadmin repository
apt:
name: git
state: present
@@ -35,8 +35,6 @@
dest: "{{ evoadmin_document_root}}"
version: jessie
update: no
- # Warning: Need sudo!
- become_user: "{{ evoadmin_username }}"
when: ansible_distribution_release == "jessie"
- name: "Clone evoadmin repository (Debian 9 or later)"
@@ -45,11 +43,17 @@
dest: "{{ evoadmin_document_root}}"
version: master
update: yes
- # Warning: Need sudo!
- become_user: "{{ evoadmin_username }}"
when: ansible_distribution_major_version | version_compare('9', '>=')
-- include: remount_usr_rw.yml
+- name: Change ownership on git repository
+ file:
+ dest: "{{ evoadmin_document_root}}"
+ owner: "{{ evoadmin_username }}"
+ group: "{{ evoadmin_username }}"
+ recurse: yes
+
+- include_role:
+ name: remount-usr
when: evoadmin_scripts_dir | search ("/usr")
- name: "Create {{ evoadmin_scripts_dir }}"
@@ -66,12 +70,12 @@
# we use a shell command to have a "changed" thet really reflects the result.
- name: Fix permissions
- shell: "chmod -R --verbose u=rwX,g=rX,o= {{ item }}"
+ command: "chmod -R --verbose u=rwX,g=rX,o= {{ evoadmin_document_root }}"
register: command_result
changed_when: "'changed' in command_result.stdout"
# failed_when: False
- with_items:
- - "{{ evoadmin_home_dir}}/www"
+ args:
+ warn: no
- name: Add evoadmin sudoers file
template:
diff --git a/webapps/evoadmin-web/tasks/web.yml b/webapps/evoadmin-web/tasks/web.yml
index 0944c2cd..59c41582 100644
--- a/webapps/evoadmin-web/tasks/web.yml
+++ b/webapps/evoadmin-web/tasks/web.yml
@@ -6,7 +6,7 @@
section: PHP
option: "disable_functions"
value: "shell-exec,system,passthru,putenv,popen"
- notify: reload apache
+ notify: reload apache2
when: ansible_distribution_release == "jessie"
- name: "Set custom values for PHP config (Debian 9 or later)"
@@ -15,7 +15,7 @@
section: PHP
option: "disable_functions"
value: "shell-exec,system,passthru,putenv,popen"
- notify: reload apache
+ notify: reload apache2
when: ansible_distribution_major_version | version_compare('9', '>=')
- name: Install evoadmin VHost
diff --git a/webapps/evoadmin-web/templates/web-mail.tpl.j2 b/webapps/evoadmin-web/templates/web-mail.tpl.j2
index 262995c3..57c92779 100644
--- a/webapps/evoadmin-web/templates/web-mail.tpl.j2
+++ b/webapps/evoadmin-web/templates/web-mail.tpl.j2
@@ -20,10 +20,10 @@ PASSWORD : PASSE1
*****************************************
URL du site :
-http://{{ evoadmin_tpl_servername }}
+http://SERVERNAME
URL des stats :
-http://{{ evoadmin_tpl_servername }}/cgi-RANDOM/awstats.pl
+http://SERVERNAME/cgi-RANDOM/awstats.pl
(acces par IP ou login a demander !)
Repertoire de connexion : HOME_DIR/LOGIN/
@@ -60,7 +60,7 @@ ou etre un alias de {{ evoadmin_tpl_servername }} (enregistrement DNS CNAME).
Si vous avez besoin de faire des tests, vous devez
ajouter la ligne suivante au fichier "/etc/hosts" sous Linux/Unix
ou au fichier "system32\drivers\etc\hosts" sous Windows NT/XP :
-{{ evoadmin_tpl_address }} {{ evoadmin_tpl_servername }}
+{{ evoadmin_tpl_address }} SERVERNAME
Attention, par defaut, toutes les connexions vers l'exterieur
sont bloquees. Si vous avez besoin de recuperer des donnees
@@ -71,7 +71,7 @@ Afin de securiser au maximum le serveur, certaines URL
particulieres sont non autorisees pour eviter diverses
attaques (XSS, robots, trojans, injections, etc.).
Exemple d'URL refusee :
-http://{{ evoadmin_tpl_servername }}/cmd32.exe
+http://SERVERNAME/cmd32.exe
En cas de soucis avec votre application, prevenez-nous.
Si vous desirez mettre en place des parametres particuliers
diff --git a/webapps/handlers/main.yml b/webapps/handlers/main.yml
deleted file mode 100644
index b1d39d12..00000000
--- a/webapps/handlers/main.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-# handlers file for webapps
diff --git a/webapps/roundcube/defaults/main.yml b/webapps/roundcube/defaults/main.yml
new file mode 100644
index 00000000..5e0c1a81
--- /dev/null
+++ b/webapps/roundcube/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+roundcube_host: "roundcube.{{ ansible_fqdn }}"
+roundcube_imap_host: "localhost"
+roundcube_imap_port: 143
diff --git a/webapps/roundcube/handlers/main.yml b/webapps/roundcube/handlers/main.yml
new file mode 100644
index 00000000..bdba6e6b
--- /dev/null
+++ b/webapps/roundcube/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart imapproxy
+ systemd:
+ name: imapproxy
+ state: restarted
diff --git a/webapps/roundcube/tasks/main.yml b/webapps/roundcube/tasks/main.yml
new file mode 100644
index 00000000..9eac3dd9
--- /dev/null
+++ b/webapps/roundcube/tasks/main.yml
@@ -0,0 +1,114 @@
+---
+- name: configure roundcube-core
+ debconf:
+ name: roundcube-core
+ question: "{{ item.key }}"
+ value: "{{ item.value }}"
+ vtype: "{{ item.type }}"
+ with_items:
+ - { key: 'roundcube/database-type', type: 'select', value: 'sqlite3' }
+ - { key: 'roundcube/db/basepath', type: 'string', value: '/var/lib/roundcube/' }
+ tags:
+ - roundcube
+
+- name: install Roundcube
+ apt:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - imapproxy
+ - roundcube
+ - roundcube-sqlite3
+ - roundcube-plugins
+ - php-net-sieve
+ - php-zip
+ tags:
+ - roundcube
+
+- name: configure imapproxy imap host
+ lineinfile:
+ dest: /etc/imapproxy.conf
+ regexp: "^server_hostname"
+ line: "server_hostname {{ roundcube_imap_host }}"
+ notify: restart imapproxy
+ tags:
+ - roundcube
+
+- name: configure imapproxy imap port
+ lineinfile:
+ dest: /etc/imapproxy.conf
+ regexp: "^server_port"
+ line: "server_port {{ roundcube_imap_port }}"
+ notify: reload imapproxy
+ tags:
+ - roundcube
+
+- name: enable and start imapproxy
+ service:
+ name: imapproxy
+ state: started
+ enabled: True
+ tags:
+ - roundcube
+
+- name: configure roundcube imap host
+ lineinfile:
+ dest: /etc/roundcube/config.inc.php
+ regexp: "\\$config\\['default_host'\\]"
+ line: "$config['default_host'] = array('127.0.0.1');"
+ tags:
+ - roundcube
+
+- name: configure roudcube imap port
+ lineinfile:
+ dest: /etc/roundcube/config.inc.php
+ regexp: "\\$config\\['default_port'\\]"
+ insertafter: "\\$config\\['default_host'\\]"
+ line: "$config['default_port'] = 1143;"
+ tags:
+ - roundcube
+
+- name: configure managesieve plugin
+ copy:
+ src: /usr/share/roundcube/plugins/managesieve/config.inc.php.dist
+ dest: /etc/roundcube/plugins/managesieve/config.inc.php
+ mode: "0644"
+ remote_src: True
+ tags:
+ - roundcube
+
+- name: enable default plugins
+ replace:
+ dest: /etc/roundcube/config.inc.php
+ regexp: "^\\$config\\['plugins'\\] = array\\($"
+ replace: "$config['plugins'] = array('zipdownload','managesieve'"
+ tags:
+ - roundcube
+
+- name: deploy roundcube vhost
+ template:
+ src: apache2.conf.j2
+ dest: /etc/apache2/sites-available/rouncube.conf
+ mode: "0640"
+ notify: reload apache2
+ tags:
+ - roundcube
+
+- name: enable roundcube vhost
+ file:
+ src: /etc/apache2/sites-available/rouncube.conf
+ dest: /etc/apache2/sites-enabled/rouncube.conf
+ state: link
+ notify: reload apache2
+ tags:
+ - roundcube
+
+- name: enable roundcube link in default site index
+ lineinfile:
+ dest: /var/www/index.html
+ state: present
+ regexp: "Webmail"
+ line: ' Webmail'
+ insertbefore: ""
+ tags:
+ - roundcube
diff --git a/webapps/roundcube/templates/apache2.conf.j2 b/webapps/roundcube/templates/apache2.conf.j2
new file mode 100644
index 00000000..47865c01
--- /dev/null
+++ b/webapps/roundcube/templates/apache2.conf.j2
@@ -0,0 +1,46 @@
+
+ ServerName {{ roundcube_host }}
+ Redirect permanent / https://{{ roundcube_host }}
+
+
+
+
+ # FQDN principal
+ ServerName {{ roundcube_host }}
+
+ # Repertoire principal
+ DocumentRoot /var/lib/roundcube/
+
+ # Return 503 if imapproxy doesn't run
+
+ Redirect 503 /
+
+
+ Include /etc/roundcube/apache.conf
+
+ # LOG
+ CustomLog /var/log/apache2/access.log vhost_combined
+ CustomLog /var/lib/roundcube/logs/access.log combined
+ ErrorLog /var/lib/roundcube/logs/error.log
+
+ # REWRITE
+ UseCanonicalName On
+ RewriteEngine On
+ RewriteCond %{HTTP_HOST} !^{{ roundcube_host }}$
+ RewriteRule ^/(.*) http://%{SERVER_NAME}/$1 [L,R]
+
+ # PHP
+ #php_admin_flag engine off
+ #AddType text/html .html
+ #php_admin_flag display_errors On
+ #php_flag short_open_tag On
+ #php_flag register_globals On
+ #php_admin_value memory_limit 256M
+ #php_admin_value max_execution_time 60
+ #php_admin_value upload_max_filesize 8M
+ #php_admin_flag allow_url_fopen Off
+ php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f www-roundcube"
+ php_admin_value error_log "/home/roundcube/log/php.log"
+ #php_admin_value open_basedir "/usr/share/php:/home/roundcube:/tmp"
+
+
diff --git a/webapps/tasks/main.yml b/webapps/tasks/main.yml
deleted file mode 100644
index a86da0fd..00000000
--- a/webapps/tasks/main.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-
-- include: wordpress.yml
- when: webapps_wordpress_install
diff --git a/webapps/tasks/wordpress.yml b/webapps/tasks/wordpress.yml
deleted file mode 100644
index e85433c1..00000000
--- a/webapps/tasks/wordpress.yml
+++ /dev/null
@@ -1,48 +0,0 @@
- #- name: Init global variables
- # include: './tasks/var_common.yml'
-
- - name: init dir_wpcli
- set_fact: dir_wpcli="{{ dir }}/wp-cli"
-
- - debug: var=dir_wpcli
- when: debug_mode
- tags: debug_mode
-
- - name: Git clone Wordpress repository
- include: './tasks/git.yml'
- vars:
- service_git: WordPress
- url_git: "{{ webapps_wordpress_upstream }}"
- dest_git: "{{ dir_www }}"
- version_git: "{{ webapps_wordpress_version }}"
-
- - name: Creation directory wp-cli
- file: >
- path: "{{ dir_wpcli }}"
- state: directory
-
- - name: Download wp-cli.phar
- include: './tasks/download.yml'
- vars:
- url: 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar'
- dest: "{{ dir_wpcli }}"
-
- - name: Configuration for db
- shell: >
- php wp-cli.phar core config --dbname="{{ db_name }}" --dbuser="{{ db_user }}" --dbpass="{{ db_pwd }}" --dbhost="{{ db_host }}" --path="{{ dir_www }}"
- chdir: "{{ dir_wpcli }}"
-
- - name: Wordpress site installation
- shell: >
- php wp-cli.phar core install --url="{{ host }}" --title="{{ site_title }}" --admin_user="admin" --admin_password="{{ admin_pwd }}" --admin_email="{{ user }}@{{ ansible_fqdn }}" --skip-email --path="{{ dir_www }}"
- chdir: "{{ dir_wpcli }}"
-
- - name: Init variables to sending the email about the installation
- include: './tasks/var_email_install.yml'
- vars:
- admin_user: 'admin'
- type: 'Installation'
-
- - name: Send email
- include: './tasks/email.yml'
-
diff --git a/webapps/vars/main.yml b/webapps/vars/main.yml
deleted file mode 100644
index 5ec52e44..00000000
--- a/webapps/vars/main.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-# vars file for webapps
diff --git a/webapps/wordpress/defaults/main.yml b/webapps/wordpress/defaults/main.yml
new file mode 100644
index 00000000..f2508aff
--- /dev/null
+++ b/webapps/wordpress/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+wordpress_wpcli: "php {{ ansible_env.HOME }}/bin/wp-cli.phar --path={{ ansible_env.HOME }}/www"
+wordpress_version: 'latest'
+wordpress_plugins: ['wp-fail2ban']
+wordpress_host: "{{ ansible_fqdn }}"
+wordpress_title: "Wordpress Saas Evolix"
+wordpress_email: "root@localhost"
diff --git a/webapps/meta/main.yml b/webapps/wordpress/meta/main.yml
similarity index 90%
rename from webapps/meta/main.yml
rename to webapps/wordpress/meta/main.yml
index a8204bf9..73c6e08f 100644
--- a/webapps/meta/main.yml
+++ b/webapps/wordpress/meta/main.yml
@@ -1,6 +1,6 @@
galaxy_info:
author: Evolix
- description: your description
+ description: Install Wordpress site
issue_tracker_url: https://forge.evolix.org/projects/ansible-roles/issues
diff --git a/webapps/wordpress/tasks/main.yml b/webapps/wordpress/tasks/main.yml
new file mode 100644
index 00000000..d8a4598b
--- /dev/null
+++ b/webapps/wordpress/tasks/main.yml
@@ -0,0 +1,103 @@
+---
+- name: Create bin dir
+ file:
+ state: directory
+ dest: "{{ ansible_env.HOME }}/bin"
+ mode: "0750"
+
+- name: Download wp-cli
+ get_url:
+ url: "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar"
+ dest: "{{ ansible_env.HOME }}/bin/wp-cli.phar"
+ mode: "0750"
+
+- name: Download Wordpress
+ shell: '{{ wordpress_wpcli }} core download --locale=fr_FR --version={{ wordpress_version }}'
+ args:
+ creates: "{{ ansible_env.HOME }}/www/index.php"
+
+- name: Retrieve .my.cnf
+ fetch:
+ src: "{{ ansible_env.HOME }}/.my.cnf"
+ dest: "/tmp/wordpress-{{ ansible_user }}.cnf"
+ flat: yes
+
+- name: Generate random password
+ command: apg -n1 -m 12 -M LCN
+ register: shell_password
+ changed_when: false
+
+- name: Read mysql config from .my.cnf
+ set_fact:
+ db_host: "{{ lookup('ini', 'host section=client file=/tmp/wordpress-{{ ansible_user }}.cnf default=127.0.0.1') }}"
+ db_user: "{{ lookup('ini', 'user section=client file=/tmp/wordpress-{{ ansible_user }}.cnf default={{ ansible_user }}') }}"
+ db_pwd: "{{ lookup('ini', 'password section=client file=/tmp/wordpress-{{ ansible_user }}.cnf') }}"
+ db_name: "{{ lookup('ini', 'database section=mysql file=/tmp/wordpress-{{ ansible_user }}.cnf default={{ ansible_user }}') }}"
+ admin_pwd: "{{ shell_password.stdout }}"
+
+- name: Remove local .my.cnf
+ file:
+ path: "/tmp/wordpress-{{ ansible_user }}.cnf"
+ state: absent
+ delegate_to: localhost
+
+- name: Configure Wordpress (wp-config.php)
+ shell: '{{ wordpress_wpcli }} core config --dbhost={{ db_host }} --dbuser={{ db_user }} --dbpass={{ db_pwd }} --dbname={{ db_name }}'
+ args:
+ creates: "{{ ansible_env.HOME }}/www/wp-config.php"
+
+- name: Configure site
+ shell: '{{ wordpress_wpcli }} core install --url={{ wordpress_host | quote }} --title={{ wordpress_title | quote }} --admin_user=admin --admin_password="{{ admin_pwd | quote }}" --admin_email={{ wordpress_email }} --skip-email'
+ changed_when: false
+
+- name: Check if Wordpress is up to date
+ shell: '{{ wordpress_wpcli }} core check-update | grep -q Success'
+ register: check_version
+ check_mode: no
+ failed_when: false
+ changed_when: check_version.rc
+
+- name: Update Wordpress
+ shell: '{{ wordpress_wpcli }} core update --version={{ wordpress_version }}'
+ args:
+ removes: "{{ ansible_env.HOME }}/www/index.php"
+ when: check_version.rc
+
+- name: Install default plugin
+ shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} || {{ wordpress_wpcli }} plugin install {{ item }}'
+ changed_when: false
+ with_items: "{{ wordpress_plugins }}"
+
+- name: Update default plugins
+ shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} && {{ wordpress_wpcli }} plugin update {{ item }}'
+ changed_when: false
+ with_items: "{{ wordpress_plugins }}"
+
+- name: Activate default plugins
+ shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} && {{ wordpress_wpcli }} plugin activate {{ item }}'
+ changed_when: false
+ with_items: "{{ wordpress_plugins }}"
+
+- name: Send a summary mail
+ mail:
+ host: 'localhost'
+ port: 25
+ to: "{{ wordpress_email }}"
+ from: "{{ ansible_user }}@{{ ansible_fqdn }}"
+ subject: "Nouveau site Wordpress {{ ansible_user }}"
+ charset: "utf-8"
+ body: |
+ Votre nouveau site WordPress a bien été installé à l’adresse :
+
+ http://{{ wordpress_host }}
+
+ Vous pouvez vous y connecter en tant qu’administrateur avec les informations suivantes :
+
+ Identifiant : admin
+ Mot de passe : {{ admin_pwd }}
+ Connectez-vous ici : http://{{ wordpress_host }}/wp-login.php
+
+ Nous espérons que vous aimerez votre nouveau site ! Merci à vous !
+ --
+ Équipe Evolix
+ Evolix - Hébergement et Infogérance Open Source http://www.evolix.fr/