Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docker/build/edxapp/lms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ EDX_PLATFORM_REVISION: master
ELASTIC_SEARCH_CONFIG:
- host: edx.devstack.elasticsearch710
port: 9200
MEILI_SEARCH_CONFIG:
- host: edx.devstack.meilisearch184
port: 7700
use_ssl: false
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MEILI_SEARCH_CONFIG is defined as a list with a single dictionary entry (similar to ELASTIC_SEARCH_CONFIG), but it includes a use_ssl property at line 246 that belongs to ELASTIC_SEARCH_CONFIG, not MEILI_SEARCH_CONFIG. The indentation shows use_ssl: false is under ELASTIC_SEARCH_CONFIG. However, based on the structure, MEILI_SEARCH_CONFIG should have its own properties including use_ssl and api_key. Please verify the YAML structure is correctly indented.

Suggested change
use_ssl: false
use_ssl: false
api_key: ''

Copilot uses AI. Check for mistakes.
EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST: localhost
Expand Down
3 changes: 3 additions & 0 deletions docker/build/edxapp/studio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ EDX_PLATFORM_REVISION: master
ELASTIC_SEARCH_CONFIG:
- host: edx.devstack.elasticsearch710
port: 9200
MEILI_SEARCH_CONFIG:
- host: edx.devstack.meilisearch184
port: 7700
use_ssl: false
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MEILI_SEARCH_CONFIG is defined as a list with a single dictionary entry (similar to ELASTIC_SEARCH_CONFIG), but it includes a use_ssl property at line 223 that belongs to ELASTIC_SEARCH_CONFIG, not MEILI_SEARCH_CONFIG. The indentation shows use_ssl: false is under ELASTIC_SEARCH_CONFIG. However, based on the structure, MEILI_SEARCH_CONFIG should have its own properties including use_ssl and api_key. Please verify the YAML structure is correctly indented.

Suggested change
use_ssl: false

Copilot uses AI. Check for mistakes.
EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST: localhost
Expand Down
13 changes: 13 additions & 0 deletions docker/build/meilisearch-devstack/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# docker build -f docker/build/meilisearch-devstack/Dockerfile . -t edxops/meilisearch:devstack

FROM getmeili/meilisearch:v1.11.0
Comment on lines +1 to +3
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment references Meilisearch 1.11.0 but the Dockerfile uses the official Meilisearch image getmeili/meilisearch:v1.11.0. While this is correct, it would be better to use a variable for the version to ensure consistency across the codebase, similar to how meilisearch_version is used in other files.

Suggested change
# docker build -f docker/build/meilisearch-devstack/Dockerfile . -t edxops/meilisearch:devstack
FROM getmeili/meilisearch:v1.11.0
# docker build -f docker/build/meilisearch-devstack/Dockerfile . --build-arg MEILISEARCH_VERSION=1.11.0 -t edxops/meilisearch:devstack
ARG MEILISEARCH_VERSION=1.11.0
FROM getmeili/meilisearch:v${MEILISEARCH_VERSION}

Copilot uses AI. Check for mistakes.
LABEL maintainer="edxops"

# Default working directory
WORKDIR /meili_data

# Expose Meilisearch default port
EXPOSE 7700

# Start Meilisearch
CMD ["meilisearch", "--db-path", "/meili_data", "--http-addr", "0.0.0.0:7700"]
14 changes: 14 additions & 0 deletions docker/build/meilisearch/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM edxops/xenial-common:latest
LABEL maintainer="edxops"

# Copy ansible roles/playbooks into container
ADD . /edx/app/edx_ansible/edx_ansible
WORKDIR /edx/app/edx_ansible/edx_ansible/docker/plays

# Run ansible playbook for Meilisearch (you need meilisearch.yml role defined)
RUN /edx/app/edx_ansible/venvs/edx_ansible/bin/ansible-playbook meilisearch.yml -c local \
-i '127.0.0.1,'

WORKDIR /etc/meilisearch
CMD service meilisearch start && sleep 5 && tail -f /edx/var/log/meilisearch/meilisearch.log
EXPOSE 7700 7701
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Dockerfile exposes ports 7700 and 7701, but Meilisearch typically only uses port 7700 for its HTTP API. Port 7701 is not a standard Meilisearch port. If 7701 is intended for a specific purpose, it should be documented; otherwise, it should be removed from the EXPOSE directive.

