npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@samanbayaka/core

v0.0.18

Published

Moleculer Gateway service with kafka transporter

Readme

samanbayaka

This project is a modular, production-ready microservices framework built with Moleculer and Moleculer-Web latest, using NATS as a high-performance messaging transporter and AJV for robust schema validation. It provides a scalable foundation for developing distributed Node.js applications, emphasizing fault tolerance, clean architecture, and efficient service communication. The system is designed to support flexible orchestration of services while maintaining strong validation and reliability across components.

NPM version License

Features

  • Moleculer-based framework for building microservices

  • Use NATS transporter for high-performance message bus

  • Use Redpanda transporter for persistent, robust, and scalable message bus with ACL support.

  • In memory L1 cache and Redis cache for L2

  • Schema validation using AJV

  • Config-driven service initialization using etcd

  • Create a Demo service to demonstrate the workflow

  • Dynamically register Edge Services and Microservices

  • Centralized error handling middleware

  • Graceful shutdown handling SIGINT, SIGTERM

  • REPL support for debugging

  • Log shipping using agent like fluentbit to OpenObserve

  • Metrics shipping using Opentelemetry to OpenObserve

  • Token based access of restricted endpoints

Installation

pnpm install samanbayaka

Once the package is installed, you can import the library using import or require approach:

import sbk from "samanbayaka"

Prerequisites

It is assumed that NATS, Redpanda, Redis,fluentbit,OpenObserve and etcd are installed and properly configured. All services should be discoverable through the /etc/hosts file.

Minimum required Node.js version: >= 22.x.x

node -v
nvm use 22

Additionally, OpenObserve is used to view logs and telemetry and fluentbit for log shipping.

Environment variables

To connect to the etcd configuration server, the application requires the SBK_CONFIG_URL environment variable. The etcd server listens on the default port 2379.

Export the environment variable before running the application.

export SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>'

or

To make the variable available across terminal sessions, add it to your shell configuration file.

Open your .bashrc file:

nano ~/.bashrc

Add the following line:

export SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>'

Save the file and reload the configuration:

source ~/.bashrc

or

You can provide the environment variable only for a single execution without exporting it.

SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' node index.mjs

Optionally, you may verify the set environment variables.

echo $SBK_CONFIG_URL

Configuration files

Create a directory to store the configuration files, then copy all configuration files from the current project path into this directory and update them as needed. Before copying, ensure that your current working directory is the project directory.

