refactor(credentials)!: give applications their own administrator account

Application roles used the host administrator account.
user-administrator/tasks/00_core.yml:17 hashes its password into the OS
user, files/administrator grants that name ALL=(ALL) ALL without
NOPASSWD, and rotate.py lists it in ROTATION_EXEMPT, so the value is
password-authenticated sudo that cannot be rotated to recover. Every role
that typed it into a web form was typing the host sudo credential, and the
staged Playwright env carrying it is written mode 0644.

roles/user-administrator/meta/users.yml now declares platform_administrator
beside administrator: no host account, no rotation exemption, mailbox and
identity so it stays SSO-capable and can receive the mail applications send
to their admin. Every use moves to it, all fields and not only the
password: leaving .email behind built accounts from both identities at
once, with the host operator's address under the platform account's login
name, and an IdP matching on e-mail resolves such an account back to the
host operator.

The account is reachable by two spellings, and both are migrated:
lookup('users', 'administrator') in its two- and three-argument forms, and
the dotted lookup('config', application_id, 'users.administrator.email')
that five roles used. administrator is now referenced nowhere outside
roles/user-administrator.

Four lints hold the boundary:

  - no role outside user-administrator may use the host administrator, in
    either spelling or as a *user_key literal
  - a role that looks a user up must declare it in its own meta/users.yml,
    because required_user_policies only pins passwords for users declared
    by a role resolved into the inventory, and those are the invokable
    roles; a user declared only by a non-invokable role keeps the
    {{ 42 | strong_password }} fallback, which re-renders per evaluation
  - a role that iterates a user or passes it as a *user_key must declare it
  - the biber and mapache test personas may be read only from the
    Playwright and CLI test surfaces

Two credentials that were derived by hashing the admin password get their
own declaration, because deriving them tied an unrelated rotation to a
password change: web-app-fider jwt_secret, which signs session and e-mail
sign-in tokens, and web-app-nextcloud integration_suitecrm_client_secret,
whose two ends must be re-registered in lockstep.

web-app-keycloak separates the two admins it has: a new meta/users.yml
declares keycloak_bootstrap for the temporary account the container creates
on first start, while the permanent account is platform_administrator. Both
resolve in vars/main.yml so the lookup runs once per role.

web-app-semaphore's break-glass admin no longer shares ansible_become_password
and no longer forwards its mail to the host administrator; tasks/02_breakglass.yml
realigns the password on every deploy, so it converges on its own.

The six roles whose meta/secrets.yml declared administrator_password as its
only credential lose the file.

tests/integration/ansible/lookups/test_declared_users_resolve.py runs the
lookup through the real plugin loader and fails on a declared user that
cannot be resolved or whose username, e-mail or password renders empty. The
two declarations reading ansible_become_password resolve to an empty string
when that variable is absent, and nothing raises on it.