Suggested change
EXPOSE 7700 7701
EXPOSE 7700

Copilot uses AI. Check for mistakes.
5 changes: 5 additions & 0 deletions docker/plays/meilisearch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- hosts: all
become: True
roles:
- common
- meilisearch
1 change: 1 addition & 0 deletions playbooks/edx_continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- oraclejdk
- elasticsearch
- opensearch
- meilisearch
- forum
- { role: "xqueue", update_users: True }
- edx_ansible
Expand Down
2 changes: 1 addition & 1 deletion playbooks/elasticsearch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@
state: present
wait_timeout: 60
become: False
when: elb_pre_post
when: elb_pre_post
49 changes: 49 additions & 0 deletions playbooks/meilisearch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
- hosts: all
become: true
vars:
# By default take instances in and out of the elb(s) they
# are attached to
# To skip elb operations use "-e elb_pre_post=false"
elb_pre_post: true
# Number of instances to operate on at a time
serial_count: 1
CLUSTER_NAME: "commoncluster"
MEILI_VERSION: "v1.11.0" # change to desired version
MEILI_PORT: 7700
serial: "{{ serial_count }}"
pre_tasks:
- action: ec2_metadata_facts
when: elb_pre_post
- debug:
var: ansible_ec2_instance_id
when: elb_pre_post
- name: Instance De-register
local_action: ec2_elb
args:
instance_id: "{{ ansible_ec2_instance_id }}"
region: us-east-1
state: absent
wait_timeout: 60
become: false
when: elb_pre_post

roles:
- common
- role: aws
when: COMMON_ENABLE_AWS_ROLE
- meilisearch # add the roles for meilisearch

post_tasks:
- debug:
var: ansible_ec2_instance_id
when: elb_pre_post
- name: Register instance in the elb
local_action: ec2_elb
args:
instance_id: "{{ ansible_ec2_instance_id }}"
ec2_elbs: "{{ ec2_elbs }}"
region: us-east-1
state: present
wait_timeout: 60
become: false
when: elb_pre_post
2 changes: 1 addition & 1 deletion playbooks/roles/common/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,4 @@
tags:
- "install"
- "install:configuration"
- "logrotate"
- "logrotate"
2 changes: 1 addition & 1 deletion playbooks/roles/common_vars/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,4 @@ CONFIGURE_JWTS: false
COMMON_RETIREMENT_SERVICE_SETUP: false

# How to log in as "lms" to xqueue.
COMMON_XQUEUE_LMS_PASSWORD: password
COMMON_XQUEUE_LMS_PASSWORD: password
10 changes: 10 additions & 0 deletions playbooks/roles/edxapp/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,15 @@ EDXAPP_ELASTIC_SEARCH_CONFIG:
port: "{{ EDXAPP_SEARCH_PORT }}"
use_ssl: "{{ EDXAPP_SEARCH_USE_SSL }}"

# list of dictionaries of the format
# { 'url': 'http://hostname:port', 'api_key': 'masterKey' }
# https://github.com/meilisearch/meilisearch-python
EDXAPP_MEILI_SEARCH_CONFIG:
- host: "{{ EDXAPP_SEARCH_HOST }}"
port: "{{ EDXAPP_SEARCH_PORT }}"
use_ssl: "{{ EDXAPP_SEARCH_USE_SSL }}"
api_key: "{{ EDXAPP_SEARCH_API_KEY }}"
Comment on lines +177 to +180
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EDXAPP_MEILI_SEARCH_CONFIG defaults reference EDXAPP_SEARCH_HOST, EDXAPP_SEARCH_PORT, EDXAPP_SEARCH_USE_SSL, and EDXAPP_SEARCH_API_KEY, which appear to be reusing the Elasticsearch search variables. This could lead to configuration conflicts if both Elasticsearch and Meilisearch are used. Consider using dedicated variables like EDXAPP_MEILI_SEARCH_HOST, EDXAPP_MEILI_SEARCH_PORT, etc., or clarify if this reuse is intentional.

Copilot uses AI. Check for mistakes.

EDXAPP_SETTINGS: '{{ COMMON_EDXAPP_SETTINGS }}'

