Browse Source

add davical support. needs some cleanup

Cullum Smith 2 years ago
parent
commit
c658e94f0b

+ 1
- 0
roles/acme/vars/main.yml View File

@@ -8,3 +8,4 @@ acme_alt_names:
8 8
   - ttrss
9 9
   - matrix
10 10
   - git
11
+  - dav

+ 13
- 2
roles/base/tasks/main.yml View File

@@ -23,10 +23,18 @@
23 23
   when: private_interface is defined
24 24
   notify: enable private network
25 25
 
26
+- name: create /etc in www chroot
27
+  file:
28
+    path: /var/www/etc
29
+    state: directory
30
+
26 31
 - name: generate resolv.conf
27 32
   template:
28 33
     src: resolv.conf.j2
29
-    dest: /etc/resolv.conf
34
+    dest: '{{ item }}'
35
+  with_items:
36
+    - /etc/resolv.conf
37
+    - /var/www/etc/resolv.conf
30 38
 
31 39
 - name: generate ntpd.conf
32 40
   template:
@@ -61,7 +69,10 @@
61 69
 - name: generate /etc/hosts
62 70
   template:
63 71
     src: hosts.j2
64
-    dest: /etc/hosts
72
+    dest: '{{ item }}'
73
+  with_items:
74
+    - /etc/hosts
75
+    - /var/www/etc/hosts
65 76
 
66 77
 - name: generate login.conf
67 78
   template:

+ 10
- 0
roles/davical/defaults/main.yml View File

@@ -0,0 +1,10 @@
1
+---
2
+httpd_secure_port: 8080
3
+davical_adminpw: changeme
4
+davical_uid: 903
5
+davical_max_upload_bytes: 5000000
6
+davical_refresh_interval: 60
7
+davical_locale: en_NZ
8
+davical_ignore_groups:
9
+  - ssh
10
+  - sudo

+ 15
- 0
roles/davical/handlers/main.yml View File

@@ -0,0 +1,15 @@
1
+---
2
+- name: reload httpd
3
+  service:
4
+    name: httpd
5
+    state: reloaded
6
+
7
+- name: reload nginx
8
+  service:
9
+    name: nginx
10
+    state: reloaded
11
+
12
+- name: restart php-fpm
13
+  service:
14
+    name: php72_fpm
15
+    state: restarted

+ 129
- 0
roles/davical/tasks/main.yml View File