pwd
sudo mkdir -p /usr/local/etc/<your_folder>
sudo cp config/*.*  /usr/local/etc/<your_folder>

Log files

For production, it is recommended to create a new directory named <your_folder> under /var/log to store logs.

sudo mkdir -p /var/log/<your_folder>
sudo chown -R $USER:$(id -gn) /var/log/<your_folder>
sudo chmod 755 /var/log/<your_folder>

Optionally, you can clear the contents of the log files if they become too large by running:

truncate -s 0 /var/log/<your_folder>/sbk-*.log

Configure agent for log shipping

You can configure fluentbit as the log shipping agent to forward logs to OpenObserve. By default, OpenObserve listens on port 5080. The fluentbit configuration is as follows:

Open /etc/fluent-bit/fluent-bit.conf and paste the following:

[SERVICE]
    Flush         1
    Log_Level     info
    Daemon        off
    Parsers_File  parsers.conf

[INPUT]
    Name                 tail
    Path                 /var/log/<your_folder>/*.log
    Tag                  <your_tag_name>
    DB                   /var/log/fluent-bit-tail.db
    db.compare_filename  True
    Mem_Buf_Limit        50MB
    Skip_Long_Lines      On

[OUTPUT]
    Name                  http
    Match                 *
    Host                  <your_openobserve_server_host>
    Port                  <your_openobserve_server_port>
    URI                   /api/default/<your_tag_name>/_json
    HTTP_User             <your_openobserve_user>
    HTTP_Passwd           <your_opeobserve_password>
    Format                json
    Json_date_key         time
    Json_date_format      iso8601
    TLS                   off
    compress              gzip

Setup logrotate (optional)

Create config file:

sudo nano /etc/logrotate.d/sbk

Paste this:

/var/log/samanbayaka/sbk-*.log {
  daily
  rotate 14
  compress
  delaycompress
  missingok
  notifempty
  copytruncate
  create 0640 node node
}

Setup SSL certificate for system endpoints

openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout <your_filename>.key \
  -out <your_filename>.crt \
  -days 365

Documentations

Errors

sbk.Errors exposes the Moleculer Errors object.

getConfigs

sbk.getConfigs is a function that returns a configuration object from a specific path of etcd server.

createDemo

sbk.createDemo is an asynchronous function that creates a demo service to help users understand the project.

registerSystemAPI

sbk.registerSystemAPI is an asynchronous function that registers a gateway service to expose REST APIs for system management. It is a mandatory service that must be registered for every project.

registerEdgeAPI

sbk.registerEdgeAPI is an asynchronous function that registers a gateway service to expose REST APIs for the underlying microservices.

registerServices

sbk.registerServices is an asynchronous function that registers microservices based on the business needs.

Function Signature
sbk.registerServices(schema)
Parameter
  • schema - An object that follows the Moleculer service schema structure.

Example:

{
  name: "math",
  actions: {
    add: {
      rest: {
        method: "GET",
        path: "/add"
      },
      openapi: {
        summary: "addition",
        description: "addition of two numbers",
        parameters: [
          {
            name: "addend1",
            in: "query",
            description: "addend",
            schema: {
              type: "integer"
            },
            examples: [
              5,
              8
            ],
          },
          {
            name: "addend2",
            in: "query",
            description: "addend",
            schema: {
              type: "integer"
            },
            examples: [
              7,
              9
            ],
          },
        ],
      },
      handler: async(ctx) =>{
        return Number(ctx.params.query.addend1) + Number(ctx.params.query.addend2)
      }
    },
    sub: {
      rest: {
        method: "POST",
        path: "/sub"
      },
      openapi: {
        summary: "substraction",
        description: "substraction of two numbers",
        parameters: [
          {
            name: "minuend",
            in: "query",
            description: "minuend",
            schema: {
              type: "integer"
            },
            examples: [
              15,
              18
            ],
          },
          {
            name: "subtrahend",
            in: "query",
            description: "subtrahend",
            schema: {
              type: "integer"
            },
            examples: [
              7,
              9
            ],
          },
        ],
      },
      handler: async(ctx) =>{
        return Number(ctx.params.query.minuend) - Number(ctx.params.query.subtrahend)
      }
    },
  }
}

registerBridgeServices

sbk.registerBridgeServices is an asynchronous function used to initialize and manage message brokers such as Kafka, MQTT, and RabbitMQ.

Function Signature
sbk.registerBridgeServices(
  type,
  brokerOpts = {},
  callback = () => {}
)
Parameters
  • type (string) - Specifies the broker type to initialize. Supported values:

    • "kafka"
    • "mqtt"
    • "amqp"

Example:

"kafka"
  • brokerOpts (object) - Configuration object used to initialize the broker client, producer, and consumer. Example structure:
{
  name: <your_service_name>
  client: {},
  producer: {},
  consumer: {
    groupId: "all",
    interMessageDelayMs: 10,
  },
  logLevel: "INFO",
  gzip: true,
  msgPack: true,
  rest: false,
}

Configuration Options

| Property | Type | Description | |---|---|---| | name | string | Only lowercase letters (a–z), digits (0–9), and hyphens (-) are allowed. | | client | object | Broker client configuration | | producer | object | Producer configuration | | consumer | object | Consumer configuration | | consumer.groupId | string | Consumer group identifier is mandatory for the consumer | | consumer.interMessageDelayMs | number | Optional delay between messages in milliseconds | | logLevel | string | Logging level (NOTHING, ERROR, WARN, INFO, DEBUG), default NOTHING | | gzip | boolean | Enables message compression; only GZIP is supported, default true | | msgPack | boolean | Enables MessagePack serialization, default true | | rest | boolean | Enables REST end point, default false |

  • callback (function) - Callback function executed when a message/event is received.

Arguments

| Argument | Description | |---|---| | ctx | Broker context | | payload | Incoming message payload |

Example:

(ctx, payload) => {
  ctx.broker.logger.debug(payload)
}

Usage

Register gateway service

The gateway is a critical service that exposes all endpoints as REST APIs. At least one Gateway service must be running to make the REST APIs accessible.

mkdir gateway
cd gateway
pnpm init
pnpm install samanbayaka
touch index.mjs

Open index.mjs and paste the following:

import sbk from "samanbayaka"
await sbk.registerEdgeAPI()

Register microservices

mkdir <your_service_name>
cd <your_service_name>
pnpm init
pnpm install samanbayaka
touch index.mjs

A microservice, such as hello, can be created as follows:

mkdir hello
cd hello
pnpm init
pnpm install samanbayaka
touch index.mjs

Open index.mjs and paste the following:

import sbk from "samanbayaka"
await sbk.registerServices({
  name: "hello",
  version: "v1",

  actions: {
    hello: {
      rest: {
        method: "GET",
        path: "/hello"
      },

      /**
       * Enable caching to this action
       */
      cache: {

        /**
         * Cache entries expire after 30 seconds.
         * For L1 caching, TTL should be defined as [L2_TTL, L1_TTL].
         * Example: ttl: [60, 10] → L2 TTL is 60 seconds and L1 TTL is 10 seconds.
         */      
        ttl: 30
      },
      handler(ctx){
        return "Hello Samanbayaka"
      }
    },
    welcome: {
      rest: "GET /welcome",
      handler(ctx) {
        return `Welcome, ${ctx.params.query?.name || "Guest"} - ${ctx.broker.nodeID}`
      }
    },
  },
})

