<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Cristiano Pacheco</title>
    <description>The latest articles on Forem by Cristiano Pacheco (@cristiano-pacheco).</description>
    <link>https://forem.com/cristiano-pacheco</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F484038%2F4ec5254e-b5e5-45b7-bfb7-5f57e5313669.png</url>
      <title>Forem: Cristiano Pacheco</title>
      <link>https://forem.com/cristiano-pacheco</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cristiano-pacheco"/>
    <language>en</language>
    <item>
      <title>Good-bye Docker, Hello Nix: Configuring a Magento 2 Development Environment with Rooter</title>
      <dc:creator>Cristiano Pacheco</dc:creator>
      <pubDate>Tue, 20 Feb 2024 10:50:29 +0000</pubDate>
      <link>https://forem.com/run_as_root/good-bye-docker-hello-nix-configuring-a-magento-2-development-environment-with-rooter-11in</link>
      <guid>https://forem.com/run_as_root/good-bye-docker-hello-nix-configuring-a-magento-2-development-environment-with-rooter-11in</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;
Creating a Magento 2 dev environment

&lt;ul&gt;
&lt;li&gt;1. Creating the project directory&lt;/li&gt;
&lt;li&gt;2. Entering in the created directory&lt;/li&gt;
&lt;li&gt;3. Creating the environment with rooter&lt;/li&gt;
&lt;li&gt;4. Allowing direnv to execute&lt;/li&gt;
&lt;li&gt;5. Cloning the Magento 2 repository&lt;/li&gt;
&lt;li&gt;6. Starting the environment stack&lt;/li&gt;
&lt;li&gt;7. Setting up the database&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Rooter Appendix

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;.devenv&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Versioning&lt;/li&gt;
&lt;li&gt;
Diving deeper into the most important files

&lt;ul&gt;
&lt;li&gt;.env&lt;/li&gt;
&lt;li&gt;.envrc&lt;/li&gt;
&lt;li&gt;devenv.nix&lt;/li&gt;
&lt;li&gt;devenv.yaml&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Accessing the traefik dashboard&lt;/li&gt;

&lt;li&gt;Accessing the mailpit UI&lt;/li&gt;

&lt;li&gt;Rooter commands&lt;/li&gt;

&lt;li&gt;Xdebug&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;In 2023, I switched from Linux to macOS. I used Linux for years, mainly because it supported Docker natively. However, during a system update, I encountered a problem with the video driver that cost me an entire Saturday searching for solutions, tweaking files I didn't even know existed until finally, at the end of the day, I found a workaround to get the darn Nvidia driver working.&lt;/p&gt;

&lt;p&gt;Come Monday morning, I shared my tech nightmare with a friend at work, who promptly asked:&lt;/p&gt;

&lt;p&gt;"Why don't you switch to macOS?"&lt;/p&gt;

&lt;p&gt;I replied: "Because it doesn't have native Docker support, and I don't want to use a virtual machine."&lt;/p&gt;

&lt;p&gt;With a virtual machine, you have to allocate a good chunk of RAM, not to mention the slower disk processing. While disk speed might not matter much for many applications, it makes a huge difference for a Magento 2 environment.&lt;/p&gt;

&lt;p&gt;"Why do you even need Docker?" he asked.&lt;/p&gt;

&lt;p&gt;That sparked a quick conversation where he introduced me to &lt;a href="https://nixos.org/" rel="noopener noreferrer"&gt;Nix&lt;/a&gt; and &lt;a href="https://devenv.sh/" rel="noopener noreferrer"&gt;devenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With these tools, it's possible to create a development environment that's entirely reproducible and native to macOS!&lt;/p&gt;

&lt;p&gt;It was love at first sight! When I saw it in action, my mind was blown!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu07m8ivwe6owetxkkxce.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu07m8ivwe6owetxkkxce.gif" alt="shocked" width="168" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During that conversation, I first contacted one of the early versions of &lt;a href="https://github.com/run-as-root/rooter" rel="noopener noreferrer"&gt;rooter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Rooter is a powerful command-line tool to automate repetitive tasks in creating and maintaining development environments.&lt;/p&gt;

&lt;p&gt;Shortly after, I bought a MacBook and started using &lt;code&gt;rooter&lt;/code&gt; to manage my projects. Nowadays, I don't have Docker installed on my machine, and I couldn't be happier!&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;You need macOS operating system and the softwares below installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/run-as-root/rooter" rel="noopener noreferrer"&gt;rooter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nixos.org/" rel="noopener noreferrer"&gt;nix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devenv.sh/" rel="noopener noreferrer"&gt;devenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://direnv.net/" rel="noopener noreferrer"&gt;direnv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just follow the instructions on the &lt;code&gt;rooter&lt;/code&gt; &lt;a href="https://github.com/run-as-root/rooter?tab=readme-ov-file#prerequisites" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just giving a brief introduction about the these tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;rooter&lt;/strong&gt; is a CLI tool created By &lt;a href="https://www.linkedin.com/in/matthiaswalter/" rel="noopener noreferrer"&gt;Matthias Walter&lt;/a&gt;. This tool will be your best friend during your development journey. It is similar to &lt;a href="https://docs.warden.dev/" rel="noopener noreferrer"&gt;Warden&lt;/a&gt; or &lt;a href="https://ddev.readthedocs.io/" rel="noopener noreferrer"&gt;DDEV&lt;/a&gt;. It takes care of things like automatic DNS resolution using dnsmasq, managing project routes with &lt;a href="https://traefik.io/traefik/" rel="noopener noreferrer"&gt;Traefik&lt;/a&gt;, creating SSL certificates, and even includes handy commands for importing and exporting databases, plus a whole lot more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;nix&lt;/strong&gt; has been around since 2003 and it's super reliable. It's like a toolbox with lots of useful tools inside, such as a programming language, an operating system, and a package manager. It helps you make software systems that are consistent and easy to recreate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;devenv&lt;/strong&gt; is kind of like &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;docker-compose&lt;/a&gt;, but way stronger. It's like being able to use a programming language to set up your environment, giving you even more control and flexibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;direnv&lt;/strong&gt; is a tool that figures out and loads all the stuff you need for your current project whenever you step into its folder in your terminal. We'll get to see how it works soon.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a Magento 2 dev environment
&lt;/h2&gt;

&lt;p&gt;So getting straight to the point, let's set up a development environment to run Magento 2.&lt;/p&gt;

&lt;p&gt;At this point, I'm assuming you've got &lt;code&gt;rooter&lt;/code&gt; and all the necessary tools it relies on installed and ready to roll. Let's dive in!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Creating the project directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/Sites/magento2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Entering in the created directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Sites/magento2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Creating the environment with &lt;code&gt;rooter&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rooter &lt;span class="nb"&gt;env&lt;/span&gt;:create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rooter will ask what type of environment:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbakfqszz19t45juvrro8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbakfqszz19t45juvrro8.png" alt="rooter env type" width="653" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Type 2 and enter for Magento 2&lt;/p&gt;

&lt;p&gt;It generated 4 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.envrc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devenv.nix&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devenv.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Allowing direnv to execute
&lt;/h3&gt;

&lt;p&gt;You probably saw this message in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hhq7txudw2fglyg61cj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hhq7txudw2fglyg61cj.png" alt="dir env allow" width="718" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to allow direnv to execute.&lt;/p&gt;

&lt;p&gt;Run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;direnv allow &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you'll see something like this in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fml35oz8pj3a8kgh57xo2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fml35oz8pj3a8kgh57xo2.png" alt="dir env steup" width="564" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this moment, your dev stack declared in the &lt;code&gt;devenv.nix&lt;/code&gt; file will be downloaded and configured. This is the longest step. Wait until the installation process finishes.&lt;/p&gt;

&lt;p&gt;You will see something like this when the process finishes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp9vn7h1yv5tb4oqvmi4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp9vn7h1yv5tb4oqvmi4.png" alt="direnv installation finished" width="566" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, please take a look into this image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7lcwijvehopogposj8s.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7lcwijvehopogposj8s.gif" alt="direnv loading" width="586" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've noticed, when I'm not in the project folder, the PHP version in the terminal is different, not 8.2. But as soon as I step into the project folder, direnv works its magic and loads the entire setup into the terminal. Pretty neat, isn't it?&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Cloning the Magento 2 repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project &lt;span class="nt"&gt;--repository-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://repo.magento.com/ magento/project-community-edition:2.4.6-p4 magento2-codebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It'll clone the Magento 2 repository into a directory named magento2-codebase. Once it's done, just copy everything from the magento2-codebase folder to the current directory, and then you can delete the magento2-codebase directory with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; magento2-codebase/&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-Rf&lt;/span&gt; magento2-codebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Starting the environment stack
&lt;/h3&gt;

&lt;p&gt;I like to start the environment in the debug mode in the first attempt, because this shows detailed output about the initialization and in case there is an issue, it is visible right away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rooter &lt;span class="nb"&gt;env&lt;/span&gt;:start &lt;span class="nt"&gt;--debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically devenv will download all services upon first start. That could also be nginx, opensearch, rabbitmq etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpubgow1dybsmlpudu82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpubgow1dybsmlpudu82.png" alt="opensearch lib download" width="570" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the first start I like to stop the environment (CMD + c) and start it again without the debug flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rooter &lt;span class="nb"&gt;env&lt;/span&gt;:start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason being that now it is running in the background rather than the foreground which it was with &lt;code&gt;--debug&lt;/code&gt; flag passed.&lt;/p&gt;

