mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-12-02 07:38:22 +00:00
Add global CAPTCHA config and EspoCRM seeder
- Introduce shared CAPTCHA settings and RECAPTCHA_ENABLED/HCAPTCHA_ENABLED flags in group_vars - Wire reCAPTCHA/hCaptcha credentials into EspoCRM, Keycloak, Listmonk and Nextcloud - Replace EspoCRM set_flags.php with generic seed_config.php and hook it into entrypoint/env - Fix run_once handling in sys-ctl-cln-disc-space and minor CSS Jinja spacing issue https://chatgpt.com/share/692a1d4f-1154-800f-a4ae-bb068aa24a53
This commit is contained in:
@@ -88,3 +88,15 @@ RBAC:
|
|||||||
GROUP:
|
GROUP:
|
||||||
NAME: "/roles" # Name of the group which holds the RBAC roles
|
NAME: "/roles" # Name of the group which holds the RBAC roles
|
||||||
CLAIM: "groups" # Name of the claim containing the RBAC groups
|
CLAIM: "groups" # Name of the claim containing the RBAC groups
|
||||||
|
|
||||||
|
# You need to set both keys to enable them
|
||||||
|
CAPTCHA:
|
||||||
|
RECAPTCHA:
|
||||||
|
KEY: ""
|
||||||
|
SECRET: ""
|
||||||
|
HCAPTCHA:
|
||||||
|
KEY: ""
|
||||||
|
SECRET: ""
|
||||||
|
|
||||||
|
RECAPTCHA_ENABLED: "{{ (CAPTCHA.RECAPTCHA.KEY | length > 0) and (CAPTCHA.RECAPTCHA.SECRET | length > 0) }}"
|
||||||
|
HCAPTCHA_ENABLED: "{{ (CAPTCHA.HCAPTCHA.KEY | length > 0) and (CAPTCHA.HCAPTCHA.SECRET | length > 0) }}"
|
||||||
|
|||||||
@@ -15,3 +15,5 @@
|
|||||||
system_service_tpl_exec_start: "{{ system_service_script_exec }} {{ SIZE_PERCENT_CLEANUP_DISC_SPACE }}"
|
system_service_tpl_exec_start: "{{ system_service_script_exec }} {{ SIZE_PERCENT_CLEANUP_DISC_SPACE }}"
|
||||||
system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"'
|
system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"'
|
||||||
system_service_force_linear_sync: false
|
system_service_force_linear_sync: false
|
||||||
|
|
||||||
|
- include_tasks: utils/run_once.yml
|
||||||
@@ -1,5 +1,2 @@
|
|||||||
- block:
|
- include_tasks: 01_core.yml
|
||||||
- include_tasks: 01_core.yml
|
|
||||||
- include_tasks: utils/run_once.yml
|
|
||||||
when: run_once_sys_ctl_cln_disc_space is not defined
|
when: run_once_sys_ctl_cln_disc_space is not defined
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ body, html[native-dark-active] {
|
|||||||
background: linear-gradient({{ CSS_GRADIENT_ANGLE }}deg, var(--color-01-93), var(--color-01-91), var(--color-01-95), var(--color-01-93));
|
background: linear-gradient({{ CSS_GRADIENT_ANGLE }}deg, var(--color-01-93), var(--color-01-91), var(--color-01-95), var(--color-01-93));
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
color: var(--color-01-40);
|
color: var(--color-01-40);
|
||||||
font-family: {{design.font.type}};
|
font-family: {{ design.font.type }};
|
||||||
}
|
}
|
||||||
|
|
||||||
{# All links (applies to all anchor elements regardless of state) #}
|
{# All links (applies to all anchor elements regardless of state) #}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ features:
|
|||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
logout: true
|
logout: true
|
||||||
recaptcha: true # Required for leads formulars
|
recaptcha: "{{ RECAPTCHA_ENABLED | bool }}" # Required for leads formulars
|
||||||
server:
|
server:
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
@@ -30,6 +30,10 @@ server:
|
|||||||
- espo.crm.{{ PRIMARY_DOMAIN }}
|
- espo.crm.{{ PRIMARY_DOMAIN }}
|
||||||
email:
|
email:
|
||||||
from_name: "Customer Relationship Management ({{ PRIMARY_DOMAIN }})"
|
from_name: "Customer Relationship Management ({{ PRIMARY_DOMAIN }})"
|
||||||
|
credentials:
|
||||||
|
recaptcha:
|
||||||
|
key: "{{ CAPTCHA.RECAPTCHA.KEY }}"
|
||||||
|
secret: "{{ CAPTCHA.RECAPTCHA.SECRET }}"
|
||||||
docker:
|
docker:
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
|
|||||||
@@ -16,18 +16,14 @@ bool_norm () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- Environment initialization ----------------------------------------------
|
# --- Environment initialization ----------------------------------------------
|
||||||
MAINTENANCE="$(bool_norm "${ESPO_INIT_MAINTENANCE_MODE:-false}")"
|
MAINTENANCE="$(bool_norm "${ESPOCRM_SEED_MAINTENANCE_MODE}")"
|
||||||
CRON_DISABLED="$(bool_norm "${ESPO_INIT_CRON_DISABLED:-false}")"
|
CRON_DISABLED="$(bool_norm "${ESPOCRM_SEED_CRON_DISABLED}")"
|
||||||
USE_CACHE="$(bool_norm "${ESPO_INIT_USE_CACHE:-true}")"
|
USE_CACHE="$(bool_norm "${ESPOCRM_SEED_USE_CACHE}")"
|
||||||
|
|
||||||
APP_DIR="/var/www/html"
|
APP_DIR="/var/www/html"
|
||||||
|
|
||||||
# Provided by env.j2 (fallback ensures robustness)
|
# Provided by env.j2 (fallback ensures robustness)
|
||||||
SET_FLAGS_SCRIPT="${ESPOCRM_SET_FLAGS_SCRIPT:-/usr/local/bin/set_flags.php}"
|
SEED_CONFIG_SCRIPT="${ESPOCRM_SCRIPT_SEED}"
|
||||||
if [ ! -f "$SET_FLAGS_SCRIPT" ]; then
|
|
||||||
log "WARN: SET_FLAGS_SCRIPT '$SET_FLAGS_SCRIPT' not found; falling back to /usr/local/bin/set_flags.php"
|
|
||||||
SET_FLAGS_SCRIPT="/usr/local/bin/set_flags.php"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Wait for bootstrap.php (max 60s, e.g. fresh volume) ----------------------
|
# --- Wait for bootstrap.php (max 60s, e.g. fresh volume) ----------------------
|
||||||
log "Waiting for ${APP_DIR}/bootstrap.php..."
|
log "Waiting for ${APP_DIR}/bootstrap.php..."
|
||||||
@@ -41,10 +37,10 @@ if [ ! -f "${APP_DIR}/bootstrap.php" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Apply config flags via set_flags.php ------------------------------------
|
# --- Apply config flags via seed_config.php ------------------------------------
|
||||||
log "Applying runtime flags via set_flags.php..."
|
log "Applying runtime flags via seed_config.php..."
|
||||||
if ! php "${SET_FLAGS_SCRIPT}"; then
|
if ! php "${SEED_CONFIG_SCRIPT}"; then
|
||||||
log "ERROR: set_flags.php execution failed"
|
log "ERROR: seed_config.php execution failed"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
147
roles/web-app-espocrm/files/seed_config.php
Normal file
147
roles/web-app-espocrm/files/seed_config.php
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Generic EspoCRM config seeder.
|
||||||
|
*
|
||||||
|
* Automatically scans all environment variables starting with ESPOCRM_SEED_,
|
||||||
|
* converts them into EspoCRM camelCase config keys, and writes them via ConfigWriter.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ESPOCRM_SEED_RECAPTCHA_SECRET_KEY=xyz
|
||||||
|
* becomes:
|
||||||
|
* recaptchaSecretKey => "xyz"
|
||||||
|
*/
|
||||||
|
|
||||||
|
require "/var/www/html/bootstrap.php";
|
||||||
|
|
||||||
|
$app = new \Espo\Core\Application();
|
||||||
|
$c = $app->getContainer();
|
||||||
|
$config = $c->get("config");
|
||||||
|
$writer = $c->get("injectableFactory")->create("\Espo\Core\Utils\Config\ConfigWriter");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an ENV suffix like "RECAPTCHA_SECRET_KEY" to camelCase "recaptchaSecretKey".
|
||||||
|
*/
|
||||||
|
function to_camel_case(string $input): string
|
||||||
|
{
|
||||||
|
$input = strtolower($input);
|
||||||
|
$parts = explode('_', $input);
|
||||||
|
$result = array_shift($parts);
|
||||||
|
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$result .= ucfirst($part);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize booleans if the value looks boolean-like.
|
||||||
|
* Returns true/false for typical boolean strings, otherwise the original string.
|
||||||
|
*/
|
||||||
|
function cast_value(string $value)
|
||||||
|
{
|
||||||
|
$normalized = strtolower(trim($value));
|
||||||
|
|
||||||
|
if (in_array($normalized, ['1', 'true', 'yes', 'on'], true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($normalized, ['0', 'false', 'no', 'off'], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value; // keep as string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple debug logger to STDERR.
|
||||||
|
* This keeps STDOUT clean so automation can rely on "CHANGED"/"UNCHANGED".
|
||||||
|
*/
|
||||||
|
function seed_debug(string $message): void
|
||||||
|
{
|
||||||
|
fwrite(STDERR, "[seed] " . $message . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine debug mode from ESPOCRM_SEED_DEBUG
|
||||||
|
$debugEnv = getenv('ESPOCRM_SEED_DEBUG');
|
||||||
|
$debug = false;
|
||||||
|
if ($debugEnv !== false) {
|
||||||
|
$normalized = strtolower(trim($debugEnv));
|
||||||
|
$debug = in_array($normalized, ['1', 'true', 'yes', 'on'], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug("Seeder started, scanning ESPOCRM_SEED_* variables …");
|
||||||
|
}
|
||||||
|
|
||||||
|
$changed = false;
|
||||||
|
|
||||||
|
foreach ($_ENV as $envKey => $envValue) {
|
||||||
|
// Only process variables beginning with ESPOCRM_SEED_
|
||||||
|
if (strpos($envKey, 'ESPOCRM_SEED_') !== 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the config part (after prefix)
|
||||||
|
$rawKey = substr($envKey, strlen('ESPOCRM_SEED_')); // e.g. "RECAPTCHA_SECRET_KEY"
|
||||||
|
|
||||||
|
if ($rawKey === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to camelCase
|
||||||
|
$configKey = to_camel_case($rawKey);
|
||||||
|
|
||||||
|
// Normalize boolean or keep string
|
||||||
|
$value = cast_value((string) $envValue);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug(sprintf(
|
||||||
|
"ENV %s -> config key '%s' = %s",
|
||||||
|
$envKey,
|
||||||
|
$configKey,
|
||||||
|
var_export($value, true)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$current = $config->get($configKey);
|
||||||
|
|
||||||
|
if ($current !== $value) {
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug(sprintf(
|
||||||
|
"Updating '%s': %s -> %s",
|
||||||
|
$configKey,
|
||||||
|
var_export($current, true),
|
||||||
|
var_export($value, true)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$writer->set($configKey, $value);
|
||||||
|
$changed = true;
|
||||||
|
} else {
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug(sprintf(
|
||||||
|
"No change for '%s' (already %s)",
|
||||||
|
$configKey,
|
||||||
|
var_export($current, true)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($changed) {
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug("Changes detected, saving configuration …");
|
||||||
|
}
|
||||||
|
$writer->save();
|
||||||
|
echo "CHANGED\n";
|
||||||
|
} else {
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug("No changes detected.");
|
||||||
|
}
|
||||||
|
echo "UNCHANGED\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
seed_debug("Seeder finished.");
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* set_flags.php – Ensure EspoCRM runtime flags are set idempotently.
|
|
||||||
*/
|
|
||||||
|
|
||||||
require "/var/www/html/bootstrap.php";
|
|
||||||
|
|
||||||
$app = new \Espo\Core\Application();
|
|
||||||
$c = $app->getContainer();
|
|
||||||
$cfg = $c->get("config");
|
|
||||||
$w = $c->get("injectableFactory")->create("\Espo\Core\Utils\Config\ConfigWriter");
|
|
||||||
|
|
||||||
// Read from ENV
|
|
||||||
$flags = [
|
|
||||||
"maintenanceMode" => in_array(strtolower(getenv("ESPO_INIT_MAINTENANCE_MODE") ?: "false"), ["1","true","yes","on"]),
|
|
||||||
"cronDisabled" => in_array(strtolower(getenv("ESPO_INIT_CRON_DISABLED") ?: "false"), ["1","true","yes","on"]),
|
|
||||||
"useCache" => in_array(strtolower(getenv("ESPO_INIT_USE_CACHE") ?: "true"), ["1","true","yes","on"])
|
|
||||||
];
|
|
||||||
|
|
||||||
$changed = false;
|
|
||||||
foreach ($flags as $k => $v) {
|
|
||||||
if ($cfg->get($k) !== $v) {
|
|
||||||
$w->set($k, $v);
|
|
||||||
$changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($changed) {
|
|
||||||
$w->save();
|
|
||||||
echo "CHANGED\n";
|
|
||||||
} else {
|
|
||||||
echo "UNCHANGED\n";
|
|
||||||
}
|
|
||||||
@@ -13,10 +13,10 @@
|
|||||||
- docker compose up
|
- docker compose up
|
||||||
- docker compose build
|
- docker compose build
|
||||||
|
|
||||||
- name: "Deploy '{{ ESPOCRM_SET_FLAG_SCRIPT_HOST_ABS }}'"
|
- name: "Deploy '{{ ESPOCRM_SCRIPT_SEED_HOST_ABS }}'"
|
||||||
copy:
|
copy:
|
||||||
src: "{{ ESPOCRM_SET_FLAG_SCRIPT_FILE }}"
|
src: "{{ ESPOCRM_SCRIPT_SEED_FILE }}"
|
||||||
dest: "{{ ESPOCRM_SET_FLAG_SCRIPT_HOST_ABS }}"
|
dest: "{{ ESPOCRM_SCRIPT_SEED_HOST_ABS }}"
|
||||||
notify:
|
notify:
|
||||||
- docker compose up
|
- docker compose up
|
||||||
- docker compose build
|
- docker compose build
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
- name: Run flag setter as root (fallback)
|
- name: Run flag setter as root (fallback)
|
||||||
command: >
|
command: >
|
||||||
docker exec --user root {{ ESPOCRM_CONTAINER }}
|
docker exec --user root {{ ESPOCRM_CONTAINER }}
|
||||||
php {{ ESPOCRM_SET_FLAG_SCRIPT_DOCKER }}
|
php {{ ESPOCRM_SCRIPT_SEED_DOCKER }}
|
||||||
register: flags_result_root
|
register: flags_result_root
|
||||||
changed_when: "'CHANGED' in flags_result_root.stdout"
|
changed_when: "'CHANGED' in flags_result_root.stdout"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM "{{ ESPOCRM_IMAGE }}:{{ ESPOCRM_VERSION }}"
|
FROM "{{ ESPOCRM_IMAGE }}:{{ ESPOCRM_VERSION }}"
|
||||||
|
|
||||||
COPY {{ ESPOCRM_SET_FLAG_SCRIPT_HOST_REL }} {{ ESPOCRM_SET_FLAG_SCRIPT_DOCKER }}
|
COPY {{ ESPOCRM_SCRIPT_SEED_HOST_REL }} {{ ESPOCRM_SCRIPT_SEED_DOCKER }}
|
||||||
RUN chmod +x {{ ESPOCRM_SET_FLAG_SCRIPT_DOCKER }}
|
RUN chmod +x {{ ESPOCRM_SCRIPT_SEED_DOCKER }}
|
||||||
|
|
||||||
COPY {{ ESPOCRM_ENTRYPOINT_SCRIPT_HOST_REL }} {{ ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER }}
|
COPY {{ ESPOCRM_ENTRYPOINT_SCRIPT_HOST_REL }} {{ ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER }}
|
||||||
RUN chmod +x {{ ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER }}
|
RUN chmod +x {{ ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER }}
|
||||||
|
|||||||
@@ -104,8 +104,19 @@ ESPOCRM_CONFIG_OIDC_USERNAME_CLAIM={{ OIDC.ATTRIBUTES.USERNAME }}
|
|||||||
# ESPOCRM_CONFIG_OIDC_GROUP_CLAIM=group
|
# ESPOCRM_CONFIG_OIDC_GROUP_CLAIM=group
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# --- Espo init toggles controlled at container start (used by custom entrypoint)
|
## Seed Configuration
|
||||||
ESPO_INIT_MAINTENANCE_MODE=false # false = disable maintenance (recommended)
|
|
||||||
ESPO_INIT_CRON_DISABLED=false # false = enable cron jobs in config
|
ESPOCRM_SEED_DEBUG={{ MODE_DEBUG | lower }}
|
||||||
ESPO_INIT_USE_CACHE=true # true = enable caching
|
|
||||||
ESPOCRM_SET_FLAGS_SCRIPT={{ ESPOCRM_SET_FLAG_SCRIPT_DOCKER }}
|
ESPOCRM_SCRIPT_SEED={{ ESPOCRM_SCRIPT_SEED_DOCKER }}
|
||||||
|
|
||||||
|
## Espo init toggles controlled at container start (used by custom entrypoint)
|
||||||
|
ESPOCRM_SEED_MAINTENANCE_MODE={{ ESPOCRM_MAINTENANCE_MODE }}
|
||||||
|
ESPOCRM_SEED_CRON_DISABLED={{ ESPOCRM_CRON_DISABLED }}
|
||||||
|
ESPOCRM_SEED_USE_CACHE={{ ESPOCRM_USE_CACHE }}
|
||||||
|
|
||||||
|
## ReCAPTCHA
|
||||||
|
ESPOCRM_SEED_RECAPTCHA_VERSION="v3"
|
||||||
|
ESPOCRM_SEED_RECAPTCHA_ENABLED="{{ ESPOCRM_RECAPTCHA_ENABLED }}"
|
||||||
|
ESPOCRM_SEED_RECAPTCHA_PUBLIC_KEY="{{ ESPOCRM_RECAPTCHA_KEY }}"
|
||||||
|
ESPOCRM_SEED_RECAPTCHA_SECRET_KEY="{{ ESPOCRM_RECAPTCHA_SECRET }}"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
application_id: "web-app-espocrm"
|
application_id: "web-app-espocrm"
|
||||||
entity_name: "{{ application_id | get_entity_name }}"
|
entity_name: "{{ application_id | get_entity_name }}"
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
database_type: "mariadb"
|
database_type: "mariadb"
|
||||||
|
|
||||||
@@ -31,17 +32,28 @@ ESPOCRM_ENTRYPOINT_SCRIPT_HOST_ABS: "{{ [ docker_compose.directories.volumes, ES
|
|||||||
ESPOCRM_ENTRYPOINT_SCRIPT_HOST_REL: "volumes/{{ ESPOCRM_ENTRYPOINT_SCRIPT_FILE }}"
|
ESPOCRM_ENTRYPOINT_SCRIPT_HOST_REL: "volumes/{{ ESPOCRM_ENTRYPOINT_SCRIPT_FILE }}"
|
||||||
ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER: "{{ [ '/usr/local/bin/', ESPOCRM_ENTRYPOINT_SCRIPT_FILE ] | path_join }}"
|
ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER: "{{ [ '/usr/local/bin/', ESPOCRM_ENTRYPOINT_SCRIPT_FILE ] | path_join }}"
|
||||||
|
|
||||||
### Set Flag
|
|
||||||
ESPOCRM_SET_FLAG_SCRIPT_FILE: "set_flags.php"
|
|
||||||
ESPOCRM_SET_FLAG_SCRIPT_HOST_ABS: "{{ [ docker_compose.directories.volumes, ESPOCRM_SET_FLAG_SCRIPT_FILE ] | path_join }}"
|
|
||||||
ESPOCRM_SET_FLAG_SCRIPT_HOST_REL: "volumes/{{ ESPOCRM_SET_FLAG_SCRIPT_FILE }}"
|
|
||||||
ESPOCRM_SET_FLAG_SCRIPT_DOCKER: "{{ [ '/usr/local/bin/', ESPOCRM_SET_FLAG_SCRIPT_FILE ] | path_join }}"
|
|
||||||
|
|
||||||
ESPOCRM_CONFIG_FILE_PRIVATE: "/var/www/html/data/config-internal.php"
|
ESPOCRM_CONFIG_FILE_PRIVATE: "/var/www/html/data/config-internal.php"
|
||||||
ESPOCRM_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}"
|
ESPOCRM_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}"
|
||||||
ESPOCRM_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}"
|
ESPOCRM_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}"
|
||||||
ESPOCRM_USER: "www-data"
|
ESPOCRM_USER: "www-data"
|
||||||
|
|
||||||
ESPO_INIT_MAINTENANCE_MODE: "{{ applications | get_app_conf(application_id, 'maintenance_mode') | default(false) }}"
|
|
||||||
ESPO_INIT_CRON_DISABLED: "{{ ESPO_INIT_MAINTENANCE_MODE }}" # disable cron only when in maintenance
|
## Seeding
|
||||||
ESPO_INIT_USE_CACHE: "{{ not ESPO_INIT_MAINTENANCE_MODE }}" # enable cache when NOT in maintenance
|
|
||||||
|
### Seeding Script Parameter
|
||||||
|
ESPOCRM_SCRIPT_SEED_FILE: "seed_config.php"
|
||||||
|
ESPOCRM_SCRIPT_SEED_HOST_ABS: "{{ [ docker_compose.directories.volumes, ESPOCRM_SCRIPT_SEED_FILE ] | path_join }}"
|
||||||
|
ESPOCRM_SCRIPT_SEED_HOST_REL: "volumes/{{ ESPOCRM_SCRIPT_SEED_FILE }}"
|
||||||
|
ESPOCRM_SCRIPT_SEED_DOCKER: "{{ [ '/usr/local/bin/', ESPOCRM_SCRIPT_SEED_FILE ] | path_join }}"
|
||||||
|
|
||||||
|
### Seeding Values
|
||||||
|
|
||||||
|
#### Maintanance
|
||||||
|
ESPOCRM_MAINTENANCE_MODE: "{{ applications | get_app_conf(application_id, 'maintenance_mode') }}"
|
||||||
|
ESPOCRM_CRON_DISABLED: "{{ ESPOCRM_MAINTENANCE_MODE }}" # disable cron only when in maintenance
|
||||||
|
ESPOCRM_USE_CACHE: "{{ not ESPOCRM_MAINTENANCE_MODE }}" # enable cache when NOT in maintenance
|
||||||
|
|
||||||
|
#### reCAPTCHA
|
||||||
|
ESPOCRM_RECAPTCHA_ENABLED: "{{ applications | get_app_conf(application_id, 'features.recaptcha') }}"
|
||||||
|
ESPOCRM_RECAPTCHA_KEY: "{{ applications | get_app_conf(application_id, 'credentials.recaptcha.key') }}"
|
||||||
|
ESPOCRM_RECAPTCHA_SECRET: "{{ applications | get_app_conf(application_id, 'credentials.recaptcha.secret') }}"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ features:
|
|||||||
desktop: true
|
desktop: true
|
||||||
ldap: true
|
ldap: true
|
||||||
central_database: true
|
central_database: true
|
||||||
recaptcha: true
|
recaptcha: "{{ RECAPTCHA_ENABLED | bool }}"
|
||||||
|
|
||||||
# Doesn't make sense to activate logout page for keycloak, because the logout page
|
# Doesn't make sense to activate logout page for keycloak, because the logout page
|
||||||
# anyhow should be included via iframe in keycloak.
|
# anyhow should be included via iframe in keycloak.
|
||||||
@@ -45,12 +45,10 @@ docker:
|
|||||||
pids_limit: 1024
|
pids_limit: 1024
|
||||||
database:
|
database:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
credentials:
|
credentials:
|
||||||
recaptcha:
|
recaptcha:
|
||||||
website_key: "" # Required if you enabled recaptcha:
|
key: "{{ CAPTCHA.RECAPTCHA.KEY }}"
|
||||||
secret_key: "" # Required if you enabled recaptcha:
|
secret: "{{ CAPTCHA.RECAPTCHA.SECRET }}"
|
||||||
|
|
||||||
accounts:
|
accounts:
|
||||||
bootstrap:
|
bootstrap:
|
||||||
username: "administrator"
|
username: "administrator"
|
||||||
|
|||||||
@@ -34,5 +34,4 @@
|
|||||||
|
|
||||||
- name: "Load reCAPTCHA Update routines for '{{ application_id }}'"
|
- name: "Load reCAPTCHA Update routines for '{{ application_id }}'"
|
||||||
include_tasks: update/06_recaptcha.yml
|
include_tasks: update/06_recaptcha.yml
|
||||||
when: applications | get_app_conf(application_id, 'features.recaptcha', False)
|
when: KEYCLOAK_RECAPTCHA_ENABLED | bool
|
||||||
|
|
||||||
|
|||||||
@@ -2114,7 +2114,7 @@
|
|||||||
"autheticatorFlow": false,
|
"autheticatorFlow": false,
|
||||||
"userSetupAllowed": false
|
"userSetupAllowed": false
|
||||||
},
|
},
|
||||||
{%- if applications | get_app_conf(application_id, 'features.recaptcha', False) %}
|
{%- if KEYCLOAK_RECAPTCHA_ENABLED | bool %}
|
||||||
{
|
{
|
||||||
"authenticatorConfig": "Google reCaptcha",
|
"authenticatorConfig": "Google reCaptcha",
|
||||||
"authenticator": "registration-recaptcha-action",
|
"authenticator": "registration-recaptcha-action",
|
||||||
@@ -2204,15 +2204,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"authenticatorConfig": [
|
"authenticatorConfig": [
|
||||||
{%- if applications | get_app_conf(application_id, 'features.recaptcha', False) %}
|
{%- if KEYCLOAK_RECAPTCHA_ENABLED | bool %}
|
||||||
{
|
{
|
||||||
"alias": "Google reCaptcha",
|
"alias": "Google reCaptcha",
|
||||||
"config": {
|
"config": {
|
||||||
"action": "register",
|
"action": "register",
|
||||||
"useRecaptchaNet": "false",
|
"useRecaptchaNet": "false",
|
||||||
"recaptcha.v3": "true",
|
"recaptcha.v3": "true",
|
||||||
"secret.key": "{{ applications | get_app_conf(application_id, 'credentials.recaptcha.secret_key', True) }}",
|
"secret.key": "{{ KEYCLOAK_RECAPTCHA_SECRET }}",
|
||||||
"site.key": "{{ applications | get_app_conf(application_id, 'credentials.recaptcha.website_key', True) }}"
|
"site.key": "{{ KEYCLOAK_RECAPTCHA_KEY }}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ KEYCLOAK_LDAP_USER_OBJECT_CLASSES: >
|
|||||||
) | join(', ')
|
) | join(', ')
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
# reCAPTCHA
|
||||||
|
KEYCLOAK_RECAPTCHA_ENABLED: "{{ applications | get_app_conf(application_id, 'features.recaptcha') }}"
|
||||||
|
KEYCLOAK_RECAPTCHA_KEY: "{{ applications | get_app_conf(application_id, 'credentials.recaptcha.key') }}"
|
||||||
|
KEYCLOAK_RECAPTCHA_SECRET: "{{ applications | get_app_conf(application_id, 'credentials.recaptcha.secret') }}"
|
||||||
|
|
||||||
# Dictionaries
|
# Dictionaries
|
||||||
KEYCLOAK_DICTIONARY_REALM_RAW: "{{ lookup('template', 'import/realm.json.j2') }}"
|
KEYCLOAK_DICTIONARY_REALM_RAW: "{{ lookup('template', 'import/realm.json.j2') }}"
|
||||||
KEYCLOAK_DICTIONARY_REALM: >-
|
KEYCLOAK_DICTIONARY_REALM: >-
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ features:
|
|||||||
central_database: true
|
central_database: true
|
||||||
oidc: true
|
oidc: true
|
||||||
logout: true
|
logout: true
|
||||||
hcaptcha: true
|
hcaptcha: "{{ HCAPTCHA_ENABLED | bool }}"
|
||||||
server:
|
server:
|
||||||
domains:
|
domains:
|
||||||
canonical:
|
canonical:
|
||||||
@@ -23,9 +23,13 @@ docker:
|
|||||||
database:
|
database:
|
||||||
enabled: true
|
enabled: true
|
||||||
listmonk:
|
listmonk:
|
||||||
image: listmonk/listmonk
|
image: listmonk/listmonk
|
||||||
version: latest
|
version: latest
|
||||||
backup:
|
backup:
|
||||||
no_stop_required: true
|
no_stop_required: true
|
||||||
name: listmonk
|
name: listmonk
|
||||||
port: 9000
|
port: 9000
|
||||||
|
credentials:
|
||||||
|
hcaptcha:
|
||||||
|
key: "{{ CAPTCHA.HCAPTCHA.KEY }}"
|
||||||
|
secret: "{{ CAPTCHA.HCAPTCHA.SECRET }}"
|
||||||
@@ -3,13 +3,3 @@ credentials:
|
|||||||
description: "Initial password for the Listmonk administrator account"
|
description: "Initial password for the Listmonk administrator account"
|
||||||
algorithm: "sha256"
|
algorithm: "sha256"
|
||||||
validation: "^[a-f0-9]{64}$"
|
validation: "^[a-f0-9]{64}$"
|
||||||
|
|
||||||
hcaptcha_site_key:
|
|
||||||
description: "Public site key used by Listmonk to render hCaptcha"
|
|
||||||
algorithm: "plain"
|
|
||||||
validation: "^[0-9a-zA-Z_-]{32,}$"
|
|
||||||
|
|
||||||
hcaptcha_secret:
|
|
||||||
description: "Private hCaptcha secret key for server-side verification"
|
|
||||||
algorithm: "plain"
|
|
||||||
validation: "^[0-9a-zA-Z_-]{32,}$"
|
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ LISTMONK_SETTINGS:
|
|||||||
value: 'true'
|
value: 'true'
|
||||||
|
|
||||||
- key: "security.captcha_key"
|
- key: "security.captcha_key"
|
||||||
value: '"{{ applications | get_app_conf(application_id, "credentials.hcaptcha_site_key") }}"'
|
value: '"{{ applications | get_app_conf(application_id, "credentials.hcaptcha.key") }}"'
|
||||||
|
|
||||||
- key: "security.captcha_secret"
|
- key: "security.captcha_secret"
|
||||||
value: '"{{ applications | get_app_conf(application_id, "credentials.hcaptcha_secret") }}"'
|
value: '"{{ applications | get_app_conf(application_id, "credentials.hcaptcha.secret") }}"'
|
||||||
|
|
||||||
# SMTP servers
|
# SMTP servers
|
||||||
- key: "smtp"
|
- key: "smtp"
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ features:
|
|||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
logout: true
|
logout: true
|
||||||
hcaptcha: true
|
hcaptcha: "{{ HCAPTCHA_ENABLED | bool }}"
|
||||||
default_quota: '1000000000' # Quota to assign if no quota is specified in the OIDC response (bytes)
|
default_quota: '1000000000' # Quota to assign if no quota is specified in the OIDC response (bytes)
|
||||||
legacy_login_mask:
|
legacy_login_mask:
|
||||||
enabled: False # If true, then legacy login mask is shown. Otherwise just SSO
|
enabled: False # If true, then legacy login mask is shown. Otherwise just SSO
|
||||||
|
|||||||
Reference in New Issue
Block a user