Compare commits

..

4 Commits

20 changed files with 191 additions and 33 deletions

View File

@ -649,7 +649,7 @@ defaults_applications:
## PHPMyAdmin ## PHPMyAdmin
phpmyadmin: phpmyadmin:
version: "latest" version: "latest" # Use the latest phpmyadmin version
autologin: false # This is a high security risk. Just activate this option if you know what you're doing autologin: false # This is a high security risk. Just activate this option if you know what you're doing
oauth2_proxy: oauth2_proxy:
enabled: true enabled: true
@ -703,7 +703,6 @@ defaults_applications:
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: true # Makes sense to make the documentary allways in iframe available landingpage_iframe_enabled: true # Makes sense to make the documentary allways in iframe available
## Taiga ## Taiga
taiga: taiga:
@ -714,7 +713,13 @@ defaults_applications:
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
oidc: oidc:
enabled: True # Activate OIDC for Mastodon # Taiga doesn't have a functioning oidc support at the moment
# See
# - https://community.taiga.io/t/taiga-and-oidc-plugin/4866
#
# Due to this reason this plutin is deactivated atm
enabled: False # De\Activate OIDC for Taiga
## YOURLS ## YOURLS
yourls: yourls:

View File

@ -19,11 +19,11 @@ defaults_oidc:
issuer_url: "{{_oidc_client_issuer_url}}" # Base URL of the OIDC provider (issuer) issuer_url: "{{_oidc_client_issuer_url}}" # Base URL of the OIDC provider (issuer)
discovery_document: "{{_oidc_client_issuer_url}}/.well-known/openid-configuration" # URL for fetching the provider's configuration details discovery_document: "{{_oidc_client_issuer_url}}/.well-known/openid-configuration" # URL for fetching the provider's configuration details
authorize_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/auth" # Endpoint to start the authorization process authorize_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/auth" # Endpoint to start the authorization process
toke_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/token" # Endpoint to exchange authorization codes for tokens (note: 'toke_url' may be a typo for 'token_url') token_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/token" # Endpoint to exchange authorization codes for tokens (note: 'token_url' may be a typo for 'token_url')
user_info_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/userinfo" # Endpoint to retrieve user information user_info_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/userinfo" # Endpoint to retrieve user information
logout_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/logout" # Endpoint to log out the user logout_url: "{{_oidc_client_issuer_url}}/protocol/openid-connect/logout" # Endpoint to log out the user
change_credentials: "{{_oidc_client_issuer_url}}account/account-security/signing-in" # URL for managing or changing user credentials change_credentials: "{{_oidc_client_issuer_url}}account/account-security/signing-in" # URL for managing or changing user credentials
button_text: "SSO Login({{primary_domain | upper}})" # Default button text
############################################# #############################################
### LDAP ### ### LDAP ###
############################################# #############################################
@ -34,8 +34,6 @@ _ldap_dn_base: "dc={{primary_domain_sld}},dc={{primary_domain_tld}}"
_ldap_server_port: "{% if applications.ldap.openldap.network.local | bool %}{{ ports.localhost.ldap.openldap }}{% else %}{{ ports.localhost.ldaps.openldap }}{% endif %}" _ldap_server_port: "{% if applications.ldap.openldap.network.local | bool %}{{ ports.localhost.ldap.openldap }}{% else %}{{ ports.localhost.ldaps.openldap }}{% endif %}"
ldap: ldap:
# Enables LDAP for all roles in play if true
enabled: true
# Distinguished Names (DN) # Distinguished Names (DN)
dn: dn:
# Defines the base Distinguished Name (DN) for the LDAP directory, constructed from the second-level domain (SLD) and top-level domain (TLD). # Defines the base Distinguished Name (DN) for the LDAP directory, constructed from the second-level domain (SLD) and top-level domain (TLD).

View File