EDXAPP_LMS_ENV: 'lms.envs.{{ EDXAPP_SETTINGS }}'
Expand Down Expand Up @@ -1582,6 +1591,7 @@ generic_env_config: &edxapp_generic_env
user: '{{ edxapp_sandbox_user }}'
AFFILIATE_COOKIE_NAME: "{{ EDXAPP_AFFILIATE_COOKIE_NAME }}"
ELASTIC_SEARCH_CONFIG: "{{ EDXAPP_ELASTIC_SEARCH_CONFIG }}"
MEILI_SEARCH_CONFIG: "{{ EDXAPP_MEILI_SEARCH_CONFIG }}"
PLATFORM_TWITTER_ACCOUNT: "{{ EDXAPP_PLATFORM_TWITTER_ACCOUNT }}"
PLATFORM_FACEBOOK_ACCOUNT: "{{ EDXAPP_PLATFORM_FACEBOOK_ACCOUNT }}"
HELP_TOKENS_BOOKS: "{{ EDXAPP_HELP_TOKENS_BOOKS }}"
Expand Down
30 changes: 30 additions & 0 deletions playbooks/roles/meilisearch/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
meilisearch_app_dir: "{{ COMMON_APP_DIR }}/meilisearch"
meilisearch_data_dir: "{{ COMMON_DATA_DIR }}/meilisearch"
meilisearch_log_dir: "{{ COMMON_LOG_DIR }}/meilisearch"
meilisearch_cfg_dir: "{{ COMMON_CFG_DIR }}/meilisearch"

# Meilisearch doesn’t come from apt repo (like Elasticsearch),
# we fetch the binary directly from GitHub releases.
meilisearch_download_url: "https://github.com/meilisearch/meilisearch/releases/download/{{ meilisearch_version }}/meilisearch-linux-amd64"

meilisearch_user: "meilisearch"
meilisearch_group: "meilisearch"

# Defaults for a single server installation.
MEILISEARCH_CLUSTER_MEMBERS: [] # Not typically needed, but kept for parity
MEILISEARCH_ENV: "development"
# Service management
MEILISEARCH_START_TIMEOUT: "300"
# Version of Meilisearch to install
meilisearch_version: "v1.11.0"

# Network and security settings
meilisearch_host: "0.0.0.0"
meilisearch_port: 7700
MEILISEARCH_URL: "http://{{ meilisearch_host }}:{{ meilisearch_port }}"
MEILISEARCH_PUBLIC_URL: "http://{{ meilisearch_host }}:{{ meilisearch_port }}"

# These are placeholders – actual secrets come from sandbox repo
MEILISEARCH_MASTER_KEY: "{{ lookup('env', 'MEILISEARCH_MASTER_KEY') | default('changeme', true) }}"
MEILISEARCH_API_KEY: "{{ lookup('env', 'MEILISEARCH_API_KEY') | default('changeme', true) }}"
3 changes: 3 additions & 0 deletions playbooks/roles/meilisearch/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- common
103 changes: 103 additions & 0 deletions playbooks/roles/meilisearch/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
# meilisearch
#
# Dependencies:
#
# * common
#
# Example play:
#
# This role installs and configures the Meilisearch service.
# It can be used for single-server installs (default).
#

- name: create meilisearch group
group:
name: "{{ meilisearch_group }}"
state: present
tags:
- install
- install:base

- name: create meilisearch user
user:
name: "{{ meilisearch_user }}"
group: "{{ meilisearch_group }}"
shell: /usr/sbin/nologin
system: yes
create_home: no
tags:
- install
- install:base
- name: create directories
file:
path: "{{ item }}"
state: directory
owner: "{{ meilisearch_user }}"
group: "{{ meilisearch_group }}"
mode: 0755
loop:
- "{{ meilisearch_data_dir }}"
- "{{ meilisearch_log_dir }}"
- "{{ meilisearch_cfg_dir }}"
- "{{ meilisearch_app_dir }}"
tags:
- install
- install:base

- name: download meilisearch binary
get_url:
url: "{{ meilisearch_download_url }}"
dest: "{{ meilisearch_app_dir }}/meilisearch-linux-amd64"
mode: '0755'
register: meilisearch_download
tags:
- install
- install:base

- name: rename meilisearch binary to meilisearch
command: mv "{{ meilisearch_app_dir }}/meilisearch-linux-amd64" "{{ meilisearch_app_dir }}/meilisearch"
args:
creates: "{{ meilisearch_app_dir }}/meilisearch"
when: meilisearch_download.changed
tags:
- install
- install:base

