# FAQ: Running an edx-platform Fork with Tutor

**URL:** <https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292>\
**Category:** Show & Tell\
**Tags:** how-to, tutor\
**Created:** [May 19, 2022, 1:54pm UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292 "2022-05-19T13:54:48Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [May 19, 2022, 1:54pm UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/1 "2022-05-19T13:54:48Z")

</div>

# Most cases of customization **do not** require creating a custom edx-platfom fork to achieve. Please look at [Tutor plugins](https://docs.tutor.overhang.io/plugins/index.html) and [Tutor custom themes](https://docs.tutor.overhang.io/tutorials/theming.html) before following the guides shared on this topic.

The documentation regarding this topic is scarce and all over the place, therefore I would like to share my methods for running an `edx-platform` fork using Tutor and also create a FAQ to supplement the [Configuration and customization — Tutor documentation](https://docs.tutor.overhang.io/configuration.html#running-a-fork-of-edx-platform) entry in the Tutor documentation.

Please feel free to add to this thread.

**Disclaimer** : **Please beware that the listed are my methods for working on an `edx-platform` fork and may not be the best method, I also cannot guarantee that my solutions will work out-of-box for you.**

Additional Disclaimer: I am using MacOS, therefore all my guides will best apply to MacOS environment.

# Please create another topic and @uetuluk for questions regarding the content in this FAQ.

### Table of Contents

1. [Quickstart](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292#mini-course-docs-tutor-fork-quickstart-1) - This is a guide to help you start with your fork.
2. [Quickstart with TVM](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/4#mini-course-docs-tutor-fork-quickstart-with-edunexttvmhttpsgithubcomedunexttvm-1) - This is a version of Quickstart that uses [GitHub - eduNEXT/tvm: Tutor Version Manager and Tutor enVironment Manager](https://github.com/eduNEXT/tvm).

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [May 19, 2022, 2:23pm UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/2 "2022-05-19T14:23:46Z")

</div>

# Mini Course Docs: Tutor Fork Quickstart

# Quickstart

Latest update: May 19, 2022 9:52 PM (Please change the versions accordingly if this post is too old.)

## Table of Contents

- [0. Prerequisites](#0-prerequisites)
- [1. Set up Environment](#1-set-up-environment)
  - [1.1. Create Virtual Python Environment](#11-create-virtual-python-environment)
  - [1.2. Install Tutor](#12-install-tutor)
  - [1.3. Environment Variables](#13-environment-variables)
  - [1.4. Save Configuration](#14-save-configuration)
    - [1.4.1. (Optional) Initialize Git Repository](#141-optional-initialize-git-repository)
    - [1.4.2. .gitignore](#142-gitignore)

  - [1.5. Additional Tutor Configuration](#15-additional-tutor-configuration)

- [2. Build Development Image](#2-build-development-image)
  - [2.1. openedx Image](#21-openedx-image)
  - [2.2. openedx Development Image](#22-openedx-development-image)
  - [2.3. (Optional) Tag Your Images](#23-optional-tag-your-images)
    - [2.3.1. Create Development Image Again to Tag it](#231-create-development-image-again-to-tag-it)
    - [2.3.2 Upload Your Image](#232-upload-your-image)

- [3. Creating Development Environment](#3-creating-development-environment)
  - [3.1. Create Your Fork](#31-create-your-fork)
  - [3.2. Download Your Forked Repo to Your Development Environment](#32-download-your-forked-repo-to-your-development-environment)
  - [3.3. Point Tutor Towards Your Forked Repo](#33-point-tutor-towards-your-forked-repo)
  - [3.4. Start Development](#34-start-development)

- [4. Build your Custom Image](#4-build-your-custom-image)
  - [4.1. Apply the Patches](#41-apply-the-patches)
  - [4.2. Remove the Patches](#42-remove-the-patches)
    - [4.2.1. Creating and enabling the Plugin](#421-creating-and-enabling-the-plugin)
    - [4.2.2. Consequences](#422-consequences)

  - [4.3. Update your Repo](#43-update-your-repo)
  - [4.4. Build your Image](#44-build-your-image)
    - [4.4.1. Tagging the Image](#441-tagging-the-image)
    - [4.4.2. Private `edx-platform` Fork](#442-private-edx-platform-fork)

  - [4.5. Use your Image in Production](#45-use-your-image-in-production)

## 0. Prerequisites

- I assume you have already successfully run `tutor local quickstart`.
- [GitHub - pyenv/pyenv: Simple Python version management](https://github.com/pyenv/pyenv)
- [GitHub - pyenv/pyenv-virtualenv: a pyenv plugin to manage virtualenv (a.k.a. python-virtualenv)](https://github.com/pyenv/pyenv-virtualenv)

## 1. Set up Environment

Collect the versions for the software you will be using.

> **For example, my current setup for Maple uses the following.**
>
> **Tutor:** 13.2.2
> 
> **Python:** 3.8.12
> 
> **edx-platform:** [https://github.com/overhangio/tutor/blob/v13.2.2/tutor/templates/config/defaults.yml#L51](https://github.com/overhangio/tutor/blob/v13.2.2/tutor/templates/config/defaults.yml#L51)
> 
> (Choose according to your release)

### 1.1. Create Virtual Python Environment

Create a folder to store your Tutor environment.

```bash
mkdir tutor-maple
cd tutor-maple

```

The following examples assume you are running the code from the `~/tutor-maple` directory. I will also refer to this directory as `$(pwd)`. You should replace `$(pwd)` with the result of running the following code in your working directory.

```bash
pwd

```

The following code can be run to create a Python environment with latest versions.

```bash
pyenv virtualenv 3.8.12 tutor-maple

```

You can then activate the environment.

```bash
pyenv local tutor-maple

```

### 1.2. Install Tutor

The easiest way to install Tutor for a development environment is by using the pip package. You can run the following code to install Tutor.

```bash
pip install "tutor[full]==v13.2.2"

```

### 1.3. Environment Variables

You should add the following variables, so that your Tutor environment will be placed in an easy to reach location. You can also change these variables to place more than one Tutor environment in your development machine.

```bash
export TUTOR_ROOT=$(pwd)/tutor
export TUTOR_PLUGINS_ROOT=$(pwd)/tutor-plugins

```

# It is extremely important that

these values **do not change** during the set up, otherwise you will end up with two broken tutor environments. The environmental variables **will change** if you use another terminal during the set up or close your terminal. Simply run the `export` commands shown above again if your terminal changed for any reason. You should follow section 1.3.1 below if you do not want to worry about the environmental variables.

**1.3.1. (Optional) Auto-export Environment Variables**

You will need to run the code above every time you want to work on this specific instance of Tutor. You can automate this process by installing [https://direnv.net/](https://direnv.net/).

You simply need to create an `.envrc` file in your working directory with the `export` commands above and they will be automatically run.

### 1.4. Save Configuration

You should run the save configuration command now to generate the Tutor environment at your working directory. These prompt should be familiar as they are the same the `tutor local quickstart`, however, we do not want to start Tutor yet, so we will only create the configuration files.

```bash
tutor config save --interactive

```

You should answer first question as **no** since you will be doing development.

#### 1.4.1. (Optional) Initialize Git Repository

You can initialize a git repository inside your working directory at this point to store your Tutor configuration. **You should be careful about uploading this git repository as it will include all your database passwords and other secretes. This repository should be a `private` repo if you have to upload it.**

```bash
git init

```

#### 1.4.2. .gitignore

You might want to create a .gitignore file, so that you do not include the Tutor data files.

```bash
tutor/volumes
tutor/data*

```

### 1.5. Additional Tutor Configuration

You should add the following values to the `config.yml` located inside your Tutor environment created in 1.3. Environment Variables . (You can find it by running `echo $(pwd)/tutor` if you lost it.)

```bash
LOCAL_PROJECT_NAME: tutor_maple
DEV_PROJECT_NAME: tutor_maple_dev

```

Your Tutor installation will be designated the name `tutor` in your Docker environment by default, if you do not change it here, you will overwrite that Docker environment.

Do not forget to save your `config.yml` file by running `tutor config save`.

## 2. Build Development Image

You are now ready to create the `openedx` and `openedx Development` images.

### 2.1. openedx Image

You can now run the familiar **quickstart** command.

```bash
tutor local quickstart

```

Once you confirm that your site is up and running, stop it.

```bash
tutor local stop

```

You have now downloaded the openedx image and are ready to build the development image.

### 2.2. openedx Development Image

The development image is created by simply running the following code.

```bash
tutor dev dc build lms

```

After the image is build, you can start your development instance in the detached mode.

```bash
tutor dev start -d

```

Once you confirmed that your development site is up and running, stop it.

```bash
tutor dev stop

```

### 2.3. (Optional) Tag Your Images

You should now tag your images to upload them to your image repository if you will be using different machines for development and production.

```bash
DOCKER_IMAGE_OPENEDX: <IMAGE REPO>/<IMAGE NAME>:<IMAGE TAG>
DOCKER_IMAGE_OPENEDX_DEV: <IMAGE REPO>/<DEV IMAGE NAME>:<IMAGE TAG>

```

You should now tag your development image.

#### 2.3.1. (Optional) Create Development Image Again to Tag it

(You can also find the image ID from Docker Desktop and use the Docker CLI to this step.)

```bash
tutor dev dc build lms

```

#### 2.3.2 (Optional) Upload Your Image

You can run the following commands to upload your images.

```bash
tutor images push openedx
docker push $(tutor config printvalue DOCKER_IMAGE_OPENEDX_DEV)

```

## 3. Creating Development Environment

You are now ready to start working on your own `edx-platform` fork.

### 3.1. Create Your Fork

Use GitHub to create a fork of the **`edx-platform`**.

[https://github.com/openedx/edx-platform](https://github.com/openedx/edx-platform)

### 3.2. Download Your Forked Repo to Your Development Environment

You are now ready to use your forked repo for development.

First receive the files from the Tutor installation.

```bash
mkdir -p $(tutor config printroot)/volumes/edx-platform
tutor dev copyfrom lms /openedx/edx-platform $(tutor config printroot)/volumes/

```

This way you will be able to use the development tools that are installed inside the Development image. It will take some time to copy over the files.

Then change the remote to point to your fork.

```bash
cd $(pwd)/tutor/volumes/edx-platform
git remote set-url origin <YOUR_REPO_URL>

```

Sync your repo.

```bash
git fetch

```

Finally change to the branch you will be using.

```bash
git checkout -b <USERNAME>-dev

```

### 3.3. Point Tutor Towards Your Forked Repo

You should create an override file `docker-compose.override.yml`at this location `$(pwd)/tutor/env/dev/docker-compose.override.yml` with the following content.

You should replace the variables with your working directory.

```bash
version: "3.7"
services:
  lms:
    volumes:
      - "<PWD>/tutor/volumes/edx-platform:/openedx/edx-platform"
  cms:
    volumes:
      - "<PWD>/tutor/volumes/edx-platform:/openedx/edx-platform"
  lms-worker:
    volumes:
      - "<PWD>/tutor/volumes/edx-platform:/openedx/edx-platform"
  cms-worker:
    volumes:
      - "<PWD>/tutor/volumes/edx-platform:/openedx/edx-platform"

```

### 3.4. Start Development

Your Tutor installation will now use your fork.

```bash
tutor dev start

```

Congratulations, you now have a development environment to start working on an `edx-platform` fork.

## 4. Build your Custom Image

You have done your changes and are now ready to build your custom image.

### 4.1. Apply the Patches

You need to make sure you have all the patches applied to your codebase because we will remove them to prevent problems.

You can find the current patches from the Dockerfile at the `$(pwd)/tutor/env/build/openedx/Dockerfile` directory.

The patches section will start with the following code.

```bash
# Identify tutor user to cherry-pick commits
RUN git config --global user.email "tutor@overhang.io" \
  && git config --global user.name "Tutor"
# Patch edx-platform

```

You can directly run the codes after the `RUN` command in your `edx-platform` fork root directory (which is `$(pwd)/tutor/volumes/edx-platform` if you use the one suggested in this guide).

> **For example, Tutor 13.2.2 uses the following patches.**
>
> ```bash
> # Fix forum notification for questions
> # https://github.com/openedx/edx-platform/pull/29611
> RUN git fetch --depth=2 https://github.com/open-craft/edx-platform/ 03731f19459e558f188c06aac5cc9ca1bbc675c2 && git cherry-pick 03731f19459e558f188c06aac5cc9ca1bbc675c2
> # SAML security fix
> # https://github.com/overhangio/edx-platform/tree/overhangio/sec-fix-saml-vulnerability
> RUN git fetch --depth=2 https://github.com/overhangio/edx-platform/ 3b985f207853e88090d68a81acd52866b71f5af7 && git cherry-pick 3b985f207853e88090d68a81acd52866b71f5af7
> # Rate limiting security fix
> # https://github.com/overhangio/edx-platform/tree/overhangio/sec-rate-limiting
> RUN git fetch --depth=2 https://github.com/overhangio/edx-platform/ b5723e416e628cac4fa84392ca13e1b72817674f && git cherry-pick b5723e416e628cac4fa84392ca13e1b72817674f
> # Fix studio-frontend by pinning the installed version
> # https://github.com/openedx/edx-platform/pull/30309
> RUN git fetch --depth=2 https://github.com/uetuluk/edx-platform/ 53ea60eee86e094f35815ac1c4114d6811f4d458 && git cherry-pick 53ea60eee86e094f35815ac1c4114d6811f4d458
> 
> ```
> 
> You simply need to run the following commands in your `edx-platform` root directory.
> 
> ```bash
> git fetch --depth=2 https://github.com/open-craft/edx-platform/ 03731f19459e558f188c06aac5cc9ca1bbc675c2 && git cherry-pick 03731f19459e558f188c06aac5cc9ca1bbc675c2
> git fetch --depth=2 https://github.com/overhangio/edx-platform/ 3b985f207853e88090d68a81acd52866b71f5af7 && git cherry-pick 3b985f207853e88090d68a81acd52866b71f5af7
> git fetch --depth=2 https://github.com/overhangio/edx-platform/ b5723e416e628cac4fa84392ca13e1b72817674f && git cherry-pick b5723e416e628cac4fa84392ca13e1b72817674f
> git fetch --depth=2 https://github.com/uetuluk/edx-platform/ 53ea60eee86e094f35815ac1c4114d6811f4d458 && git cherry-pick 53ea60eee86e094f35815ac1c4114d6811f4d458
> 
> ```

### 4.2. Remove the Patches

Now that you applied the patches, you do not need them anymore, use the following v1 plugin to remove them.

```bash
"""
NO Patch plugin to prevent applying the patch again.

name: nopatch
version: 0.1.0
patches:
  openedx-dockerfile-git-patches-default: "#"
"""

from tutor import hooks

hooks.Filters.ENV_PATCHES.add_item(
  (
  "openedx-dockerfile-git-patches-default",
  "#"
  )
)

```

#### 4.2.1. Creating and enabling the Plugin

> **If you do not know what a Tutor plugin is, you can follow this quick guide.**
>
> You need to create a file called `nopatch.py` inside the plugins directory declared in 1.3. Environment Variables. (`$(pwd)/tutor-plugins` for this guide)
> 
> Then you need to enable the plugin by running
> 
> ```bash
> tutor plugins enable nopatch
> 
> ```
> 
> And save your configuration.
> 
> ```bash
> tutor config save
> 
> ```
> 
> If you are using git, you will notice that the Dockerfile has changed to remove the patches.

#### 4.2.2. Consequences

This plugin will cause your images to never apply the patches inserted by Tutor, therefore you will have to manually check if there are any new patches every time you upgrade your Tutor version.

### 4.3. Update your Repo

You should now commit and push your changes to your fork repo since the Tutor build commands use the remote repo rather than your local one.

```bash
cd $(pwd)/tutor/volumes/edx-platform
git add .
git commit -m "Your Commit Message"

```

### 4.4. Build your Image

You can now build your image. Since you are using a custom `edx-platform` repository, you need to let Tutor know where to look.

Use the following command with added arguments to build your custom `openedx` image.

```bash
tutor images build openedx --build-arg EDX_PLATFORM_REPOSITORY="https://github.com/<USERNAME>/edx-platform" --build-arg EDX_PLATFORM_VERSION="<USERNAME>-dev"

```

#### 4.4.1. Tagging the Image

Simply follow 2.3. (Optional) Tag Your Images to tag your images.

#### 4.4.2. Private `edx-platform` Fork

If you are using a private `edx-platform` fork, you can create a **Personal access token (**[https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)) \*\*\*\*and add it to the `EDX_PLATFORM_REPOSITORY` argument.

```bash
tutor images build openedx --build-arg EDX_PLATFORM_REPOSITORY="https://<PAT>@github.com/<USERNAME>/edx-platform" --build-arg EDX_PLATFORM_VERSION="<USERNAME>-dev"

```

### 4.5. Use your Image in Production

Simply follow 2.3. (Optional) Tag Your Images to change the image Tutor will use when you run `tutor local quickstart`.

---

<div class="post-metadata">

**Author:** ![Harshgaur14](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/harshgaur14/32/3618_2.png) [@Harshgaur14](https://discuss.openedx.org/u/Harshgaur14)\
**Post date:** [May 20, 2022, 10:20am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/3 "2022-05-20T10:20:56Z")

</div>

unable to run 2.3.2 commands

```auto
cdac@cdac-OptiPlex-9020:~$ tutor images push openedx
Pushing image docker.io/overhangio/openedx:13.2.2
docker push docker.io/overhangio/openedx:13.2.2
The push refers to repository [docker.io/overhangio/openedx]
e42a06ef2097: Preparing 
e9dc8031b2df: Preparing 
c654b88ab2a6: Preparing 
41e2f2a4b779: Preparing 
35947800cd94: Preparing 
5a1ed078be27: Waiting 
07a11895f191: Waiting 
325e570fb604: Waiting 
049b17c4910b: Waiting 
210761a2bdc1: Waiting 
15163ad08e5b: Waiting 
cb1b3328a68c: Waiting 
391a60e86972: Waiting 
e3ac1bf75a5a: Waiting 
321b80b800e0: Waiting 
c48bbec30c44: Waiting 
617128a98622: Waiting 
940e1de22200: Waiting 
8366139ce96a: Waiting 
9891f8304417: Waiting 
e64e8ea9e680: Waiting 
507c41400075: Waiting 
2d5dcaa44774: Waiting 
0aa699218e55: Waiting 
80bb1dd90c3c: Waiting 
0adef47d4d95: Waiting 
bf8cedc62fb3: Waiting 
denied: requested access to the resource is denied
Error: Command failed with status 1: docker push docker.io/overhangio/openedx:13.2.2

```

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [May 23, 2022, 4:53am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/4 "2022-05-23T04:53:02Z")

</div>

@Harshgaur14 The 2.3 section is optional. The 2.3 section includes 2.3.1 and 2.3.2.

If you want to follow the 2.3 section, you will have to look at hosting Docker images.  
Here is a starting point: [Repositories | Docker Docs](https://docs.docker.com/docker-hub/repos/)

# Please create another topic for your question and tag me @uetuluk.

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [May 23, 2022, 10:13am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/7 "2022-05-23T10:13:33Z")

</div>

# Mini Course Docs: Tutor Fork Quickstart with [eduNEXT/tvm](https://github.com/eduNEXT/tvm)

# Quickstart

Latest update: May 23, 2022 6:06 PM (Please change the versions accordingly if this post is too old.)

## Table of Contents

- [0. Prerequisites](#0-prerequisites)
- [1. Set up Environment](#1-set-up-environment)
  - [1.1. Create Working Directory](#11-create-working-directory)
  - [1.2. Install TVM](#12-install-tvm)
  - [1.3. Install Tutor](#13-install-tutor)
  - [1.4. Create your Environment](#14-create-your-environment)
  - [1.5. Enable your Environment](#15-enable-your-environment)
  - [1.6. Install Required Plugins](#16-install-required-plugins)
  - [1.7. Save Configuration](#17-save-configuration)
  - [1.7.1. (Optional) Initialize Git Repository](#171-optional-initialize-git-repository)
  - [1.7.2. (Optional) .gitignore](#172-optional-gitignore)
  - [1.8. Additional Tutor Configuration](#18-additional-tutor-configuration)

- [2. Build Development Image](#2-build-development-image)
  - [2.1. openedx Image](#21-openedx-image)
  - [2.2. openedx Development Image](#22-openedx-development-image)
  - [2.3. (Optional) Tag Your Images](#23-optional-tag-your-images)
  - [2.3.1. (Optional) Create Development Image Again to Tag it](#231-optional-create-development-image-again-to-tag-it)
  - [2.3.2 (Optional) Upload Your Image](#232-optional-upload-your-image)

- [3. Creating Development Environment](#3-creating-development-environment)
  - [3.1. Create Your Fork](#31-create-your-fork)
  - [3.2. Download Your Forked Repo to Your Development Environment](#32-download-your-forked-repo-to-your-development-environment)
  - [3.3. Point Tutor Towards Your Forked Repo](#33-point-tutor-towards-your-forked-repo)
  - [3.4. Start Development](#34-start-development)

- [4. Build your Custom Image](#4-build-your-custom-image)
  - [4.1. Apply the Patches](#41-apply-the-patches)
  - [4.2. Remove the Patches](#42-remove-the-patches)
  - [4.2.1. Creating and enabling the Plugin](#421-creating-and-enabling-the-plugin)
  - [4.2.2. Consequences](#422-consequences)
  - [4.3. Update your Repo](#43-update-your-repo)
  - [4.4. Build your Image](#44-build-your-image)
  - [4.4.1. Tagging the Image](#441-tagging-the-image)
  - [4.4.2. Private `edx-platform` Fork](#442-private-edx-platform-fork)
  - [4.5. Use your Image in Production](#45-use-your-image-in-production)

## 0. Prerequisites

- [https://github.com/pyenv/pyenv](https://github.com/pyenv/pyenv)
- [https://github.com/pyenv/pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)

## 1. Set up Environment

Collect the versions for the software you will be using.

> **For example, my current setup for Maple uses the following.**
>
> **Tutor:** 13.2.2
> 
> **Python:** 3.8.12
> 
> **edx-platform:** [https://github.com/overhangio/tutor/blob/v13.2.2/tutor/templates/config/defaults.yml#L51](https://github.com/overhangio/tutor/blob/v13.2.2/tutor/templates/config/defaults.yml#L51)
> 
> **TVM:** 1.0.0
> 
> (Choose according to your release)

### 1.1. Create Working Directory

Create a folder to store your Tutor environment.

```auto
mkdir tutor-maple
cd tutor-maple

```

The following examples assume you are running the code from the `~/tutor-maple` directory. I will also refer to this directory as `$(pwd)`. You should replace `$(pwd)` with the result of running the following code in your working directory.

```auto
pwd

```

### 1.2. Install TVM

You should now install the TVM package.

```bash
pip install git+https://github.com/eduNEXT/tvm.git@v1.0.0

```

### 1.3. Install Tutor

The TVM enables you to install Tutor with a simple command.

```auto
tvm install v13.2.2

```

### 1.4. Create your Environment

You can now use the Environment Manager function of `tvm` to create your work environment.

```bash
tvm project init

```

### 1.5. Enable your Environment

You need to enable the environment after creating it.

```bash
source .tvm/bin/activate

```

### 1.6. Install Required Plugins

You need to install the MFE plugin at this point for the installation to succeed.

```bash
tvm plugins install mfe

```

You can install additional Python plugins by running the `tvm plugins install` command with the plugin name. The list of official plugins are here: [https://overhang.io/tutor/plugins](https://overhang.io/tutor/plugins)

### 1.7. Save Configuration

You should run the save configuration command now to generate the Tutor environment at your working directory. We do not want to start Tutor yet, so we will only create the configuration files.

```auto
tutor config save --interactive

```

You should answer first question as **no** since you will be doing development.

### 1.7.1. (Optional) Initialize Git Repository

You can initialize a git repository inside your working directory at this point to store your Tutor configuration. **You should be careful about uploading this git repository as it will include all your database passwords and other secretes. This repository should be a `private` repo if you have to upload it.**

```auto
git init

```

### 1.7.2. (Optional) .gitignore

You might want to create a .gitignore file, so that you do not include the Tutor data files.

```auto
volumes
data*
.tvm

```

### 1.8. Additional Tutor Configuration

You should add the following values to the `config.yml` located inside your Tutor environment created in 1.4. Create your Environment. (You can find it by running `echo $(pwd)` if you lost it.)

```auto
LOCAL_PROJECT_NAME: tutor_maple
DEV_PROJECT_NAME: tutor_maple_dev

```

Your Tutor installation will be designated the name `tutor` in your Docker environment by default, if you do not change it here, you will overwrite that Docker environment.

Do not forget to save your `config.yml` file by running `tutor config save`.

## 2. Build Development Image

You are now ready to create the `openedx` and `openedx Development` images.

### 2.1. openedx Image

You can now run the familiar **quickstart** command.

```auto
tutor local quickstart

```

Once you confirm that your site is up and running, stop it.

```auto
tutor local stop

```

You have now downloaded the openedx image and are ready to build the development image.

### 2.2. openedx Development Image

The development image is created by simply running the following code.

```auto
tutor dev dc build lms

```

After the image is build, you can start your development instance in the detached mode.

```auto
tutor dev start -d

```

Once you confirmed that your development site is up and running, stop it.

```auto
tutor dev stop

```

### 2.3. (Optional) Tag Your Images

You should now tag your images to upload them to your image repository if you will be using different machines for development and production.

```auto
DOCKER_IMAGE_OPENEDX: <IMAGE REPO>/<IMAGE NAME>:<IMAGE TAG>
DOCKER_IMAGE_OPENEDX_DEV: <IMAGE REPO>/<DEV IMAGE NAME>:<IMAGE TAG>

```

You should now tag your development image.

### 2.3.1. (Optional) Create Development Image Again to Tag it

(You can also find the image ID from Docker Desktop and use the Docker CLI to this step.)

```auto
tutor dev dc build lms

```

### 2.3.2 (Optional) Upload Your Image

You can run the following commands to upload your images.

```auto
tutor images push openedx
docker push $(tutor config printvalue DOCKER_IMAGE_OPENEDX_DEV)

```

## 3. Creating Development Environment

You are now ready to start working on your own `edx-platform` fork.

### 3.1. Create Your Fork

Use GitHub to create a fork of the **`edx-platform`**.

[https://github.com/openedx/edx-platform](https://github.com/openedx/edx-platform)

### 3.2. Download Your Forked Repo to Your Development Environment

You are now ready to use your forked repo for development.

First receive the files from the Tutor installation.

```auto
mkdir -p $(tutor config printroot)/volumes/edx-platform
tutor dev copyfrom lms /openedx/edx-platform $(tutor config printroot)/volumes/

```

This way you will be able to use the development tools that are installed inside the Development image. It will take some time to copy over the files.

Then change the remote to point to your fork.

```auto
cd $(pwd)/volumes/edx-platform
git remote set-url origin <YOUR_REPO_URL>

```

Sync your repo.

```auto
git fetch

```

Finally change to the branch you will be using.

```auto
git checkout -b <USERNAME>-dev

```

### 3.3. Point Tutor Towards Your Forked Repo

You should create an override file `docker-compose.override.yml`at this location `$(pwd)/env/dev/docker-compose.override.yml` with the following content.

You should replace the variables with your working directory.

```auto
version: "3.7"
services:
  lms:
    volumes:
      - "<PWD>/volumes/edx-platform:/openedx/edx-platform"
  cms:
    volumes:
      - "<PWD>/volumes/edx-platform:/openedx/edx-platform"
  lms-worker:
    volumes:
      - "<PWD>/volumes/edx-platform:/openedx/edx-platform"
  cms-worker:
    volumes:
      - "<PWD>/volumes/edx-platform:/openedx/edx-platform"

```

### 3.4. Start Development

Your Tutor installation will now use your fork.

```auto
tutor dev start

```

Congratulations, you now have a development environment to start working on an `edx-platform` fork.

## 4. Build your Custom Image

You have done your changes and are now ready to build your custom image.

### 4.1. Apply the Patches

You need to make sure you have all the patches applied to your codebase because we will remove them to prevent problems.

You can find the current patches from the Dockerfile at the `$(pwd)/env/build/openedx/Dockerfile` directory.

The patches section will start with the following code.

```auto
# Identify tutor user to cherry-pick commits
RUN git config --global user.email "tutor@overhang.io" \\
  && git config --global user.name "Tutor"
# Patch edx-platform

```

You can directly run the codes after the `RUN` command in your `edx-platform` fork root directory (which is `$(pwd)/volumes/edx-platform` if you use the one suggested in this guide).

> **For example, Tutor 13.2.2 uses the following patches.**
>
> ```auto
> # Fix forum notification for questions
> # <https://github.com/openedx/edx-platform/pull/29611>
> RUN git fetch --depth=2 <https://github.com/open-craft/edx-platform/> 03731f19459e558f188c06aac5cc9ca1bbc675c2 && git cherry-pick 03731f19459e558f188c06aac5cc9ca1bbc675c2
> # SAML security fix
> # <https://github.com/overhangio/edx-platform/tree/overhangio/sec-fix-saml-vulnerability>
> RUN git fetch --depth=2 <https://github.com/overhangio/edx-platform/> 3b985f207853e88090d68a81acd52866b71f5af7 && git cherry-pick 3b985f207853e88090d68a81acd52866b71f5af7
> # Rate limiting security fix
> # <https://github.com/overhangio/edx-platform/tree/overhangio/sec-rate-limiting>
> RUN git fetch --depth=2 <https://github.com/overhangio/edx-platform/> b5723e416e628cac4fa84392ca13e1b72817674f && git cherry-pick b5723e416e628cac4fa84392ca13e1b72817674f
> # Fix studio-frontend by pinning the installed version
> # <https://github.com/openedx/edx-platform/pull/30309>
> RUN git fetch --depth=2 <https://github.com/uetuluk/edx-platform/> 53ea60eee86e094f35815ac1c4114d6811f4d458 && git cherry-pick 53ea60eee86e094f35815ac1c4114d6811f4d458
> 
> ```
> 
> You simply need to run the following commands in your `edx-platform` root directory.
> 
> ```auto
> git fetch --depth=2 <https://github.com/open-craft/edx-platform/> 03731f19459e558f188c06aac5cc9ca1bbc675c2 && git cherry-pick 03731f19459e558f188c06aac5cc9ca1bbc675c2
> git fetch --depth=2 <https://github.com/overhangio/edx-platform/> 3b985f207853e88090d68a81acd52866b71f5af7 && git cherry-pick 3b985f207853e88090d68a81acd52866b71f5af7
> git fetch --depth=2 <https://github.com/overhangio/edx-platform/> b5723e416e628cac4fa84392ca13e1b72817674f && git cherry-pick b5723e416e628cac4fa84392ca13e1b72817674f
> git fetch --depth=2 <https://github.com/uetuluk/edx-platform/> 53ea60eee86e094f35815ac1c4114d6811f4d458 && git cherry-pick 53ea60eee86e094f35815ac1c4114d6811f4d458
> 
> ```

### 4.2. Remove the Patches

Now that you applied the patches, you do not need them anymore, use the following v1 plugin to remove them.

```auto
"""
NO Patch plugin to prevent applying the patch again.

name: nopatch
version: 0.1.0
patches:
  openedx-dockerfile-git-patches-default: "#"
"""

from tutor import hooks

hooks.Filters.ENV_PATCHES.add_item(
  (
  "openedx-dockerfile-git-patches-default",
  "#"
  )
)

```

### 4.2.1. Creating and enabling the Plugin

> **If you do not know what a Tutor plugin is, you can follow this quick guide.**
>
> You need to create a file called `nopatch.py` inside the plugins directory declared in 1.4. Create your Environment. (`$(pwd)/plugins` for this guide)
> 
> Then you need to enable the plugin by running
> 
> ```auto
> tutor plugins enable nopatch
> 
> ```
> 
> And save your configuration.
> 
> ```auto
> tutor config save
> 
> ```
> 
> If you are using git, you will notice that the Dockerfile has changed to remove the patches.

### 4.2.2. Consequences

This plugin will cause your images to never apply the patches inserted by Tutor, therefore you will have to manually check if there are any new patches every time you upgrade your Tutor version.

### 4.3. Update your Repo

You should now commit and push your changes to your fork repo since the Tutor build commands use the remote repo rather than your local one.

```auto
cd $(pwd)/volumes/edx-platform
git add .
git commit -m "Your Commit Message"

```

### 4.4. Build your Image

You can now build your image. Since you are using a custom `edx-platform` repository, you need to let Tutor know where to look.

Use the following command with added arguments to build your custom `openedx` image.

```auto
tutor images build openedx --build-arg EDX_PLATFORM_REPOSITORY="<https://github.com/><USERNAME>/edx-platform" --build-arg EDX_PLATFORM_VERSION="<USERNAME>-dev"

```

### 4.4.1. Tagging the Image

Simply follow 2.3. (Optional) Tag Your Images to tag your images.

### 4.4.2. Private `edx-platform` Fork

If you are using a private `edx-platform` fork, you can create a **Personal access token (**[https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)) \*\*\*\*and add it to the `EDX_PLATFORM_REPOSITORY` argument.

```auto
tutor images build openedx --build-arg EDX_PLATFORM_REPOSITORY="<https://<PAT>@github.com/><USERNAME>/edx-platform" --build-arg EDX_PLATFORM_VERSION="<USERNAME>-dev"

```

### 4.5. Use your Image in Production

Simply follow 2.3. (Optional) Tag Your Images to change the image Tutor will use when you run `tutor local quickstart`.

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [May 24, 2022, 10:31am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/8 "2022-05-24T10:31:45Z")

</div>

# Question: I receive the following error when I tried to follow section 4.1. Apply the Patches. What should I do?

> …  
> …  
> Untracked files:  
> (use “git add …” to include in what will be committed)  
> cms/envs/tutor/  
> lms/envs/tutor/  
> results.txt
> 
> no changes added to commit (use “git add” and/or “git commit -a”)  
> The previous cherry-pick is now empty, possibly due to conflict resolution.  
> If you wish to commit it anyway, use:
> 
> ```auto
> git commit --allow-empty
> 
> ```
> 
> Otherwise, please use ‘git cherry-pick --skip’

# Answer

The first time you are forking the edx-platform repository, the patches will be already applied, therefore, you can simply skip this step.

Additionally, you should commit these files generated by Tutor to keep track of them.

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [May 31, 2022, 3:02am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/9 "2022-05-31T03:02:02Z")

</div>

# Question

How do I change the appearance of my Open edX installation?

# Answer

You **do not need** to follow the complete guide for simple changes to the appearance of your Open edX installation.  
You can follow until section 2.3 in both guides (not including 2.3) to set up your development environment, then follow the instructions for custom theming. [Changing the appearance of Open edX — Tutor documentation](https://docs.tutor.overhang.io/tutorials/theming.html)

---

<div class="post-metadata">

**Author:** ![hijulien-gan](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/hijulien-gan/32/3609_2.png) [@hijulien-gan](https://discuss.openedx.org/u/hijulien-gan)\
**Post date:** [June 6, 2022, 1:30am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/10 "2022-06-06T01:30:58Z")

</div>

OK,Thank you very much

---

<div class="post-metadata">

**Author:** ![SamnangLaor](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/samnanglaor/32/3307_2.png) [@SamnangLaor](https://discuss.openedx.org/u/SamnangLaor)\
**Post date:** [June 8, 2022, 3:56pm UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/11 "2022-06-08T15:56:58Z")

</div>

@uetuluk , After follow your guidance, my container which is build from fork-repo keep restarting.  
How can I debug what wrong with my code customization.

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [June 9, 2022, 4:04am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/12 "2022-06-09T04:04:20Z")

</div>

@SamnangLaor Please create another topic with more details.

> [@uetuluk](#):
>
> Please create another topic and @uetuluk for questions regarding the content in this FAQ.

---

<div class="post-metadata">

**Author:** ![alokkumar245](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/alokkumar245/32/3841_2.png) [@alokkumar245](https://discuss.openedx.org/u/alokkumar245)\
**Post date:** [June 20, 2022, 10:34am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/13 "2022-06-20T10:34:40Z")

</div>

I have been working on maple tutor. After I enable ecommerce plugin and quickstart dev then the whole setup is upgraded to nutmeg . How to stabalize my maple version?

---

<div class="post-metadata">

**Author:** ![uetuluk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/uetuluk/32/3015_2.png) [@uetuluk](https://discuss.openedx.org/u/uetuluk)\
**Post date:** [June 21, 2022, 2:08am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/14 "2022-06-21T02:08:06Z")

</div>

@alokkumar245 Please create another topic with more details.

> [@uetuluk](#):
>
> Please create another topic and @uetuluk for questions regarding the content in this FAQ.

---

<div class="post-metadata">

**Author:** ![eazaika](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/eazaika/32/5333_2.png) [@eazaika](https://discuss.openedx.org/u/eazaika)\
**Post date:** [August 2, 2023, 8:51am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/15 "2023-08-02T08:51:34Z")

</div>

Found some fun bug!  
Dont forget change or remove form ~/.bashrc:

```auto
PATH=~/.local/bin/:$PATH
_tutor_completion() {
    local IFS=$'\n'
    local response

    response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD _TUTOR_COMPLETE=bash_complete $1)

    for completion in $response; do
        IFS=',' read type value <<< "$completion"

        if [[$type == 'dir']]; then
            COMREPLY=()
            compopt -o dirnames
        elif [[$type == 'file']]; then
            COMREPLY=()
            compopt -o default
        elif [[$type == 'plain']]; then
            COMPREPLY+=($value)
        fi
    done

    return 0
}

_tutor_completion_setup() {
    complete -o nosort -F _tutor_completion tutor
}

_tutor_completion_setup;

```

if you already have global tutor installation. Bcs global path to tutor (~/.local/bin/) have primary order to pyenv path to tutor (~/.pyenv/shims/).  
So, I worked with global tutor some time (

---

<div class="post-metadata">

**Author:** ![smadi](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/smadi/32/6961_2.png) [@smadi](https://discuss.openedx.org/u/smadi)\
**Post date:** [June 27, 2024, 7:36pm UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/16 "2024-06-27T19:36:27Z")

</div>

Hi @uetuluk and thank you for the detailed tutorial, it is really hard to figure out the steps to get started on local development for someone who has just started. I think this is really important subject that needs to be clarified in more detail.  
Are the steps in this tutorial still valid and will work on the latest release of Tutor 18 and the redwood openedx platform? If not it would you please update it so people who are trying to get a properly running local development environment wouldn’t spend hours looking up multiple sources and sometimes using trial and error to get started. Your feedback is really appreciated. Thank you in advance

---

<div class="post-metadata">

**Author:** ![carT](https://avatars.discourse-cdn.com/v4/letter/c/3ec8ea/32.png) [@carT](https://discuss.openedx.org/u/carT)\
**Post date:** [November 7, 2025, 11:11am UTC](https://discuss.openedx.org/t/faq-running-an-edx-platform-fork-with-tutor/7292/17 "2025-11-07T11:11:12Z")

</div>

> [@uetuluk](#):
>
> 4.4. Build your Image

would work pass a git command regarding a particular branch on that repository, have you tried so far?