@ -294,4 +294,5 @@ OPENID_CONNECT_CLIENT_ID={{oidc.client.id}}
OPENID_CONNECT_CLIENT_SECRET={{oidc.client.secret}} OPENID_CONNECT_CLIENT_SECRET={{oidc.client.secret}}
OPENID_CONNECT_ISSUER={{oidc.client.issuer_url}} OPENID_CONNECT_ISSUER={{oidc.client.issuer_url}}
OPENID_CONNECT_REDIRECT=https://{{domains[application_id]}} OPENID_CONNECT_REDIRECT=https://{{domains[application_id]}}
# OPENID_CONNECT_UID_FIELD=sub default
{% endif %} {% endif %}

View File

@ -60,7 +60,7 @@ SMTP_FROM_ADDRESS=Mastodon <{{system_email.from}}>
# @see https://stackoverflow.com/questions/72081776/how-mastodon-configured-login-using-sso # @see https://stackoverflow.com/questions/72081776/how-mastodon-configured-login-using-sso
OIDC_ENABLED={{ applications[application_id].oidc.enabled | string | lower }} OIDC_ENABLED={{ applications[application_id].oidc.enabled | string | lower }}
OIDC_DISPLAY_NAME="{{primary_domain | upper}} SSO" OIDC_DISPLAY_NAME="{{oidc.button_text}}"
OIDC_ISSUER={{oidc.client.issuer_url}} OIDC_ISSUER={{oidc.client.issuer_url}}
OIDC_DISCOVERY=true OIDC_DISCOVERY=true
OIDC_SCOPE="openid,profile,email" OIDC_SCOPE="openid,profile,email"

View File

@ -49,7 +49,7 @@ email:
# @See https://matrix-org.github.io/synapse/latest/openid.html # @See https://matrix-org.github.io/synapse/latest/openid.html
oidc_providers: oidc_providers:
- idp_id: keycloak - idp_id: keycloak
idp_name: "{{primary_domain | upper}} SSO" idp_name: "{{oidc.button_text}}"
issuer: "{{oidc.client.issuer_url}}" issuer: "{{oidc.client.issuer_url}}"
client_id: "{{oidc.client.id}}" client_id: "{{oidc.client.id}}"
client_secret: "{{oidc.client.secret}}" client_secret: "{{oidc.client.secret}}"

View File