Register bridge services

for producer
mkdir <your_service_name>-<type>-<topic>
cd <your_service_name>-<type>-<topic>
pnpm init
pnpm install samanbayaka
touch index.mjs

An bridge service, such as a producer that publishes messages to the STUDENT topic, can be created as follows:

mkdir producer-kafka-student
cd producer-kafka-student
pnpm init
pnpm install samanbayaka
touch index.mjs

Open index.mjs and paste the following:

import sbk from "samanbayaka"
await sbk.registerBridgeServices(
  "kafka",
  {
    name: "producer-kafka-student", 
    rest: true,
    ...
  }, 
  () => {}
)

In the service configuration name end with "*" i.e. producer-kafka-student* can capable to publish to the all topics start with STUDENT like STUDENT.SCIENCE, STUDENT.ARTS etc.

name: "producer-kafka-student*"

If you do not expose the service as a REST API and run it as a private/internal service, either remove the rest property or set it to false.

rest: false

for consumer

mkdir <your_service_name>-<type>-<topic>-<group>
cd <your_service_name>-<type>-<topic>-<group>
pnpm init
pnpm install samanbayaka
touch index.mjs

An bridge service, such as a consumer that subscribe messages from the STUDENT topic having group name junior, can be created as follows:

mkdir consumer-kafka-student-junior
cd consumer-kafka-student-junior
pnpm init
pnpm install samanbayaka
touch index.mjs

Open index.mjs and paste the following:

import sbk from "samanbayaka"
await sbk.registerBridgeServices(
  "kafka",
  {
    name: "consumer-kafka-student", 
    consumer: {
      groupId: "junior",
      interMessageDelayMs: 10,
      ...
    },
    ...
  }, 
  () => {}
)

