Setting up a Personal QMK Configurator Development Environment

User avatar
snacksthecat
✶✶✶✶

09 Sep 2022, 23:31

As some may already know I recently needed to setup a personal instance of QMK Configurator to test some things. I did a full write up on my site about how to do this but wanted to post this as well on the forums to spread the info a bit more since my blog is tucked away. Here's a link to the instructions on my site:

https://www.snacksthecat.com/p/setting- ... vironment/

qmk-configurator.png
qmk-configurator.png (107.14 KiB) Viewed 2964 times

Intro

This guide explains the steps I went through to setup my own instance of QMK Configurator. These steps should serve as a general how-to guide and hopefully fill in some gaps for people who may have gotten stuck. Some of the details, specifically adding your own custom keyboard to the configurator, can be approached a few different ways; so the information in that section may be less prescriptive and more for reference.

I did this on a machine running Ubuntu Jammy. I was not able to get this all working locally due to some networking challenges I couldn’t figure out. Due to that issue (and since I wanted to give some people access over the Internet anyways), I hosted my configurator using a cloud service provider. I chose to use Kamatera since they offer a 30 day free trial for 1 server and pricing beyond that was reasonable, but anything similar would work.

As a prerequisite you’ll need to already have Docker and Docker Compose setup. Instructions for installing Docker on Ubuntu (and other distros) can be found on the Docker website. You don’t need Docker Desktop unless you find that useful for managing your containers.

I’d recommend reading through this full post first before trying to follow it step-by-step. I don’t explicity state it in any of the steps but you should try building the containers at various points along the way. The command is: docker compose build

TOC
  1. Setup
  2. Configuring the Web Stack
  3. Additional Modification(s)
  4. Add a Custom Keyboard
  5. Define a Default Layout
  6. Docker Compose
Last edited by snacksthecat on 09 Sep 2022, 23:39, edited 1 time in total.

User avatar
snacksthecat
✶✶✶✶

09 Sep 2022, 23:31

1. Setup

Clone the qmk_web_stack repo from GitHub

Code: Select all

git clone --recurse-submodules https://github.com/qmk/qmk_web_stack.git
One of the submodules fails to clone so you’ll need to do that manually

Code: Select all

cd qmk_web_stack
git clone --recurse-submodules https://github.com/qmk/qmk_metrics_aggregator.git
Run this script in the main project directory to update all submodules to their latest.

Code: Select all

./fix-submodules.sh
You’ll receive an error on qmk_metrics_aggregator but you can ignore it.


2. Configuring the Web Stack

docker-compose.yml

Open docker-compose.yml in a text editor and update the configuration values.

Below is an example where I’ve highlighted the changes for my config.

Note: I couldn’t get the configurator working end-to-end on a local machine, so I ended up using a cloud hosting service. As such, this config assumes that you’re doing the same. You might still be able to get it to work locally.

Double Note: You should probably change to minio secret if you plan to host this online

Code: Select all

version: '3'