Existing deployments keep the admin account their application database
already holds, under the old name. Roles that re-apply the credential every
run converge; 30 roles feed it from config with no provisioning task and do
not, so those accounts need a reset. web-app-friendica additionally guards
on "'administrator' not in stdout", which the substring platform-administrator
satisfies, and web-app-n8n initialises an owner that already exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-10-08 16:28:52 +02:00
1 parent a599623331
commit 3c72c2002a
283 files changed
+1053 -545

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
+2 -2
View File
@@ -14,8 +14,8 @@ AGENT_MODEL={{ AGENT_BROKER_MODEL | dotenv_quote }}
AGENT_PLATFORMS={{ AGENT_BROKER_PLATFORMS | to_json | dotenv_quote }}
KEYCLOAK_URL={{ lookup('tls', 'web-app-keycloak', 'url.base') }}
KEYCLOAK_REALM={{ OIDC.CLIENT.REALM | dotenv_quote }}
KEYCLOAK_ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
KEYCLOAK_ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
KEYCLOAK_ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
KEYCLOAK_ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ACCESS_CACHE_SECONDS={{ AGENT_BROKER_AGENTS.access_cache_seconds }}
IDLE_STOP={{ AGENT_BROKER_AGENTS.idle_stop | bool | string | lower }}
IDLE_MINUTES={{ AGENT_BROKER_AGENTS.idle_minutes }}
@@ -14,7 +14,7 @@ IDLE_MINUTES={{ AGENT_BROKER_AGENTS.idle_minutes }}
IDLE_STOP={{ AGENT_BROKER_AGENTS.idle_stop | bool | string | lower }}
MAX_RUNNING={{ AGENT_BROKER_AGENTS.max_running }}
REQUEST_TIMEOUT={{ AGENT_BROKER_REQUEST_TIMEOUT + 300 }}
USER_A_EMAIL={{ lookup('users', 'administrator').email }}
USER_A_NAME={{ lookup('users', 'administrator').username }}
USER_A_EMAIL={{ lookup('users', 'platform_administrator').email }}
USER_A_NAME={{ lookup('users', 'platform_administrator').username }}
USER_B_EMAIL={{ lookup('users', 'biber').email }}
USER_B_NAME={{ lookup('users', 'biber').username }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
+1 -1
View File
@@ -4,7 +4,7 @@ PYTHONPATH={{ LITELLM_CONFIG_PATH_DOCKER | dirname }}
LITELLM_MASTER_KEY={{ LITELLM_MASTER_KEY | dotenv_quote }}
DATABASE_URL={{ lookup('database', application_id, 'url_full') | dotenv_quote }}
STORE_MODEL_IN_DB=False
UI_USERNAME={{ lookup('users', 'administrator').username }}
UI_USERNAME={{ lookup('users', 'platform_administrator').username }}
UI_PASSWORD={{ lookup('config', application_id, 'secrets.credentials.ui_password') | dotenv_quote }}
{% for _provider in LITELLM_KEYED_PROVIDERS %}
{{ _provider | upper }}_API_KEY={{ LITELLM_PROVIDER_KEYS[_provider] | dotenv_quote }}
+1 -1
View File
@@ -55,4 +55,4 @@ LITELLM_TEST_CONTRACT:
LITELLM_UI_ROLE: "web-app-litellm"
LITELLM_UI_SSO: "{{ (LITELLM_UI_ROLE in group_names) and (lookup('sso', LITELLM_UI_ROLE, 'is_oidc_native') | bool) }}"
LITELLM_UI_BASE_URL: "{{ lookup('tls', LITELLM_UI_ROLE, 'url.base') }}"
LITELLM_UI_ADMIN: "{{ lookup('users', 'administrator').username }}"
LITELLM_UI_ADMIN: "{{ lookup('users', 'platform_administrator').username }}"
-4
View File
@@ -1,9 +1,5 @@
---
credentials:
administrator_password:
description: Initial password for the LDAP administrator (e.g. cn=admin,dc=example,dc=com)
algorithm: sha256
validation: ^[a-f0-9]{64}$
administrator_database_password:
description: Password used internally for the database-backed directory admin
algorithm: bcrypt
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -27,7 +27,7 @@ trap 'rm -f "$mail_tmp"' EXIT
{% set email = lookup('email') %}
cat > "$mail_tmp" <<ERRMAIL
To: {{ lookup('users', 'administrator').email }}
To: {{ lookup('users', 'platform_administrator').email }}
From: systemd <{{ email['from'] }}>
Subject: ${friendly}
Content-Transfer-Encoding: 8bit
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -5,7 +5,7 @@
{{
(matomo_token_override | default('') | string | trim)
if (matomo_token_override | default('') | string | trim) != ''
else (lookup('users', 'administrator').tokens['web-app-matomo'] | default('') | string | trim)
else (lookup('users', 'platform_administrator').tokens['web-app-matomo'] | default('') | string | trim)
}}
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
+1 -1
View File
@@ -11,7 +11,7 @@
command: >-
certbundle
--domains "{{ CURRENT_PLAY_DOMAINS_ALL | join(',') }}"
--certbot-email "{{ lookup('users', 'administrator').email }}"
--certbot-email "{{ lookup('users', 'platform_administrator').email }}"
--certbot-acme-challenge-method "{{ CERTBOT_ACME_CHALLENGE_METHOD }}"
--chunk-size 100
{% if CERTBOT_ACME_CHALLENGE_METHOD != 'webroot' %}
@@ -7,7 +7,7 @@
- name: "📜 receive certificate for '{{ domain }}'"
command: >-
certbot certonly --agree-tos --email {{ lookup('users', 'administrator').email }}
certbot certonly --agree-tos --email {{ lookup('users', 'platform_administrator').email }}
--non-interactive {% if CERTBOT_ACME_CHALLENGE_METHOD != "webroot" %}
--dns-{{ CERTBOT_ACME_CHALLENGE_METHOD }}
--dns-{{ CERTBOT_ACME_CHALLENGE_METHOD }}-credentials {{ CERTBOT_CREDENTIALS_FILE }}
+2
View File
@@ -0,0 +1,2 @@
---
no-reply: {}
+8
View File
@@ -1,4 +1,12 @@
---
platform_administrator:
description: Application administrator for {{ ORGANIZATION }} on {{ DOMAIN_PRIMARY }}
firstname: Platform
lastname: Administrator
username: platform-administrator
authorized_keys: []
accounts: [mailbox, identity]
administrator:
description: System Administrator for {{ ORGANIZATION }} on {{ DOMAIN_PRIMARY }}
firstname: Administrator
+2
View File
@@ -0,0 +1,2 @@
---
root: {}
+2 -2
View File
@@ -53,8 +53,8 @@ akaunting:
min_storage: 527MB
company:
name: Akaunting on {{ DOMAIN_PRIMARY | upper }}
email: "{{ lookup('users', 'administrator').email }}"
setup_admin_email: "{{ lookup('users', 'administrator').email }}"
email: "{{ lookup('users', 'platform_administrator').email }}"
setup_admin_email: "{{ lookup('users', 'platform_administrator').email }}"
ports:
local:
http: 8025
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
AKAUNTING_ADMIN_EMAIL={{ AKAUNTING_ADMIN_EMAIL | dotenv_quote }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+3 -3
View File
@@ -56,6 +56,6 @@ BASEROW_MCP_CONTRACT:
limits: "{{ lookup('config', application_id, 'mcp.limits') }}"
schema_sha256: "{{ lookup('config', application_id, 'mcp.tools.schema_sha256') }}"
BASEROW_BOOTSTRAP_ADMIN_USERNAME: "{{ lookup('users', 'administrator').username }}"
BASEROW_BOOTSTRAP_ADMIN_EMAIL: "{{ lookup('users', 'administrator').email }}"
BASEROW_BOOTSTRAP_ADMIN_PASSWORD: "{{ lookup('users', 'administrator').password }}"
BASEROW_BOOTSTRAP_ADMIN_USERNAME: "{{ lookup('users', 'platform_administrator').username }}"
BASEROW_BOOTSTRAP_ADMIN_EMAIL: "{{ lookup('users', 'platform_administrator').email }}"
BASEROW_BOOTSTRAP_ADMIN_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
@@ -20,13 +20,13 @@
- exec
- -i
- -e
- "TARGET_NAME={{ lookup('users', 'administrator').username | upper }}"
- "TARGET_NAME={{ lookup('users', 'platform_administrator').username | upper }}"
- -e
- "NEW_NAME={{ lookup('users', 'administrator').username | upper }}"
- "NEW_NAME={{ lookup('users', 'platform_administrator').username | upper }}"
- -e
- "NEW_EMAIL={{ lookup('users', 'administrator').email }}"
- "NEW_EMAIL={{ lookup('users', 'platform_administrator').email }}"
- -e
- "NEW_PASSWORD_B64={{ lookup('users', 'administrator').password | b64encode }}"
- "NEW_PASSWORD_B64={{ lookup('users', 'platform_administrator').password | b64encode }}"
- "{{ BBB_GREENLIGHT_CONTAINER_ADDRESS | quote }}" # nocheck: container-address-quote, container-address-needs-shell compose_mode_force role, so the lookup can only yield a bare name
- bash
- -lc
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
@@ -13,9 +13,9 @@
ADMIN_HANDLE={{ BLUESKY_ADMIN_HANDLE | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+3 -3
View File
@@ -37,9 +37,9 @@ BLUESKY_LDAP_ENABLED: "{{ lookup('config', application_id, 'services.ldap.enable
BLUESKY_JWT_SECRET: "{{ lookup('config', application_id, 'secrets.credentials.jwt_secret') }}"
BLUESKY_ROTATION_KEY: "{{ lookup('config', application_id, 'secrets.credentials.plc_rotation_key_k256_private_key_hex') }}"
BLUESKY_ADMIN_EMAIL: "{{ lookup('users', 'administrator').email }}"
BLUESKY_ADMIN_PASSWORD: "{{ lookup('users', 'administrator').password }}"
BLUESKY_ADMIN_HANDLE: "kc-{{ lookup('users', 'administrator').username }}.{{ BLUESKY_PDS_HANDLE_DOMAIN }}"
BLUESKY_ADMIN_EMAIL: "{{ lookup('users', 'platform_administrator').email }}"
BLUESKY_ADMIN_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
BLUESKY_ADMIN_HANDLE: "kc-{{ lookup('users', 'platform_administrator').username }}.{{ BLUESKY_PDS_HANDLE_DOMAIN }}"
BLUESKY_PDS_INTERNAL_URL: "http://127.0.0.1:{{ BLUESKY_API_PORT }}"
BLUESKY_FRONT_PROXY_CONTENT: "{{ lookup('template', 'extra_locations.conf.j2') }}"
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
+1 -1
View File
@@ -9,7 +9,7 @@ container_hostname: "{{ lookup('container_hostname', application_id) }}"
BRIDGY_CONTAINER: "{{ lookup('config', application_id, 'services.bridgy-fed.name') }}"
BRIDGY_ADMIN_EMAIL: "{{ lookup('users', 'administrator').email }}"
BRIDGY_ADMIN_EMAIL: "{{ lookup('users', 'platform_administrator').email }}"
BRIDGY_REPO_URL: "{{ lookup('config', application_id, 'services.bridgy-fed.repository') }}"
BRIDGY_REF: "{{ lookup('config', application_id, 'services.bridgy-fed.ref') }}"
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
+1 -1
View File
@@ -9,7 +9,7 @@ container_hostname: "{{ entity_name }}"
CHESS_HOSTNAME: "{{ container_hostname }}"
CHESS_DOMAIN: "{{ domain }}"
CHESS_ADMIN_URL: ""
CHESS_ADMIN_EMAIL: "{{ lookup('users', 'administrator').email }}"
CHESS_ADMIN_EMAIL: "{{ lookup('users', 'platform_administrator').email }}"
CHESS_SERVICE: "{{ entity_name }}"
CHESS_CONTAINER: "{{ lookup('config', application_id, 'services.' ~ entity_name ~ '.name') }}"
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', DASHBOARD_APPLICATION_ID, 'url.base') }}
@@ -26,9 +26,9 @@ DASHBOARD_TARGET_ROLES_JSON={{ lookup('roles_with_service', 'dashboard') | to_js
DESIGN_SERVICE_ENABLED={{ lookup('config', application_id, 'services.design.enabled') | string | lower }}
LOGIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
LOGIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
LOGIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
LOGIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
LOGOUT_SERVICE_ENABLED={{ lookup('config', application_id, 'services.logout.enabled') | string | lower }}
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
+2 -2
View File
@@ -76,8 +76,8 @@
- name: "✅ Decidim | Ensure administrator user exists with correct credentials"
ansible.builtin.shell: > # nocheck: container-exec-resolver DECIDIM_LOCAL_CID resolved at delegate_to runtime
container exec -i -e RAILS_ENV={{ ENVIRONMENT | quote }}
-e DECIDIM_ADMIN_EMAIL={{ lookup('users', 'administrator').email | quote }}
-e DECIDIM_ADMIN_PASSWORD={{ lookup('users', 'administrator').password | quote }}
-e DECIDIM_ADMIN_EMAIL={{ lookup('users', 'platform_administrator').email | quote }}
-e DECIDIM_ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | quote }}
{{ DECIDIM_LOCAL_CID | quote }}
bundle exec rails runner -
args:
@@ -1,6 +1,6 @@
ADMIN_EMAIL={{ lookup('users', 'administrator').email | dotenv_quote }}
ADMIN_EMAIL={{ lookup('users', 'platform_administrator').email | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | regex_replace('/+$', '') | dotenv_quote }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -37,11 +37,11 @@
- exec
- -i
- -e
- "DISCOURSE_ADMIN_EMAIL={{ lookup('users', 'administrator').email }}"
- "DISCOURSE_ADMIN_EMAIL={{ lookup('users', 'platform_administrator').email }}"
- -e
- "DISCOURSE_ADMIN_USERNAME={{ lookup('users', 'administrator').username }}"
- "DISCOURSE_ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username }}"
- -e
- "DISCOURSE_ADMIN_PASSWORD={{ lookup('users', 'administrator').password }}"
- "DISCOURSE_ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password }}"
- "{{ DISCOURSE_CONTAINER }}" # nocheck: container-exec-resolver the launcher names the container itself, so the bare name resolves in both modes
- rails
- r
@@ -56,9 +56,9 @@
- exec
- -i
- -e
- "DISCOURSE_ADMIN_EMAIL={{ lookup('users', 'administrator').email }}"
- "DISCOURSE_ADMIN_EMAIL={{ lookup('users', 'platform_administrator').email }}"
- -e
- "DISCOURSE_ADMIN_PASSWORD={{ lookup('users', 'administrator').password }}"
- "DISCOURSE_ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password }}"
- -e
- "DISCOURSE_OIDC_ENABLED={{ DISCOURSE_OIDC_ENABLED | bool | string | lower }}"
- -e
@@ -59,7 +59,7 @@ env:
#DOCKER_USE_HOSTNAME: true
## on initial signup example 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: {{ lookup('users', 'administrator').email }}
DISCOURSE_DEVELOPER_EMAILS: {{ lookup('users', 'platform_administrator').email }}
# Set Logo
{% if service_provider.platform.logo | length > 0 %}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
+1 -1
View File
@@ -1,8 +1,8 @@
---
administrator: {}
erpnext-api-bot:
username: erpnext-api-bot
firstname: Infinito
lastname: API Bot
accounts: []
description: API-only Basic-auth bot used by the Playwright suite (NOT an OIDC user)
platform_administrator: {}
@@ -1,10 +1,10 @@
ADMIN_EMAIL={{ lookup('users', 'administrator').email | dotenv_quote }}
ADMIN_EMAIL={{ lookup('users', 'platform_administrator').email | dotenv_quote }}
ADMIN_NATIVE_PASSWORD={{ ERPNEXT_INITIAL_ADMIN_PASSWORD | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
BIBER_PASSWORD={{ lookup('users', 'biber').password | dotenv_quote }}
-4
View File
@@ -1,9 +1,5 @@
---
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
+1 -1
View File
@@ -1,7 +1,7 @@
---
administrator: {}
contact:
description: General contact account
username: contact
roles:
- bot
platform_administrator: {}
@@ -74,9 +74,9 @@
ansible.builtin.shell: |
# nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec -i {{ ESPOCRM_LOCAL_CID | quote }} \
php command.php set-password {{ lookup('config', application_id, 'users.administrator.username') | quote }}
php command.php set-password {{ ESPOCRM_ADMIN_USERNAME | quote }}
args:
stdin: "{{ lookup('config', application_id, 'secrets.credentials.administrator_password') }}"
stdin: "{{ ESPOCRM_ADMIN_PASSWORD }}"
register: espocrm_admin_password
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
changed_when: espocrm_admin_password.rc == 0
+2 -2
View File
@@ -9,8 +9,8 @@ ESPOCRM_DATABASE_PASSWORD={{ lookup('database', application_id, 'password') | do
CRON_DISABLED=true
ESPOCRM_ADMIN_USERNAME={{ lookup('config', application_id, 'users.administrator.username') }}
ESPOCRM_ADMIN_PASSWORD={{ lookup('config', application_id, 'secrets.credentials.administrator_password') | dotenv_quote }}
ESPOCRM_ADMIN_USERNAME={{ ESPOCRM_ADMIN_USERNAME }}
ESPOCRM_ADMIN_PASSWORD={{ ESPOCRM_ADMIN_PASSWORD | dotenv_quote }}
ESPOCRM_SITE_URL={{ ESPOCRM_URL }}
@@ -1,10 +1,10 @@
{% if not ESPOCRM_LDAP_ENABLED | bool %}
ADMIN_NATIVE_PASSWORD={{ lookup('config', application_id, 'secrets.credentials.administrator_password') | dotenv_quote }}
ADMIN_NATIVE_PASSWORD={{ ESPOCRM_ADMIN_PASSWORD | dotenv_quote }}
{% endif %}
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ ESPOCRM_ADMIN_PASSWORD | dotenv_quote }}
ADMIN_USERNAME={{ lookup('config', application_id, 'users.administrator.username') | dotenv_quote }}
ADMIN_USERNAME={{ ESPOCRM_ADMIN_USERNAME | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
+3
View File
@@ -6,6 +6,9 @@ swarm_stack_converge_retries: 600
websocket_port: "{{ lookup('config', application_id, 'services.espocrm.ports.local.websocket') }}"
ESPOCRM_ADMIN_USERNAME: "{{ lookup('users', 'platform_administrator').username }}"
ESPOCRM_ADMIN_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
ESPOCRM_VERSION: "{{ lookup('config', application_id, 'services.' ~ entity_name ~'.version') }}"
ESPOCRM_IMAGE: "{{ lookup('config', application_id, 'services.' ~ entity_name ~'.image') }}"
ESPOCRM_CONTAINER: "{{ lookup('config', application_id, 'services.' ~ entity_name ~'.name') }}"
+6
View File
@@ -1,5 +1,11 @@
---
credentials:
jwt_secret:
description: Key Fider signs its session and e-mail sign-in tokens with. Held separately from any login password, because a password change would otherwise
invalidate every issued token.
algorithm: alphanumeric
validation: "^[A-Za-z0-9]{32,}$"
length: 64
mcp_bearer:
description: "Bearer an MCP client must present to this role's adapter instance. Distinct from the upstream credential the adapter presents, because authenticating
to the application says nothing about who called the adapter."
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
+2 -2
View File
@@ -64,8 +64,8 @@
config: "{{ lookup('database', application_id) }}"
query_file: "{{ role_path }}/files/sql/create-admin-user.sql"
named_args:
full_name: "{{ lookup('users', 'administrator').firstname }} {{ lookup('users', 'administrator').lastname }}"
email: "{{ lookup('users', 'administrator').email }}"
full_name: "{{ lookup('users', 'platform_administrator').firstname }} {{ lookup('users', 'platform_administrator').lastname }}"
email: "{{ lookup('users', 'platform_administrator').email }}"
mask_values: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
changed_when: true
+1 -1
View File
@@ -2,7 +2,7 @@
BASE_URL={{ lookup('tls', application_id, 'url.base') }}
DATABASE_URL=postgresql://{{ lookup('database', application_id, 'username') }}:{{ lookup('database', application_id, 'password') }}@{{ lookup('database', application_id, 'host') }}:{{ lookup('database', application_id, 'port') }}/{{ lookup('database', application_id, 'name') }}?sslmode=disable
JWT_SECRET={{ (application_id ~ lookup('users', 'administrator').password) | hash('sha256') }}
JWT_SECRET={{ lookup('config', application_id, 'secrets.credentials.jwt_secret') | dotenv_quote }}
ALLOW_PRIVATE_NETWORK_TARGETS=true
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+2 -2
View File
@@ -15,8 +15,8 @@ FIDER_DESIGN_LOGO_KEY: "logos/infinito-design-logo.png"
FIDER_TENANT_BOOTSTRAP_BODY:
tenantName: "{{ SOFTWARE_NAME }}"
subdomain: "fider"
name: "{{ lookup('users', 'administrator').firstname }} {{ lookup('users', 'administrator').lastname }}"
email: "{{ lookup('users', 'administrator').email }}"
name: "{{ lookup('users', 'platform_administrator').firstname }} {{ lookup('users', 'platform_administrator').lastname }}"
email: "{{ lookup('users', 'platform_administrator').email }}"
legalAgreement: true
token: ""
FIDER_MCP_ENABLED: "{{ lookup('config', application_id, 'services.fidermcp.enabled') | bool }}"
+1
View File
@@ -8,3 +8,4 @@ flowise-api-bot:
algorithm: strong_password
validation: "[^A-Za-z0-9]"
description: API-only identity used to reconcile the custom MCP server registry (NOT an OIDC user)
platform_administrator: {}
+2 -2
View File
@@ -1,8 +1,8 @@
{% include 'roles/sys-svc-container/templates/env.j2' %}
PORT={{ FLOWISE_PORT_INTERNAL }}
FLOWISE_USERNAME={{ lookup('users', 'administrator').username }}
FLOWISE_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
FLOWISE_USERNAME={{ lookup('users', 'platform_administrator').username }}
FLOWISE_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
DATABASE_TYPE=postgres
DATABASE_HOST={{ lookup('database', application_id, 'host') }}
DATABASE_PORT={{ lookup('database', application_id, 'port') }}
@@ -1,7 +1,7 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -16,9 +16,9 @@
--workdir {{ FRIENDICA_APPLICATION_DIR }}
{{ FRIENDICA_LOCAL_CID | quote }}
{{ FRIENDICA_APPLICATION_DIR }}/bin/console user add
"{{ lookup('users', 'administrator').firstname | default('Administrator') }}"
"{{ lookup('users', 'platform_administrator').firstname | default('Administrator') }}"
administrator
"{{ lookup('users', 'administrator').email }}"
"{{ lookup('users', 'platform_administrator').email }}"
en
delegate_to: "{{ FRIENDICA_HOST_NODE }}"
when: "'administrator' not in friendica_admin_search.stdout"
+2 -2
View File
@@ -28,8 +28,8 @@ SMTP_STARTTLS={{ 'on' if email.start_tls else 'off' }}
SMTP_FROM=no-reply
{% endif %}
FRIENDICA_ADMIN_MAIL={{ lookup('users', 'administrator').email }}
MAILNAME={{ lookup('users', 'administrator').email }}
FRIENDICA_ADMIN_MAIL={{ lookup('users', 'platform_administrator').email }}
MAILNAME={{ lookup('users', 'platform_administrator').email }}
FRIENDICA_CONFIG_FILE={{ FRIENDICA_CONFIG_FILE }}
{% if IS_SWARM_MODE %}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+3
View File
@@ -0,0 +1,3 @@
---
no-reply: {}
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -1,7 +1,7 @@
{% include 'roles/sys-svc-container/templates/env.j2' %}
FUSIONDIRECTORY_ADMIN_USER={{ lookup('users', 'administrator').username }}
FUSIONDIRECTORY_ADMIN_PASS={{ lookup('users', 'administrator').password | dotenv_quote }}
FUSIONDIRECTORY_ADMIN_USER={{ lookup('users', 'platform_administrator').username }}
FUSIONDIRECTORY_ADMIN_PASS={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
LDAP01_NAME={{ application_id | entity_name }}
LDAP01_HOST={{ lookup('config', 'svc-db-openldap', 'services.openldap.name') }}
LDAP01_PORT={{ lookup('config', 'svc-db-openldap', 'services.openldap.ports.local.ldap') }}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+4 -4
View File
@@ -1,9 +1,9 @@
---
administrator:
tokens:
web-app-gitea: ""
mcp-web-app-gitea:
firstname: Infinito
lastname: MCP
accounts: []
description: Account the Gitea MCP access token belongs to; a token on the administrator reads every private repository
description: Account the Gitea MCP access token belongs to; a token on the platform administrator reads every private repository
platform_administrator:
tokens:
web-app-gitea: ""
+3 -3
View File
@@ -38,9 +38,9 @@
container exec -i --user {{ GITEA_USER }} {{ GITEA_LOCAL_CID | quote }} \
/app/gitea/gitea admin user create \
--admin \
--username "{{ lookup('users', 'administrator').username }}" \
--password {{ lookup('users', 'administrator').password | quote }} \
--email "{{ lookup('users', 'administrator').email }}" \
--username "{{ lookup('users', 'platform_administrator').username }}" \
--password {{ lookup('users', 'platform_administrator').password | quote }} \
--email "{{ lookup('users', 'platform_administrator').email }}" \
-c {{ GITEA_CONFIG }}
delegate_to: "{{ GITEA_HOST_NODE }}"
register: create_admin
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+1
View File
@@ -4,3 +4,4 @@ mcp-web-app-gitlab:
lastname: MCP
accounts: []
description: Account the GitLab MCP personal access token belongs to; a token on root reads every private project
platform_administrator: {}
@@ -1,8 +1,8 @@
ADMIN_EMAIL={{ lookup('users', 'administrator').email | dotenv_quote }}
ADMIN_EMAIL={{ lookup('users', 'platform_administrator').email | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
+1 -1
View File
@@ -29,7 +29,7 @@ GITLAB_OIDC_CLIENT_SECRET: "{{ OIDC.CLIENT.SECRET }}"
GITLAB_OIDC_ISSUER: "{{ OIDC.CLIENT.ISSUER_URL }}"
GITLAB_OIDC_REDIRECT_URI: "{{ (GITLAB_URL | regex_replace('/$', '')) ~ '/users/auth/openid_connect/callback' }}"
GITLAB_INIT_ROOT_PASSWORD: "{{ lookup('users', 'administrator').password }}"
GITLAB_INIT_ROOT_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
GITLAB_MCP_ENABLED: "{{ lookup('config', application_id, 'services.gitlabmcp.enabled') | bool }}"
GITLAB_MCP_PATH: "{{ GITLAB_MCP_UPSTREAM_PATH }}"
+1
View File
@@ -2,3 +2,4 @@
hermes:
description: Platform account the Hermes agent employee acts as. Non-privileged by design, with its own mailbox. Override the `hermes` key through the
inventory `users` variable to point the agent at an account that already exists instead.
platform_administrator: {}
+1 -1
View File
@@ -15,7 +15,7 @@ HERMES_DASHBOARD_PUBLIC_URL={{ HERMES_URL | dotenv_quote }}
HERMES_DASHBOARD_OIDC_ISSUER={{ OIDC.CLIENT.ISSUER_URL | dotenv_quote }}
HERMES_DASHBOARD_OIDC_CLIENT_ID={{ OIDC.CLIENT.ID | dotenv_quote }}
{% else %}
HERMES_DASHBOARD_BASIC_AUTH_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
HERMES_DASHBOARD_BASIC_AUTH_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD={{ HERMES_WEBUI_PASSWORD | dotenv_quote }}
{% endif %}
{% endif %}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
BIBER_PASSWORD={{ lookup('users', 'biber').password | dotenv_quote }}
@@ -1,7 +0,0 @@
---
credentials:
administrator_password:
description: Initial password of the Home Assistant owner account created during headless onboarding
algorithm: alphanumeric
validation:
min_length: 32
+3 -3
View File
@@ -1,9 +1,9 @@
---
administrator:
tokens:
web-app-homeassistant: ""
mcp-web-app-homeassistant:
firstname: Infinito
lastname: MCP
accounts: []
description: Account the Home Assistant long-lived MCP token is minted for; such a token carries the rights of whoever was logged in
platform_administrator:
tokens:
web-app-homeassistant: ""
@@ -21,7 +21,7 @@ HOMEASSISTANT_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quo
# nocheck: playwright-service-gate
MCP_SERVICE_ENABLED={{ lookup('config', application_id, 'mcp.enabled') | string | lower }}
# nocheck: persona-block-rationale: Home Assistant runs its own auth provider. The hub account is provisioned from secrets.credentials.administrator_password rather than the platform user password, and meta/services.yml pins sso.enabled false, so the administrator persona holds no credential the hub accepts.
# nocheck: persona-block-rationale: Home Assistant runs its own auth provider and meta/services.yml pins sso.enabled false, so the administrator persona has no OIDC path into the hub; its owner account is created once during headless onboarding and the shared helper drives no native hub form.
PERSONA_ADMINISTRATOR_BLOCKED=true
# nocheck: persona-block-rationale: the deploy provisions only the hub administrator and the MCP service account in Home Assistant's own auth provider, and meta/services.yml pins sso.enabled false, so no auth path exists that would admit biber.
+2 -2
View File
@@ -8,8 +8,8 @@ HOMEASSISTANT_CONTAINER: "{{ lookup('config', application_id, 'services.homeassi
HOMEASSISTANT_CONFIG_PATH_HOST: "{{ [ lookup('container', application_id, 'directories.config'), 'configuration.yaml' ] | path_join }}"
HOMEASSISTANT_PORT_INTERNAL: "{{ lookup('config', application_id, 'services.homeassistant.ports.internal.http') }}"
HOMEASSISTANT_MCP_ENABLED: "{{ lookup('config', application_id, 'mcp.enabled') }}"
HOMEASSISTANT_ADMIN_USERNAME: "{{ lookup('users', 'administrator').username }}"
HOMEASSISTANT_ADMIN_PASSWORD: "{{ lookup('config', application_id, 'secrets.credentials.administrator_password') }}"
HOMEASSISTANT_ADMIN_USERNAME: "{{ lookup('users', 'platform_administrator').username }}"
HOMEASSISTANT_ADMIN_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
HOMEASSISTANT_TOKEN_CLIENT_NAME: "infinito-mcp"
HOMEASSISTANT_CONFIG_DIR: "{{ lookup('volume', application_id, 'homeassistant_config').target }}"
HOMEASSISTANT_LOGIN_REFUSED: "home assistant refused the login of"
-4
View File
@@ -1,9 +1,5 @@
---
credentials:
administrator_password:
description: Initial password for the Jellyfin local administrator seeded via the first-run /Startup wizard (break-glass; SSO/LDAP users authenticate via
the plugins).
algorithm: alphanumeric
mcp_bearer:
description: "Bearer an MCP client must present to this role's adapter instance. Distinct from the upstream credential the adapter presents, because authenticating
to the application says nothing about who called the adapter."
+1 -1
View File
@@ -1,7 +1,7 @@
---
administrator: {}
mcp-web-app-jellyfin:
firstname: Infinito
lastname: MCP
accounts: []
description: Account the Jellyfin MCP API key is minted for; it reads the library instead of the administrator
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_NATIVE_PASSWORD={{ JELLYFIN_ADMIN_PASSWORD | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
BIBER_PASSWORD={{ lookup('users', 'biber').password | dotenv_quote }}
+2 -2
View File
@@ -6,8 +6,8 @@ JELLYFIN_NAME: "{{ lookup('config', application_id, 'services.jellyfin.name') }}
JELLYFIN_BASE_URL: "{{ lookup('tls', application_id, 'url.base') }}"
JELLYFIN_API: "http://{{ DOCKER_BIND_HOST }}:{{ lookup('config', application_id, 'services.jellyfin.ports.local.http') }}"
JELLYFIN_ADMIN_USERNAME: "{{ lookup('users', 'administrator').username }}"
JELLYFIN_ADMIN_PASSWORD: "{{ lookup('config', application_id, 'secrets.credentials.administrator_password') }}"
JELLYFIN_ADMIN_USERNAME: "{{ lookup('users', 'platform_administrator').username }}"
JELLYFIN_ADMIN_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
JELLYFIN_API_CLIENT: 'MediaBrowser Client="infinito", Device="ansible", DeviceId="infinito-deploy", Version="1.0.0"'
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
+3 -3
View File
@@ -36,8 +36,8 @@ jenkins:
local:
allowsSignup: false
users:
- id: "{{ lookup('users', 'administrator').username }}"
password: "{{ lookup('users', 'administrator').password }}"
- id: "{{ lookup('users', 'platform_administrator').username }}"
password: "{{ lookup('users', 'platform_administrator').password }}"
{% endif %}
authorizationStrategy:
@@ -49,7 +49,7 @@ jenkins:
permissions:
- "Overall/Administer"
entries:
- user: "{{ lookup('users', 'administrator').username }}"
- user: "{{ lookup('users', 'platform_administrator').username }}"
- group: "authenticated"
unclassified:
location:
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+1 -1
View File
@@ -1,2 +1,2 @@
---
administrator: {}
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
+2
View File
@@ -0,0 +1,2 @@
---
platform_administrator: {}
@@ -1,6 +1,6 @@
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_PASSWORD={{ lookup('users', 'platform_administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'platform_administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') }}
+3 -3
View File
@@ -25,8 +25,8 @@ JOOMLA_UPLOAD_MAX_FILESIZE: "{{ (JOOMLA_UPLOAD_SIZE | int) }}M"
JOOMLA_POST_MAX_SIZE: "{{ ((JOOMLA_UPLOAD_SIZE | int) * 12 // 10) }}M"
JOOMLA_PHP_MEMORY_LIMIT: "{{ lookup('service_memory_mb', application_id, entity_name, 0.5) }}M"
JOOMLA_USER_NAME: "{{ lookup('users', 'administrator').username }}"
JOOMLA_USER_NAME: "{{ lookup('users', 'platform_administrator').username }}"
JOOMLA_USER: "{{ JOOMLA_USER_NAME | capitalize }}"
JOOMLA_USER_PASSWORD: "{{ lookup('users', 'administrator').password }}"
JOOMLA_USER_EMAIL: "{{ lookup('users', 'administrator').email }}"
JOOMLA_USER_PASSWORD: "{{ lookup('users', 'platform_administrator').password }}"
JOOMLA_USER_EMAIL: "{{ lookup('users', 'platform_administrator').email }}"
JOOMLA_WEB_USER: "www-data"
-4
View File
@@ -4,10 +4,6 @@ credentials:
description: Cookie secret for the SSO-proxy sidecar (hex string, 32 characters, generated via `openssl rand -hex 16`)
algorithm: plain
validation: ^.*$
administrator_password:
description: Password for the Keycloak administrator user (used in bootstrap and CLI access)
algorithm: sha256
validation: ^[a-f0-9]{64}$
oidc_client_secret:
description: Client secret for the shared OIDC client; consumed by the SSO-proxy sidecar and the Keycloak realm client, and used as the default for
OIDC.CLIENT.SECRET when the inventory sets none.
-2
View File
@@ -69,8 +69,6 @@ keycloak:
nextcloud: nextcloud
moodle: moodle
accounts:
bootstrap:
username: administrator
system:
username: "{{ SOFTWARE_NAME | replace('.', '_') | lower }}"
ports:
Loaded 100 of 283 files, more files were not shown because too many files have changed in this diff. Show more