@@ -0,0 +1,129 @@
1
+---
2
+- name: install dependencies
3
+  openbsd_pkg:
4
+    name: '{{ item }}'
5
+    state: installed
6
+  with_items:
7
+    - gtar
8
+    - p5-YAML
9
+    - p5-DBD-Pg
10
+    - p5-DBI
11
+
12
+- name: create davical user
13
+  user:
14
+    name: _davical
15
+    comment: 'Davical Pseudo-User'
16
+    shell: /sbin/nologin
17
+    home: '{{ davical_home }}'
18
+    uid: '{{ davical_uid }}'
19
+    createhome: no
20
+
21
+- name: create davical directory
22
+  file:
23
+    path: '{{ davical_home }}'
24
+    state: directory
25
+
26
+- name: generate httpd vhost
27
+  template:
28
+     src: httpd/dav.conf.j2
29
+     dest: /etc/sites/dav.conf
30
+  notify: reload httpd
31
+
32
+- name: enable davical vhost
33
+  lineinfile:
34
+    path: /etc/httpd.d/sites.conf
35
+    line: include "/etc/sites/dav.conf"
36
+  notify: reload httpd
37
+
38
+- include: ../../../tasks/nginx_proxy.yml
39
+  vars:
40
+    name: dav
41
+    port: '{{ httpd_secure_port }}'
42
+
43
+- name: create php directories
44
+  file:
45
+    path: /var/www/cache/{{ item }}
46
+    state: directory
47
+    owner: _davical
48
+    group: _davical
49
+    mode: 0700
50
+  with_items:
51
+    - davical
52
+    - davical/session
53
+    - davical/upload
54
+
55
+- name: generate php-fpm config
56
+  template:
57
+    src: php/davical.conf.j2
58
+    dest: /etc/php-fpm.d/davical.conf
59
+  notify: restart php-fpm
60
+
61
+- name: enable php-fpm
62
+  service:
63
+    name: php72_fpm
64
+    enabled: yes
65
+    state: started
66
+
67
+- name: install davical
68
+  unarchive:
69
+    src: '{{ davical_tarball }}'
70
+    dest: '{{ davical_home }}'
71
+    owner: root
72
+    group: wheel
73
+    remote_src: yes
74
+
75
+- name: install awl
76
+  unarchive:
77
+    src: '{{ awl_tarball }}'
78
+    dest: '{{ awl_home }}'
79
+    owner: root
80
+    group: wheel
81
+    remote_src: yes
82
+
83
+- name: check if database is initialized
84
+  command: psql -U davical_app davical -c 'SELECT 1 FROM awl_db_revision'
85
+  become_user: _davical
86
+  changed_when: False
87
+  failed_when: False
88
+  register: check_db
89
+
90
+- name: initialize database
91
+  shell: sed '/^export PGOPTIONS=/d' '{{ davical_home }}/dba/create-database.sh' | sh -s davical '{{ davical_adminpw }}'
92
+  become_user: _postgresql
93
+  environment:
94
+    PSQLOPTS: '-U postgres'
95
+  args:
96
+    chdir: '{{ davical_home }}/dba'
97
+    warn: False
98
+  when: check_db.rc != 0
99
+
100
+- name: read cal dkim private key
101
+  slurp:
102
+    src: /etc/mail/dkim/cal.private.key
103
+  register: slurp_dkim_private_key
104
+
105
+- name: set cal dkim private key
106
+  set_fact:
107
+    davical_dkim_private_key: '{{ slurp_dkim_private_key.content }}'
108
+
109
+- name: generate configuration
110
+  template:
111
+    src: config.php.j2
112
+    dest: /var/www/htdocs/davical/config/config.php
113
+    owner: root
114
+    group: _davical
115
+    mode: 0640
116
+
117
+- meta: flush_handlers
118
+
119
+- name: sync ldap accounts
120
+  command: php-{{ php_version }} -d error_reporting="E_ERROR" "{{ davical_home }}/scripts/cron-sync-ldap.php" dav.{{ domain }}
121
+  become_user: _davical
122
+  changed_when: False
123
+
124
+- name: add ldap sync cron job
125
+  cron:
126
+    name: davical ldap sync
127
+    user: _davical
128
+    job: /usr/local/bin/php-{{ php_version }} -d error_reporting="E_ERROR" "{{ davical_home }}/scripts/cron-sync-ldap.php" dav.{{ domain }}
129
+    minute: '*/5'

+ 67
- 0
roles/davical/templates/config.php.j2 View File