&lt;p&gt;To see what is the status of the environment, run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rooter &lt;span class="nb"&gt;env&lt;/span&gt;:status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will show something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febtuodopzhtw5635jxna.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febtuodopzhtw5635jxna.png" alt="env status" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned earlier, it uses &lt;a href="https://github.com/F1bonacc1/process-compose" rel="noopener noreferrer"&gt;process-compose&lt;/a&gt; in the background. There is a command to attach to the process-compose and get a control panel to check the various processed that got launched.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rooter &lt;span class="nb"&gt;env&lt;/span&gt;:process-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the image below, you can easily switch between the different services and watch their logs update live.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1k75okbrwd7anw5dcp4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1k75okbrwd7anw5dcp4.gif" alt="Process compose" width="582" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Setting up the database
&lt;/h3&gt;

&lt;p&gt;Run the command below to setup the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rooter magento2:db-install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rooter will drop and recreate the database and by default run the commands below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/magento setup:install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/magento setup:upgrade&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/magento indexer:reindex&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An admin user will be created with the username &lt;code&gt;admin&lt;/code&gt; and password &lt;code&gt;admin123&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you pass the option &lt;code&gt;--config-data-import&lt;/code&gt; it will run the command &lt;code&gt;bin/magento config:data:import config/store dev/rooter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The &lt;code&gt;config:data:import&lt;/code&gt; is provided by the &lt;a href="https://github.com/semaio/Magento2-ConfigImportExport" rel="noopener noreferrer"&gt;Magento2-ConfigImportExport&lt;/a&gt; module. You need to install it to use the &lt;code&gt;--config-data-import&lt;/code&gt; option flag.&lt;/p&gt;

&lt;p&gt;You can skip the reindex by passing the option &lt;code&gt;--skip-reindex&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run the commands below to set some extra configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento config:set web/unsecure/base_url https://magento2.rooter.test/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set web/secure/base_url https://magento2.rooter.test/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set web/secure/offloader_header X-Forwarded-Proto &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set web/secure/use_in_frontend 1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set web/secure/use_in_adminhtml 1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set web/seo/use_rewrites 1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set catalog/search/enable_eav_indexer 1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento config:set dev/static/sign 0 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento deploy:mode:set &lt;span class="nt"&gt;-s&lt;/span&gt; developer &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
bin/magento cache:clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the Store front and admin URLs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://magento2.rooter.test" rel="noopener noreferrer"&gt;https://magento2.rooter.test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://magento2.rooter.test/admin" rel="noopener noreferrer"&gt;https://magento2.rooter.test/admin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tcharaaam!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a59fln3vusfjdvy9pma.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a59fln3vusfjdvy9pma.gif" alt="home" width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What really blows me away is the speed. Running Magento natively on Mac makes everything super fast and smooth.&lt;/p&gt;




&lt;h3&gt;
  
  
  Rooter Appendix
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The &lt;code&gt;.devenv&lt;/code&gt; directory
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;.devenv&lt;/code&gt; directory contains the data about the profile, nix garbage collector, the stack state, etc.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.devenv/state&lt;/code&gt; directory is where some of the stack code lives, as for example, &lt;code&gt;elasticsearch&lt;/code&gt;, &lt;code&gt;mysql&lt;/code&gt;, &lt;code&gt;php-fpm&lt;/code&gt;, &lt;code&gt;nginx&lt;/code&gt;, &lt;code&gt;rabbitmq&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;You don't need to touch these folders or the files on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrgvbrdcu62raduxrgoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrgvbrdcu62raduxrgoj.png" alt=".devenv directory" width="236" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Versioning
&lt;/h4&gt;

&lt;p&gt;Which files and directories should you version or remove from versioning:&lt;/p&gt;

&lt;p&gt;You don't need to version the files and folders below, so add them to your &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.devenv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.direnv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need to version the files below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.devenv.flake.nix&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.envrc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devenv.lock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devenv.nix&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devenv.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; None of this files is required by rooter. They are required from &lt;code&gt;devenv&lt;/code&gt; and &lt;code&gt;direnv&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Diving deeper into the most important files
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;.env&lt;/code&gt; file:
&lt;/h5&gt;

&lt;p&gt;Contains all variable environments that is used in your project stack&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ey115h4spwg2ygm5n8f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ey115h4spwg2ygm5n8f.png" alt="dot env file" width="800" height="725"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ROOTER_ENV_TYPE&lt;/code&gt; defines the type of the environment, it can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;magento1&lt;/li&gt;
&lt;li&gt;magento2&lt;/li&gt;
&lt;li&gt;php-plan&lt;/li&gt;
&lt;li&gt;shopware6&lt;/li&gt;
&lt;li&gt;symfony&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;DEVENV_HTTP_PORT&lt;/code&gt; defines the http port used from the Nginx webserver&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_HTTPS_PORT&lt;/code&gt; defines the https (SSL) port used from the Nginx webserver&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_DB_PORT&lt;/code&gt; defines the Mysql/MariaDB/Percona database port&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the current version of &lt;code&gt;rooter&lt;/code&gt;, only Mysql* database is supported.&lt;/p&gt;

&lt;p&gt;Mysql* I mean any of the versions or forks of it, for instance MariaDB, Percona, etc.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_MAIL_SMTP_PORT&lt;/code&gt; defines the &lt;a href="https://github.com/axllent/mailpit" rel="noopener noreferrer"&gt;mailpit&lt;/a&gt; SMTP port&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_MAIL_UI_PORT&lt;/code&gt; defines the &lt;a href="https://github.com/axllent/mailpit" rel="noopener noreferrer"&gt;mailpit&lt;/a&gt; user interface port&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_REDIS_PORT&lt;/code&gt; the name already explains it :)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_AMQP_PORT&lt;/code&gt; defines the &lt;a href="https://rabbitmq.com/" rel="noopener noreferrer"&gt;RabbitMQ&lt;/a&gt; port that will be used in your application&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_AMQP_MANAGEMENT_PORT&lt;/code&gt; defines the RabbitMQ admin panel&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_ELASTICSEARCH_PORT&lt;/code&gt; defines the &lt;a href="https://www.elastic.co/elasticsearch" rel="noopener noreferrer"&gt;ElasticSearch&lt;/a&gt; port that will be used from your application&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_ELASTICSEARCH_TCP_PORT&lt;/code&gt; the name already explains it :)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEVENV_PROCESS_COMPOSE_PORT&lt;/code&gt; the name already explains it :)&lt;/p&gt;

&lt;p&gt;We'll see more about the process compose later.&lt;/p&gt;

&lt;p&gt;In case you noticed and are wondering, where the heck did the values of the ports defined in these variables come from?&lt;/p&gt;

&lt;p&gt;Rooter has a mechanism that will get the available ports in your environment, taking into account the existing environments that were created by rooter.&lt;/p&gt;

&lt;p&gt;It will assign ports using certain ranges, you can see how it works in &lt;a href="https://github.com/run-as-root/rooter/blob/main/src/Manager/PortManager.php" rel="noopener noreferrer"&gt;this&lt;/a&gt; file, please look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3wya2zvrod8cuniuqkis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3wya2zvrod8cuniuqkis.png" alt="rooter ports manager" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;.envrc&lt;/code&gt; file:
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy557ojp5jr7v8uu5btp0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy557ojp5jr7v8uu5btp0.png" alt="envrc file" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This file is used by the &lt;code&gt;direnv&lt;/code&gt; tool.&lt;/p&gt;

&lt;p&gt;It will load all the declared stack to the current terminal context.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;devenv.nix&lt;/code&gt; file:
&lt;/h5&gt;

&lt;p&gt;This file is used by &lt;code&gt;devenv&lt;/code&gt;, it uses the &lt;a href="https://nixos.org/manual/nix/stable/language/index.html" rel="noopener noreferrer"&gt;Nix language&lt;/a&gt; to declare the environment.&lt;/p&gt;

&lt;p&gt;You can find more information about it &lt;a href="https://devenv.sh/basics/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's get more details of the most important parts of this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Nix, when you see this line, it's like setting up a template for a function. It says that the function will at least get these four things: pkgs, inputs, lib, and config. But it's cool because it can also get more stuff using the &lt;code&gt;...&lt;/code&gt; thingy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
    &lt;span class="nv"&gt;rooterBin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;getEnv&lt;/span&gt; &lt;span class="s2"&gt;"ROOTER_BIN"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;getEnv&lt;/span&gt; &lt;span class="s2"&gt;"ROOTER_BIN"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s2"&gt;"rooter"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;composerPhar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;fetchurl&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/composer/composer/releases/download/2.2.22/composer.phar"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1lmibmdlk2rsrf4zr7xk4yi5rhlmmi8f2g8h2izb8x4sik600dbx"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nv"&gt;magerun2Phar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;fetchurl&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/netz98/n98-magerun2/releases/download/7.2.0/n98-magerun2.phar"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0z1dkxz69r9r9gf8xm458zysa51f1592iymcp478wjx87i6prvn3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;let...in&lt;/code&gt; block in the provided &lt;code&gt;devenv.nix&lt;/code&gt; file defines a scope for local definitions that can be used later in the expression. This construct allows for declaring variables and their values before using them in the main body of the Nix expression. &lt;/p&gt;