- name: drop the meilisearch config (env file)
template:
src: edx/etc/meilisearch/meilisearch.yml.j2
dest: "{{ meilisearch_cfg_dir }}/meilisearch"
mode: 0644
tags:
- install
- install:configuration

- name: drop the meilisearch systemd service config
template:
src: lib/systemd/system/meilisearch.service.j2
dest: "/lib/systemd/system/meilisearch.service"
mode: 0644
tags:
- install
- install:configuration

- name: Ensure meilisearch is enabled and started
service:
name: meilisearch
state: started
enabled: yes
tags:
- manage
- manage:start

- name: Restart meilisearch when binary is updated
service:
name: meilisearch
state: restarted
enabled: yes
when: meilisearch_download.changed
tags:
- manage
- manage:restart
- install
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# {{ ansible_managed }}

# ======================== Meilisearch Configuration =========================
#
# NOTE: Meilisearch comes with safe defaults for most settings.
# Only override what you need for your deployment.
# See official docs:
# https://www.meilisearch.com/docs/learn/configuration/instance_options
#
# This template generates a .env file that Meilisearch will load at startup.
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment mentions this template generates a .env file, but the actual file being created in the tasks is named just meilisearch (without .env extension). Either the comment should be updated to reflect the actual filename, or the destination filename in the tasks should use a .env extension.

Suggested change
# This template generates a .env file that Meilisearch will load at startup.
# This template generates a 'meilisearch' file that Meilisearch will load at startup.

Copilot uses AI. Check for mistakes.
# ----------------------------------------------------------------------------

# ---------------------------------- Paths -----------------------------------
# Path to store Meilisearch data (indexes, snapshots, dumps)
MEILI_DB_PATH={{ meilisearch_data_dir }}

# Path to store Meilisearch logs (stdout/stderr are default if unset)
MEILI_LOG_PATH={{ meilisearch_log_dir }}

# ---------------------------------- Network ---------------------------------
# The IP address Meilisearch binds to (0.0.0.0 for all interfaces)
MEILI_HTTP_ADDR={{ meilisearch_host | default("0.0.0.0") }}

# The port Meilisearch listens on
MEILI_HTTP_PORT={{ meilisearch_port | default("7700") }}
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable MEILI_HTTP_PORT is set here but the systemd service file uses {{ meilisearch_port }} directly in the ExecStart command. This creates an inconsistency - the port should be consistently sourced from either the environment variable or the Ansible variable, not both. Consider using the environment file variable in the service or removing this environment variable declaration.

Suggested change
MEILI_HTTP_PORT={{ meilisearch_port | default("7700") }}

Copilot uses AI. Check for mistakes.

# ---------------------------------- Master Key -------------------------------
# The master key is used to generate API keys. Comment out to disable auth.
# !! Make sure to secure this in production !!
MEILISEARCH_MASTER_KEY={{ MEILISEARCH_MASTER_KEY }}

# ---------------------------------- Snapshots & Dumps ------------------------
# Directory to store snapshots
MEILI_SNAPSHOT_DIR={{ meilisearch_snapshot_dir | default(meilisearch_data_dir + "/snapshots") }}

# Directory to store dumps
MEILI_DUMP_DIR={{ meilisearch_dump_dir | default(meilisearch_data_dir + "/dumps") }}

# Enable scheduled snapshots (true/false)
MEILI_SCHEDULE_SNAPSHOT={{ meilisearch_schedule_snapshot | default("false") }}

# ---------------------------------- Clustering -------------------------------
# Meilisearch does not support clustering (like Elasticsearch).
# Scaling is typically handled with sharding at the app level or proxies.
# This section is informational only.

# ---------------------------------- Experimental -----------------------------
# Maximum index size (bytes) before compaction
MEILI_MAX_INDEX_SIZE={{ meilisearch_max_index_size | default("10000000000") }} # 10GB default

# Number of threads used by Meilisearch
MEILI_MAX_THREADS={{ meilisearch_max_threads | default(ansible_processor_vcpus | default("4")) }}

# ---------------------------------- Security --------------------------------
# Whether to disable analytics sent to Meilisearch (default: false)
MEILI_NO_ANALYTICS={{ meilisearch_no_analytics | default("true") }}

# ---------------------------------- Various ---------------------------------
# Require explicit UID for created indexes (default: false)
MEILISEARCH_ENV={{ MEILISEARCH_ENV }}
Loading
Loading