@@ -0,0 +1,67 @@
1
+<?php
2
+$c->pg_connect[]  = 'dbname=davical user=davical_app';
3
+$c->system_name   = '{{ domain }} CalDAV';
4
+$c->admin_email   = 'root@{{ domain }}';
5
+
6
+$c->restrict_setup_to_admin    = true;
7
+$c->home_calendar_name         = 'calendar';
8
+$c->home_addressbook_name      = 'addressbook';
9
+$c->carddav_max_resource_size  = {{ davical_max_upload_bytes }};
10
+$c->default_privileges         = array('read-free-busy', 'schedule-deliver');
11
+$c->external_refresh           = {{ davical_refresh_interval }};
12
+$c->default_locale             = '{{ davical_locale}}';
13
+$c->allow_get_email_visibility = true;
14
+
15
+$c->enable_scheduling        = true;
16
+$c->scheduling_dkim_domain   = 'dav.{{ domain }}';
17
+$c->scheduling_dkim_selector = 'cal';
18
+$c->schedule_private_key     = '{{ davical_dkim_private_key }}';
19
+
20
+$c->trust_x_forwarded = true;
21
+
22
+$c->authenticate_hook['call'] = 'LDAP_check';
23
+$c->authenticate_hook['config'] = array(
24
+  'host'            => '127.0.0.1',
25
+  'port'            => '389',
26
+  'protocolVersion' => '3',
27
+  'optReferrals'    => 0,
28
+  'networkTimeout'  => 5,
29
+  'scope'           => 'subtree',
30
+  'baseDNUsers'     => 'ou=users,{{ basedn }}',
31
+  'filterUsers'     => 'objectClass=inetOrgPerson',
32
+  'baseDNGroups'    => 'ou=groups,{{ basedn }}',
33
+  'filterGroups'    => 'objectClass=posixGroup',
34
+  'mapping_field'   => array(
35
+    'username' => 'uid',
36
+    'modified' => 'modifyTimestamp',
37
+    'fullname' => 'cn',
38
+    'email'    =>'mail',
39
+   ),
40
+  'group_mapping_field' => array(
41
+    'username' => 'cn',
42
+    'modified' => 'modifyTimestamp',
43
+    'fullname' => 'cn' ,
44
+    'members'  => 'memberUid',
45
+  ),
46
+  'group_member_dnfix' => false,
47
+  'default_value'      => array(
48
+    'date_format_type' => 'I',
49
+    'locale'           => '{{ davical_locale }}',
50
+  ),
51
+ 'format_updated'=> array(
52
+   'Y' => array(0,4),
53
+   'm' => array(4,2),
54
+   'd' => array(6,2),
55
+   'H' => array(8,2),
56
+   'M' => array(10,2),
57
+   'S' => array(12,2),
58
+  ),
59
+);
60
+
61
+$c->do_not_sync_group_from_ldap = array(
62
+  {% for group in davical_ignore_groups %}
63
+  '{{ group }}' => true,
64
+  {% endfor %}
65
+);
66
+
67
+include('drivers_ldap.php');

+ 9
- 0
roles/davical/templates/httpd/dav.conf.j2 View File

@@ -0,0 +1,9 @@
1
+server dav.{{ domain }} {
2
+  include "/etc/httpd.d/https.conf"
3
+  root "/htdocs/davical/htdocs"
4
+  directory index index.php
5
+
6
+  location "*.php*" {
7
+    fastcgi socket "/run/davical.sock"
8
+  }
9
+}

+ 24
- 0
roles/davical/templates/php/davical.conf.j2 View File

@@ -0,0 +1,24 @@
1
+[davical]
2
+
3
+user = _davical
4
+group = _davical
5
+listen = {{ davical_fpm_sock }}
6
+
7
+listen.owner = www
8
+listen.group = www
9
+;listen.mode = 0660
10
+
11
+pm = dynamic
12
+pm.max_children = 5
13
+pm.start_servers = 2
14
+pm.min_spare_servers = 1
15
+pm.max_spare_servers = 3
16
+
17
+chroot = /var/www
18
+chdir = /htdocs/davical
19
+
20
+php_admin_value[open_basedir] = /htdocs/davical/htdocs/:/htdocs/davical/config/config.php:/htdocs/davical/inc/:/htdocs/awl/inc/:/tmp/.s.PGSQL.5432
21
+php_admin_value[include_path] = /htdocs/awl/inc:/htdocs/davical/inc
22
+php_admin_value[session.name] = DAVICAL
23
+php_admin_value[session.save_path] = /cache/davical/session
24
+php_admin_value[upload_tmp_dir] = /cache/davical/upload

+ 11
- 0
roles/davical/vars/main.yml View File