&lt;p&gt;Here's a breakdown of the let block and its components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;rooterBin&lt;/strong&gt;: Defined based on the ROOTER_BIN environment variable. If set, rooterBin uses its value; if not, it defaults to "rooter". Enables flexible configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;composerPhar/magerun2Phar&lt;/strong&gt;: Downloads the &lt;code&gt;Composer PHAR&lt;/code&gt; and &lt;code&gt;n98-magerun2&lt;/code&gt; PHAR file from GitHub using a URL and a sha256 hash for security.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;    &lt;span class="nv"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"magento2"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;PROJECT_HOST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"magento2.rooter.test"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;NGINX_PKG_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nginx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;DEVENV_STATE_NGINX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;DEVENV_STATE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/nginx"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;DEVENV_PHPFPM_SOCKET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;DEVENV_STATE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/php-fpm.sock"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;DEVENV_DB_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;DEVENV_DB_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;DEVENV_DB_PASS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;DEVENV_AMQP_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"guest"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;DEVENV_AMQP_PASS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"guest"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;env&lt;/code&gt; block declares the environment variables.&lt;/p&gt;

&lt;p&gt;The project's domain is determined by the &lt;code&gt;PROJECT_HOST&lt;/code&gt; variable. So, you can access the project using the address: &lt;code&gt;https://magento2.rooter.test&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you need to change the &lt;code&gt;PROJECT_HOST&lt;/code&gt; variable value, follow the instructions &lt;a href="https://github.com/run-as-root/rooter/blob/main/docs/CONFIGURATION.md#custom-tld" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is possible to have custom subdomains, you can see more info about it &lt;a href="https://github.com/run-as-root/rooter/blob/main/docs/CONFIGURATION.md#domains-and-subdomains" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just a heads up, the database will use as name, user, and password, all set to app by default. Feel free to tweak these settings whenever you need.&lt;/p&gt;

&lt;p&gt;Similarly, for RabbitMQ, the default user and password are both guest. You're welcome to adjust these as necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3slh6c1t0cmxe1oeblyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3slh6c1t0cmxe1oeblyg.png" alt="php declaration" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where we define and set up PHP. If you ever need to switch the PHP version, simply make the change in the highlighted section shown in the image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva57nptpoybqwh1o6ba1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva57nptpoybqwh1o6ba1.png" alt="Mysql" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same for MariaDb version. If you need a different version just change it.&lt;/p&gt;

&lt;p&gt;To know what are the supported versions, you can search in directly in the &lt;a href="https://search.nixos.org/packages" rel="noopener noreferrer"&gt;nix packages page&lt;/a&gt;, for example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8avwfu6izo8ss22c9g1f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8avwfu6izo8ss22c9g1f.gif" alt="Mysql search" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; please note that we're using the &lt;code&gt;unstable&lt;/code&gt; channel, it is the default channel for devenv, because it has more packages and with newer versions on it. So when you'll search the package, don't forget to select the unstable channel. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6ggck7a05y7oq60cs9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6ggck7a05y7oq60cs9a.png" alt="unstable channel" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last we have RabbitMQ declaration, if your project does not use it, just remove it from the &lt;code&gt;devenv.nix&lt;/code&gt; file. We'll maintain it :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1b5g72lioenu2harwdm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1b5g72lioenu2harwdm2.png" alt="Rabbit MQ" width="794" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;devenv.yaml&lt;/code&gt; file:
&lt;/h5&gt;

&lt;p&gt;This file is used by &lt;code&gt;devenv&lt;/code&gt;. It will serve to declare what is the source of the packages. You can have multiple &lt;a href="https://devenv.sh/inputs/" rel="noopener noreferrer"&gt;inputs&lt;/a&gt;, using different &lt;a href="https://nixos.wiki/wiki/Nix_channels" rel="noopener noreferrer"&gt;channels&lt;/a&gt;, for example.&lt;/p&gt;

&lt;h4&gt;
  
  
  Accessing the &lt;code&gt;traefik&lt;/code&gt; dashboard
&lt;/h4&gt;

&lt;p&gt;To access the traefik dashboard, just type &lt;code&gt;rooter traefik:dashboard&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqe0yeslhhge29a9loe7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqe0yeslhhge29a9loe7i.png" alt="traefik" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Accessing the &lt;code&gt;mailpit&lt;/code&gt; UI
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://mailpit.axllent.org/" rel="noopener noreferrer"&gt;Mailpit&lt;/a&gt; is a fork of &lt;a href="https://github.com/mailhog/MailHog" rel="noopener noreferrer"&gt;mailhog&lt;/a&gt;, It is newer and constantly receives updates.&lt;/p&gt;

&lt;p&gt;It is per environment it will have always the URL with this pattern:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://PROJECT_NAME-mail.rooter.test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In our case it will be:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://magento2-mail.rooter.test" rel="noopener noreferrer"&gt;http://magento2-mail.rooter.test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatcmny7lexvfqlnoyr0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatcmny7lexvfqlnoyr0j.png" alt="mailpit" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;PROJECT_NAME&lt;/code&gt; variable is defined in the &lt;code&gt;devenv.nix&lt;/code&gt; file&lt;/p&gt;

&lt;h4&gt;
  
  
  Rooter commands
&lt;/h4&gt;

&lt;p&gt;Just a heads up, to explore the existing rooter commands, you can simply run the command &lt;code&gt;rooter commands&lt;/code&gt;. This will give you a list of all available commands. Happy exploring!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx8gty5onb8b2rbo5wgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx8gty5onb8b2rbo5wgq.png" alt="rooter commands" width="800" height="970"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Xdebug
&lt;/h4&gt;

&lt;p&gt;The only thing action you need to configure Xdebug is to set this environment env to your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export XDEBUG_CONFIG="idekey=PHPSTORM-XDEBUG"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can append it with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export XDEBUG_CONFIG="idekey=PHPSTORM-XDEBUG"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're able to debug your Magento 2 store on CLI or throughout web without any configuration.&lt;/p&gt;

&lt;p&gt;On PHPStorm for instance, you just have to click on the "Bug" button to start listening to Xdebug connections:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1dvth5rg2tfhn3ng8dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1dvth5rg2tfhn3ng8dd.png" alt="Xdebug" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you have any specific scenarios you'd like guidance on, like setting up Magento with multiple websites or store views, feel free to leave your question in the comments below. I'll do my best to assist you!&lt;/p&gt;

&lt;p&gt;I hope you found this helpful! 👋 &lt;/p&gt;

</description>
      <category>magento2</category>
      <category>tutorial</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Preventing Transaction Loss: Unleashing the Power of Resilient Transactions with RabbitMQ dead-letter Exchanges in Magento 2</title>
      <dc:creator>Cristiano Pacheco</dc:creator>
      <pubDate>Mon, 28 Aug 2023 10:57:40 +0000</pubDate>
      <link>https://forem.com/run_as_root/preventing-transaction-loss-unleashing-the-power-of-resilient-transactions-with-rabbitmq-dead-letter-exchanges-in-magento-2-8h0</link>
      <guid>https://forem.com/run_as_root/preventing-transaction-loss-unleashing-the-power-of-resilient-transactions-with-rabbitmq-dead-letter-exchanges-in-magento-2-8h0</guid>
      <description>&lt;p&gt;This post will guide Magento 2 developers through implementing a message queue retry mechanism using the RabbitMQ dead-letter exchange feature.&lt;/p&gt;

&lt;p&gt;To assist us in this endeavor, we will leverage the &lt;a href="https://github.com/run-as-root/magento2-message-queue-retry" rel="noopener noreferrer"&gt;Message Queue Retry&lt;/a&gt; module by &lt;a href="https://run-as-root.sh" rel="noopener noreferrer"&gt;run-as-root&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is RabbitMQ?&lt;/li&gt;
&lt;li&gt;What is a dead-letter exchange?&lt;/li&gt;
&lt;li&gt;Examples of transaction loss scenarios&lt;/li&gt;
&lt;li&gt;Practical case scenario&lt;/li&gt;
&lt;li&gt;Crafting an effective retry strategy for queue messages&lt;/li&gt;
&lt;li&gt;Practical case scenario with queue retry&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is RabbitMQ?
&lt;/h3&gt;

&lt;p&gt;RabbitMQ is a widely embraced open-source Message Queue software, facilitating seamless interaction and scalability across numerous applications. As a proficient messaging broker, RabbitMQ furnishes a unified platform catering to Asynchronous messaging needs. Within this platform, applications gain the capability to transmit and receive messages securely, with RabbitMQ diligently ensuring the sanctuary of your messages until they are consumed.&lt;/p&gt;

&lt;p&gt;Since version 2.1.0, Magento 2 has offered native RabbitMQ support, enabling effortless queue configuration through XML settings. For further details, you can explore additional information &lt;a href="https://developer.adobe.com/commerce/php/development/components/message-queues/configuration/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a dead-letter exchange?
&lt;/h3&gt;

&lt;p&gt;This feature functions as a safety net within the messaging architecture, intended to manage messages that encounter unsuccessful processing by the consumer. &lt;/p&gt;

&lt;p&gt;The dead-letter exchange operates as a mechanism for directing these problematic messages to a designated queue referred to as a dead-letter queue. This facilitates developers in isolating and inspecting troublesome messages without interrupting the primary processing flow, enabling them to analyze these messages, identify the underlying reasons for processing failures, and implement essential adjustments to ensure smooth operation. &lt;/p&gt;

&lt;p&gt;It's particularly recommended for scenarios where upholding message integrity, diagnosing processing errors, and averting message loss is paramount.&lt;/p&gt;