services:
  qmk_api:
    build: ./qmk_api
    ports:
      - "5001:5001"
    environment:
      PYTHONUNBUFFERED: 1
      API_URL: http://<your_url>:5001/
      QMK_GIT_URL: https://github.com/<your_github>/qmk_firmware.git
      QMK_GIT_BRANCH: master
      FLASK_GRAPHITE_HOST: qmk_metrics_aggregator
      REDIS_HOST: redis
      RELOAD: 1
      S3_HOST: http://<your_url>:9000
      S3_ACCESS_KEY: minio_dev
      S3_SECRET_KEY: minio_dev_secret
      UPDATE_API: 'true'
    volumes:
      - ./qmk_api:/qmk_api
      - ./qmk_compiler:/qmk_compiler

  qmk_api_tasks:
    build: ./qmk_api_tasks
    command: /bin/true
    ports:
      - "5002:5002"
    environment:
      PYTHONUNBUFFERED: 1
      API_URL: http://<your_url>:5001/
      MSG_ON_GOOD_COMPILE: "no"
      MSG_ON_BAD_COMPILE: "no"
      MSG_ON_S3_SUCCESS: "no"
      REDIS_HOST: redis
      RELOAD: 1
      S3_HOST: http://<your_url>:9000
      S3_ACCESS_KEY: minio_dev
      S3_SECRET_KEY: minio_dev_secret
      UPDATE_API: 'true'
    volumes:
      - ./qmk_api_tasks:/qmk_api_tasks
      - ./qmk_compiler:/qmk_compiler

  qmk_bot:
    build: ./qmk_bot
    environment:
      PYTHONUNBUFFERED: 1
      API_URL: http://<your_url>:5001/
      REDIS_HOST: redis
      RELOAD: 1
      S3_HOST: http://<your_url>:9000
    volumes:
      - ./qmk_bot:/qmk_bot
      - ./qmk_compiler:/qmk_compiler

  qmk_compiler:
    build: ./qmk_compiler
    environment:
      GRAPHITE_HOST: qmk_metrics_aggregator
      MINIO_ACCESS_KEY: minio_dev
      MINIO_SECRET_KEY: minio_dev_secret
      PYTHONUNBUFFERED: 1
      API_URL: http://<your_url>:5001/
      LOG_LEVEL: DEBUG
      QMK_GIT_URL: https://github.com/<your_github>/qmk_firmware.git
      QMK_GIT_BRANCH: master
      REDIS_HOST: redis
      RELOAD: 1
      S3_HOST: http://<your_url>:9000
    volumes:
      - ./qmk_compiler:/qmk_compiler

  qmk_metrics_aggregator:
    build: ./qmk_metrics_aggregator
    environment:
      PYTHONUNBUFFERED: 1
      METRIC_TTL: 600
      GRAPHITE_HOST: graphite
      GRAPHITE_RESOLUTION: 60
    volumes:
      - ./qmk_metrics_aggregator/qmk_metrics_aggregator:/qmk_metrics_aggregator

  qmk_configurator:
    build: ./qmk_configurator
    ports:
      - "5000:80"
    environment:
      QMK_API_URL: http://<your_url>:5001
    volumes:
      - ./qmk_configurator/public/keymaps:/qmk_configurator/dist/keymaps

  minio:
    image: minio/minio
    volumes:
      - minio_data:/data
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ACCESS_KEY: minio_dev
      MINIO_SECRET_KEY: minio_dev_secret
      PYTHONUNBUFFERED: 1
      S3_ACCESS_KEY: minio_dev
      S3_SECRET_KEY: minio_dev_secret
    command: server minio_data --console-address ":9001"
    restart: always

  redis:
    image: qmkfm/redis
    ports:
      - "6379:6379"
    restart: always

  graphite:
    image: qmkfm/qmk_graphite
    ports:
      - "5003:80"
    restart: always

volumes:
  minio_data:

3. Additional Modifications

qmk_api

requirements.txt

I was receiving an error with some of the python package dependencies after launching the configurator. To fix that issue, I needed to add a specific version of one additional dependency in requirements.txt

Code: Select all

werkzeug==2.1.2

User avatar
snacksthecat
✶✶✶✶

09 Sep 2022, 23:31

4. Add a Custom Keyboard

If you’re setting up your own Configurator, it’s likely that the reason for this is to test out your own keyboard firmware. The instructions below will explain how to do that.

It took me a lot of experimenting before I was able to get everything working. I wanted to avoid modifying any of the submodule files but found that some were unavoidable for various reasons.

Note: These instructions explain how to point the configurator to your own keyboard list. So the default list will no longer be available after doing these steps. The steps below are only necessary if that’s your intention.

Custom Keyboard Data

The configurator pulls both the list of keyboard and the individual keyboard info/readme files from https://keyboards.qmk.fm

There were two ways I could think of to get around this: point these URLs to pull from static files or create a custom API that returns this data. Since I was needing the flexibility to make frequent changes I chose the latter. Files are probably easier, though. In either case, the JSON served up to the configurator needs to mimic the structures that are returned by the real keyboards.qmk.fm

These are the relevent endpoints and the structures to mimic:

keyboard_list.json

https://keyboards.qmk.fm/v1/keyboard_list.json

Structure:

Code: Select all

{
   "keyboards":[
      "converter/ibmpc_usb/teensy",
      "converter/ibmpc_usb/promicro"
   ],
   "last_updated":"2022-09-07 03:45:37 GMT"
}
info.json

https://keyboards.qmk.fm/v1/keyboards/< ... /info.json

Structure:

Code: Select all