@@ -0,0 +1,11 @@
1
+---
2
+php_version: 7.2
3
+davical_home: /var/www/htdocs/davical
4
+awl_home: /var/www/htdocs/awl
5
+davical_fpm_sock: /var/www/run/davical.sock
6
+basedn: "{{ domain.split('.') | map('regex_replace', '(.*)', 'dc=\\1') | join(',') }}"
7
+
8
+davical_version: '1.1.8'
9
+awl_version: '0.60'
10
+davical_tarball: https://www.davical.org/downloads/davical_{{ davical_version }}.orig.tar.xz
11
+awl_tarball: https://www.davical.org/downloads/awl_{{ awl_version }}.orig.tar.xz

+ 15
- 0
roles/dkim/tasks/main.yml View File

@@ -33,6 +33,21 @@
33 33
   args:
34 34
     creates: /etc/mail/dkim/dkim.txt
35 35
 
36
+- name: generate cal dkim private key
37
+  command: openssl genrsa -out /etc/mail/dkim/cal.private.key 2048
38
+  args:
39
+    creates: /etc/mail/dkim/cal.private.key
40
+
41
+- name: generate cal dkim public key
42
+  command: openssl rsa -in /etc/mail/dkim/cal.private.key -pubout -out /etc/mail/dkim/cal.public.key
43
+  args:
44
+    creates: /etc/mail/dkim/cal.public.key
45
+
46
+- name: generate cal dkim TXT record
47
+  shell: ( echo p= ; grep -Ev -- '-+(BEGIN|END) PUBLIC KEY-+' /etc/mail/dkim/cal.public.key) | tr -d '\n' | fold -w255 | awk 'BEGIN { print "cal._domainkey.dav     IN TXT ( \"v=DKIM1; k=rsa; \"" } { print "    " "\"" $0 "\"" } END { print ") ;" }' > /etc/mail/dkim/cal.txt
48
+  args:
49
+    creates: /etc/mail/dkim/cal.txt
50
+
36 51
 - name: enable and start daemon
37 52
   service:
38 53
     name: dkimproxy_out

+ 8
- 2
roles/httpd/templates/www.conf.j2 View File