@ -36,7 +36,7 @@ return array (
'oidc_login_default_quota' => '{{applications[application_id].default_quota}}', 'oidc_login_default_quota' => '{{applications[application_id].default_quota}}',
// Login button text // Login button text
'oidc_login_button_text' => 'Log in with OpenID', 'oidc_login_button_text' => '{{oidc.button_text}}',
// Hide the NextCloud password change form. // Hide the NextCloud password change form.
'oidc_login_hide_password_form' => true, 'oidc_login_hide_password_form' => true,

View File

@ -29,7 +29,7 @@ plugin_configuration:
title: "keycloak" title: "keycloak"
style: "keycloak" style: "keycloak"
authorizeUrl: "{{ oidc.client.authorize_url }}" authorizeUrl: "{{ oidc.client.authorize_url }}"
tokenUrl: "{{ oidc.client.toke_url }}" tokenUrl: "{{ oidc.client.token_url }}"
displayNameClaim: "" displayNameClaim: ""
userInfoUrl: "{{ oidc.client.user_info_url }}" userInfoUrl: "{{ oidc.client.user_info_url }}"
logoutUrl: "{{ oidc.client.logout_url }}" logoutUrl: "{{ oidc.client.logout_url }}"

View File

@ -0,0 +1,15 @@
# Development Notes
## Get Settings
## LDAP
```bash
docker compose exec web bash -c 'cd /app && RAILS_ENV=production bundle exec rails runner "puts Setting.all.select { |s| s.name.start_with?(\"ldap\") }.map { |s| \"#{s.name} = #{s.value}\" }"'
```
### All
```bash
docker compose exec web bash -c 'cd /app && RAILS_ENV=production bundle exec rails runner "Setting.all.each { |s| puts \"#{s.name} = #{s.value}\" }"'
```

View File

@ -1,27 +1,34 @@
# OpenProject Role # OpenProject 🧭
## Description
This role deploys [OpenProject](https://www.openproject.org/) using Docker Compose and provides a fully integrated experience for project collaboration with optional support for LDAP authentication and SMTP email delivery. Ideal for teams or individuals who want to get started with OpenProject quickly without manually setting up infrastructure.
## Overview ## Overview
This role is designed to deploy the [OpenProject](https://www.openproject.org/) application using Docker. It includes tasks for setting up the environment, pulling the Docker repository, and configuring a reverse proxy with Nginx. It was developed by [Kevin Veen-Birkenbach](https://www.veen.world/) Designed for simplicity, this role automates everything needed to run OpenProject in a containerized environment. It configures essential services such as the application itself, a PostgreSQL database, reverse proxy, and optional LDAP integration for identity management.
## Handlers ## Purpose
Defined in `handlers/main.yml`, the handler `recreate openproject` is used for recreating the OpenProject instance with specific environment settings. The purpose of this role is to reduce the complexity of setting up OpenProject with modern production-ready defaults. By combining Docker Compose and Ansible automation, it enables a hands-off setup for both small teams and larger internal infrastructures.
## Tasks ## Features
Outlined in `tasks/main.yml`, the role includes tasks for: - 🐳 **Docker-First Deployment**: Uses Docker Compose to launch the entire OpenProject stack.
- 🔒 **LDAP Integration (optional)**: Automatically connects to your LDAP server for centralized authentication.
- 📬 **SMTP Configuration**: Sends notification emails via your own mail server.
- 🧩 **OIDC Ready**: Prepared to extend with OpenID Connect login (e.g., Keycloak).
- 🔄 **Plugin Support**: Supports custom plugin installation via a pluggable `Gemfile.plugins`.
- 🛠️ **Role-Oriented Architecture**: Easily integrates with your infrastructure (e.g., database, reverse proxy).
- Including Nginx Docker proxy domain tasks. ## Developer Notes
- Creating the repository directory.
- Pulling the OpenProject Docker repository.
- Warning if the repository is not reachable.
- Copying the `.env` file from a template.
## Usage See the [Development.md](./Development.md) file for how to inspect and modify live settings inside the container, including full LDAP and SMTP configuration via the Rails console.
To use this role, include it in your Ansible playbook and set the necessary variables, especially those required in the `.env` file template. ## Credits 📝
## Notes Developed and maintained by **Kevin Veen-Birkenbach**
Learn more at [www.veen.world](https://www.veen.world)
Ensure that Docker and Docker Compose are installed and configured correctly on the target machine. Also, ensure that the necessary ports are open and accessible. Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais)
License: [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl)

View File

@ -0,0 +1,27 @@
---
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: "Deploys OpenProject with full Docker Compose integration and optional LDAP/SMTP/SSO setup."
license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl"
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
min_ansible_version: "2.9"
platforms:
- name: Archlinux
versions:
- rolling
galaxy_tags:
- openproject
- project-management
- docker
- compose
- ldap
- sso
- automation
repository: https://s.veen.world/cymais
issue_tracker_url: https://s.veen.world/cymaisissues
documentation: https://s.veen.world/cymais
dependencies: []

View File

@ -0,0 +1,47 @@
- name: "Create LDAP auth source"
community.postgresql.postgresql_query:
db: openproject
login_user: postgres
query: >
INSERT INTO ldap_auth_sources
(name, host, port, account, account_password, base_dn, attr_login,
attr_firstname, attr_lastname, attr_mail, onthefly_register, attr_admin,
created_at, updated_at, tls_mode, filter_string, verify_peer, tls_certificate_string)
VALUES (
'{{ openproject_ldap.name }}',
'{{ openproject_ldap.host }}',
{{ openproject_ldap.port }},
'{{ openproject_ldap.account }}',
'{{ openproject_ldap.account_password }}',
'{{ openproject_ldap.base_dn }}',
'{{ openproject_ldap.attr_login }}',
'{{ openproject_ldap.attr_firstname }}',
'{{ openproject_ldap.attr_lastname }}',
'{{ openproject_ldap.attr_mail }}',
{{ openproject_ldap.onthefly_register }},
'{{ openproject_ldap.attr_admin }}',
NOW(),
NOW(),
{{ openproject_ldap.tls_mode }},
'{{ openproject_ldap.filter_string }}',
{{ openproject_ldap.verify_peer }},
'{{ openproject_ldap.tls_certificate_string }}'
)
ON CONFLICT (name) DO NOTHING;
become: true
vars_files:
- vars/ldap.yml
- name: "Check existing LDAP sources"
community.postgresql.postgresql_query:
db: openproject
login_user: postgres
query: "SELECT id, name FROM ldap_auth_sources"
register: ldap_entries
when: enable_debug | bool
- name: "Debug LDAP entries"
debug:
var: ldap_entries
when: enable_debug | bool

View File

@ -44,3 +44,21 @@
- name: "copy docker-compose.yml and env file" - name: "copy docker-compose.yml and env file"
include_tasks: copy-docker-compose-and-env.yml include_tasks: copy-docker-compose-and-env.yml
- name: flush docker service
meta: flush_handlers
- name: "Set OpenProject settings via rails"
vars:
rails_env: "RAILS_ENV=production"
rails_cmd: "bundle exec rails runner"
docker_container:
name: openproject-web
command: >
bash -c "cd /app &&
{{ rails_env }} {{ rails_cmd }} 'Setting[:{{ item.key }}] = {{ item.value | to_json }}'"
loop: "{{ openproject_settings | dict2items }}"
- name: Setup LDAP
include_tasks: ldap.yml
when: applications[application_id].ldap.enabled | bool

View File

@ -0,0 +1,17 @@
openproject_ldap:
name: "{{ primary_domain }}" # Display name for the LDAP connection in OpenProject
host: "{{ ldap.server.domain }}" # LDAP server address
port: "{{ ldap.server.port }}" # LDAP server port (typically 389 or 636)
account: "{{ ldap.dn.administrator }}" # Bind DN (used for authentication)
account_password: "{{ ldap.bind_credential }}" # Bind password
base_dn: "{{ ldap.dn.users }}" # Base DN for user search
attr_login: "{{ ldap.attributes.user_id | default('uid') }}" # LDAP attribute used for login
attr_firstname: "givenName" # LDAP attribute for first name
attr_lastname: "sn" # LDAP attribute for last name
attr_mail: "mail" # LDAP attribute for email
attr_admin: "" # Optional: LDAP attribute for admin group (leave empty if unused)
onthefly_register: true # Automatically create users on first login
tls_mode: 0 # 0 = No TLS, 1 = TLS, 2 = STARTTLS
verify_peer: false # Whether to verify the SSL certificate
filter_string: "" # Optional: Custom filter for users (e.g., "(objectClass=person)")
tls_certificate_string: "" # Optional: Client certificate string for TLS (usually left empty)

View File

@ -0,0 +1,7 @@
openproject_settings:
email_delivery_method: "smtp"
smtp_address: "{{ system_email.host }}"
smtp_domain: "{{ system_email.domain }}"
smtp_user_name: "{{ system_email.username }}"
smtp_password: "{{ system_email.password }}"
smtp_ssl: false

View File

@ -1,7 +1,7 @@
# Configuration @see https://hub.docker.com/_/phpmyadmin # Configuration @see https://hub.docker.com/_/phpmyadmin
PMA_HOST= central-mariadb PMA_HOST= central-mariadb
{% if applications.[application_id].autologin | bool %} {% if applications[application_id].autologin | bool %}
PMA_USER= root PMA_USER= root
PMA_PASSWORD= "{{central_mariadb_root_password}}" PMA_PASSWORD= "{{central_mariadb_root_password}}"
{% endif %} {% endif %}

View File

@ -0,0 +1,15 @@
# Development
## Build front container
```bash
docker compose up -d --force-recreate taiga-front
```
## Debug
Verify front configuration:
```bash
docker compose exec -it taiga-front cat /usr/share/nginx/html/conf.json
```

View File

@ -34,7 +34,7 @@ By using this role, teams can set up Taiga in minutes on Arch Linux systems —
## Features ## Features
- 🐳 **Docker-Based Deployment:** Easy containerized setup of backend, frontend, async workers, and events service. - 🐳 **Docker-Based Deployment:** Easy containerized setup of backend, frontend, async workers, and events service.
- 🛡️ **OIDC Support:** Seamless login integration with providers like Keycloak when `applications[application_id].oidc.enabled` is `true`. - 🔐 **OIDC (Single Sign-On):** Supported via [taiga-contrib-openid-auth (robrotheram)](https://github.com/robrotheram/taiga-contrib-openid-auth)
- 📨 **Email Backend:** Supports SMTP and console backends for development. - 📨 **Email Backend:** Supports SMTP and console backends for development.
- 🔁 **Async & Realtime Events:** Includes RabbitMQ and support for Taigas event system. - 🔁 **Async & Realtime Events:** Includes RabbitMQ and support for Taigas event system.
- 🌐 **Reverse Proxy Ready:** Integrates with Nginx using the `nginx-domain-setup` role. - 🌐 **Reverse Proxy Ready:** Integrates with Nginx using the `nginx-domain-setup` role.

View File

@ -47,8 +47,8 @@ services:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
taiga: taiga:
# volumes: # volumes:
# - ./conf.json:/usr/share/nginx/html/conf.json # - {{ taiga_frontend_conf_path }}:/usr/share/nginx/html/conf.json:ro
taiga-events: taiga-events:
image: taigaio/taiga-events:latest image: taigaio/taiga-events:latest

View File

@ -50,13 +50,13 @@ ENABLE_TELEMETRY = True
{% if applications[application_id].oidc.enabled %} {% if applications[application_id].oidc.enabled %}
# OICD # OICD
# @See https://github.com/robrotheram/taiga-contrib-openid-auth # @See https://github.com/robrotheram/taiga-contrib-openid-auth
ENABLE_OPENID="True" ENABLE_OPENID=True
OPENID_URL="{{oidc.client.authorize_url}}" OPENID_URL="{{oidc.client.authorize_url}}"
OPENID_USER_URL="{{oidc.client.user_info_url}}" OPENID_USER_URL="{{oidc.client.user_info_url}}"
OPENID_TOKEN_URL="{{oidc.client.token_url}}" OPENID_TOKEN_URL="{{oidc.client.token_url}}"
OPENID_CLIENT_ID="{{oidc.client.id}}" OPENID_CLIENT_ID="{{oidc.client.id}}"
OPENID_CLIENT_SECRET="{{oidc.client.secret}}" OPENID_CLIENT_SECRET="{{oidc.client.secret}}"
OPENID_NAME="SSO" OPENID_NAME="{{oidc.button_text}}"
# Default Values # Default Values
# #
# OPENID_ID_FIELD="sub" # OPENID_ID_FIELD="sub"

View File

@ -5,4 +5,5 @@ docker_repository_address: "https://github.com/taigaio/taiga-docker"
email_backend: "smtp" ## use an SMTP server or display the emails in the console (either "smtp" or "console") email_backend: "smtp" ## use an SMTP server or display the emails in the console (either "smtp" or "console")
docker_compose_init: "{{docker_compose.directories.instance}}docker-compose-inits.yml.j2" docker_compose_init: "{{docker_compose.directories.instance}}docker-compose-inits.yml.j2"
taiga_image_backend: "{{ 'robrotheram/taiga-back-openid' if applications[application_id].oidc.enabled else 'taigaio/taiga-back' }}" taiga_image_backend: "{{ 'robrotheram/taiga-back-openid' if applications[application_id].oidc.enabled else 'taigaio/taiga-back' }}"
taiga_image_frontend: "{{ 'robrotheram/taiga-front-openid' if applications[application_id].oidc.enabled else 'taigaio/taiga-front' }}" taiga_image_frontend: "{{ 'robrotheram/taiga-front-openid' if applications[application_id].oidc.enabled else 'taigaio/taiga-front' }}"
taiga_frontend_conf_path: "{{docker_compose.directories.config}}conf.json"