&lt;h4&gt;
  
  
  Examples of transaction loss scenarios:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Exporting the customers' data to a CRM&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Possible issue&lt;/strong&gt;: The CRM credentials were modified, but the changes were not reflected in the Magento integration settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consequence&lt;/strong&gt;: This mismatch in credentials will result in failed API calls due to the usage of incorrect or invalid authentication information.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Exporting the orders to an ERP&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Possible issue&lt;/strong&gt;: During a marketing campaign, the store's throughput surged by 200%, leading to a substantial rise in incoming orders; however, the ERP system could only accommodate its standard order import capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consequence&lt;/strong&gt;: Only a fraction of the increased order influx will be successfully exported to the ERP system, potentially causing delays and incomplete order processing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Scheduled price uplift&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine having the capability to schedule a comprehensive price uplift by 10% for the entire catalog of your store.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Possible issue&lt;/strong&gt;: Deadlock encountered while saving product and price information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consequence&lt;/strong&gt;: The product prices may not be accurate.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical case scenario
&lt;/h3&gt;

&lt;p&gt;A typical case in e-commerce is exporting orders to an ERP or OMS. We will implement an asynchronous order export architecture, where for each placed order, a message is created with the order id and sent to a queue. So that a consumer can later read this message and export it to the external system.&lt;/p&gt;

&lt;p&gt;To simplify this example, let's declare the topic's name, exchange, queue, and bindings with the same name: &lt;code&gt;erp_order_export&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To handle this messaging, we'll utilize RabbitMQ as the broker.&lt;/p&gt;

&lt;p&gt;You can find the complete code for the module on &lt;a href="https://github.com/cristiano-pacheco/magento2-order-export" rel="noopener noreferrer"&gt;this&lt;/a&gt; repository.&lt;/p&gt;

&lt;p&gt;We have to create four files to declare our queue.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;etc/communication.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
    &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:Communication/etc/communication.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;topic&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;request=&lt;/span&gt;&lt;span class="s"&gt;"CristianoPacheco\OrderExport\Api\Data\OrderExportDataInterface"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;etc/queue_consumer.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework-message-queue:etc/consumer.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;consumer&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;queue=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;connection=&lt;/span&gt;&lt;span class="s"&gt;"amqp"&lt;/span&gt;
              &lt;span class="na"&gt;handler=&lt;/span&gt;&lt;span class="s"&gt;"CristianoPacheco\OrderExport\Queue\Consumer\ErpOrderExportConsumer::execute"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;etc/queue_publisher.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework-message-queue:etc/publisher.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;publisher&lt;/span&gt; &lt;span class="na"&gt;topic=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"amqp"&lt;/span&gt; &lt;span class="na"&gt;exchange=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/publisher&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;etc/queue_topology.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework-message-queue:etc/topology.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;exchange&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;connection=&lt;/span&gt;&lt;span class="s"&gt;"amqp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;binding&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;topic=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;destinationType=&lt;/span&gt;&lt;span class="s"&gt;"queue"&lt;/span&gt; &lt;span class="na"&gt;destination=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/exchange&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the command below in order to Magento send the command to create the exchange, queue and bindings on RabbitMQ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento setup:upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will look like this on RabbitMQ admin:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cn2as7fygwibk5y8s5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cn2as7fygwibk5y8s5d.png" alt="exchange" width="723" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcoztkd9mjxxnctkt20ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcoztkd9mjxxnctkt20ga.png" alt="Queue" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Visually, our configs will generate something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma4lo5xr9xyjqzat4ymf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma4lo5xr9xyjqzat4ymf.png" alt="queue" width="800" height="847"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: It would make more sense to configure a &lt;a href="https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchange-direct" rel="noopener noreferrer"&gt;direct exchange&lt;/a&gt;. However, up to the current version of Magento (2.4.6), only &lt;a href="https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchange-topic" rel="noopener noreferrer"&gt;topic exchanges&lt;/a&gt; are supported.&lt;/p&gt;

&lt;p&gt;Now that the queue is set up, we must send the order ID to the &lt;code&gt;erp_order_export&lt;/code&gt; queue every time a successful order is placed.&lt;/p&gt;

&lt;p&gt;We can easily do this by listening to the event &lt;code&gt;sales_model_service_quote_submit_success&lt;/code&gt; via an observer:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;etc/events.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:Event/etc/events.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;event&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sales_model_service_quote_submit_success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;observer&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_export_order"&lt;/span&gt; &lt;span class="na"&gt;instance=&lt;/span&gt;&lt;span class="s"&gt;"CristianoPacheco\OrderExport\Observer\SendOrderToQueueObserver"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/event&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I won't post here the Observer code or the entire implementation. The complete working code is in the &lt;a href="https://github.com/cristiano-pacheco/magento2-order-export" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. If you want to simulate the scenarios, please install the module.&lt;/p&gt;

&lt;p&gt;Our consumer will use a service to perform our "fake" order export. To simulate an error, our service will always throw an exception:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;CristianoPacheco\OrderExport\Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;CristianoPacheco\OrderExport\Api\Data\OrderExportDataInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExportOrderToErpService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;OrderExportDataInterface&lt;/span&gt; &lt;span class="nv"&gt;$orderExportData&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$orderId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$orderExportData&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getOrderId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"The order &lt;/span&gt;&lt;span class="nv"&gt;$orderId&lt;/span&gt;&lt;span class="s2"&gt; id is invalid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the current configuration, orders will enter the &lt;code&gt;erp_order_export&lt;/code&gt; queue and can be "exported" during the execution of our consumer.&lt;/p&gt;

&lt;p&gt;To run our consumer and export only one order per execution, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento queue:consumer:start erp_order_export &lt;span class="nt"&gt;--single-thread&lt;/span&gt; &lt;span class="nt"&gt;--max-messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What will happen at the end of the execution?&lt;/p&gt;

&lt;p&gt;The service will throw an exception, and it will be handled here:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vendor/magento/framework-message-queue/Consumer.php:261&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famgo3g8dis9jnkmn36s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famgo3g8dis9jnkmn36s4.png" alt="exception-handle" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the message will be rejected, and the requeue flag will have &lt;code&gt;false&lt;/code&gt; as the value. In other words, the message will be removed from the queue, and the order will not be exported to the ERP.&lt;/p&gt;

&lt;p&gt;Well done! We managed to simulate a transaction loss.&lt;/p&gt;

&lt;p&gt;In day-to-day scenarios, probably (I hope so), exceptions are handled at the service or the consumer's execution entry point, and the message would be sent back to the original queue or even taken manually in cases of error, such as sending an alert, or persisting the message in a database, etc.&lt;/p&gt;

&lt;p&gt;What if there was a way to automatically identify without manual work when there are errors in message processing, allowing the possibility to optimize and standardize this process?&lt;/p&gt;

&lt;p&gt;Yes, there is. We can delegate this hard work to RabbitMQ via a dead-letter exchange.&lt;/p&gt;

&lt;h3&gt;
  
  
  Crafting an Effective Retry Strategy for Queue Messages
&lt;/h3&gt;

&lt;p&gt;So, how do we ensure that our messages reach their destination in the face of these intermittent failures? This is where the concept of a retry strategy comes into play. A retry strategy outlines how we handle failed operations by making subsequent attempts at sending the same message. When exporting an order to ERP, adopting a well-defined retry strategy can significantly enhance the reliability of our application.&lt;/p&gt;

&lt;p&gt;For this specific case, three attempts are reasonable.&lt;/p&gt;

&lt;p&gt;So let's define our requirements, it should be possible to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reprocess the messages&lt;/li&gt;
&lt;li&gt;Set processing retry limit&lt;/li&gt;
&lt;li&gt;Set an interval in minutes for each retry attempt&lt;/li&gt;
&lt;li&gt;Find out what error was generated during message processing&lt;/li&gt;
&lt;li&gt;See what the message payload is&lt;/li&gt;
&lt;li&gt;If the limit of retries is reached, we must provide a way to manage message processing manually