{
   "last_updated":"2022-09-07 23:57:46 GMT",
   "keyboards":{
      "converter/ibmpc_usb/teensy":{
         "keyboard_name":"converter/ibmpc_usb/teensy",
         "keyboard_folder":"converter/ibmpc_usb/teensy",
         "layouts":{
            "LAYOUT_fullkey":{
               "layout":[
                  {"x":2.0,"y":0.0,"w":1.0,"label":"F13"},
                  {"x":3.0,"y":0.0,"w":1.0,"label":"F14"},
                  {"x":4.0,"y":0.0,"w":1.0,"label":"F15"},
                  {"x":5.0,"y":0.0,"w":1.0,"label":"F16"},
                  {"x":6.5,"y":0.0,"w":1.0,"label":"F17"},
                  {"x":7.5,"y":0.0,"w":1.0,"label":"F18"},
                  {"x":8.5,"y":0.0,"w":1.0,"label":"F19"},
                  {"x":9.5,"y":0.0,"w":1.0,"label":"F20"},
                  {"x":11.0,"y":0.0,"w":1.0,"label":"F21"},
                  {"x":12.0,"y":0.0,"w":1.0,"label":"F22"},
                  {"x":13.0,"y":0.0,"w":1.0,"label":"F23"},
                  {"x":14.0,"y":0.0,"w":1.0,"label":"F24"},
                  {"x":0.0,"y":1.0,"w":1.0,"label":"ESC"},
                  {"x":2.0,"y":1.0,"w":1.0,"label":"F1"},
                  {"x":3.0,"y":1.0,"w":1.0,"label":"F2"},
                  {"x":4.0,"y":1.0,"w":1.0,"label":"F3"},
                  {"x":5.0,"y":1.0,"w":1.0,"label":"F4"},
                  {"x":6.5,"y":1.0,"w":1.0,"label":"F5"},
                  {"x":7.5,"y":1.0,"w":1.0,"label":"F6"},
                  {"x":8.5,"y":1.0,"w":1.0,"label":"F7"},
                  {"x":9.5,"y":1.0,"w":1.0,"label":"F8"},
                  {"x":11.0,"y":1.0,"w":1.0,"label":"F9"},
                  {"x":12.0,"y":1.0,"w":1.0,"label":"F10"},
                  {"x":13.0,"y":1.0,"w":1.0,"label":"F11"},
                  {"x":14.0,"y":1.0,"w":1.0,"label":"F12"},
                  {"x":15.5,"y":1.0,"w":1.0,"label":"PSCR"},
                  {"x":16.5,"y":1.0,"w":1.0,"label":"SLCK"},
                  {"x":17.5,"y":1.0,"w":1.0,"label":"PAUS"},
                  {"x":20.0,"y":1.0,"w":1.0,"label":"VOLD"},
                  {"x":21.0,"y":1.0,"w":1.0,"label":"VOLU"},
                  {"x":22.0,"y":1.0,"w":1.0,"label":"MUTE"},
                  {"x":0.0,"y":2.5,"w":1.0,"label":"GRV"},
                  {"x":1.0,"y":2.5,"w":1.0,"label":"1"},
                  {"x":2.0,"y":2.5,"w":1.0,"label":"2"},
                  {"x":3.0,"y":2.5,"w":1.0,"label":"3"},
                  {"x":4.0,"y":2.5,"w":1.0,"label":"4"},
                  {"x":5.0,"y":2.5,"w":1.0,"label":"5"},
                  {"x":6.0,"y":2.5,"w":1.0,"label":"6"},
                  {"x":7.0,"y":2.5,"w":1.0,"label":"7"},
                  {"x":8.0,"y":2.5,"w":1.0,"label":"8"},
                  {"x":9.0,"y":2.5,"w":1.0,"label":"9"},
                  {"x":10.0,"y":2.5,"w":1.0,"label":"0"},
                  {"x":11.0,"y":2.5,"w":1.0,"label":"MINS"},
                  {"x":12.0,"y":2.5,"w":1.0,"label":"EQL"},
                  {"x":13.0,"y":2.5,"w":1.0,"label":"INT3"},
                  {"x":14.0,"y":2.5,"w":1.0,"label":"BSPC"},
                  {"x":15.5,"y":2.5,"w":1.0,"label":"INS"},
                  {"x":16.5,"y":2.5,"w":1.0,"label":"HOME"},
                  {"x":17.5,"y":2.5,"w":1.0,"label":"PGUP"},
                  {"x":19.0,"y":2.5,"w":1.0,"label":"NLCK"},
                  {"x":20.0,"y":2.5,"w":1.0,"label":"PSLS"},
                  {"x":21.0,"y":2.5,"w":1.0,"label":"PAST"},
                  {"x":22.0,"y":2.5,"w":1.0,"label":"PMNS"},
                  {"x":0.0,"y":3.5,"w":1.5,"label":"TAB"},
                  {"x":1.5,"y":3.5,"w":1.0,"label":"Q"},
                  {"x":2.5,"y":3.5,"w":1.0,"label":"W"},
                  {"x":3.5,"y":3.5,"w":1.0,"label":"E"},
                  {"x":4.5,"y":3.5,"w":1.0,"label":"R"},
                  {"x":5.5,"y":3.5,"w":1.0,"label":"T"},
                  {"x":6.5,"y":3.5,"w":1.0,"label":"Y"},
                  {"x":7.5,"y":3.5,"w":1.0,"label":"U"},
                  {"x":8.5,"y":3.5,"w":1.0,"label":"I"},
                  {"x":9.5,"y":3.5,"w":1.0,"label":"O"},
                  {"x":10.5,"y":3.5,"w":1.0,"label":"P"},
                  {"x":11.5,"y":3.5,"w":1.0,"label":"LBRC"},
                  {"x":12.5,"y":3.5,"w":1.0,"label":"RBRC"},
                  {"x":13.5,"y":3.5,"w":1.5,"label":"BSLS"},
                  {"x":15.5,"y":3.5,"w":1.0,"label":"DEL"},
                  {"x":16.5,"y":3.5,"w":1.0,"label":"END"},
                  {"x":17.5,"y":3.5,"w":1.0,"label":"PGDN"},
                  {"x":19.0,"y":3.5,"w":1.0,"label":"P7"},
                  {"x":20.0,"y":3.5,"w":1.0,"label":"P8"},
                  {"x":21.0,"y":3.5,"w":1.0,"label":"P9"},
                  {"x":22.0,"y":3.5,"w":1.0,"label":"PPLS"},
                  {"x":0.0,"y":4.5,"w":1.75,"label":"CAPS"},
                  {"x":1.75,"y":4.5,"w":1.0,"label":"A"},
                  {"x":2.75,"y":4.5,"w":1.0,"label":"S"},
                  {"x":3.75,"y":4.5,"w":1.0,"label":"D"},
                  {"x":4.75,"y":4.5,"w":1.0,"label":"F"},
                  {"x":5.75,"y":4.5,"w":1.0,"label":"G"},
                  {"x":6.75,"y":4.5,"w":1.0,"label":"H"},
                  {"x":7.75,"y":4.5,"w":1.0,"label":"J"},
                  {"x":8.75,"y":4.5,"w":1.0,"label":"K"},
                  {"x":9.75,"y":4.5,"w":1.0,"label":"L"},
                  {"x":10.75,"y":4.5,"w":1.0,"label":"SCLN"},
                  {"x":11.75,"y":4.5,"w":1.0,"label":"QUOT"},
                  {"x":12.75,"y":4.5,"w":1.0,"label":"NUHS"},
                  {"x":13.75,"y":4.5,"w":1.25,"label":"ENT"},
                  {"x":19.0,"y":4.5,"w":1.0,"label":"P4"},
                  {"x":20.0,"y":4.5,"w":1.0,"label":"P5"},
                  {"x":21.0,"y":4.5,"w":1.0,"label":"P6"},
                  {"x":22.0,"y":4.5,"w":1.0,"label":"PCMM"},
                  {"x":0.0,"y":5.5,"w":1.25,"label":"LSFT"},
                  {"x":1.25,"y":5.5,"w":1.0,"label":"NUBS"},
                  {"x":2.25,"y":5.5,"w":1.0,"label":"Z"},
                  {"x":3.25,"y":5.5,"w":1.0,"label":"X"},
                  {"x":4.25,"y":5.5,"w":1.0,"label":"C"},
                  {"x":5.25,"y":5.5,"w":1.0,"label":"V"},
                  {"x":6.25,"y":5.5,"w":1.0,"label":"B"},
                  {"x":7.25,"y":5.5,"w":1.0,"label":"N"},
                  {"x":8.25,"y":5.5,"w":1.0,"label":"M"},
                  {"x":9.25,"y":5.5,"w":1.0,"label":"COMM"},
                  {"x":10.25,"y":5.5,"w":1.0,"label":"DOT"},
                  {"x":11.25,"y":5.5,"w":1.0,"label":"SLSH"},
                  {"x":12.25,"y":5.5,"w":1.0,"label":"INT1"},
                  {"x":13.25,"y":5.5,"w":1.75,"label":"RSFT"},
                  {"x":16.5,"y":5.5,"w":1.0,"label":"UP"},
                  {"x":19.0,"y":5.5,"w":1.0,"label":"P1"},
                  {"x":20.0,"y":5.5,"w":1.0,"label":"P2"},
                  {"x":21.0,"y":5.5,"w":1.0,"label":"P3"},
                  {"x":22.0,"y":5.5,"w":1.0,"label":"PENT"},
                  {"x":0.0,"y":6.5,"w":1.25,"label":"LCTL"},
                  {"x":1.25,"y":6.5,"w":1.25,"label":"LGUI"},
                  {"x":2.5,"y":6.5,"w":1.25,"label":"LALT"},
                  {"x":3.75,"y":6.5,"w":1.25,"label":"INT5"},
                  {"x":5.0,"y":6.5,"w":2.75,"label":"SPC"},
                  {"x":7.75,"y":6.5,"w":1.25,"label":"INT4"},
                  {"x":9.0,"y":6.5,"w":1.25,"label":"INT2"},
                  {"x":10.25,"y":6.5,"w":1.25,"label":"RALT"},
                  {"x":11.5,"y":6.5,"w":1.25,"label":"RGUI"},
                  {"x":12.75,"y":6.5,"w":1.0,"label":"APP"},
                  {"x":13.75,"y":6.5,"w":1.25,"label":"LCTL"},
                  {"x":15.5,"y":6.5,"w":1.0,"label":"LEFT"},
                  {"x":16.5,"y":6.5,"w":1.0,"label":"DOWN"},
                  {"x":17.5,"y":6.5,"w":1.0,"label":"RGHT"},
                  {"x":19.0,"y":6.5,"w":2.0,"label":"P0"},
                  {"x":21.0,"y":6.5,"w":1.0,"label":"PDOT"},
                  {"x":22.0,"y":6.5,"w":1.0,"label":"PEQL"}
               ],
               "filename":"keyboards/converter/ibmpc_usb/ibmpc_usb.h",
               "c_macro":true
            },
         },
         "maintainer":"qmk",
         "manufacturer":"snacksthecat",
         "url":"",
         "usb":{
            "vid":"0xFEED",
            "pid":"0x6536",
            "device_version":"1.0.0",
            "device_ver":"0x0101"
         },
         "processor":"atmega32u4",
         "processor_type":"avr",
         "platform":"unknown",
         "protocol":"LUFA",
         "bootloader":"atmel-dfu",
         "mouse_key":{
            "enabled":true
         },
         "config_h_features":{
            "bootmagic":false,
            "mousekey":true,
            "extrakey":true,
            "console":true,
            "command":true,
            "nkro":true
         },
         "features":{
            "bootmagic":false,
            "mousekey":true,
            "extrakey":true,
            "console":true,
            "command":true,
            "nkro":true
         },
         "debounce":0,
         "indicators":{
            "caps_lock":"b6"
         },
         "tapping":{
            "term":175
         },
         "matrix_size":{
            "cols":16,
            "rows":8
         },
         "split":{
            "transport":{
               "protocol":"i2c"
            }
         }
      }
   }
}
readme.md

