diff --git a/airflow/config_templates/config.yml b/airflow/config_templates/config.yml
index 1b52af6690735..00a69eb67bf75 100644
--- a/airflow/config_templates/config.yml
+++ b/airflow/config_templates/config.yml
@@ -1303,6 +1303,13 @@
type: string
example: ~
default:
+ - name: instance_name_has_markup
+ description: |
+ Whether the custom page title for the DAGs overview page contains any Markup language
+ version_added: 2.3.0
+ type: boolean
+ example: ~
+ default: "False"
- name: auto_refresh_interval
description: |
How frequently, in seconds, the DAG data will auto-refresh in graph or tree view
diff --git a/airflow/config_templates/default_airflow.cfg b/airflow/config_templates/default_airflow.cfg
index c09532aa600a1..031ff60b16548 100644
--- a/airflow/config_templates/default_airflow.cfg
+++ b/airflow/config_templates/default_airflow.cfg
@@ -655,6 +655,9 @@ session_lifetime_minutes = 43200
# Sets a custom page title for the DAGs overview page and site title for all pages
# instance_name =
+# Whether the custom page title for the DAGs overview page contains any Markup language
+instance_name_has_markup = False
+
# How frequently, in seconds, the DAG data will auto-refresh in graph or tree view
# when auto-refresh is turned on
auto_refresh_interval = 3
diff --git a/airflow/www/views.py b/airflow/www/views.py
index 5d8dbebe5c3f3..fa7f676c4a692 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -770,6 +770,9 @@ def index(self):
state_color_mapping["null"] = state_color_mapping.pop(None)
page_title = conf.get(section="webserver", key="instance_name", fallback="DAGs")
+ page_title_has_markup = conf.getboolean(
+ section="webserver", key="instance_name_has_markup", fallback=False
+ )
dashboard_alerts = [
fm for fm in settings.DASHBOARD_UIALERTS if fm.should_show(current_app.appbuilder.sm)
@@ -815,7 +818,7 @@ def _iter_parsed_moved_data_table_names():
migration_moved_data_alerts=sorted(set(_iter_parsed_moved_data_table_names())),
current_page=current_page,
search_query=arg_search_query if arg_search_query else '',
- page_title=page_title,
+ page_title=Markup(page_title) if page_title_has_markup else page_title,
page_size=dags_per_page,
num_of_pages=num_of_pages,
num_dag_from=min(start + 1, num_of_all_dags),
diff --git a/docs/apache-airflow/howto/customize-ui.rst b/docs/apache-airflow/howto/customize-ui.rst
index 179c223417119..f11a874146cfe 100644
--- a/docs/apache-airflow/howto/customize-ui.rst
+++ b/docs/apache-airflow/howto/customize-ui.rst
@@ -84,7 +84,9 @@ Customizing DAG UI Header and Airflow Page Titles
Airflow now allows you to customize the DAG home page header and page title. This will help
distinguish between various installations of Airflow or simply amend the page text.
-Note: the custom title will be applied to both the page header and the page title.
+.. note::
+
+ The custom title will be applied to both the page header and the page title.
To make this change, simply:
@@ -117,6 +119,10 @@ After
.. image:: ../img/change-site-title/example_instance_name_configuration.png
+.. note::
+
+ From version 2.3.0 you can include markup in ``instance_name`` variable for further customization. To enable, set ``instance_name_has_markup`` under the ``[webserver]`` section inside ``airflow.cfg`` to ``True``.
+
Add custom alert messages on the dashboard
------------------------------------------
diff --git a/tests/www/views/test_views_base.py b/tests/www/views/test_views_base.py
index f3664b4f09f54..00eb7d3f93426 100644
--- a/tests/www/views/test_views_base.py
+++ b/tests/www/views/test_views_base.py
@@ -390,3 +390,14 @@ def test_page_instance_name_xss_prevention(admin_client):
escaped_xss_string = "<script>alert('Give me your credit card number')</script>"
check_content_in_response(escaped_xss_string, resp)
check_content_not_in_response(xss_string, resp)
+
+
+@conf_vars(
+ {
+ ("webserver", "instance_name"): "Bold Site Title Test",
+ ("webserver", "instance_name_has_markup"): "True",
+ }
+)
+def test_page_instance_name_with_markup(admin_client):
+ resp = admin_client.get('home', follow_redirects=True)
+ check_content_in_response('Bold Site Title Test', resp)