The interMessageDelayMs option introduces a delay between two consecutive message/event consumptions, measured in milliseconds. If you do not need any delay between message consumption, simply remove the interMessageDelayMs property from the consumer options.


Run the services

  • For development/testing environment
cd <your_path>/gateway
SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' node index.mjs
cd <your_path>/hello
SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' node index.mjs
  • For production environment
cd <your_path>/gateway
SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
cd <your_path>/hello
SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1

or

cd <your_path>/gateway
SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log
cd <your_path>/hello
SBK_CONFIG_URL='http://<your_etcd_user>:<your_etcd_pass>@<your_etcd_hostname>:<your_etcd_port>' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log

Demo

You can also run the demo service to better understand how microservices work in the Moleculer ecosystem and how REST APIs are exposed.

mkdir demo
cd demo
pnpm init
pnpm install samanbayaka
touch demo.mjs

Open and edit the demo.mjs file as follows

import sbk from "samanbayaka"
await sbk.createDemo()

Run the service, demo

node demo.mjs

Dockers

etcd

To manage configurations centrally, use the docker-compose.yml file to run etcd and all .yml configuration files must be deployed to /usr/local/etc/your_project_name.

mkdir -p etcd
cd etcd
touch docker-compose.yml
export ETCD_ROOT_PW=<your_root_pass>
export ETCD_CONFIG_ADMIN_PW=<your_config_admin_pass>
sudo mkdir -p /usr/local/etc/<your_project_name>

Open docker-compose.yml and paste the following:

