mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 15:06:26 +02:00
Huge role refactoring/cleanup. Other commits will propably follow. Because some bugs will exist. Still important for longrun and also for auto docs/help/slideshow generation
This commit is contained in:
39
roles/web-app-espocrm/README.md
Normal file
39
roles/web-app-espocrm/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# EspoCRM
|
||||
|
||||
## Description
|
||||
|
||||
Enhance your sales and service processes with EspoCRM, an open-source CRM featuring workflow automation, LDAP/OIDC single sign-on, and a sleek, lightweight UI! 🚀💼
|
||||
|
||||
## Overview
|
||||
|
||||
This Ansible role deploys EspoCRM using Docker. It handles:
|
||||
|
||||
- MariaDB database provisioning via the `service-rdbms-central` role
|
||||
- Nginx domain setup with WebSocket and reverse-proxy configuration
|
||||
- Environment variable management through Jinja2 templates
|
||||
- Docker Compose orchestration for **web**, **daemon**, and **websocket** services
|
||||
- Automatic OIDC scope configuration within the EspoCRM container
|
||||
|
||||
With this role, you'll have a production-ready CRM environment that's secure, scalable, and real-time.
|
||||
|
||||
## Features
|
||||
|
||||
- **Workflow Automation:** Create and manage automated CRM processes with ease 🛠️
|
||||
- **LDAP/OIDC SSO:** Integrate with corporate identity providers for seamless login 🔐
|
||||
- **WebSocket Notifications:** Real-time updates via ZeroMQ and WebSockets 🌐
|
||||
- **Config via Templates:** Fully customizable `.env` and `docker-compose.yml` with Jinja2 ⚙️
|
||||
- **Health Checks & Logging:** Monitor service health and logs with built-in checks and journald 📈
|
||||
- **Modular Role Composition:** Leverages central roles for database and Nginx, ensuring consistency across deployments 🔄
|
||||
|
||||
## Further Resources
|
||||
|
||||
- [EspoCRM Official Website](https://www.espocrm.com/) 🌍
|
||||
- [EspoCRM Documentation](https://docs.espocrm.com/) 📖
|
||||
- [CyMaIS Project Repository](https://github.com/kevinveenbirkenbach/cymais) 🔗
|
||||
|
||||
## Credits
|
||||
|
||||
Developed and maintained by **Kevin Veen-Birkenbach**.
|
||||
Consulting & Coaching Solutions: [veen.world](https://www.veen.world) 🌟
|
||||
Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais) 📂
|
||||
License: [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl) ⚖️
|
21
roles/web-app-espocrm/meta/main.yml
Normal file
21
roles/web-app-espocrm/meta/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
galaxy_info:
|
||||
author: "Kevin Veen-Birkenbach"
|
||||
description: "Empower your customer relationship management with EspoCRM. Tailored for businesses of all sizes, EspoCRM enables you to manage your sales, customer interactions, and business processes with ease, fostering productivity and streamlined communication across teams."
|
||||
license: "CyMaIS NonCommercial License (CNCL)"
|
||||
license_url: "https://s.veen.world/cncl"
|
||||
company: |
|
||||
Kevin Veen-Birkenbach
|
||||
Consulting & Coaching Solutions
|
||||
https://www.veen.world
|
||||
galaxy_tags:
|
||||
- espocrm
|
||||
- crm
|
||||
- sales
|
||||
repository: "https://s.veen.world/cymais"
|
||||
issue_tracker_url: "https://s.veen.world/cymaisissues"
|
||||
documentation: "https://s.veen.world/cymais"
|
||||
logo:
|
||||
class: "fa-solid fa-phone"
|
||||
run_after:
|
||||
- web-app-keycloak
|
||||
- web-app-mailu
|
9
roles/web-app-espocrm/meta/schema.yml
Normal file
9
roles/web-app-espocrm/meta/schema.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
credentials:
|
||||
administrator_password:
|
||||
description: "Initial password for the EspoCRM administrator user"
|
||||
algorithm: "sha256"
|
||||
validation: "^[a-f0-9]{64}$"
|
||||
database_password:
|
||||
description: "Password for the EspoCRM database user"
|
||||
algorithm: "bcrypt"
|
||||
validation: "^\\$2[aby]\\$.{56}$"
|
8
roles/web-app-espocrm/meta/users.yml
Normal file
8
roles/web-app-espocrm/meta/users.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
users:
|
||||
administrator:
|
||||
username: "administrator"
|
||||
contact:
|
||||
description: "General contact account"
|
||||
username: "contact"
|
||||
roles:
|
||||
- mail-bot
|
29
roles/web-app-espocrm/tasks/main.yml
Normal file
29
roles/web-app-espocrm/tasks/main.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
- name: "include service-rdbms-central"
|
||||
include_role:
|
||||
name: service-rdbms-central
|
||||
|
||||
- name: "Include setup for domain '{{ domain }}'"
|
||||
include_role:
|
||||
name: webserver-proxy-domain
|
||||
vars:
|
||||
ws_path: "/ws"
|
||||
ws_port: "{{ ports.localhost.websocket[application_id] }}"
|
||||
client_max_body_size: "100m"
|
||||
vhost_flavour: "ws_generic"
|
||||
domain: "{{ domains | get_domain(application_id) }}"
|
||||
http_port: "{{ ports.localhost.http[application_id] }}"
|
||||
|
||||
- name: Set OIDC scopes in EspoCRM config (inside web container)
|
||||
ansible.builtin.shell: |
|
||||
docker compose exec -T web php -r '
|
||||
require "/var/www/html/bootstrap.php";
|
||||
$writer = (new \Espo\Core\Application())
|
||||
->getContainer()
|
||||
->get("injectableFactory")
|
||||
->create("\Espo\Core\Utils\Config\ConfigWriter");
|
||||
$writer->set("oidcScopes", ["openid", "profile", "email"]);
|
||||
$writer->save();
|
||||
'
|
||||
args:
|
||||
chdir: "{{ docker_compose.directories.instance }}"
|
44
roles/web-app-espocrm/templates/docker-compose.yml.j2
Normal file
44
roles/web-app-espocrm/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,44 @@
|
||||
{% include 'roles/docker-compose/templates/base.yml.j2' %}
|
||||
web:
|
||||
image: "{{ applications[application_id].images.espocrm }}"
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}
|
||||
ports:
|
||||
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:80"
|
||||
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
volumes:
|
||||
- data:/var/www/html
|
||||
|
||||
daemon:
|
||||
image: "{{ applications[application_id].images.espocrm }}"
|
||||
restart: {{docker_restart_policy}}
|
||||
logging:
|
||||
driver: journald
|
||||
entrypoint: web-app-daemon.sh
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
volumes:
|
||||
- data:/var/www/html
|
||||
|
||||
websocket:
|
||||
image: "{{ applications[application_id].images.espocrm }}"
|
||||
restart: {{docker_restart_policy}}
|
||||
logging:
|
||||
driver: journald
|
||||
environment:
|
||||
- ESPOCRM_CONFIG_USE_WEB_SOCKET=true
|
||||
- ESPOCRM_CONFIG_WEB_SOCKET_URL=wss://{{ domains | get_domain(application_id) }}/ws
|
||||
- ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN=tcp://*:7777
|
||||
- ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN=tcp://websocket:7777
|
||||
entrypoint: web-app-websocket.sh
|
||||
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
volumes:
|
||||
- data:/var/www/html
|
||||
ports:
|
||||
- "127.0.0.1:{{ ports.localhost.websocket[application_id] }}:8080"
|
||||
|
||||
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||
data:
|
||||
|
||||
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
105
roles/web-app-espocrm/templates/env.j2
Normal file
105
roles/web-app-espocrm/templates/env.j2
Normal file
@@ -0,0 +1,105 @@
|
||||
#############################################
|
||||
# EspoCRM Docker Environment (.env) – ENGLISH
|
||||
# See: https://hub.docker.com/r/espocrm/espocrm
|
||||
#############################################
|
||||
|
||||
# ------------------------------------------------
|
||||
# Database connection
|
||||
# ------------------------------------------------
|
||||
ESPOCRM_DATABASE_PLATFORM=Mysql
|
||||
ESPOCRM_DATABASE_HOST={{ database_host }}
|
||||
ESPOCRM_DATABASE_PORT={{ database_port }}
|
||||
ESPOCRM_DATABASE_NAME={{ database_name }}
|
||||
ESPOCRM_DATABASE_USER={{ database_username }}
|
||||
ESPOCRM_DATABASE_PASSWORD={{ database_password }}
|
||||
|
||||
# Disable EspoCRM’s built-in cron (handled externally)
|
||||
CRON_DISABLED=true
|
||||
|
||||
# ------------------------------------------------
|
||||
# Initial admin account
|
||||
# ------------------------------------------------
|
||||
ESPOCRM_ADMIN_USERNAME={{ applications[application_id].users.administrator.username }}
|
||||
ESPOCRM_ADMIN_PASSWORD={{ applications[application_id].credentials.administrator_password }}
|
||||
|
||||
# Public base URL of the EspoCRM instance
|
||||
ESPOCRM_SITE_URL={{ domains | get_url(application_id, web_protocol) }}
|
||||
|
||||
# ------------------------------------------------
|
||||
# General UI & locale settings
|
||||
# ------------------------------------------------
|
||||
ESPOCRM_CONFIG_LANGUAGE={{ HOST_LL_CC }}
|
||||
ESPOCRM_CONFIG_DATE_FORMAT={{ HOST_DATE_FORMAT }}
|
||||
ESPOCRM_CONFIG_TIME_FORMAT={{ HOST_TIME_FORMAT }}
|
||||
ESPOCRM_CONFIG_TIME_ZONE={{ HOST_TIMEZONE }}
|
||||
# ESPOCRM_CONFIG_WEEK_START: 0 = Sunday, 1 = Monday
|
||||
ESPOCRM_CONFIG_WEEK_START=1
|
||||
ESPOCRM_CONFIG_DEFAULT_CURRENCY={{ HOST_CURRENCY }}
|
||||
#ESPOCRM_CONFIG_THOUSAND_SEPARATOR={{ HOST_THOUSAND_SEPARATOR }}
|
||||
#ESPOCRM_CONFIG_DECIMAL_MARK={{HOST_DECIMAL_MARK}}
|
||||
|
||||
# ------------------------------------------------
|
||||
# Logger
|
||||
# ------------------------------------------------
|
||||
ESPOCRM_CONFIG_LOGGER_LEVEL={{ 'DEBUG' if enable_debug | bool else 'INFO' }}
|
||||
ESPOCRM_CONFIG_LOGGER_PATH=php://stdout
|
||||
ESPOCRM_CONFIG_LOGGER_ROTATION=false
|
||||
|
||||
# ------------------------------------------------
|
||||
# System SMTP settings
|
||||
# ------------------------------------------------
|
||||
ESPOCRM_CONFIG_SMTP_SERVER={{ system_email.host }}
|
||||
ESPOCRM_CONFIG_SMTP_PORT={{ system_email.port }}
|
||||
ESPOCRM_CONFIG_SMTP_SECURITY={{ "TLS" if system_email.start_tls else "SSL"}}
|
||||
ESPOCRM_CONFIG_SMTP_AUTH=true
|
||||
ESPOCRM_CONFIG_SMTP_USERNAME={{ users['contact'].email }}
|
||||
ESPOCRM_CONFIG_SMTP_PASSWORD={{ users['contact'].mailu_token }}
|
||||
ESPOCRM_CONFIG_OUTBOUND_EMAIL_FROM_NAME={{ applications[application_id].email.from_name}}
|
||||
ESPOCRM_CONFIG_OUTBOUND_EMAIL_FROM_ADDRESS={{ users['contact'].email }}
|
||||
|
||||
# ------------------------------------------------
|
||||
# LDAP settings (optional)
|
||||
# Applied only if the feature flag is true
|
||||
# ------------------------------------------------
|
||||
{% if applications | is_feature_enabled('ldap',application_id) %}
|
||||
ESPOCRM_CONFIG_AUTHENTICATION_METHOD=Ldap
|
||||
ESPOCRM_CONFIG_LDAP_HOST={{ ldap.server.domain }}
|
||||
ESPOCRM_CONFIG_LDAP_PORT={{ ldap.server.port }}
|
||||
# ESPOCRM_CONFIG_LDAP_SECURITY: "", SSL or TLS
|
||||
ESPOCRM_CONFIG_LDAP_SECURITY={{ ldap.server.security }}
|
||||
ESPOCRM_CONFIG_LDAP_USERNAME={{ ldap.dn.administrator.data }}
|
||||
ESPOCRM_CONFIG_LDAP_PASSWORD={{ ldap.bind_credential }}
|
||||
ESPOCRM_CONFIG_LDAP_BASE_DN={{ ldap.dn.ou.users }}
|
||||
ESPOCRM_CONFIG_LDAP_USER_LOGIN_FILTER=(sAMAccountName=%USERNAME%)
|
||||
{% endif %}
|
||||
|
||||
# ------------------------------------------------
|
||||
# OpenID Connect settings (optional)
|
||||
# Applied only if the feature flag is true
|
||||
# ------------------------------------------------
|
||||
{% if applications | is_feature_enabled('oidc',application_id) %}
|
||||
|
||||
# ------------------------------------------------
|
||||
# OpenID Connect settings
|
||||
# ------------------------------------------------
|
||||
ESPOCRM_CONFIG_OIDC_ALLOW_ADMIN_USER=true
|
||||
ESPOCRM_CONFIG_AUTHENTICATION_METHOD=Oidc
|
||||
ESPOCRM_CONFIG_OIDC_FALLBACK=false # set true if you want LDAP as fallback
|
||||
|
||||
ESPOCRM_CONFIG_OIDC_CLIENT_ID={{ oidc.client.id }}
|
||||
ESPOCRM_CONFIG_OIDC_CLIENT_SECRET={{ oidc.client.secret }}
|
||||
|
||||
ESPOCRM_CONFIG_OIDC_AUTHORIZATION_ENDPOINT={{ oidc.client.authorize_url }}
|
||||
ESPOCRM_CONFIG_OIDC_TOKEN_ENDPOINT={{ oidc.client.token_url }}
|
||||
ESPOCRM_CONFIG_OIDC_USER_INFO_ENDPOINT={{ oidc.client.user_info_url }}
|
||||
ESPOCRM_CONFIG_OIDC_JWKS_ENDPOINT={{ oidc.client.certs }}
|
||||
|
||||
ESPOCRM_CONFIG_OIDC_AUTHORIZATION_REDIRECT_URI=https://{{ domains | get_domain(application_id) }}/oidc/callback
|
||||
#ESPOCRM_CONFIG_OIDC_SCOPES=openid,profile,email # Defined in main.yml
|
||||
|
||||
ESPOCRM_CONFIG_OIDC_CREATE_USER=true
|
||||
ESPOCRM_CONFIG_OIDC_SYNC=true
|
||||
ESPOCRM_CONFIG_OIDC_USERNAME_CLAIM={{oidc.attributes.username}}
|
||||
# ESPOCRM_CONFIG_OIDC_SYNC_TEAMS=true
|
||||
# ESPOCRM_CONFIG_OIDC_GROUP_CLAIM=group
|
||||
{% endif %}
|
33
roles/web-app-espocrm/vars/configuration.yml
Normal file
33
roles/web-app-espocrm/vars/configuration.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
images:
|
||||
espocrm: "espocrm/espocrm:latest"
|
||||
features:
|
||||
matomo: true
|
||||
css: false
|
||||
portfolio_iframe: true
|
||||
ldap: false
|
||||
oidc: true
|
||||
central_database: true
|
||||
csp:
|
||||
flags:
|
||||
script-src-elem:
|
||||
unsafe-inline: true
|
||||
unsafe-eval: true
|
||||
style-src:
|
||||
unsafe-inline: true
|
||||
script-src:
|
||||
unsafe-eval: true
|
||||
whitelist:
|
||||
connect-src:
|
||||
- wss://espocrm.{{ primary_domain }}
|
||||
- "data:"
|
||||
frame-src:
|
||||
- https://s.espocrm.com/
|
||||
domains:
|
||||
aliases:
|
||||
- "crm.{{ primary_domain }}"
|
||||
email:
|
||||
from_name: "Customer Relationship Management ({{ primary_domain }})"
|
||||
docker:
|
||||
services:
|
||||
database:
|
||||
enabled: true
|
3
roles/web-app-espocrm/vars/main.yml
Normal file
3
roles/web-app-espocrm/vars/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
application_id: "espocrm"
|
||||
# EspoCRM uses MySQL/MariaDB
|
||||
database_type: "mariadb"
|
Reference in New Issue
Block a user