From 67dd56ab0d520abf01cdbdbe10b68f6289b6ecc7 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Mon, 9 Apr 2018 15:03:39 +0800 Subject: Add radicale role: lightweight {Card,Cal}DAV server WARNING: py36-radicale2 needs manual installation at the moment. --- roles/radicale/files/_gitignore | 5 ++ roles/radicale/files/logging | 50 ++++++++++++++++ roles/radicale/files/rights | 49 ++++++++++++++++ roles/radicale/handlers/main.yml | 3 + roles/radicale/tasks/main.yml | 65 +++++++++++++++++++++ roles/radicale/templates/config.j2 | 90 +++++++++++++++++++++++++++++ roles/radicale/templates/radicale.passwd.j2 | 15 +++++ 7 files changed, 277 insertions(+) create mode 100644 roles/radicale/files/_gitignore create mode 100644 roles/radicale/files/logging create mode 100644 roles/radicale/files/rights create mode 100644 roles/radicale/handlers/main.yml create mode 100644 roles/radicale/tasks/main.yml create mode 100644 roles/radicale/templates/config.j2 create mode 100644 roles/radicale/templates/radicale.passwd.j2 (limited to 'roles') diff --git a/roles/radicale/files/_gitignore b/roles/radicale/files/_gitignore new file mode 100644 index 0000000..464ffb6 --- /dev/null +++ b/roles/radicale/files/_gitignore @@ -0,0 +1,5 @@ +# http://radicale.org/versioning/ + +.Radicale.cache +.Radicale.lock +.Radicale.tmp-* diff --git a/roles/radicale/files/logging b/roles/radicale/files/logging new file mode 100644 index 0000000..07fae21 --- /dev/null +++ b/roles/radicale/files/logging @@ -0,0 +1,50 @@ +# +# /usr/local/etc/radicale/logging +# Logging configurations for Radicale +# +# References +# * http://radicale.org/logging/ +# * https://docs.python.org/3/library/logging.config.html +# +# Aaron LI +# Created: 2017-04-27 +# + + +# NOTE: uWSGI will capture the console output, so no longer need to +# log into a separate file. + +[loggers] +keys = root + +[handlers] +keys = console + +[formatters] +keys = full + +# +# Loggers +# + +[logger_root] +handlers = console + +# +# Handlers +# + +[handler_console] +class = StreamHandler +level = INFO +#level = DEBUG +args = (sys.stdout,) +formatter = full + +# +# Formatters +# + +[formatter_full] +format = %(asctime)s - %(levelname)s: %(message)s +datefmt = %b %d %H:%M:%S diff --git a/roles/radicale/files/rights b/roles/radicale/files/rights new file mode 100644 index 0000000..9b9b253 --- /dev/null +++ b/roles/radicale/files/rights @@ -0,0 +1,49 @@ +# +# /usr/local/etc/radicale/rights +# File-based rights managements for Radicale +# +# Aaron LI +# Created: 2017-04-27 +# + +# Authentication login is matched against the "user" key, and collection's +# path is matched against the "collection" key. +# You can use Python's ConfigParser interpolation values "%(login)s" and +# "%(path)s". You can also get groups from the user regex in the collection +# with "{0}", "{1}", etc. +# +# For example, for the "user" key, ".+" means "authenticated user" and ".*" +# means "anybody" (including anonymous users). +# +# * Section names are only used for naming the rule. +# * Leading or ending slashes are trimmed from collection's path. +# * The first rule matching both user and collection patterns will be returned. +# +# See: http://radicale.org/user_documentation/#idrights-management +# + +# Use a domain-like authentication (user@device) for each owner/user +# to achieve the application-specific passwords mechanism. +[owner-devices] +user: ([^@]+)@.+ +collection: {0}(/.*)? +permission: rw + +# I use the authentication through IMAP provided by Dovecot, and I +# implement the application-specific passwords mechanism, i.e., one +# user may have different passwords for different devices/logins +# identified with different username. +# For example, a user "user@domain.com" may set different passwords +# for such different usernames, e.g., "user@domain.com@laptop", +# "user@domain.com@phone". +# +#[owner-imap-auth] +#user: ^([^@]+)@.+\..+$ +#collection: ^{0}(/.+)?$ +#permission: rw + +# Any authenticated user can reach root collection +#[read] +#user = .+ +#collection = +#permission = r diff --git a/roles/radicale/handlers/main.yml b/roles/radicale/handlers/main.yml new file mode 100644 index 0000000..94ab252 --- /dev/null +++ b/roles/radicale/handlers/main.yml @@ -0,0 +1,3 @@ +--- +- name: reload-radicale + command: service uwsgi reload radicale diff --git a/roles/radicale/tasks/main.yml b/roles/radicale/tasks/main.yml new file mode 100644 index 0000000..dbd6839 --- /dev/null +++ b/roles/radicale/tasks/main.yml @@ -0,0 +1,65 @@ +--- +# NOTE: Radicale requires nginx. + +- name: install packages + pkgng: + name: "{{ item }}" + state: present + with_items: + # - py36-radicale2 + - uwsgi-py36 + +- name: create data directory + file: + path: "{{ radicale.home }}" + state: directory + owner: radicale + group: radicale + mode: 0700 + +- name: generate config file + template: + src: config.j2 + dest: "{{ radicale.etcdir }}/config" + notify: reload-radicale + +- name: copy extra config files + copy: + src: "{{ item }}" + dest: "{{ radicale.etcdir }}/{{ item | basename }}" + with_items: + - logging + - rights + notify: reload-radicale + +- name: copy gitignore for storage + copy: + src: _gitignore + dest: "{{ radicale.home }}/.gitignore" + +- name: create nginx auth/ dirctory + file: + path: /usr/local/etc/nginx/auth + state: directory + +- name: generate passwd for nginx + template: + src: radicale.passwd.j2 + dest: /usr/local/etc/nginx/auth/radicale.passwd + group: www + mode: 0440 + notify: reload-nginx + +- name: setup uwsgi in rc.conf + blockinfile: + path: /etc/rc.conf + marker: "# {mark} ANSIBLE MANAGED - uwsgi/radicale" + block: | + uwsgi_profiles="${uwsgi_profiles} radicale" + uwsgi_radicale_socket="/var/run/uwsgi-radicale.sock" + uwsgi_radicale_uid="radicale" + uwsgi_radicale_gid="radicale" + uwsgi_radicale_flags="-L --env RADICALE_CONFIG={{ radicale.etcdir }}/config --plugin python --wsgi-file {{ radicale.wwwdir }}/radicale.wsgi" + +- name: enable and start uwsgi + command: rcenable uwsgi diff --git a/roles/radicale/templates/config.j2 b/roles/radicale/templates/config.j2 new file mode 100644 index 0000000..ca5e251 --- /dev/null +++ b/roles/radicale/templates/config.j2 @@ -0,0 +1,90 @@ +# +# /usr/local/etc/radicale/config +# Radicale - A simple calendar and contact server +# +# http://radicale.org/ +# https://github.com/Kozea/Radicale +# +# Aaron LI +# Created: 2017-04-27 +# + + +# Not needed when using uWSGI +[server] +hosts = 127.0.0.1:5232 +daemon = True + +[auth] + +# Authentication method +# Value: none | htpasswd | remote_user | http_x_remote_user +# +# * None +# Allows all usernames and passwords. It also disables rights checking. +# * htpasswd +# Use an Apache htpasswd file to store usernames and passwords. +# * remote_user +# Takes the user name from the REMOTE_USER environment variable and +# disables HTTP authentication. This can be used to provide the user +# name from a WSGI server. +# * http_x_remote_user +# Takes the user name from the "X-Remote-User" HTTP header and disables +# HTTP authentication. This can be used to provide the user name from +# a reverse proxy. +# +#type = http_x_remote_user +type = remote_user + + +# Rights backend +[rights] + +# Value: none | authenticated | owner_only | owner_write | from_file +# +# * None : Everybody (including anonymous users) has read and +# write access to all collections; +# * authenticated : An authenticated users has read and write access +# to all collections, anonymous users have no access +# to these collections; +# * owner_only : Only owners have read and write access to their +# own collections. The other users, authenticated or +# anonymous, have no access to these collections; +# * owner_write : Authenticated users have read access to all collections, +# but only owners have write access to their own +# collections. And anonymous users have no access; +# * from_file : Rights are based on a regex-based file whose name +# is specified in this config file: [right]/file +# +type = owner_only + + +# Storage backend +[storage] + +type = multifilesystem +filesystem_folder = {{ radicale.home }} + +# Command that is run after changes to storage +# See: http://radicale.org/versioning/ +hook = ([ -d .git ] || git init) && git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s) + + +# Web interface backend +[web] + +# Value: none | internal +# +# * none : Just shows the message "Radicale works!". +# * internal : Allows creation and management of address books and calendars. +# +#type = internal +type = none + + +[logging] +config = {{ radicale.etcdir }}/logging +# The logging config file just specified will provide finer controls, so +# just set the default logging level to DEBUG. +debug = True + diff --git a/roles/radicale/templates/radicale.passwd.j2 b/roles/radicale/templates/radicale.passwd.j2 new file mode 100644 index 0000000..8c59c79 --- /dev/null +++ b/roles/radicale/templates/radicale.passwd.j2 @@ -0,0 +1,15 @@ +# +# Password for Nginx auth for Radicale. +# +# Aaron LI +# + +# name:pass +{% for user in radicale.users %} +# user: {{ user.name }} +{{ user.name }}:{{ user.pass | cryptpass }} +{% for dev in user.devices|default([]) %} +{{ user.name }}@{{ dev.name }}:{{ dev.pass | cryptpass }} +{% endfor %}{# devices #} +{% endfor %}{# user #} +# EOF -- cgit v1.2.2