@@ -6,8 +6,6 @@ server {{ domain }} {
6 6
 
7 7
   location "/.well-known/*" {
8 8
     block return 301 "https://{{ domain }}$REQUEST_URI"
9
-    root "/htdocs/well-known"
10
-    request strip 1
11 9
   }
12 10
 
13 11
   location * {
@@ -19,6 +17,14 @@ server {{ domain }} {
19 17
   include "/etc/httpd.d/https.conf"
20 18
   root "/nonexistent"
21 19
 
20
+  location "/.well-known/caldav" {
21
+    block return 301 "https://dav.{{ domain }}/caldav.php/.well-known/caldav"
22
+  }
23
+
24
+  location "/.well-known/carddav" {
25
+    block return 301 "https://dav.{{ domain }}/caldav.php/.well-known/carddav"
26
+  }
27
+
22 28
   location "/.well-known/*" {
23 29
     root "/htdocs/well-known"
24 30
     request strip 1

+ 9
- 0
roles/nsd/tasks/get_dkim.yml View File

@@ -8,3 +8,12 @@
8 8
 - name: set dkim records
9 9
   set_fact:
10 10
     dkim_records: '{{ dkim_records_b64.content | b64decode }}'
11
+
12
+- name: read cal dkim records file
13
+  slurp:
14
+    src: /etc/mail/dkim/cal.txt
15
+  register: cal_dkim_records_b64
16
+
17
+- name: set cal dkim records
18
+  set_fact:
19
+    cal_dkim_records: '{{ cal_dkim_records_b64.content | b64decode }}'

+ 3
- 0
roles/nsd/templates/domain.zone.j2 View File

@@ -42,6 +42,8 @@ turn IN A {{ ip }}
42 42
 turn IN AAAA {{ ip6 }}
43 43
 git IN A {{ ip }}
44 44
 git IN AAAA {{ ip6 }}
45
+dav IN A {{ ip }}
46
+dav IN AAAA {{ ip6 }}
45 47
 
46 48
 {% for name, record in (a_records | default({})).iteritems() %}
47 49
 {{ name }} IN A {{ record.ip }}
@@ -59,6 +61,7 @@ ns{{ loop.index }} IN AAAA {{ addr }}
59 61
 
60 62
 ; DKIM
61 63
 {{ dkim_records }}
64
+{{ cal_dkim_records }}
62 65
 
63 66
 ; SRV records
64 67
 {% for r in _srv_records  + (srv_records | default([])) %}

+ 1
- 0
roles/nsd/vars/main.yml View File

@@ -16,4 +16,5 @@ _srv_records:
16 16
   - { service: 'imaps',       port: 993,  proto: 'tcp', host: 'mail' }
17 17
   - { service: 'xmpp-client', port: 5222, proto: 'tcp', host: 'xmpp' }
18 18
   - { service: 'xmpp-server', port: 5269, proto: 'tcp', host: 'xmpp' }
19
+  - { service: 'ischedules',  port: 443,  proto: 'tcp', host: 'dav'  }
19 20
   - { service: 'matrix',      port: '{{ synapse_federation_port }}', proto: 'tcp', host: 'matrix' }

+ 2
- 0
roles/php/handlers/main.yml View File

@@ -0,0 +1,2 @@
1
+---
2
+# TODO: add restart hander iff there are pools defined

+ 1
- 0
roles/php/tasks/main.yml View File

@@ -11,6 +11,7 @@
11 11
     - php-gd
12 12
     - php-pcntl
13 13
     - php-ldap
14
+    - php-imap
14 15
 
15 16
 - name: create directories
16 17
   file:

+ 1
- 0
roles/php/templates/php.ini.j2 View File

@@ -893,6 +893,7 @@ extension=gd
893 893
 extension=pdo_pgsql
894 894
 extension=pgsql
895 895
 extension=ldap
896
+extension=imap
896 897
 zend_extension=opcache.so
897 898
 
898 899
 ;extension=bz2

+ 1
- 0
roles/postgresql/templates/pg_hba.conf.j2 View File

@@ -1,2 +1,3 @@
1 1
 local all postgres peer map=postgres
2
+local davical all peer map=davical
2 3
 local all all peer

+ 4
- 0
roles/postgresql/templates/pg_ident.conf.j2 View File

@@ -1,2 +1,6 @@
1 1
 postgres _postgresql postgres
2 2
 postgres root postgres
3
+davical _davical davical_app
4
+davical _davical davical_dba
5
+davical _postgresql davical_dba
6
+davical _postgresql davical_app

+ 1
- 0
roles/smtpd/templates/aliases.j2 View File

@@ -81,6 +81,7 @@ _ttrss: /dev/null
81 81
 _synapse: /dev/null
82 82
 _turnserver: /dev/null
83 83
 _gitea: /dev/null
84
+_davical: /dev/null
84 85
 {{ provision_username }}: /dev/null
85 86
 
86 87
 # Well-known aliases -- these should be filled in!

+ 1
- 1
roles/ttrss/templates/php/ttrss.conf.j2 View File

@@ -17,7 +17,7 @@ pm.max_spare_servers = 3
17 17
 chroot = /var/www
18 18
 chdir = /htdocs/ttrss
19 19
 
20
-php_admin_value[open_basedir] = /htdocs/ttrss/;/tmp/.s.PGSQL.5432
20
+php_admin_value[open_basedir] = /htdocs/ttrss/:/tmp/.s.PGSQL.5432
21 21
 php_admin_value[session.name] = TTRSS
22 22
 php_admin_value[session.save_path] = /cache/ttrss/session
23 23
 php_admin_value[upload_tmp_dir] = /cache/ttrss/upload

+ 1
- 0
roles/ttrss/templates/rc.d/ttrss.j2 View File

@@ -1,6 +1,7 @@
1 1
 #!/bin/ksh
2 2
 
3 3
 daemon="{{ php_path }}"
4
+#TODO: log this to a file
4 5
 daemon_flags="-d disable_functions= {{ ttrss_home }}/update_daemon2.php --quiet"
5 6
 daemon_user="_ttrss"
6 7
 

+ 2
- 1
site.yml View File

@@ -16,11 +16,12 @@
16 16
     - { role: smtpd,      tags: ['smtpd']      }
17 17
     - { role: spamd,      tags: ['spamd']      }
18 18
     - { role: postgresql, tags: ['postgresql'] }
19
+    - { role: ldapd,      tags: ['ldapd']      }
19 20
     - { role: prosody,    tags: ['prosody']    }
20 21
     - { role: znc,        tags: ['znc']        }
21 22
     - { role: php,        tags: ['php']        }
22 23
     - { role: ttrss,      tags: ['ttrss']      }
23 24
     - { role: synapse,    tags: ['synapse']    }
24 25
     - { role: gitea,      tags: ['gitea']      }
25
-    - { role: ldapd,      tags: ['ldapd']      }
26
+    - { role: davical,    tags: ['davical']    }
26 27
     - { role: dank,       tags: ['dank']       }

+ 10
- 4
tasks/nginx_proxy.yml View File

@@ -16,8 +16,11 @@
16 16
           {% elif socket is defined %}
17 17
           proxy_pass  http://unix:{{ socket }}:;
18 18
           {% endif %}
19
-          proxy_set_header Host              $host;
20
-          proxy_set_header X-Forwarded-For   $remote_addr;
19
+          proxy_set_header Host              $server_name;
20
+          proxy_set_header X-Forwarded-Host  $host;
21
+          proxy_set_header X-Forwarded-Port  $server_port;
22
+          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
23
+          proxy_set_header X-Real-IP         $remote_addr;
21 24
           proxy_set_header X-Forwarded-Proto https;
22 25
           proxy_http_version 1.1;
23 26
         }
@@ -28,8 +31,11 @@
28 31
           {% elif socket is defined %}
29 32
           proxy_pass  http://unix:{{ socket }}:;
30 33
           {% endif %}
31
-          proxy_set_header Host              $host;
32
-          proxy_set_header X-Forwarded-For   $remote_addr;
34
+          proxy_set_header Host              $server_name;
35
+          proxy_set_header X-Forwarded-Host  $host;
36
+          proxy_set_header X-Forwarded-Port  $server_port;
37
+          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
38
+          proxy_set_header X-Real-IP         $remote_addr;
33 39
           proxy_set_header X-Forwarded-Proto https;
34 40
           proxy_http_version 1.1;
35 41
           add_header Access-Control-Allow-Origin *;

+ 4
- 1
vars-sample.yml View File

@@ -50,9 +50,12 @@ ntp_servers:                # Upstream NTP servers
50 50
 
51 51
 sshd_port: 11522            # SSH port. Don't choose 22 unless you like being hammered 24/7 by botnets!
52 52
 
53
-ldap_rootpw: supersecret    # The default is changeme. You may want to put this in an ansible vault. It
53
+ldap_rootpw: changeme       # The default is changeme. You may want to put this in an ansible vault. It
54 54
                             #   will be converted to a blowfish hash in ldapd.conf.
55 55
 
56
+davical_adminpw: changeme   # This is the default password for the "admin" caldav user. You should change
57
+                            #   it in the web interface when you log in for the first time.
58
+
56 59
 
57 60
 # ===== OPTIONAL VARIABLES =====
58 61
 private_interface: vio1     # If your hosting provider provides a private network, you can set it here.

Loading…
Cancel
Save