diff --git a/README.md b/README.md index dcfb58b..c15642c 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ concise area of concern. - [`gitea`](roles/gitea/README.md): Deploy [gitea.io](https://gitea.io), a lightweight, self-hosted git service. +- [`hedgedoc`](roles/hedgedoc/README.md): Deploy [hedgedoc](https://hedgedoc.org/), + a collaborative real-time markdown editor using websockts + - [`jellyfin`](roles/jellyfin/README.md): Deploy [jellyfin.org](https://jellyfin.org), the free software media system for streaming stored media to any device. diff --git a/playbooks/hedgedoc.yml b/playbooks/hedgedoc.yml new file mode 100644 index 0000000..a1fd741 --- /dev/null +++ b/playbooks/hedgedoc.yml @@ -0,0 +1,6 @@ +--- +- name: Install and configure hedgedoc + hosts: "{{ hedgedoc_hosts | default('hedgedoc') }}" + become: "{{ hedgedoc_become | default(true, false) }}" + roles: + - role: finallycoffee.services.hedgedoc diff --git a/roles/hedgedoc/README.md b/roles/hedgedoc/README.md new file mode 100644 index 0000000..e69de29 diff --git a/roles/hedgedoc/defaults/main/config.yml b/roles/hedgedoc/defaults/main/config.yml new file mode 100644 index 0000000..98a0b25 --- /dev/null +++ b/roles/hedgedoc/defaults/main/config.yml @@ -0,0 +1,52 @@ +--- +hedgedoc_config_domain: ~ +hedgedoc_config_log_level: "info" +hedgedoc_config_session_secret: ~ +hedgedoc_config_protocol_use_ssl: true +hedgedoc_config_hsts_enable: true +hedgedoc_config_csp_enable: true +hedgedoc_config_cookie_policy: 'lax' +hedgedoc_config_allow_free_url: true +hedgedoc_config_allow_email_register: false +hedgedoc_config_allow_anonymous: true +hedgedoc_config_allow_gravatar: true +hedgedoc_config_require_free_url_authentication: true +hedgedoc_config_default_permission: 'full' + +hedgedoc_config_db_username: hedgedoc +hedgedoc_config_db_password: ~ +hedgedoc_config_db_database: hedgedoc +hedgedoc_config_db_host: localhost +hedgedoc_config_db_port: 5432 +hedgedoc_config_db_dialect: postgres + +hedgedoc_config_database: + username: "{{ hedgedoc_config_db_username }}" + password: "{{ hedgedoc_config_db_password }}" + database: "{{ hedgedoc_config_db_database }}" + host: "{{ hedgedoc_config_db_host }}" + port: "{{ hedgedoc_config_db_port | int }}" + dialect: "{{ hedgedoc_config_db_dialect }}" +hedgedoc_config_base: + production: + domain: "{{ hedgedoc_config_domain }}" + loglevel: "{{ hedgedoc_config_log_level }}" + sessionSecret: "{{ hedgedoc_config_session_secret }}" + protocolUseSSL: "{{ hedgedoc_config_protocol_use_ssl }}" + cookiePolicy: "{{ hedgedoc_config_cookie_policy }}" + allowFreeURL: "{{ hedgedoc_config_allow_free_url }}" + allowAnonymous: "{{ hedgedoc_config_allow_anonymous }}" + allowEmailRegister: "{{ hedgedoc_config_allow_email_register }}" + allowGravatar: "{{ hedgedoc_config_allow_gravatar }}" + requireFreeURLAuthentication: >-2 + {{ hedgedoc_config_require_free_url_authentication }} + defaultPermission: "{{ hedgedoc_config_default_permission }}" + hsts: + enable: "{{ hedgedoc_config_hsts_enable }}" + csp: + enable: "{{ hedgedoc_config_csp_enable }}" + db: "{{ hedgedoc_config_database }}" +hedgedoc_config: ~ +hedgedoc_full_config: >-2 + {{ hedgedoc_config_base | default({}, true) + | combine(hedgedoc_config | default({}, true), recursive=True) }} diff --git a/roles/hedgedoc/defaults/main/container.yml b/roles/hedgedoc/defaults/main/container.yml new file mode 100644 index 0000000..cbe73dd --- /dev/null +++ b/roles/hedgedoc/defaults/main/container.yml @@ -0,0 +1,54 @@ +--- +hedgedoc_container_image_registry: quay.io +hedgedoc_container_image_namespace: hedgedoc +hedgedoc_container_image_name: hedgedoc +hedgedoc_container_image_flavour: alpine +hedgedoc_container_image_tag: ~ +hedgedoc_container_image: >-2 + {{ + ([ + hedgedoc_container_image_registry, + hedgedoc_container_image_namespace | default([], true), + hedgedoc_container_image_name, + ] | flatten | join('/')) + + ':' + + hedgedoc_container_image_tag | default( + hedgedoc_version + ( + ((hedgedoc_container_image_flavour is string) + and (hedgedoc_container_image_flavour | length > 0)) + | ternary('-' + + hedgedoc_container_image_flavour | default('', true), + '' + ) + ), + true + ) + }} +hedgedoc_container_image_source: pull +hedgedoc_container_name: hedgedoc +hedgedoc_container_state: >-2 + {{ (hedgedoc_state == 'present') | ternary('started', 'absent') }} + +hedgedoc_container_config_file: "/hedgedoc/config.json" +hedgedoc_container_upload_path: "/hedgedoc/public/uploads" + +hedgedoc_container_env: ~ +hedgedoc_container_user: >-2 + {{ hedgedoc_run_user_id }}:{{ hedgedoc_run_group_id }} +hedgedoc_container_ports: ~ +hedgedoc_container_networks: ~ +hedgedoc_container_etc_hosts: ~ +hedgedoc_container_base_volumes: + - "{{ hedgedoc_config_file }}:{{ hedgedoc_container_config_file }}:ro" + - "{{ hedgedoc_uploads_path }}:{{ hedgedoc_container_upload_path }}:rw" +hedgedoc_container_volumes: ~ +hedgedoc_container_all_volumes: >-2 + {{ hedgedoc_container_base_volumes | default([], true) + + hedgedoc_container_volumes | default([], true) }} +hedgedoc_container_base_labels: + version: "{{ hedgedoc_container_tag | default(hedgedoc_version, true) }}" +hedgedoc_container_labels: ~ +hedgedoc_container_all_labels: >-2 + {{ hedgedoc_container_base_labels | default({}, true) + | combine(hedgedoc_container_labels | default({}, true)) }} +hedgedoc_container_restart_policy: "unless-stopped" diff --git a/roles/hedgedoc/defaults/main/main.yml b/roles/hedgedoc/defaults/main/main.yml new file mode 100644 index 0000000..e9a69aa --- /dev/null +++ b/roles/hedgedoc/defaults/main/main.yml @@ -0,0 +1,9 @@ +--- +hedgedoc_user: hedgedoc +hedgedoc_version: 1.9.9 + +hedgedoc_state: present +hedgedoc_deployment_method: docker + +hedgedoc_config_file: "/etc/hedgedoc/config.json" +hedgedoc_uploads_path: "/var/lib/hedgedoc-uploads" diff --git a/roles/hedgedoc/defaults/main/user.yml b/roles/hedgedoc/defaults/main/user.yml new file mode 100644 index 0000000..0452fb7 --- /dev/null +++ b/roles/hedgedoc/defaults/main/user.yml @@ -0,0 +1,5 @@ +--- +hedgedoc_run_user_id: >-2 + {{ hedgedoc_user_info.uid | default(hedgedoc_user }} +hedgedoc_run_group_id: >-2 + {{ hedgedoc_user_info.group | default(hedgedoc_user }} diff --git a/roles/hedgedoc/meta/main.yml b/roles/hedgedoc/meta/main.yml new file mode 100644 index 0000000..e0af646 --- /dev/null +++ b/roles/hedgedoc/meta/main.yml @@ -0,0 +1,12 @@ +--- +allow_duplicates: true +dependencies: [] +galaxy_info: + role_name: hedgedoc + description: >-2 + Deploy hedgedoc, a collaborative markdown editor, using docker + galaxy_tags: + - hedgedoc + - markdown + - collaboration + - docker diff --git a/roles/hedgedoc/tasks/check.yml b/roles/hedgedoc/tasks/check.yml new file mode 100644 index 0000000..7f5e04b --- /dev/null +++ b/roles/hedgedoc/tasks/check.yml @@ -0,0 +1,23 @@ +--- +- name: Check for valid state + ansible.builtin.fail: + msg: >-2 + Unsupported state '{{ hedgedoc_state }}'. Supported + states are {{ hedgedoc_states | join(', ') }}. + when: hedgedoc_state not in hedgedoc_states + +- name: Check for valid deployment method + ansible.builtin.fail: + msg: >-2 + Deployment method '{{ hedgedoc_deployment_method }}' + is not supported. Supported are: + {{ hedgedoc_deployment_methods | join(', ') }} + when: hedgedoc_deployment_method not in hedgedoc_deployment_methods + +- name: Ensure required variables are given + ansible.builtin.file: + msg: "Required variable '{{ item }}' is undefined!" + loop: "{{ hedgedoc_required_arguments }}" + when: >-2 + item not in hostvars[inventory_hostname] + or hostvars[inventory_hostname][item] | length == 0 diff --git a/roles/hedgedoc/tasks/deploy-docker.yml b/roles/hedgedoc/tasks/deploy-docker.yml new file mode 100644 index 0000000..91fc7e9 --- /dev/null +++ b/roles/hedgedoc/tasks/deploy-docker.yml @@ -0,0 +1,24 @@ +--- +- name: Ensure container image '{{ hedgedoc_container_image }}' is {{ hedgedoc_state }} + community.docker.docker_image: + name: "{{ hedgedoc_container_image }}" + state: "{{ hedgedoc_state }}" + source: "{{ hedgedoc_container_image_source }}" + force_source: >-2 + {{ hedgedoc_container_force_source | default( + hedgedoc_container_image_tag | default(false, true), true) }} + register: hedgedoc_container_image_info + until: hedgedoc_container_image_info is success + retries: 5 + delay: 3 + +- name: Ensure container '{{ hedgedoc_container_name }}' is {{ hedgedoc_container_state }} + community.docker.docker_container: + name: "{{ hedgedoc_container_name }}" + image: "{{ hedgedoc_container_image }}" + env: "{{ hedgedoc_container_env | default(omit, true) }}" + labels: "{{ hedgedoc_container_all_labels }}" + volumes: "{{ hedgedoc_container_all_volumes }}" + etc_hosts: "{{ hedgedoc_container_etc_hosts | default(omit, true) }}" + restart_policy: "{{ hedgedoc_container_restart_policy | default(omit, true) }}" + state: "{{ hedgedoc_container_state }}" diff --git a/roles/hedgedoc/tasks/main.yml b/roles/hedgedoc/tasks/main.yml new file mode 100644 index 0000000..3d561a0 --- /dev/null +++ b/roles/hedgedoc/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- name: Check preconditions + ansible.builtin.include_tasks: + file: "check.yml" + +- name: Ensure user '{{ hedgedoc_user }}' is {{ hedgedoc_state }} + ansible.builtin.user: + name: "{{ hedgedoc_user }}" + state: "{{ hedgedoc_state }}" + system: "{{ hedgedoc_user_system | default(true, false) }}" + register: hedgedoc_user_info + +- name: Ensure configuration file '{{ hedgedoc_config_file }}' is {{ hedgedoc_state }} + ansible.builtin.copy: + dest: "{{ hedgedoc_config_file }}" + content: "{{ hedgedoc_full_config | to_nice_json }}" + when: hedgedoc_state == 'present' + +- name: Ensure hedgedoc is deployed using {{ hedgedoc_deployment_method }} + ansible.builtin.include_tasks: + file: "deploy-{{ hedgedoc_deployment_method }}.yml" diff --git a/roles/hedgedoc/vars/main.yml b/roles/hedgedoc/vars/main.yml new file mode 100644 index 0000000..b6e954c --- /dev/null +++ b/roles/hedgedoc/vars/main.yml @@ -0,0 +1,10 @@ +--- +hedgedoc_states: + - present + - absent +hedgedoc_deployment_methods: + - docker + +hedgedoc_required_arguments: + - hedgedoc_config_domain + - hedgedoc_config_session_secret