&lt;ul&gt;
&lt;li&gt;Resend the message to the queue&lt;/li&gt;
&lt;li&gt;Discard the message&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Steps to achieve our goal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We will add a second queue (&lt;code&gt;erp_order_export_delay&lt;/code&gt;) in RabbitMQ to store the message for a specific lifetime. This queue will not have a consumer. It will only serve to "delay" processing the message in the source queue (&lt;code&gt;erp_order_export&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the time to live is reached, RabbitMQ will automatically send the message to the source queue (&lt;code&gt;erp_order_export&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the retry limit is reached, the message will be stored in a database table for manual management.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maybe the ERP server is down, or some order data is incorrect, so we have to reprocess the messages later.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 1 and 2 can be configured in the queue declaration, and RabbitMQ natively supports it.&lt;/p&gt;

&lt;p&gt;Step 3 is a capability provided by the run as root &lt;a href="https://github.com/run-as-root/magento2-message-queue-retry" rel="noopener noreferrer"&gt;Message Queue Retry&lt;/a&gt; module.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical case scenario with queue retry
&lt;/h3&gt;

&lt;p&gt;Firstly we need to &lt;a href="https://github.com/run-as-root/magento2-message-queue-retry#installation" rel="noopener noreferrer"&gt;install&lt;/a&gt; the message queue retry module and &lt;a href="https://github.com/run-as-root/magento2-message-queue-retry#3-enabling-the-message-queue-retry-admin-configuration" rel="noopener noreferrer"&gt;enable&lt;/a&gt; the behavior to persist the messages on the database after the retry limit is reached.&lt;/p&gt;

&lt;p&gt;No we have to configure our dead-letter exchange. The complete implementation of code below can be found &lt;a href="https://github.com/cristiano-pacheco/magento2-order-export/tree/dead-letter-exchange" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll use the &lt;code&gt;exp_order_export_delay&lt;/code&gt; as the name for the topic, exchange, queue and bindings.&lt;/p&gt;

&lt;p&gt;Declaring the topic:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;etc/communication.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:Communication/etc/communication.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;topic&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;request=&lt;/span&gt;&lt;span class="s"&gt;"CristianoPacheco\OrderExport\Api\Data\OrderExportDataInterface"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;topic&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;request=&lt;/span&gt;&lt;span class="s"&gt;"CristianoPacheco\OrderExport\Api\Data\OrderExportDataInterface"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Declaring the retry limit:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;etc/queue_retry.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:RunAsRoot:module:RunAsRoot_MessageQueueRetry:/etc/queue_retry.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;topic&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;retryLimit=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Declaring the dead-letter exchange:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;etc/queue_topology.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework-message-queue:etc/topology.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;exchange&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;connection=&lt;/span&gt;&lt;span class="s"&gt;"amqp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;binding&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;topic=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt; &lt;span class="na"&gt;destinationType=&lt;/span&gt;&lt;span class="s"&gt;"queue"&lt;/span&gt; &lt;span class="na"&gt;destination=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-exchange"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export_delay&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-routing-key"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export_delay&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/binding&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/exchange&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;exchange&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;connection=&lt;/span&gt;&lt;span class="s"&gt;"amqp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;binding&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;topic=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;destinationType=&lt;/span&gt;&lt;span class="s"&gt;"queue"&lt;/span&gt;
                 &lt;span class="na"&gt;destination=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-exchange"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-routing-key"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-message-ttl"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;60000&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- 1 minute in  milliseconds --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/binding&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/exchange&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a closer look at each change in the file above.&lt;/p&gt;

&lt;p&gt;1- the arguments &lt;code&gt;x-dead-letter-exchange&lt;/code&gt; and &lt;code&gt;x-dead-letter-routing-key&lt;/code&gt; will tell RabbitMQ to automatically send the messages to the &lt;code&gt;erp_order_export_delay&lt;/code&gt; exchange in case the message is &lt;a href="https://www.rabbitmq.com/confirms.html" rel="noopener noreferrer"&gt;negatively acknowledged&lt;/a&gt; (rejected or nack with requeue parameter set to false).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-exchange"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export_delay&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-routing-key"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export_delay&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- We declared a the &lt;code&gt;erp_order_export_delay&lt;/code&gt; exchange and bound it to the &lt;code&gt;erp_order_export_delay&lt;/code&gt; queue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;exchange&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;connection=&lt;/span&gt;&lt;span class="s"&gt;"amqp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;binding&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;topic=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt; &lt;span class="na"&gt;destinationType=&lt;/span&gt;&lt;span class="s"&gt;"queue"&lt;/span&gt; &lt;span class="na"&gt;destination=&lt;/span&gt;&lt;span class="s"&gt;"erp_order_export_delay"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- The arguments &lt;code&gt;x-dead-letter-exchange&lt;/code&gt; and &lt;code&gt;x-dead-letter-routing-key&lt;/code&gt; defines the return path for the message and the &lt;code&gt;x-message-ttl&lt;/code&gt; has an integer number in milliseconds that defines when the message will return to the exchanged defined in the previous two arguments.&lt;/p&gt;

&lt;p&gt;Remembering that this queue does not have a consumer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-exchange"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-dead-letter-routing-key"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;erp_order_export&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"x-message-ttl"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;60000&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- 1 minute in  milliseconds --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visually, our new configs will generate something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6qtv7ttuiotgttgufem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6qtv7ttuiotgttgufem.png" alt="queue-after-config" width="800" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We always send the messages to an exchange and the exchange will forward the messages to one or more queues. It is the same with dead-letter exchanges.&lt;/p&gt;

&lt;p&gt;Now we have to manually delete the &lt;code&gt;erp_order_export&lt;/code&gt; exchange and queue in RabbitMQ, because it won't be updated. You can do it in the RabbitMQ admin panel or via CLI.&lt;/p&gt;

&lt;p&gt;After you did it, you have to run the command below to reflect our changes in RabbitMQ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento setup:upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we navigate again in the RabbitMQ panel we should see:&lt;/p&gt;

&lt;p&gt;Exchanges:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhazsls98p4699zaeyviv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhazsls98p4699zaeyviv.png" alt="dead-letter-exchanges" width="718" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we open our exchanges an expand the bindings, is it possible to see the arguments we have declared before:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxj1znm0kj9sc3rd8srx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxj1znm0kj9sc3rd8srx.png" alt="exchange-1" width="782" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm5xak26y98lffgxzoao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm5xak26y98lffgxzoao.png" alt="exchange-2" width="771" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Queues:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv3m304jvaxfyhmv3zon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv3m304jvaxfyhmv3zon.png" alt="Queues" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you notice that queues now have a few more features?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcipfzbmcrupa7ltc662.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcipfzbmcrupa7ltc662.png" alt="queue-features" width="143" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A homework for you, hover the mouse over each feature and wait a few seconds, a caption will be displayed informing what it is about. Also access each queue and expand the bindings section, see the values contained there.&lt;/p&gt;

&lt;p&gt;Now that we finished our RabbitMQ configuration, let's place a new order and start the &lt;code&gt;erp_order_export&lt;/code&gt; consumer to see what will occur.&lt;/p&gt;

&lt;p&gt;After place an order a new massage is in the &lt;code&gt;erp_order_export&lt;/code&gt; queue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0atw5nkdp37imz7qk3j8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0atw5nkdp37imz7qk3j8.png" alt="first-execution" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's start our consumer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento queue:consumer:start erp_order_export &lt;span class="nt"&gt;--single-thread&lt;/span&gt; &lt;span class="nt"&gt;--max-messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we take a look at the queues we'll see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn5gyb3c2fn6o47el2ci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn5gyb3c2fn6o47el2ci.png" alt="second-execution" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During message consumption, our service threw an exception, simulating a problem and the message was &lt;code&gt;rejected&lt;/code&gt;. RabbitMQ sent the message to the &lt;code&gt;erp_order_expor_delay&lt;/code&gt; queue.&lt;/p&gt;

&lt;p&gt;After one minute the message was automatically sent to the &lt;code&gt;erp_order_export&lt;/code&gt; queue.&lt;/p&gt;

&lt;p&gt;Let's inspect the message headers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4b48c0l9u4wernb1a7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4b48c0l9u4wernb1a7s.png" alt="first-rejection" width="701" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;x-death&lt;/code&gt; header has interesting information about the retries.&lt;/p&gt;

&lt;p&gt;Relevant attribute for us to analyse are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt; - it is the retry number&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reason&lt;/code&gt; - In our case, can be rejected or expired&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;time&lt;/code&gt; - The timestamp of the occurrence&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exchange&lt;/code&gt;, &lt;code&gt;queue&lt;/code&gt;, &lt;code&gt;routing-keys&lt;/code&gt; - Where the message was at the time of occurrence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what that image says is:&lt;/p&gt;

&lt;p&gt;Reading from bottom to top&lt;/p&gt;

&lt;p&gt;First occurrence&lt;/p&gt;

&lt;p&gt;The message was in the &lt;code&gt;erp_order_export&lt;/code&gt; queue and while processing it, it was rejected on Saturday, August 26, 2023 9:12:33 PM GMT-03:00&lt;/p&gt;

&lt;p&gt;Second occurrence&lt;/p&gt;

&lt;p&gt;The message was in the &lt;code&gt;erp_order_export_delay&lt;/code&gt; queue, and it was rejected on Saturday, August 26, 2023 9:12:53 PM GMT-03:00&lt;/p&gt;

&lt;p&gt;It has 20 seconds difference because I configured the TTL for 20 seconds :)&lt;/p&gt;

&lt;p&gt;This is the message headers after the second retry:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbctsaq1bd3sahp81t0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbctsaq1bd3sahp81t0u.png" alt="second-execution" width="549" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the third retry:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7pfvhmopq29ulmxkom9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7pfvhmopq29ulmxkom9.png" alt="third-execution" width="515" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What will occur in the next consumer execution?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ini3y2myn7y3uyen9u0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ini3y2myn7y3uyen9u0.png" alt="fourth-execution" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, the run-as-root module intercepted the message processing failure, verified that the message has reached the retry limit and then persisted the message in the Magento database.&lt;/p&gt;

&lt;p&gt;Now it is possible to manage the message through the admin panel, in the path:&lt;/p&gt;

&lt;p&gt;Run as Root &amp;gt; Manage Messages&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1wdd6349xlm39mqiurs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1wdd6349xlm39mqiurs.png" alt="magento-admin" width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now to can decide if you'll discard the message or send it back to the &lt;code&gt;erp_order_export&lt;/code&gt; queue.&lt;/p&gt;

&lt;p&gt;In summary, while multiple approaches exist to tackle this issue, my aim has been to show a straightforward method for to implement a retry mechanism. &lt;/p&gt;

&lt;p&gt;That's it for today, happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>magento2</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Configuring a docker environment for a Magento 2 project</title>
      <dc:creator>Cristiano Pacheco</dc:creator>
      <pubDate>Tue, 25 Jul 2023 19:09:07 +0000</pubDate>
      <link>https://forem.com/run_as_root/configuring-a-docker-environment-for-a-magento-2-project-2bo6</link>
      <guid>https://forem.com/run_as_root/configuring-a-docker-environment-for-a-magento-2-project-2bo6</guid>
      <description>&lt;p&gt;This post will demonstrate how to configure a docker environment with the Warden tool for an existing Magento 2 project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is Warden?&lt;/li&gt;
&lt;li&gt;Why Warden?&lt;/li&gt;
&lt;li&gt;Quickstart&lt;/li&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;Project Stack&lt;/li&gt;
&lt;li&gt;
Configuring a single website/store Magento 2 project

&lt;ul&gt;
&lt;li&gt;Creating the project folder&lt;/li&gt;
&lt;li&gt;Creating the project folder&lt;/li&gt;
&lt;li&gt;Clone the Magento 2 code-base into the code-base folder&lt;/li&gt;
&lt;li&gt;Clone the Warden Magento 2 template&lt;/li&gt;
&lt;li&gt;
Update the warden .env file

&lt;ul&gt;
&lt;li&gt;A brief explanation of the keys in the .env file&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Run the docker environment&lt;/li&gt;

&lt;li&gt;Run composer install&lt;/li&gt;

&lt;li&gt;Copy and rename the env.warden.php file&lt;/li&gt;

&lt;li&gt;

Import the Magento 2 database

&lt;ul&gt;
&lt;li&gt;An Example of the content of this set-default-config.sh script&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Sign the SSL certificate&lt;/li&gt;

&lt;li&gt;Update your /etc/hosts file with the store domain&lt;/li&gt;

&lt;li&gt;Installing the sample data (Optional)&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

Configuring a multiple website/store view Magento 2 project

&lt;ul&gt;
&lt;li&gt;Create a project folder&lt;/li&gt;
&lt;li&gt;Enter the created multisite directory&lt;/li&gt;
&lt;li&gt;Clone the Magento 2 code-base into the multisite code-base folder&lt;/li&gt;
&lt;li&gt;Clone the Warden Magento 2 template&lt;/li&gt;
&lt;li&gt;Change the warden .env file&lt;/li&gt;
&lt;li&gt;Define custom variables for the store domains&lt;/li&gt;
&lt;li&gt;Updates the the defaults config script&lt;/li&gt;
&lt;li&gt;Run the docker environment&lt;/li&gt;
&lt;li&gt;Composer install&lt;/li&gt;
&lt;li&gt;Copy and rename the env.warden.php file into the etc folder&lt;/li&gt;
&lt;li&gt;Import the Magento 2 multisite database&lt;/li&gt;
&lt;li&gt;Sign the SSL certificates for all domains&lt;/li&gt;
&lt;li&gt;Append your /etc/hosts file with the store domains&lt;/li&gt;
&lt;li&gt;Configuring the application domains&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is Warden?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.warden.dev/index.html" rel="noopener noreferrer"&gt;Warden&lt;/a&gt; is a CLI utility for orchestrating Docker-based developer environments that fully support Magento 1, Magento 2, Laravel, Symfony, and Shopware 6 on macOS, Linux and Windows (via WSL2).&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Warden?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Warden lets you run multiple environments simultaneously without conflicting ports.&lt;/li&gt;
&lt;li&gt;Allows you to configure stack versions easily via .env file configuration.&lt;/li&gt;
&lt;li&gt;Provides the full stack needed for a Magento 2 development environment.&lt;/li&gt;
&lt;li&gt;You can extend it and add new features according to your needs.&lt;/li&gt;
&lt;li&gt;No need to version the docker environment in the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quickstart
&lt;/h3&gt;

&lt;p&gt;We will configure two Magento 2 projects, the first project will have one website and one store view, and the second project will have multiple websites and store views.&lt;/p&gt;

&lt;p&gt;The commands exposed here will work in Linux or macOS environment.&lt;/p&gt;

&lt;p&gt;We will use the &lt;code&gt;~/Sites&lt;/code&gt; directory to place the projects. Feel free to put your project in any path on your computer if you change the commands informed here.&lt;/p&gt;

&lt;p&gt;For each project, the following directory structure will be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦project-name
 ┣ 📂code-base
 ┗ 📂docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;project-name/code-base&lt;/code&gt; directory will contain the Magento 2 project code&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;project-name/docker&lt;/code&gt; directory will contain the warden template for our docker environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The structure above is just a personal taste to use in my projects, you can structure as you see fit. For example using the &lt;code&gt;~/.warden&lt;/code&gt; directory&lt;/p&gt;

&lt;p&gt;Your Magento 2 project can be versioned alone in the repository, and there is no need to change the directory architecture.&lt;/p&gt;

&lt;p&gt;Here we'll use a &lt;a href="https://github.com/cristiano-pacheco/warden-env-magento2" rel="noopener noreferrer"&gt;fork&lt;/a&gt; of the &lt;a href="https://github.com/davidalger/warden-env-magento2" rel="noopener noreferrer"&gt;Warden Magento 2 Template&lt;/a&gt; that have a Makefile and a few common commands to facilitate the day-to-day work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;All you need is &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;, &lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;docker-compose&lt;/a&gt; and &lt;a href="https://docs.warden.dev/installing.html" rel="noopener noreferrer"&gt;Warden&lt;/a&gt; installed on your computer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Stack:
&lt;/h3&gt;

&lt;p&gt;For a practical example, we will set up the development environment for an existing Magento 2 project with the stack below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Magento 2.4.4 open source&lt;/li&gt;
&lt;li&gt;Nginx 1.16&lt;/li&gt;
&lt;li&gt;PHP 8.1

&lt;ul&gt;
&lt;li&gt;Composer 2&lt;/li&gt;
&lt;li&gt;Xdebug 3&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;MariaDB 10.4&lt;/li&gt;

&lt;li&gt;Elastic Search 7.16&lt;/li&gt;

&lt;li&gt;Redis 6.2&lt;/li&gt;

&lt;li&gt;RabbitMQ 3.9&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;More details about the required stack for Magento 2 &lt;a href="https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring a single website/store Magento 2 project
&lt;/h3&gt;

&lt;h5&gt;
  
  
  1 Creating the project folder
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ~/Sites/magento244
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2 Enter the created directory
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/Sites/magento244
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3 Clone the Magento 2 code-base into the code-base folder
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:cristiano-pacheco/magento244.git code-base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4 Clone the Warden Magento 2 template
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:cristiano-pacheco/warden-env-magento2.git docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  5 Update the warden .env file
&lt;/h5&gt;

&lt;p&gt;Enter the docker directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/Sites/magento244/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the .env file with the content below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARDEN_ENV_NAME=magento244
WARDEN_ENV_TYPE=magento2
WARDEN_WEB_ROOT=/../code-base

TRAEFIK_DOMAIN=magento244.test
TRAEFIK_SUBDOMAIN=app

WARDEN_DB=1
WARDEN_ELASTICSEARCH=1
WARDEN_VARNISH=0
WARDEN_RABBITMQ=1
WARDEN_REDIS=1

ELASTICSEARCH_VERSION=7.16
MARIADB_VERSION=10.4
NODE_VERSION=10
PHP_VERSION=8.1
PHP_XDEBUG_3=1
COMPOSER_VERSION=2
RABBITMQ_VERSION=3.9
REDIS_VERSION=6.2
VARNISH_VERSION=7.0

MYSQL_USER=magento
MYSQL_PASSWORD=magento
MYSQL_DATABASE=magento

WARDEN_SYNC_IGNORE=

WARDEN_ALLURE=0
WARDEN_SELENIUM=0
WARDEN_SELENIUM_DEBUG=0
WARDEN_BLACKFIRE=0
WARDEN_SPLIT_SALES=0
WARDEN_SPLIT_CHECKOUT=0
WARDEN_TEST_DB=0
WARDEN_MAGEPACK=0

BLACKFIRE_CLIENT_ID=
BLACKFIRE_CLIENT_TOKEN=
BLACKFIRE_SERVER_ID=
BLACKFIRE_SERVER_TOKEN=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  A brief explanation of the keys in the .env file:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WARDEN_ENV_NAME&lt;/strong&gt;
It will be the prefix of the docker containers name and will also serve to &lt;a href="https://docs.warden.dev/configuration/xdebug.html" rel="noopener noreferrer"&gt;configure the xdebug&lt;/a&gt; in your IDE
Example:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan6t9bixxsgitk8sh733.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan6t9bixxsgitk8sh733.png" alt="warden-env-name" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WARDEN_ENV_TYPE&lt;/strong&gt;&lt;br&gt;
It will define the &lt;a href="https://github.com/davidalger/warden/tree/master/environments" rel="noopener noreferrer"&gt;docker compose yaml&lt;/a&gt; files that will be used in the &lt;a href="https://docs.warden.dev/environments.html" rel="noopener noreferrer"&gt;environment&lt;/a&gt;, which can vary according to the chosen platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WARDEN_WEB_ROOT&lt;/strong&gt;&lt;br&gt;
Self explained, you have to inform the root directory of the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TRAEFIK_DOMAIN&lt;/strong&gt;&lt;br&gt;
Traefik is used to &lt;a href="https://doc.traefik.io/traefik/routing/routers/" rel="noopener noreferrer"&gt;route&lt;/a&gt; the requests to the services (containers) dynamically. For example, when there is the cookie XDEBUG_SESSION with the value PHPSTORM, it will send the requests to the php-debug container that has the xdebug enabled. On the contrary, the php-fpm container will receive the request.&lt;br&gt;
You can set the domain you want, just pay attention to the .test suffix, it you configure a domain with a different value you will lost the &lt;a href="https://docs.warden.dev/configuration/dns-resolver.html" rel="noopener noreferrer"&gt;Automatic DNS Resolution&lt;/a&gt; feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TRAEFIK_SUBDOMAIN&lt;/strong&gt;&lt;br&gt;
It is used to set a subdomain for your application, in our example the store can be accessed with the address &lt;code&gt;https://TRAEFIK_SUBDOMAIN.TRAEFIK_DOMAIN&lt;/code&gt; that is: &lt;code&gt;https://app.magento244.test&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WARDEN_DB&lt;/strong&gt;, &lt;strong&gt;WARDEN_ELASTICSEARCH&lt;/strong&gt;, &lt;strong&gt;WARDEN_VARNISH&lt;/strong&gt;, &lt;strong&gt;WARDEN_RABBITMQ&lt;/strong&gt;, &lt;strong&gt;WARDEN_REDIS&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The keys above you can use 0 to disable and 1 to enable. When the value is 0 the container will not run.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;_VERSION&lt;/strong&gt;&lt;br&gt;
The keys with the suffix &lt;code&gt;_VERSION&lt;/code&gt; is to set a specific version to the service. For Magento 2.4.3, for example, you may use PHP 7.4. To do it, you can leave the key as: &lt;code&gt;PHP_VERSION=7.4&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PHP_XDEBUG_3&lt;/strong&gt;&lt;br&gt;
If you set this key with value &lt;code&gt;1&lt;/code&gt;, a different &lt;a href="https://hub.docker.com/r/wardenenv/php-fpm/tags" rel="noopener noreferrer"&gt;tag&lt;/a&gt; of the container &lt;a href="https://hub.docker.com/r/wardenenv/php-fpm" rel="noopener noreferrer"&gt;php-fpm&lt;/a&gt; image will be used. Let's look at the docker-compose yaml generated by warden with the command &lt;code&gt;warden env config&lt;/code&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fporuttzhwqfj60tmd7rw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fporuttzhwqfj60tmd7rw.png" alt="warden-env-config" width="538" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;COMPOSER_VERSION&lt;/strong&gt;
If it has the value = 1 or you ommit this key composer in version 1 will be the default executable, however you can run composer in version 2 with the command &lt;code&gt;composer2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;strong&gt;If you omit or set the value 1 for &lt;code&gt;COMPOSER_VERSION&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyb9lachtmlhc0acul2s2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyb9lachtmlhc0acul2s2.png" alt="composer" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you set the value 2 for &lt;code&gt;COMPOSER_VERSION&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj24n5un8pqql0x6fl4b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj24n5un8pqql0x6fl4b4.png" alt="composer2" width="772" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I prefer to inform the value 2 and already run composer in version 2 with the &lt;code&gt;composer&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;There are more interesting things to configure such as Magento 2 tests, live reload, elastic search and more. You can see this information &lt;a href="https://docs.warden.dev/configuration.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h5&gt;
  
  
  6 Run the docker environment
&lt;/h5&gt;

&lt;p&gt;Inside the &lt;code&gt;~/Sites/magento244/docker&lt;/code&gt; directory type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make docker-up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  7 Run composer install
&lt;/h5&gt;

&lt;p&gt;Inside the &lt;code&gt;~/Sites/magento244/docker&lt;/code&gt; run the command &lt;br&gt;
below to access the PHP container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the composer install command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  8 Copy and rename the &lt;code&gt;env.warden.php&lt;/code&gt; file
&lt;/h5&gt;

&lt;p&gt;It will copy the file to the &lt;code&gt;code-base/etc&lt;/code&gt; directory with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp ~/Sites/magento244/code-base/app/etc/env.warden.php ~/Sites/magento244/code-base/app/etc/env.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;env.warden.php&lt;/code&gt; file has the default configuration entries with the warden hosts for the Mysql database, Redis (session and store cache), RabbitMQ, and Elastic Search.&lt;/p&gt;

&lt;h5&gt;
  
  
  9 Import the Magento 2 database
&lt;/h5&gt;

&lt;p&gt;There is a &lt;a href="https://github.com/cristiano-pacheco/magento244/blob/main/dump.sql.gz" rel="noopener noreferrer"&gt;sample database&lt;/a&gt; inside our &lt;a href="https://github.com/cristiano-pacheco/magento244" rel="noopener noreferrer"&gt;Magento&lt;/a&gt; project, so copy the &lt;code&gt;~/Sites/magento244/code-base/dump.sql.gz&lt;/code&gt; file to &lt;code&gt;~/Sites/magento244/docker/backfill/magento-db.sql.gz&lt;/code&gt; with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp ~/Sites/magento244/code-base/dump.sql.gz ~/Sites/magento244/docker/backfill/magento-db.sql.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a new tab in your terminal and enter the directory &lt;code&gt;~/Sites/magento244/docker&lt;/code&gt; and type the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make db-import
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;db-import&lt;/code&gt; command is one of the custom commands inside the Makefile.&lt;/p&gt;

&lt;p&gt;This command imports the Magento-db.sql.gz database dump to the Magento database in the warden MySQL docker container.&lt;/p&gt;

&lt;p&gt;In addition to importing the database, the &lt;code&gt;~/Sites/magento244/docker/tools/set-default-config.sh&lt;/code&gt; script is then executed to define the project's base URL and create a user for the Magento administrative panel.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;~/Sites/magento244/docker/tools/set-default-config.sh&lt;/code&gt; file, I usually put all the relevant settings to the Magento 2 environment to avoid errors and also to speed up the restoration of the environment as faithful as possible to the actual project.&lt;/p&gt;

&lt;p&gt;Example of settings that are added in this file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project base URLs&lt;/li&gt;
&lt;li&gt;Media and asset URLs&lt;/li&gt;
&lt;li&gt;Payment test credentials&lt;/li&gt;
&lt;li&gt;Changing the Algolia index to the development index, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  An Example of the content of this &lt;code&gt;set-default-config.sh&lt;/code&gt; script:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/common.sh

:: Import the config from files
warden &lt;span class="nb"&gt;env exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php-fpm bin/magento app:config:import

:: Set BASE URL Config
warden &lt;span class="nb"&gt;env exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php-fpm bin/magento config:set web/unsecure/base_url &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;URL_FRONT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
warden &lt;span class="nb"&gt;env exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php-fpm bin/magento config:set web/secure/base_url &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;URL_FRONT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
warden &lt;span class="nb"&gt;env exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php-fpm bin/magento config:set web/unsecure/base_link_url &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;URL_FRONT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
warden &lt;span class="nb"&gt;env exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php-fpm bin/magento config:set web/secure/base_link_url &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;URL_FRONT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

:: Create an admin user
warden &lt;span class="nb"&gt;env exec&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; php-fpm bin/magento admin:user:create &lt;span class="nt"&gt;--admin-user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="nt"&gt;--admin-password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;123123q &lt;span class="nt"&gt;--admin-email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin@example.com &lt;span class="nt"&gt;--admin-firstname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Admin &lt;span class="nt"&gt;--admin-lastname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Admin

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  10 Sign the SSL certificate
&lt;/h5&gt;

&lt;p&gt;Still, inside the &lt;code&gt;~/Sites/magento244/docker&lt;/code&gt; directory, type the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden sign-certificate app.magento244.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  11 Update your &lt;code&gt;/etc/hosts&lt;/code&gt; file with the store domain:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo echo '127.0.0.1 app.magento244.test' &amp;gt;&amp;gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Do the step above only if &lt;a href="https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html" rel="noopener noreferrer"&gt;dnsmasq&lt;/a&gt; is not being used.&lt;/p&gt;

&lt;h5&gt;
  
  
  12 Installing the sample data (Optional)
&lt;/h5&gt;

&lt;p&gt;Access the php container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the command below to install the sample data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/magento sampledata:deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the command below to update the project database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/magento setup:upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're able to access the store with the URLS \o/: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Store Address:&lt;/strong&gt; &lt;a href="https://app.magento244.test" rel="noopener noreferrer"&gt;https://app.magento244.test&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Backend admin panel:&lt;/strong&gt; &lt;a href="https://app.magento244.test/backend" rel="noopener noreferrer"&gt;https://app.magento244.test/backend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foi3oyfrtnwjwt8y1l3ow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foi3oyfrtnwjwt8y1l3ow.png" alt="Store with single domain" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring a multiple website/store view Magento 2 project
&lt;/h3&gt;

&lt;p&gt;This Magento 2 store has been configured with the below structure of websites/stores/store views:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizp3b1ixmdpt3lh0k6ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizp3b1ixmdpt3lh0k6ao.png" alt="store views" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, the main difference is how to configure a local warden environment to support multiple websites/store views with different domains.&lt;/p&gt;
&lt;h5&gt;
  
  
  1 Create a project folder
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ~/Sites/magento244-multisite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  2 Enter the created multisite directory
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/Sites/magento244-multisite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  3 Clone the Magento 2 code-base into the multisite code-base folder
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:cristiano-pacheco/magento244-multisite.git code-base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  4 Clone the Warden Magento 2 template
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:cristiano-pacheco/warden-env-magento2.git docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  5 Change the warden .env file
&lt;/h5&gt;

&lt;p&gt;Enter the docker directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/Sites/magento244-multisite/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the .env file with the content below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARDEN_ENV_NAME=magento244-multisite
WARDEN_ENV_TYPE=magento2
WARDEN_WEB_ROOT=/../code-base

TRAEFIK_DOMAIN=magento244-multisite.test
TRAEFIK_SUBDOMAIN=app

WARDEN_DB=1
WARDEN_ELASTICSEARCH=1
WARDEN_VARNISH=0
WARDEN_RABBITMQ=1
WARDEN_REDIS=1

ELASTICSEARCH_VERSION=7.16
MARIADB_VERSION=10.4
NODE_VERSION=10
PHP_VERSION=8.1
PHP_XDEBUG_3=1
COMPOSER_VERSION=2
RABBITMQ_VERSION=3.9
REDIS_VERSION=6.2
VARNISH_VERSION=7.0

MYSQL_USER=magento
MYSQL_PASSWORD=magento
MYSQL_DATABASE=magento

WARDEN_SYNC_IGNORE=

WARDEN_ALLURE=0
WARDEN_SELENIUM=0
WARDEN_SELENIUM_DEBUG=0
WARDEN_BLACKFIRE=0
WARDEN_SPLIT_SALES=0
WARDEN_SPLIT_CHECKOUT=0
WARDEN_TEST_DB=0
WARDEN_MAGEPACK=0

BLACKFIRE_CLIENT_ID=
BLACKFIRE_CLIENT_TOKEN=
BLACKFIRE_SERVER_ID=
BLACKFIRE_SERVER_TOKEN=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More details about the configuration above was shared in the step 5 of Configuring a single website/store Magento 2 project&lt;/p&gt;

&lt;h5&gt;
  
  
  6 Define custom variables for the store domains
&lt;/h5&gt;

&lt;p&gt;We will define custom variables in &lt;code&gt;~/Sites/magento244-multisite/docker/tools/common.sh&lt;/code&gt; to be able to reuse them later in our &lt;code&gt;set-default-configs.sh&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;URL_WEBSITE_TWO_FRONT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://app.magento244-website-two.test/
&lt;span class="nv"&gt;URL_STORE_VIEW_THREE_US_FRONT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://app.magento244-store-view-three-us.test/
&lt;span class="nv"&gt;URL_STORE_VIEW_THREE_DE_FRONT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://app.magento244-store-view-three-de.test/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  7 Updates the the defaults config script
&lt;/h5&gt;

&lt;p&gt;Add the content of &lt;a href="https://github.com/cristiano-pacheco/warden-env-magento2/blob/multisite/tools/set-default-config.sh" rel="noopener noreferrer"&gt;this file&lt;/a&gt; to the &lt;code&gt;~/Sites/magento244-multisite/docker/tools/set-default-configs.sh&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The goal of the &lt;code&gt;set-default-configs.sh&lt;/code&gt; script was explained here.&lt;/p&gt;

&lt;h5&gt;
  
  
  8 Run the docker environment
&lt;/h5&gt;

&lt;p&gt;Inside the &lt;code&gt;~/Sites/magento244-multisite/docker&lt;/code&gt; directory type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make docker-up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  9 Composer install
&lt;/h5&gt;

&lt;p&gt;Inside the &lt;code&gt;~/Sites/magento244-multisite/docker&lt;/code&gt; run the command below to access the PHP container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the composer install command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  10 Copy and rename the &lt;code&gt;env.warden.php&lt;/code&gt; file into the etc folder
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp ~/Sites/magento244-multisite/code-base/app/etc/env.warden.php ~/Sites/magento244-multisite/code-base/app/etc/env.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  11 Import the Magento 2 multisite database
&lt;/h5&gt;

&lt;p&gt;There is a &lt;a href="https://github.com/cristiano-pacheco/magento244-multisite/blob/main/dump.sql.gz" rel="noopener noreferrer"&gt;sample database&lt;/a&gt; inside our &lt;a href="https://github.com/cristiano-pacheco/magento244-multisite" rel="noopener noreferrer"&gt;Magento&lt;/a&gt; project, so copy the &lt;code&gt;~/Sites/magento244-multisite/code-base/dump.sql.gz&lt;/code&gt; file to &lt;code&gt;~/Sites/magento244-multisite/docker/backfill/magento-db.sql.gz&lt;/code&gt; with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp ~/Sites/magento244-multisite/code-base/dump.sql.gz ~/Sites/magento244-multisite/docker/backfill/magento-db.sql.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a new tab in your terminal and enter the directory &lt;code&gt;~/Sites/magento244-multisite/docker&lt;/code&gt; and type the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make DB-import
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  12 Sign the SSL certificates for all domains
&lt;/h5&gt;

&lt;p&gt;Still, type the commands below inside the &lt;code&gt;~/Sites/magento244-multisite/docker&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;To sign the certificate to the main and the admin store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden sign-certificate app.magento244-multisite.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sign the certificate to the website-two:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden sign-certificate app.magento244-website-two.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sign the certificate to the Store View Three US:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden sign-certificate app.magento244-store-view-three-us.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sign the certificate to the Store View Three DE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warden sign-certificate app.magento244-store-view-three-de.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  13 Append your &lt;code&gt;/etc/hosts&lt;/code&gt; file with the store domains
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1 app.magento244-multisite.test
127.0.0.1 app.magento244-website-two.test
127.0.0.1 app.magento244-store-view-three-us.test
127.0.0.1 app.magento244-store-view-three-de.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Do the step above only if &lt;a href="https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html" rel="noopener noreferrer"&gt;dnsmasq&lt;/a&gt; is not being used.&lt;/p&gt;

&lt;h5&gt;
  
  
  14 Configuring the application domains:
&lt;/h5&gt;

&lt;p&gt;According to the &lt;a href="https://docs.warden.dev/configuration/multipledomains.html" rel="noopener noreferrer"&gt;Warden documentation&lt;/a&gt; we have to create a &lt;code&gt;warden-env.yml&lt;/code&gt; file inside the &lt;code&gt;.warden&lt;/code&gt; directory. Type the commands below:&lt;/p&gt;

&lt;p&gt;Create the &lt;code&gt;.warden-env.yml&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch ~/Sites/magento244-multisite/docker/.warden/warden-env.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put the content below to the &lt;code&gt;.warden-dev.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.5"
services:
  nginx:
    labels:
      - traefik.http.routers.${WARDEN_ENV_NAME}-nginx.rule=
        HostRegexp(`{subdomain:.+}.${TRAEFIK_DOMAIN}`)
        || Host(`${TRAEFIK_DOMAIN}`)
        || HostRegexp(`{subdomain:.+}.magento244-multisite.test`)
        || Host(`magento244-multisite.test`)
        || HostRegexp(`{subdomain:.+}.magento244-website-two.test`)
        || Host(`magento244-website-two.test`)
        || HostRegexp(`{subdomain:.+}.magento244-store-view-three-us.test`)
        || Host(`magento244-store-view-three-us.test`)
        || HostRegexp(`{subdomain:.+}.magento244-store-view-three-de.test`)
        || Host(`magento244-store-view-three-de.test`)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can have a copy of this file &lt;a href="https://github.com/cristiano-pacheco/warden-env-magento2/blob/multisite/.warden/warden-env.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you're done with the settings, look at the &lt;a href="https://traefik.warden.test/dashboard/#/http/routers" rel="noopener noreferrer"&gt;traefik address&lt;/a&gt; to see where this mapping ended up. It will be like as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg09o7z2mum6btyi8f6qb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg09o7z2mum6btyi8f6qb.png" alt="traefik" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;stores.php&lt;/code&gt; the Add the Magento 2 run params to the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd touch ~/Sites/magento244-multisite/code-base/app/etc/stores.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the content of &lt;a href="https://github.com/cristiano-pacheco/magento244-multisite/blob/main/app/etc/stores.php" rel="noopener noreferrer"&gt;this file&lt;/a&gt; in the file above.&lt;/p&gt;

&lt;p&gt;Add the &lt;code&gt;app/etc/stores.php&lt;/code&gt; to the &lt;code&gt;composer.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;It should look like the image below after the change:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbk07awbxm6enr4ojm8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbk07awbxm6enr4ojm8c.png" alt="multi-store-config" width="602" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will force composer to load this file on every request. the file then sets up the store for Magento to load based on the domain, passing the &lt;code&gt;MAGE_RUN_CODE&lt;/code&gt; and &lt;code&gt;MAGE_RUN_TYPE&lt;/code&gt; variables to Nginx.&lt;/p&gt;

&lt;p&gt;Now you're able to access the stores with the URLS \o/: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default Store Address&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://app.magento244-multisite.test" rel="noopener noreferrer"&gt;https://app.magento244-multisite.test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend admin panel&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://app.magento244-multisite.test/backend" rel="noopener noreferrer"&gt;https://app.magento244-multisite.test/backend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Website Two Address&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://app.magento244-multisite.test" rel="noopener noreferrer"&gt;https://app.magento244-multisite.test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Store View Three US Address&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://app.magento244-store-view-three-us.test" rel="noopener noreferrer"&gt;https://app.magento244-store-view-three-us.test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Store View Three DE Address&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://app.magento244-store-view-three-de.test" rel="noopener noreferrer"&gt;https://app.magento244-store-view-three-de.test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;br&gt;
Inside the directory &lt;code&gt;~/Sites/magento244-multisite/code-base&lt;/code&gt;, type the command make, and you will see an output like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakp6pz2504cgp1jn8cy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakp6pz2504cgp1jn8cy3.png" alt="make-command" width="636" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it. If you have any questions, please let us know in the comments 👋&lt;/p&gt;

</description>
      <category>php</category>
      <category>magento2</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