services:
  etcd:
    image: quay.io/coreos/etcd:v3.5.5
    container_name: <your_container_name>

    ports:
      - "<your_api_port>:2379"
      - "<your_cluster_port>:2380"

    volumes:
      - /usr/local/etc/<your_project_name>:/etcd-data

    command:
      - /usr/local/bin/etcd
      - --name=etcd
      - --data-dir=/etcd-data
      - --listen-client-urls=http://0.0.0.0:2379
      - --advertise-client-urls=http://etcd:2379
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-advertise-peer-urls=http://etcd:2380
      - --initial-cluster=etcd=http://etcd:2380
      - --initial-cluster-state=new

    restart: unless-stopped

  etcd-init:
    image: quay.io/coreos/etcd:v3.5.5
    depends_on:
      - etcd

    volumes:
      - /usr/local/etc/<your_project_name>:/etcd-data

    environment:
      - ETCDCTL_API=3

    entrypoint: 
      - /bin/sh
      - -c

    command:
      - |
        set -e

        echo "waiting for etcd..."

        for i in $(seq 1 30); do
          etcdctl --endpoints=http://etcd:2379 endpoint health && break
          echo "retry $$i..."
          sleep 2
        done

        echo "etcd initialized"

        echo "Creating the root role"
        etcdctl --endpoints=http://etcd:2379 role add root || true

        echo "Creating the root user"
        etcdctl --endpoints=http://etcd:2379 user add root:${ETCD_ROOT_PW} || true

        echo "Granting the root role to the root user"
        etcdctl --endpoints=http://etcd:2379 user grant-role root root

        echo "Enable authentication"
        etcdctl --endpoints=http://etcd:2379 auth enable || true

        # -------------------------------------------------------

        echo "Creating admin role"
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add admin || true

        echo "Granting broad permissions"
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true admin readwrite / || true

        echo "Creating configadmin user"
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add configadmin:${ETCD_CONFIG_ADMIN_PW} || true

        echo "Assign role"
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role configadmin admin || true

        # ---------------------------------------------------------

        echo "Creating Roles and Granting"

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add default || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true default read /config/sbk/core/ || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true default read /config/sbk/mols/ || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add gtwy || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true gtwy read /config/sbk/gtwy/ || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add mbus || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true mbus read /config/sbk/mbus/ || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add sap || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true sap read /config/sbk/sap/ || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add dbs || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true dbs read /config/sbk/dbs/ || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add noti || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true noti read /config/sbk/noti/ || true

        # ---------------------------------------------------------
        
        echo "Creating User and Assign Role"

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add sbk:<your_pass> || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role sbk default || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add gtwy:<your_pass> || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role gtwy default || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role gtwy gtwy || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add mbus:<your_pass> || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role mbus default || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role mbus mbus || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add sap:<your_pass> || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role sap default || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role sap sap || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add dbs:<your_pass> || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role dbs default || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role dbs dbs || true

        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add noti:<your_pass> || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role noti default || true
        etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role noti noti || true

        # ------------------------------ configurations ------------------------------
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sys/yaml/sysconfig "$(cat /etcd-data/sysconfig.yml)" || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sys/certs/SERVER_KEY "" || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sys/certs/SERVER_CRT "" || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/envs/REVISION "" || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/envs/APP_ENV development || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/envs/LOG_LEVEL warn || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/envs/MAX_L1_TTL 120 || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/envs/MAX_L2_TTL 600 || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/envs/TELEMETRY false || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/broker/yaml/nats "$(cat /etcd-data/nats.yml)" || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/catcher/yaml/redis "$(cat /etcd-data/redis.yml)" || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/core/telemetry/yaml/openobserve "$(cat /etcd-data/openobserve.yml)" || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/gtwy/yaml/auth "$(cat /etcd-data/auth.yml)" || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/gtwy/yaml/roles "$(cat /etcd-data/roles.yml)" || true
        #--------------------------------------------------
        # regx pattern for allow corss site like 
        # abc.example.com, pqr.example.com
        # and cors origins like abc.example1.com
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/gtwy/CORS "^(?:[a-zA-Z0-9-]+\\.)?(?:wbsedcl\\.in|wbsedcl\\.incom)$" || true

        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/kafka "$(cat /etcd-data/kafka.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/mqtt "$(cat /etcd-data/mqtt.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/amqp "$(cat /etcd-data/amqp.yml)" || true

        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sap/yaml/isu "$(cat /etcd-data/isu.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sap/yaml/erp "$(cat /etcd-data/erp.yml)" || true

        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/gisdb "$(cat /etcd-data/gisdb.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/geomdb "$(cat /etcd-data/geomdb.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/acmadb "$(cat /etcd-data/acmadb.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/isudb "$(cat /etcd-data/isudb.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/crmdb "$(cat /etcd-data/crmdb.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/mdasdb "$(cat /etcd-data/mdasdb.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/route-sms "$(cat /etcd-data/route-sms.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/route-otp "$(cat /etcd-data/route-otp.yml)" || true
        # etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/outlook "$(cat /etcd-data/outlook.yml)" || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$demo' true || true
                
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$sysmgr' true || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$sysmgr/envs/PORT' <your_port> || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$sysmgr/envs/BROADCAST_INTERVAL' 600000 || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$sysmgr/envs/LOG_LEVEL' warn || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$sysmgr/envs/MAX_L1_TTL' 0 || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$sysmgr/envs/MAX_L2_TTL' 0 || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$edge' true || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$edge/envs/PORT' <your_port> || true

        # Identity and Access Management service
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$inam' true || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$inam/envs/PORT' <your_port> || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$asset' true || true
        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put '/config/sbk/mols/$cnfmgr' true || true

        etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/mols/dbs-pg-gisadmin true || true


        #etcdctl --endpoints=http://etcd:2379 --user=<your_user>:<your_pass> get /config/sbk/ --prefix
        #etcdctl --endpoints=http://etcd:2379 --user=<your_user>:<your_pass> get /config/sbk/core/app_env

        echo "etcd initialization completed"

Optionally verify:

docker ps | grep '<your_container_name>'

Optionally check health:

docker exec -it <your_container_name> etcdctl --endpoints=http://etcd:2379 --user <your_user>:<your_password> endpoint health