https://keyboards.qmk.fm/v1/keyboards/< ... /readme.md

Structure:

(just a normal readme.md file)

Explained

Your JSON files or APIs will need to be accessible following the URL patterns above. So If I wanted to serve up this JSON data from https://snacksthecat.com, I would need to follow the URL pattern:

Code: Select all

https://snacksthecat.com/v1/keyboards/<keyboard>/info.json
|-------base url-------||----path----||-kb name-||--file--| 

qmk_configurator

Dockerfile

Once I had my APIs setup, I added the necessary environment variable to the qmk_configurator Dockerfile so that it gets picked up by the constants declaration file

Code: Select all

ENV VITE_API_URL=/api
ENV VITE_KEYBOARDS_URL=https://snacksthecat.com

User avatar
snacksthecat
✶✶✶✶

09 Sep 2022, 23:31

5. Define a Default Layout

If you were to spin up the configurator at this point, it should load, but with a totally blank layout. The steps below explain how to create a default layout that gets picked up by the configurator when the keyboard first loads.

qmk_configurator

public/keymaps

The default keymaps for the configurator are all located in:

/qmk_web_stack/qmk_configurator/public/keymaps/

They’re organized by letter, so navigate into the folder with the first letter of your keyboard’s name.

You’ll need to create a new file with a filename that follows this pattern:

