Tutor local launch after install/enabling plugin

Why is it necessary to run tutor local launch after installing and enabling a plugin?

I am automating tutor deployments from my pipeline and noticed in the browser that I was missing environment variable definitions required by plugins (tutor-mfe).

I basically only ran tutor local launch once with the non-interactive flag in my pipeline then built up the tutor instance declaratively with a series of commands: adding config, plugins, enabling plugins etc. Then performed a tutor local reboot --detach but it looks like I should really do a tutor local launch (time consuming). This makes it less desirable to run automatically every time in my pipeline.

I’m assuming tutor local launch retrieves any required configurations from the installed plugins. Not sure why the plugin command wouldn’t do this.

UPDATED

As I expected running tutor local launch a second time doesn’t work. It broke my working tutor installation.

WARNINGS:
course_metadata.Course.collaborators: (fields.W340) null has no effect on ManyToManyField.
course_metadata.Degree.specializations: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.courses: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.programs: (fields.W340) null has no effect on ManyToManyField.
taxonomy.JobPostings.job: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
	HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
taxonomy.SkillsQuiz.skills: (fields.W340) null has no effect on ManyToManyField.
2024-02-05 21:59:55,637 INFO 22 [course_discovery.apps.core.management.commands.install_es_indexes] /openedx/discovery/course_discovery/apps/core/management/commands/install_es_indexes.py:18 - Attempting to establish initial connection to Elasticsearch host [http://elasticsearch:9200/]...
/openedx/venv/lib/python3.8/site-packages/elasticsearch/connection/base.py:208: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.
  warnings.warn(message, category=ElasticsearchWarning)
2024-02-05 21:59:56,223 INFO 22 [course_discovery.apps.core.management.commands.install_es_indexes] /openedx/discovery/course_discovery/apps/core/management/commands/install_es_indexes.py:21 - ...success!
2024-02-05 21:59:56,224 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:37 - Making sure alias [course_run] exists...
2024-02-05 21:59:58,323 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:46 - ...alias updated.
2024-02-05 21:59:58,324 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:37 - Making sure alias [learner_pathway] exists...
2024-02-05 21:59:58,706 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:46 - ...alias updated.
2024-02-05 21:59:58,706 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:37 - Making sure alias [course] exists...
2024-02-05 21:59:59,032 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:46 - ...alias updated.
2024-02-05 21:59:59,032 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:37 - Making sure alias [program] exists...
2024-02-05 21:59:59,329 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:46 - ...alias updated.
2024-02-05 21:59:59,329 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:37 - Making sure alias [person] exists...
2024-02-05 21:59:59,646 INFO 22 [course_discovery.apps.core.utils] /openedx/discovery/course_discovery/apps/core/utils.py:46 - ...alias updated.
System check identified some issues:

WARNINGS:
course_metadata.Course.collaborators: (fields.W340) null has no effect on ManyToManyField.
course_metadata.Degree.specializations: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.courses: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.programs: (fields.W340) null has no effect on ManyToManyField.
taxonomy.JobPostings.job: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
	HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
taxonomy.SkillsQuiz.skills: (fields.W340) null has no effect on ManyToManyField.
2024-02-05 22:00:03,179 INFO 36 [course_discovery.apps.core.management.commands.create_or_update_partner] /openedx/discovery/course_discovery/apps/core/management/commands/create_or_update_partner.py:134 - Partner created with code dev
System check identified some issues:

WARNINGS:
course_metadata.Course.collaborators: (fields.W340) null has no effect on ManyToManyField.
course_metadata.Degree.specializations: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.courses: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.programs: (fields.W340) null has no effect on ManyToManyField.
taxonomy.JobPostings.job: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
	HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
taxonomy.SkillsQuiz.skills: (fields.W340) null has no effect on ManyToManyField.
2024-02-05 22:00:06,349 INFO 50 [course_discovery.apps.core.management.commands.create_or_update_partner] /openedx/discovery/course_discovery/apps/core/management/commands/create_or_update_partner.py:134 - Partner created with code openedx
System check identified some issues:

WARNINGS:
course_metadata.Course.collaborators: (fields.W340) null has no effect on ManyToManyField.
course_metadata.Degree.specializations: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.courses: (fields.W340) null has no effect on ManyToManyField.
course_metadata.SearchDefaultResultsConfiguration.programs: (fields.W340) null has no effect on ManyToManyField.
taxonomy.JobPostings.job: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
	HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
taxonomy.SkillsQuiz.skills: (fields.W340) null has no effect on ManyToManyField.
2024-02-05 22:00:09,401 INFO 64 [course_discovery.apps.course_metadata.management.commands.refresh_course_metadata] /openedx/discovery/course_discovery/apps/course_metadata/management/commands/refresh_course_metadata.py:134 - Command is not using threads to write data.
2024-02-05 22:00:09,403 INFO 64 [course_discovery.apps.course_metadata.management.commands.refresh_course_metadata] /openedx/discovery/course_discovery/apps/course_metadata/management/commands/refresh_course_metadata.py:178 - Executing Loader CoursesApiDataLoader, url: http://best-edx.charite.de/api/courses/v1/
2024-02-05 22:00:09,510 INFO 64 [course_discovery.apps.course_metadata.management.commands.refresh_course_metadata] /openedx/venv/lib/python3.8/site-packages/backoff/_common.py:105 - Backing off run_loader(...) for 0.2s (requests.exceptions.HTTPError: 503 Server Error: Service Unavailable for url: http://lms:8000/oauth2/access_token)
2024-02-05 22:00:09,753 INFO 64 [course_discovery.apps.course_metadata.management.commands.refresh_course_metadata] /openedx/venv/lib/python3.8/site-packages/backoff/_common.py:105 - Backing off run_loader(...) for 5.7s (requests.exceptions.HTTPError: 503 Server Error: Service Unavailable for url: http://lms:8000/oauth2/access_token)
2024-02-05 22:00:15,428 ERROR 64 [course_discovery.apps.course_metadata.management.commands.refresh_course_metadata] /openedx/venv/lib/python3.8/site-packages/backoff/_common.py:120 - Giving up run_loader(...) after 3 tries (requests.exceptions.HTTPError: 503 Server Error: Service Unavailable for url: http://lms:8000/oauth2/access_token)
2024-02-05 22:00:15,428 ERROR 64 [course_discovery.apps.course_metadata.management.commands.refresh_course_metadata] /openedx/discovery/course_discovery/apps/course_metadata/management/commands/refresh_course_metadata.py:40 - CoursesApiDataLoader failed!
Traceback (most recent call last):
  File "/openedx/discovery/course_discovery/apps/course_metadata/management/commands/refresh_course_metadata.py", line 37, in execute_loader
    run_loader()
  File "/openedx/venv/lib/python3.8/site-packages/backoff/_sync.py", line 105, in retry
    ret = target(*args, **kwargs)
  File "/openedx/discovery/course_discovery/apps/course_metadata/management/commands/refresh_course_metadata.py", line 34, in run_loader
    return loader_class(*loader_args).ingest()
  File "/openedx/discovery/course_discovery/apps/course_metadata/data_loaders/api.py", line 50, in __init__
    super().__init__(partner, api_url, max_workers, is_threadsafe, enable_api)
  File "/openedx/discovery/course_discovery/apps/course_metadata/data_loaders/__init__.py", line 36, in __init__
    self.username = self.get_username_from_client(self.api_client)
  File "/openedx/discovery/course_discovery/apps/course_metadata/data_loaders/__init__.py", line 46, in get_username_from_client
    token = client.get_jwt_access_token()
  File "/openedx/venv/lib/python3.8/site-packages/edx_rest_api_client/client.py", line 283, in get_jwt_access_token
    self._ensure_authentication()
  File "/openedx/venv/lib/python3.8/site-packages/edx_rest_api_client/client.py", line 262, in _ensure_authentication
    oauth_access_token_response = get_and_cache_oauth_access_token(
  File "/openedx/venv/lib/python3.8/site-packages/edx_rest_api_client/client.py", line 177, in get_and_cache_oauth_access_token
    oauth_access_token_response = get_oauth_access_token(
  File "/openedx/venv/lib/python3.8/site-packages/edx_rest_api_client/client.py", line 127, in get_oauth_access_token
    response.raise_for_status()  # Raise an exception for bad status codes.
  File "/openedx/venv/lib/python3.8/site-packages/requests/models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 503 Server Error: Service Unavailable for url: http://lms:8000/oauth2/access_token
CommandError: One or more of the data loaders above failed.
Error: Command failed with status 1: docker compose -f /home/gitlab/interagent-tutor/tutor/env/local/docker-compose.yml -f /home/gitlab/interagent-tutor/tutor/env/local/docker-compose.prod.yml --project-name tutor_local -f /home/gitlab/interagent-tutor/tutor/env/local/docker-compose.jobs.yml run --rm discovery-job sh -e -c make migrate

# Development partners
./manage.py create_or_update_partner  \
  --site-id 1 \
  --site-domain best-edx-discovery.charite.de:8381 \
  --code dev \
  --name "Open edX - development" \
  --lms-url="http://lms:8000" \
  --studio-url="http://cms:8000" \
  --courses-api-url "http://best-edx.charite.de:8000/api/courses/v1/" \
  --organizations-api-url "http://best-edx.charite.de:8000/api/organizations/v1/"

# Production partner
./manage.py create_or_update_partner  \
  --site-id 2 \
  --site-domain best-edx-discovery.charite.de \
  --code openedx \
  --name "Open edX" \
  --lms-url="http://lms:8000" \
  --studio-url="http://cms:8000" \
  --courses-api-url "http://best-edx.charite.de/api/courses/v1/" \
  --organizations-api-url "http://best-edx.charite.de/api/organizations/v1/"

./manage.py refresh_course_metadata --partner_code=$DEFAULT_PARTNER_CODE
./manage.py update_index --disable-change-limit

Hi. To answer the question about using tutor local launch after adding a plugin, the launch command internally does the update of configuration and environment. This is not done by reboot. When a plugin is added, the launch is needed to ensure the hooks added by the plugin (in actions and filters) are looped into to tutor core.
https://docs.tutor.edly.io/plugins/intro.html#introduction

Also, looking at the traceback, it seems your LMS service is not working as expected. Typically, if you are not using any custom edx-platform and are only adding plugins/updating configs, the launch should not cause any issues. What is printed in LMS logs (tutor local logs --tail=500 lms)?

lms-url=“http://lms:8000
studio-url=“http://cms:8000

503 Server Error: Service Unavailable for url: http://lms:8000/oauth2/access_token)

it looks to me like your URL’s are not configured correctly?
As a side note you should avoid using “edX” in your site name/url as per the Trademarks agreement:

Regarding the domain name, this is just a development environment and it’s not publicly hosted.

Currently, we only made a few changes to the default setup.

We followed the tutor documentation to run open edx behind a web proxy.
https://docs.tutor.edly.io/tutorials/proxy.html

Our setup uses Traefik, which forwards traffic to Caddy and it’s working correctly. But as soon as I login as a user (with the MFE plugin enabled) I get redirected to a broken page. MFE creates a new login form. When we disable MFE, logging in through the default login form works as expected with no redirect issues.

It is obvious now that this is due to our changes to the domain name conventions.

It looks fine.

utor_local-lms-1 | 2024-02-14 19:01:05,876 WARNING 7 [audit] [user None] [ip 192.168.65.1] login.py:265 - Login failed - password for user.id: 4 is invalid
tutor_local-lms-1 | 2024-02-14 19:01:05,876 ERROR 7 [edx.student] [user None] [ip 192.168.65.1] login.py:650 - {‘success’: False, ‘value’: Markup(‘Email or password is incorrect.’), ‘error_code’: ‘incorrect-email-or-password’, ‘context’: {‘failure_count’: 1}}
tutor_local-lms-1 | Traceback (most recent call last):
tutor_local-lms-1 | File “/openedx/edx-platform/./openedx/core/djangoapps/user_authn/views/login.py”, line 591, in login_user
tutor_local-lms-1 | _handle_failed_authentication(user, possibly_authenticated_user)
tutor_local-lms-1 | File “/openedx/edx-platform/./openedx/core/djangoapps/user_authn/views/login.py”, line 297, in _handle_failed_authentication
tutor_local-lms-1 | raise AuthFailedError(
tutor_local-lms-1 | openedx.core.djangoapps.user_authn.exceptions.AuthFailedError
tutor_local-lms-1 | [pid: 7|app: 0|req: 7/30] 172.22.0.5 () {68 vars in 1579 bytes} [Wed Feb 14 19:01:05 2024] POST /api/user/v2/account/login_session/ => generated 182 bytes in 219 msecs (HTTP/1.1 400) 10 headers in 794 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:01:09,905 INFO 25 [tracking] [user None] [ip 192.168.65.1] logger.py:41 - {“name”: “/api/user/v2/account/login_session/”, “context”: {“user_id”: null, “path”: “/api/user/v2/account/login_session/”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “”, “session”: “6d91d93a489349ad37d3c69ba1ac79aa”, “ip”: “192.168.65.1”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {}, "POST": {"email_or_username": ["ivorscott"], "next": ["/"], "password": "********"}}”, “time”: “2024-02-14T19:01:09.905532+00:00”, “event_type”: “/api/user/v2/account/login_session/”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | 2024-02-14 19:01:10,022 INFO 25 [tracking] [user 4] [ip 192.168.65.1] logger.py:41 - {“name”: “edx.user.login”, “context”: {“user_id”: null, “path”: “/api/user/v2/account/login_session/”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “”, “session”: “6d91d93a489349ad37d3c69ba1ac79aa”, “ip”: “192.168.65.1”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: {“user_id”: 4, “event_type”: “login”}, “time”: “2024-02-14T19:01:10.022270+00:00”, “event_type”: “edx.user.login”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | 2024-02-14 19:01:10,022 INFO 25 [audit] [user 4] [ip 192.168.65.1] user.py:1245 - Login success - user.id: 4
tutor_local-lms-1 | 2024-02-14 19:01:10,032 INFO 25 [openedx_events.tooling] [user 4] [ip 192.168.65.1] tooling.py:168 - Responses of the Open edX Event <org.openedx.learning.auth.session.login.completed.v1>:
tutor_local-lms-1 |
tutor_local-lms-1 | [pid: 25|app: 0|req: 6/31] 172.22.0.5 () {68 vars in 1579 bytes} [Wed Feb 14 19:01:09 2024] POST /api/user/v2/account/login_session/ => generated 74 bytes in 216 msecs (HTTP/1.1 200) 15 headers in 3275 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:01:10,115 INFO 7 [tracking] [user 4] [ip 192.168.65.1] logger.py:41 - {“name”: “/”, “context”: {“user_id”: 4, “path”: “/”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “ivorscott”, “session”: “720a2c1e77dd42bca00f17950f08b3e2”, “ip”: “192.168.65.1”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {}, "POST": {}}”, “time”: “2024-02-14T19:01:10.115515+00:00”, “event_type”: “/”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 7|app: 0|req: 8/32] 172.22.0.5 () {64 vars in 3365 bytes} [Wed Feb 14 19:01:10 2024] GET / => generated 0 bytes in 11 msecs (HTTP/1.1 302) 8 headers in 471 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:01:10,129 INFO 25 [tracking] [user 4] [ip 192.168.65.1] logger.py:41 - {“name”: “/dashboard”, “context”: {“user_id”: 4, “path”: “/dashboard”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “ivorscott”, “session”: “720a2c1e77dd42bca00f17950f08b3e2”, “ip”: “192.168.65.1”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {}, "POST": {}}”, “time”: “2024-02-14T19:01:10.129334+00:00”, “event_type”: “/dashboard”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 25|app: 0|req: 7/33] 172.22.0.5 () {64 vars in 3383 bytes} [Wed Feb 14 19:01:10 2024] GET /dashboard => generated 0 bytes in 14 msecs (HTTP/1.1 302) 8 headers in 515 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:01:10,273 INFO 7 [tracking] [user 4] [ip 192.168.65.1] logger.py:41 - {“name”: “/”, “context”: {“user_id”: 4, “path”: “/”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “ivorscott”, “session”: “720a2c1e77dd42bca00f17950f08b3e2”, “ip”: “192.168.65.1”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {}, "POST": {}}”, “time”: “2024-02-14T19:01:10.273011+00:00”, “event_type”: “/”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 7|app: 0|req: 9/34] 172.22.0.5 () {62 vars in 3340 bytes} [Wed Feb 14 19:01:10 2024] GET / => generated 0 bytes in 45 msecs (HTTP/1.1 302) 8 headers in 471 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:01:10,439 INFO 25 [tracking] [user None] [ip 172.22.0.5] logger.py:41 - {“name”: “/api/mfe_config/v1”, “context”: {“user_id”: null, “path”: “/api/mfe_config/v1”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “”, “session”: “”, “ip”: “172.22.0.5”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/learner-dashboard/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {"mfe": ["learner-dashboard"]}, "POST": {}}”, “time”: “2024-02-14T19:01:10.439766+00:00”, “event_type”: “/api/mfe_config/v1”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 25|app: 0|req: 8/35] 172.22.0.10 () {58 vars in 1122 bytes} [Wed Feb 14 19:01:10 2024] GET /api/mfe_config/v1?mfe=learner-dashboard => generated 1587 bytes in 9 msecs (HTTP/1.1 200) 8 headers in 256 bytes (1 switches on core 0)
tutor_local-lms-1 | [pid: 7|app: 0|req: 10/36] 172.22.0.5 () {64 vars in 3292 bytes} [Wed Feb 14 19:01:10 2024] POST /login_refresh => generated 212 bytes in 54 msecs (HTTP/1.1 200) 10 headers in 1737 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:02:06,907 INFO 25 [tracking] [user None] [ip 172.22.0.5] logger.py:41 - {“name”: “/api/mfe_config/v1”, “context”: {“user_id”: null, “path”: “/api/mfe_config/v1”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “”, “session”: “”, “ip”: “172.22.0.5”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/authn/login?next=%2F”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {"mfe": ["authn"]}, "POST": {}}”, “time”: “2024-02-14T19:02:06.907284+00:00”, “event_type”: “/api/mfe_config/v1”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 25|app: 0|req: 9/37] 172.22.0.10 () {58 vars in 1100 bytes} [Wed Feb 14 19:02:06 2024] GET /api/mfe_config/v1?mfe=authn => generated 1587 bytes in 21 msecs (HTTP/1.1 200) 8 headers in 256 bytes (1 switches on core 0)
tutor_local-lms-1 | [pid: 7|app: 0|req: 11/38] 172.22.0.5 () {64 vars in 3292 bytes} [Wed Feb 14 19:02:06 2024] POST /login_refresh => generated 213 bytes in 63 msecs (HTTP/1.1 200) 10 headers in 1737 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-14 19:02:08,354 INFO 25 [tracking] [user None] [ip 172.22.0.5] logger.py:41 - {“name”: “/api/mfe_config/v1”, “context”: {“user_id”: null, “path”: “/api/mfe_config/v1”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “”, “session”: “”, “ip”: “172.22.0.5”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/learner-dashboard/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {"mfe": ["learner-dashboard"]}, "POST": {}}”, “time”: “2024-02-14T19:02:08.353987+00:00”, “event_type”: “/api/mfe_config/v1”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 25|app: 0|req: 10/39] 172.22.0.10 () {58 vars in 1122 bytes} [Wed Feb 14 19:02:08 2024] GET /api/mfe_config/v1?mfe=learner-dashboard => generated 1587 bytes in 13 msecs (HTTP/1.1 200) 8 headers in 256 bytes (1 switches on core 0)
tutor_local-lms-1 | [pid: 7|app: 0|req: 12/40] 172.22.0.5 () {64 vars in 3292 bytes} [Wed Feb 14 19:02:08 2024] POST /login_refresh => generated 213 bytes in 46 msecs (HTTP/1.1 200) 10 headers in 1737 bytes (1 switches on core 0)
tutor_local-lms-1 | 2024-02-15 08:45:29,134 INFO 25 [tracking] [user None] [ip 172.22.0.5] logger.py:41 - {“name”: “/api/mfe_config/v1”, “context”: {“user_id”: null, “path”: “/api/mfe_config/v1”, “course_id”: “”, “org_id”: “”, “enterprise_uuid”: “”}, “username”: “”, “session”: “”, “ip”: “172.22.0.5”, “agent”: “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”, “host”: “best-edx.charite.local”, “referer”: “https://best-edx-apps.charite.local/learner-dashboard/”, “accept_language”: “en-US,en;q=0.9,de;q=0.8,cs;q=0.7,sk;q=0.6”, “event”: “{"GET": {"mfe": ["learner-dashboard"]}, "POST": {}}”, “time”: “2024-02-15T08:45:29.134122+00:00”, “event_type”: “/api/mfe_config/v1”, “event_source”: “server”, “page”: null}
tutor_local-lms-1 | [pid: 25|app: 0|req: 11/41] 172.22.0.10 () {58 vars in 1122 bytes} [Thu Feb 15 08:45:29 2024] GET /api/mfe_config/v1?mfe=learner-dashboard => generated 1587 bytes in 87 msecs (HTTP/1.1 200) 8 headers in 256 bytes (1 switches on core 0)
tutor_local-lms-1 | [pid: 7|app: 0|req: 13/42] 172.22.0.5 () {64 vars in 2193 bytes} [Thu Feb 15 08:45:29 2024] POST /login_refresh => generated 213 bytes in 99 msecs (HTTP/1.1 200) 10 headers in 1737 bytes (1 switches on core 0)

We are still searching for a solution while using the mfe plugin. I have confirmed the issue is with the urls we use. Everything works as expected when we don’t use a subdomain for the LMS_HOST.

For example:

LMS_HOST=charite.local
CMS_HOST=studio.charite.local
MFE_HOST=apps.charite.local
ECOMMERCE_HOST=ecommerce.charite.local
DISCOVERY_HOST=discovery.charite.local
PREVIEW_LMS_HOST=preview.charite.local

Unfortunately, this is not an option for us. We do plan to deploy a public version of open edx eventually (without edx in the domain name :slight_smile: ) We already have a website at “charite.de” so LMS_HOST needs to exist as a subdomain.

MFE seems to required additional configuration to use the urls we have:

LMS_HOST=best-edx.charite.local
CMS_HOST=best-edx-studio.charite.local
MFE_HOST=best-edx-apps.charite.local
ECOMMERCE_HOST=best-edx-ecommerce.charite.local
DISCOVERY_HOST=best-edx-discovery.charite.local
PREVIEW_LMS_HOST=best-edx-preview.charite.local

This issue is a duplicate from:

I simply created a new environment variable: BASE_DOMAIN=charite.local and a plugin to patch settings.

from tutor import hooks

hooks.Filters.ENV_PATCHES.add_items(
    [    
        (
            "lms-env",
            """
"SESSION_COOKIE_DOMAIN": ".{{ BASE_DOMAIN }}"
"""
        ),
        (
            "cms-env",
            """
"SESSION_COOKIE_DOMAIN": ".{{ BASE_DOMAIN }}"
"""
        ),
        (
            "openedx-cms-production-settings",
            """
SESSION_COOKIE_DOMAIN: ".{{ BASE_DOMAIN }}"
"""
        ),
        (
            "openedx-lms-production-settings",
            """
SESSION_COOKIE_DOMAIN: ".{{ BASE_DOMAIN }}"
"""
        )
    ]
)

Patches append a new variable to the files, it doesn’t replace the old values which creates a duplicate. This seems unintuitive but the last key is always read so it works.