<keyboard_name>_default.json

Note: If your keyboard name has slashes in it, you’ll need to replace them with underscores. For instance, my default filename was: converter_ibmpc_usb_teensy_default.json

Below is an example of the contents of one of these default layout files (excuse the formatting):

Code: Select all

{
  "keyboard": "converter/ibmpc_usb/teensy",
  "keymap": "default",
  "commit": "c8ae1cf59b4a2b23a3db6fb638a122ca7b39f5ec",
  "layout": "LAYOUT_fullkey",
  "layers": [
    [
                   "KC_F13", "KC_F14", "KC_F15", "KC_F16", "KC_F17", "KC_F18", "KC_F19", "KC_F20", "KC_F21", "KC_F22", "KC_F23", "KC_F24",
"KC_ESC",        "KC_F1",  "KC_F2",  "KC_F3",  "KC_F4",  "KC_F5",  "KC_F6",  "KC_F7",  "KC_F8",  "KC_F9",  "KC_F10", "KC_F11", "KC_F12", "KC_PSCR", "KC_SLCK", "QK_BOOT", "KC_VOLD", "KC_VOLU", "KC_MUTE",

"KC_GRV", "KC_1", "KC_2", "KC_3", "KC_4", "KC_5", "KC_6", "KC_7", "KC_8", "KC_9", "KC_0", "KC_MINS", "KC_EQL", "KC_INT3", "KC_BSPC", "KC_INS", "KC_HOME", "KC_PGUP", "KC_NLCK", "KC_PSLS", "KC_PAST", "KC_PMNS",
"KC_TAB", "KC_Q", "KC_W", "KC_E", "KC_R", "KC_T", "KC_Y", "KC_U", "KC_I", "KC_O", "KC_P", "KC_LBRC", "KC_RBRC", "KC_BSLS", "KC_DEL", "KC_END", "KC_PGDN", "KC_P7", "KC_P8", "KC_P9", "KC_PPLS",
"KC_CAPS", "KC_A", "KC_S", "KC_D", "KC_F", "KC_G", "KC_H", "KC_J", "KC_K", "KC_L", "KC_SCLN", "KC_QUOT", "KC_NUHS", "KC_ENT", "KC_P4", "KC_P5", "KC_P6", "KC_PCMM",
"KC_LSFT", "KC_NUBS", "KC_Z", "KC_X", "KC_C", "KC_V", "KC_B", "KC_N", "KC_M", "KC_COMM", "KC_DOT", "KC_SLSH", "KC_INT1", "KC_RSFT", "KC_UP", "KC_P1", "KC_P2", "KC_P3", "KC_PENT",
"KC_LCTL", "KC_LGUI", "KC_LALT", "KC_INT5", "KC_SPC", "KC_INT4", "KC_INT2", "KC_RALT", "KC_RGUI", "KC_APP", "KC_RCTL", "KC_LEFT", "KC_DOWN", "KC_RGHT", "KC_P0", "KC_PDOT", "KC_PEQL"
    ]
  ]
}
The “layers” node is basically a JSON-ified version of your keymap.c file.

You can read more about the specifics of the default keymap file on the QMK website. It’s the same file that you can download/upload to the configurator to save/load your keymap.


6. Docker Compose

Finally it’s time to build and launch the containers which should bring your configurator online and make everything work end-to-end with all of your changes.

Navigate to the main project directory:

Code: Select all

cd ~\qmk_web_stack
Run the following command to build all of the Docker containers. It will take some minutes.

Code: Select all

docker compose build
Hopefully it builds OK. If so, launch all of the containers using the following command:

Code: Select all

docker compose up
You’ll want to keep an eye on the log output and make sure that all service workers get launched. If you see some ugly errors, most likely one of these failed to launch and you’ll need to backtrack.

Now you should be able to visit your configurator at: http://<your_url>:5000

Congratulations, you're done!

Post Reply

Return to “Workshop”