dev cicd + tron + docs #377
72
.woodpecker/billing_documents.yml
Normal file
72
.woodpecker/billing_documents.yml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- DOCUMENTS_IMAGE_PATH: billing/documents
|
||||||
|
DOCUMENTS_DOCKERFILE: ci/prod/compose/billing_documents.dockerfile
|
||||||
|
DOCUMENTS_ENV: prod
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: main
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: version
|
||||||
|
image: alpine:latest
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail 2>/dev/null || set -eu
|
||||||
|
- apk add --no-cache git
|
||||||
|
- GIT_REV="$(git rev-parse --short HEAD)"
|
||||||
|
- BUILD_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
- APP_V="$(cat version)"
|
||||||
|
- BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
|
- BUILD_USER="${WOODPECKER_MACHINE:-woodpecker}"
|
||||||
|
- printf "GIT_REV=%s\nBUILD_BRANCH=%s\nAPP_V=%s\nBUILD_DATE=%s\nBUILD_USER=%s\n" \
|
||||||
|
"$GIT_REV" "$BUILD_BRANCH" "$APP_V" "$BUILD_DATE" "$BUILD_USER" | tee .env.version
|
||||||
|
|
||||||
|
- name: proto
|
||||||
|
image: golang:alpine
|
||||||
|
depends_on: [ version ]
|
||||||
|
commands:
|
||||||
|
- set -eu
|
||||||
|
- apk add --no-cache bash git build-base protoc protobuf-dev
|
||||||
|
- go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||||
|
- go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||||
|
- export PATH="$(go env GOPATH)/bin:$PATH"
|
||||||
|
- bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
- name: secrets
|
||||||
|
image: alpine:latest
|
||||||
|
depends_on: [ version ]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: { from_secret: VAULT_ADDR }
|
||||||
|
VAULT_ROLE_ID: { from_secret: VAULT_APP_ROLE }
|
||||||
|
VAULT_SECRET_ID: { from_secret: VAULT_SECRET_ID }
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail
|
||||||
|
- apk add --no-cache bash coreutils openssh-keygen curl sed python3
|
||||||
|
- mkdir -p secrets
|
||||||
|
- ./ci/vlt kv_to_file kv ops/deploy/ssh_key private_b64 secrets/SSH_KEY.b64 600
|
||||||
|
- base64 -d secrets/SSH_KEY.b64 > secrets/SSH_KEY
|
||||||
|
- chmod 600 secrets/SSH_KEY
|
||||||
|
- ssh-keygen -y -f secrets/SSH_KEY >/dev/null
|
||||||
|
- ./ci/vlt kv_get kv registry user > secrets/REGISTRY_USER
|
||||||
|
- ./ci/vlt kv_get kv registry password > secrets/REGISTRY_PASSWORD
|
||||||
|
|
||||||
|
- name: build-image
|
||||||
|
image: gcr.io/kaniko-project/executor:debug
|
||||||
|
depends_on: [ proto, secrets ]
|
||||||
|
commands:
|
||||||
|
- sh ci/scripts/billing_documents/build-image.sh
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
image: alpine:latest
|
||||||
|
depends_on: [ secrets, build-image ]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: { from_secret: VAULT_ADDR }
|
||||||
|
VAULT_ROLE_ID: { from_secret: VAULT_APP_ROLE }
|
||||||
|
VAULT_SECRET_ID: { from_secret: VAULT_SECRET_ID }
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail
|
||||||
|
- apk add --no-cache bash openssh-client rsync coreutils curl sed python3
|
||||||
|
- mkdir -p /root/.ssh
|
||||||
|
- install -m 600 secrets/SSH_KEY /root/.ssh/id_rsa
|
||||||
|
- sh ci/scripts/billing_documents/deploy.sh
|
||||||
76
.woodpecker/gateway_tron.yml
Normal file
76
.woodpecker/gateway_tron.yml
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- TRON_GATEWAY_IMAGE_PATH: gateway/tron
|
||||||
|
TRON_GATEWAY_DOCKERFILE: ci/prod/compose/tron_gateway.dockerfile
|
||||||
|
TRON_GATEWAY_MONGO_SECRET_PATH: sendico/db
|
||||||
|
TRON_GATEWAY_RPC_SECRET_PATH: sendico/gateway/tron
|
||||||
|
TRON_GATEWAY_WALLET_SECRET_PATH: sendico/gateway/tron/wallet
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_PATH: sendico/gateway/tron/vault
|
||||||
|
TRON_GATEWAY_ENV: prod
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: main
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: version
|
||||||
|
image: alpine:latest
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail 2>/dev/null || set -eu
|
||||||
|
- apk add --no-cache git
|
||||||
|
- GIT_REV="$(git rev-parse --short HEAD)"
|
||||||
|
- BUILD_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
- APP_V="$(cat version)"
|
||||||
|
- BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
|
- BUILD_USER="${WOODPECKER_MACHINE:-woodpecker}"
|
||||||
|
- printf "GIT_REV=%s\nBUILD_BRANCH=%s\nAPP_V=%s\nBUILD_DATE=%s\nBUILD_USER=%s\n" \
|
||||||
|
"$GIT_REV" "$BUILD_BRANCH" "$APP_V" "$BUILD_DATE" "$BUILD_USER" | tee .env.version
|
||||||
|
|
||||||
|
- name: proto
|
||||||
|
image: golang:alpine
|
||||||
|
depends_on: [ version ]
|
||||||
|
commands:
|
||||||
|
- set -eu
|
||||||
|
- apk add --no-cache bash git build-base protoc protobuf-dev
|
||||||
|
- go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||||
|
- go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||||
|
- export PATH="$(go env GOPATH)/bin:$PATH"
|
||||||
|
- bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
- name: secrets
|
||||||
|
image: alpine:latest
|
||||||
|
depends_on: [ version ]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: { from_secret: VAULT_ADDR }
|
||||||
|
VAULT_ROLE_ID: { from_secret: VAULT_APP_ROLE }
|
||||||
|
VAULT_SECRET_ID: { from_secret: VAULT_SECRET_ID }
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail
|
||||||
|
- apk add --no-cache bash coreutils openssh-keygen curl sed python3
|
||||||
|
- mkdir -p secrets
|
||||||
|
- ./ci/vlt kv_to_file kv ops/deploy/ssh_key private_b64 secrets/SSH_KEY.b64 600
|
||||||
|
- base64 -d secrets/SSH_KEY.b64 > secrets/SSH_KEY
|
||||||
|
- chmod 600 secrets/SSH_KEY
|
||||||
|
- ssh-keygen -y -f secrets/SSH_KEY >/dev/null
|
||||||
|
- ./ci/vlt kv_get kv registry user > secrets/REGISTRY_USER
|
||||||
|
- ./ci/vlt kv_get kv registry password > secrets/REGISTRY_PASSWORD
|
||||||
|
|
||||||
|
- name: build-image
|
||||||
|
image: gcr.io/kaniko-project/executor:debug
|
||||||
|
depends_on: [ proto, secrets ]
|
||||||
|
commands:
|
||||||
|
- sh ci/scripts/tron_gateway/build-image.sh
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
image: alpine:latest
|
||||||
|
depends_on: [ secrets, build-image ]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: { from_secret: VAULT_ADDR }
|
||||||
|
VAULT_ROLE_ID: { from_secret: VAULT_APP_ROLE }
|
||||||
|
VAULT_SECRET_ID: { from_secret: VAULT_SECRET_ID }
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail
|
||||||
|
- apk add --no-cache bash openssh-client rsync coreutils curl sed python3
|
||||||
|
- mkdir -p /root/.ssh
|
||||||
|
- install -m 600 secrets/SSH_KEY /root/.ssh/id_rsa
|
||||||
|
- sh ci/scripts/tron_gateway/deploy.sh
|
||||||
267
Makefile
Normal file
267
Makefile
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
# Sendico Development Environment - Makefile
|
||||||
|
# Docker Compose + Makefile build system
|
||||||
|
|
||||||
|
.PHONY: help init build up down restart logs rebuild clean vault-init proto
|
||||||
|
|
||||||
|
COMPOSE := docker compose -f docker-compose.dev.yml --env-file .env.dev
|
||||||
|
SERVICE ?=
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
GREEN := \033[0;32m
|
||||||
|
YELLOW := \033[1;33m
|
||||||
|
NC := \033[0m
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "$(GREEN)Sendico Development Environment$(NC)"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(YELLOW)Quick Start:$(NC)"
|
||||||
|
@echo " make init Initialize dev environment (first time setup)"
|
||||||
|
@echo " make up Start all services"
|
||||||
|
@echo " make vault-init Initialize Vault (if services need it)"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(YELLOW)Main Commands:$(NC)"
|
||||||
|
@echo " make build Build all service images"
|
||||||
|
@echo " make down Stop all services"
|
||||||
|
@echo " make restart Restart all services"
|
||||||
|
@echo " make status Show service status"
|
||||||
|
@echo " make logs [SERVICE=x] View logs (all or specific service)"
|
||||||
|
@echo " make rebuild SERVICE=x Rebuild specific service"
|
||||||
|
@echo " make clean Remove all containers and volumes"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(YELLOW)Selective Operations:$(NC)"
|
||||||
|
@echo " make infra-up Start infrastructure only (mongo, nats, vault)"
|
||||||
|
@echo " make services-up Start application services only"
|
||||||
|
@echo " make list-services List all available services"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(YELLOW)Build Groups:$(NC)"
|
||||||
|
@echo " make build-core Build core services (discovery, ledger, fees, documents)"
|
||||||
|
@echo " make build-fx Build FX services (oracle, ingestor)"
|
||||||
|
@echo " make build-payments Build payment orchestrator"
|
||||||
|
@echo " make build-gateways Build gateway services (chain, tron, mntx, tgsettle)"
|
||||||
|
@echo " make build-api Build API services (notification, bff)"
|
||||||
|
@echo " make build-frontend Build Flutter web frontend"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(YELLOW)Development:$(NC)"
|
||||||
|
@echo " make proto Generate protobuf code"
|
||||||
|
@echo " make health Check service health"
|
||||||
|
@echo ""
|
||||||
|
@echo "Examples:"
|
||||||
|
@echo " make logs SERVICE=dev-ledger"
|
||||||
|
@echo " make rebuild SERVICE=dev-ledger"
|
||||||
|
|
||||||
|
# First-time initialization
|
||||||
|
init:
|
||||||
|
@echo "$(GREEN)Initializing development environment...$(NC)"
|
||||||
|
@if [ ! -f ci/dev/mongo.key ]; then \
|
||||||
|
echo "$(YELLOW)Generating MongoDB keyfile...$(NC)"; \
|
||||||
|
openssl rand -base64 756 | tr -d '\n' > ci/dev/mongo.key; \
|
||||||
|
chown 999:999 ci/dev/mongo.key; \
|
||||||
|
chmod 400 ci/dev/mongo.key; \
|
||||||
|
fi
|
||||||
|
@if [ ! -f .env.dev ]; then \
|
||||||
|
echo "$(YELLOW)Creating .env.dev with default values...$(NC)"; \
|
||||||
|
echo "# Sendico Development Environment Configuration" > .env.dev; \
|
||||||
|
echo "# Simple plaintext credentials for infrastructure" >> .env.dev; \
|
||||||
|
echo "" >> .env.dev; \
|
||||||
|
echo "# MongoDB Configuration" >> .env.dev; \
|
||||||
|
echo "MONGO_USER=dev_root" >> .env.dev; \
|
||||||
|
echo "MONGO_PASSWORD=dev_password_123" >> .env.dev; \
|
||||||
|
echo "" >> .env.dev; \
|
||||||
|
echo "# NATS Configuration" >> .env.dev; \
|
||||||
|
echo "NATS_USER=dev_nats" >> .env.dev; \
|
||||||
|
echo "NATS_PASSWORD=nats_password_123" >> .env.dev; \
|
||||||
|
echo "" >> .env.dev; \
|
||||||
|
echo "# Vault Configuration (for application data only)" >> .env.dev; \
|
||||||
|
echo "VAULT_ADDR=http://dev-vault:8200" >> .env.dev; \
|
||||||
|
fi
|
||||||
|
@echo "$(GREEN)Verifying .env.dev...$(NC)"
|
||||||
|
@cat .env.dev | grep -q "MONGO_USER=" || (echo "$(YELLOW)Error: .env.dev is incomplete$(NC)" && exit 1)
|
||||||
|
@echo "$(GREEN)Running proto generation...$(NC)"
|
||||||
|
@./generate_protos.sh
|
||||||
|
@echo "$(GREEN)Building Docker images...$(NC)"
|
||||||
|
@$(COMPOSE) build
|
||||||
|
@echo "$(GREEN)✅ Initialization complete!$(NC)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Next steps:"
|
||||||
|
@echo " 1. make up # Start services"
|
||||||
|
@echo " 2. make vault-init # Initialize Vault (if needed)"
|
||||||
|
|
||||||
|
# Build all images
|
||||||
|
build:
|
||||||
|
@echo "$(GREEN)Building all service images...$(NC)"
|
||||||
|
@./generate_protos.sh
|
||||||
|
@$(COMPOSE) build
|
||||||
|
|
||||||
|
# Start all services
|
||||||
|
up:
|
||||||
|
@echo "$(GREEN)Starting development environment...$(NC)"
|
||||||
|
@$(COMPOSE) up -d
|
||||||
|
@echo ""
|
||||||
|
@echo "$(GREEN)✅ Development environment started!$(NC)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Services:"
|
||||||
|
@echo " MongoDB: mongodb://dev_root:dev_password_123@localhost:27017/admin?replicaSet=dev-rs"
|
||||||
|
@echo " NATS: nats://dev_nats:nats_password_123@localhost:4222"
|
||||||
|
@echo " NATS UI: http://localhost:8222"
|
||||||
|
@echo " Vault: http://localhost:8200 (run 'make vault-init' first)"
|
||||||
|
@echo ""
|
||||||
|
@echo "View logs: make logs [SERVICE=name]"
|
||||||
|
@echo "Stop: make down"
|
||||||
|
|
||||||
|
# Stop all services
|
||||||
|
down:
|
||||||
|
@echo "$(YELLOW)Stopping development environment...$(NC)"
|
||||||
|
@$(COMPOSE) down
|
||||||
|
|
||||||
|
# Restart all services
|
||||||
|
restart:
|
||||||
|
@echo "$(YELLOW)Restarting services...$(NC)"
|
||||||
|
@$(COMPOSE) restart
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
logs:
|
||||||
|
ifdef SERVICE
|
||||||
|
@$(COMPOSE) logs -f $(SERVICE)
|
||||||
|
else
|
||||||
|
@$(COMPOSE) logs -f
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Rebuild specific service
|
||||||
|
rebuild:
|
||||||
|
ifndef SERVICE
|
||||||
|
$(error SERVICE is required: make rebuild SERVICE=ledger)
|
||||||
|
endif
|
||||||
|
@echo "$(GREEN)Rebuilding $(SERVICE)...$(NC)"
|
||||||
|
@$(COMPOSE) build $(SERVICE)
|
||||||
|
@$(COMPOSE) up -d --force-recreate $(SERVICE)
|
||||||
|
@echo "$(GREEN)✅ $(SERVICE) rebuilt$(NC)"
|
||||||
|
@echo "View logs: make logs SERVICE=$(SERVICE)"
|
||||||
|
|
||||||
|
# Generate protobuf code
|
||||||
|
proto:
|
||||||
|
@echo "$(GREEN)Generating protobuf code...$(NC)"
|
||||||
|
@./generate_protos.sh
|
||||||
|
@echo "$(GREEN)✅ Protobuf generation complete$(NC)"
|
||||||
|
|
||||||
|
# Clean everything
|
||||||
|
clean:
|
||||||
|
@echo "$(YELLOW)WARNING: This will remove all containers and volumes!$(NC)"
|
||||||
|
@read -p "Are you sure? [y/N] " -n 1 -r; \
|
||||||
|
echo; \
|
||||||
|
if [[ $$REPLY =~ ^[Yy]$$ ]]; then \
|
||||||
|
$(COMPOSE) down -v --remove-orphans; \
|
||||||
|
docker system prune -f; \
|
||||||
|
echo "$(GREEN)✅ Cleanup complete$(NC)"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize Vault (first time only)
|
||||||
|
vault-init:
|
||||||
|
@echo "$(GREEN)Initializing Vault...$(NC)"
|
||||||
|
@echo "$(YELLOW)Make sure Vault is running: make up$(NC)"
|
||||||
|
@sleep 2
|
||||||
|
@echo "Checking Vault status..."
|
||||||
|
@docker exec dev-vault vault status || echo "Vault not initialized yet"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(GREEN)Initializing Vault with 1 key share...$(NC)"
|
||||||
|
@docker exec dev-vault vault operator init -key-shares=1 -key-threshold=1 > vault-keys.txt || echo "Vault already initialized"
|
||||||
|
@if [ -f vault-keys.txt ]; then \
|
||||||
|
echo "$(GREEN)✅ Vault initialized!$(NC)"; \
|
||||||
|
echo ""; \
|
||||||
|
echo "$(YELLOW)IMPORTANT: Save vault-keys.txt securely!$(NC)"; \
|
||||||
|
echo "It contains the unseal key and root token."; \
|
||||||
|
echo ""; \
|
||||||
|
UNSEAL_KEY=$$(grep 'Unseal Key 1:' vault-keys.txt | awk '{print $$NF}'); \
|
||||||
|
echo "Unsealing Vault..."; \
|
||||||
|
docker exec dev-vault vault operator unseal $$UNSEAL_KEY; \
|
||||||
|
echo ""; \
|
||||||
|
echo "$(GREEN)✅ Vault is unsealed and ready!$(NC)"; \
|
||||||
|
echo ""; \
|
||||||
|
echo "Root token: $$(grep 'Initial Root Token:' vault-keys.txt | awk '{print $$NF}')"; \
|
||||||
|
echo "UI: http://localhost:8200"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Infrastructure only (mongo + nats + vault)
|
||||||
|
infra-up:
|
||||||
|
@echo "$(GREEN)Starting infrastructure only...$(NC)"
|
||||||
|
@$(COMPOSE) up -d dev-mongo-1 dev-mongo-2 dev-mongo-3 dev-nats dev-vault
|
||||||
|
@$(COMPOSE) up dev-mongo-init
|
||||||
|
|
||||||
|
# Services only (assumes infra is running)
|
||||||
|
services-up:
|
||||||
|
@echo "$(GREEN)Starting application services...$(NC)"
|
||||||
|
@$(COMPOSE) up -d \
|
||||||
|
dev-discovery \
|
||||||
|
dev-fx-oracle \
|
||||||
|
dev-fx-ingestor \
|
||||||
|
dev-billing-fees \
|
||||||
|
dev-billing-documents \
|
||||||
|
dev-ledger \
|
||||||
|
dev-payments-orchestrator \
|
||||||
|
dev-chain-gateway \
|
||||||
|
dev-tron-gateway \
|
||||||
|
dev-mntx-gateway \
|
||||||
|
dev-tgsettle-gateway \
|
||||||
|
dev-notification \
|
||||||
|
dev-bff \
|
||||||
|
dev-frontend
|
||||||
|
|
||||||
|
# Status check
|
||||||
|
status:
|
||||||
|
@$(COMPOSE) ps
|
||||||
|
|
||||||
|
# List all services
|
||||||
|
list-services:
|
||||||
|
@echo "$(GREEN)Infrastructure Services:$(NC)"
|
||||||
|
@echo " - dev-mongo-1, dev-mongo-2, dev-mongo-3 (MongoDB Replica Set)"
|
||||||
|
@echo " - dev-nats (NATS with JetStream)"
|
||||||
|
@echo " - dev-vault (Vault for application secrets)"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(GREEN)Application Services:$(NC)"
|
||||||
|
@echo " - dev-discovery :9407 (Service Registry)"
|
||||||
|
@echo " - dev-fx-oracle :50051, :9400 (FX Quotes)"
|
||||||
|
@echo " - dev-fx-ingestor :9102 (FX Rate Ingestion)"
|
||||||
|
@echo " - dev-billing-fees :50060, :9402 (Fee Calculation)"
|
||||||
|
@echo " - dev-billing-documents :50061, :9409 (Billing Documents)"
|
||||||
|
@echo " - dev-ledger :50052, :9401 (Double-Entry Ledger)"
|
||||||
|
@echo " - dev-payments-orchestrator :50062, :9403 (Payment Orchestration)"
|
||||||
|
@echo " - dev-chain-gateway :50070, :9404 (EVM Blockchain Gateway)"
|
||||||
|
@echo " - dev-tron-gateway :50071, :9408 (TRON Blockchain Gateway)"
|
||||||
|
@echo " - dev-mntx-gateway :50075, :9405, :8084 (Card Payouts)"
|
||||||
|
@echo " - dev-tgsettle-gateway :50080, :9406 (Telegram Settlements)"
|
||||||
|
@echo " - dev-notification :8081 (Notifications)"
|
||||||
|
@echo " - dev-bff :8080 (Backend for Frontend)"
|
||||||
|
@echo " - dev-frontend :3000 (Flutter Web UI)"
|
||||||
|
|
||||||
|
# Health check all services
|
||||||
|
health:
|
||||||
|
@echo "$(GREEN)Checking service health...$(NC)"
|
||||||
|
@$(COMPOSE) ps --format json | grep -v "State" || echo "Run 'make up' first"
|
||||||
|
|
||||||
|
# Build specific service group
|
||||||
|
build-infra:
|
||||||
|
@echo "$(GREEN)Building infrastructure images...$(NC)"
|
||||||
|
# Infrastructure uses official images, nothing to build
|
||||||
|
|
||||||
|
build-core:
|
||||||
|
@echo "$(GREEN)Building core services...$(NC)"
|
||||||
|
@$(COMPOSE) build dev-discovery dev-ledger dev-billing-fees dev-billing-documents
|
||||||
|
|
||||||
|
build-fx:
|
||||||
|
@echo "$(GREEN)Building FX services...$(NC)"
|
||||||
|
@$(COMPOSE) build dev-fx-oracle dev-fx-ingestor
|
||||||
|
|
||||||
|
build-payments:
|
||||||
|
@echo "$(GREEN)Building payment services...$(NC)"
|
||||||
|
@$(COMPOSE) build dev-payments-orchestrator
|
||||||
|
|
||||||
|
build-gateways:
|
||||||
|
@echo "$(GREEN)Building gateway services...$(NC)"
|
||||||
|
@$(COMPOSE) build dev-chain-gateway dev-tron-gateway dev-mntx-gateway dev-tgsettle-gateway
|
||||||
|
|
||||||
|
build-api:
|
||||||
|
@echo "$(GREEN)Building API services...$(NC)"
|
||||||
|
@$(COMPOSE) build dev-notification dev-bff
|
||||||
|
|
||||||
|
build-frontend:
|
||||||
|
@echo "$(GREEN)Building frontend...$(NC)"
|
||||||
|
@$(COMPOSE) build dev-frontend
|
||||||
399
SETUP.md
Normal file
399
SETUP.md
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
# Sendico Development Environment - Setup Guide
|
||||||
|
|
||||||
|
Complete Docker Compose + Makefile build system for local development.
|
||||||
|
|
||||||
|
## 🎯 What's Included
|
||||||
|
|
||||||
|
**13 Services:**
|
||||||
|
- ✅ Discovery (Service Registry)
|
||||||
|
- ✅ FX Oracle & FX Ingestor
|
||||||
|
- ✅ Billing Fees
|
||||||
|
- ✅ Ledger (Double-Entry Accounting)
|
||||||
|
- ✅ Payments Orchestrator
|
||||||
|
- ✅ Chain Gateway (Blockchain)
|
||||||
|
- ✅ MNTX Gateway (Card Payouts)
|
||||||
|
- ✅ TGSettle Gateway (Telegram Settlements)
|
||||||
|
- ✅ Notification
|
||||||
|
- ✅ BFF (Backend for Frontend / Server)
|
||||||
|
- ✅ Frontend (Flutter Web)
|
||||||
|
|
||||||
|
**Infrastructure:**
|
||||||
|
- MongoDB Replica Set (3 nodes)
|
||||||
|
- NATS with JetStream
|
||||||
|
- Vault (single node, for application data only)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. First time setup
|
||||||
|
make init
|
||||||
|
|
||||||
|
# 2. Start everything
|
||||||
|
make up
|
||||||
|
|
||||||
|
# 3. Initialize Vault (if services need blockchain keys, external API keys)
|
||||||
|
make vault-init
|
||||||
|
|
||||||
|
# 4. Check status
|
||||||
|
make status
|
||||||
|
|
||||||
|
# 5. View frontend
|
||||||
|
open http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Prerequisites
|
||||||
|
|
||||||
|
- Docker & Docker Compose
|
||||||
|
- Make
|
||||||
|
- Go 1.24+ (for local proto generation)
|
||||||
|
- protoc, protoc-gen-go, protoc-gen-go-grpc (for proto generation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Configuration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Edit `.env.dev` (created after `make init`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# MongoDB
|
||||||
|
MONGO_USER=dev_root
|
||||||
|
MONGO_PASSWORD=dev_password_123
|
||||||
|
|
||||||
|
# NATS
|
||||||
|
NATS_USER=dev_nats
|
||||||
|
NATS_PASSWORD=nats_password_123
|
||||||
|
|
||||||
|
# Vault (for application data only)
|
||||||
|
VAULT_ADDR=http://dev-vault:8200
|
||||||
|
```
|
||||||
|
|
||||||
|
**IMPORTANT:** These are plaintext credentials for dev infrastructure only!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Service Ports
|
||||||
|
|
||||||
|
**Infrastructure:**
|
||||||
|
- MongoDB: `localhost:27017`
|
||||||
|
- NATS: `localhost:4222`
|
||||||
|
- NATS Monitoring: `localhost:8222`
|
||||||
|
- Vault: `localhost:8200`
|
||||||
|
|
||||||
|
**Services:**
|
||||||
|
- Discovery: `localhost:9407`
|
||||||
|
- FX Oracle: `localhost:50051` (gRPC), `localhost:9400` (metrics)
|
||||||
|
- FX Ingestor: `localhost:9102`
|
||||||
|
- Billing Fees: `localhost:50060` (gRPC), `localhost:9402` (metrics)
|
||||||
|
- Ledger: `localhost:50052` (gRPC), `localhost:9401` (metrics)
|
||||||
|
- Payments Orchestrator: `localhost:50062` (gRPC), `localhost:9403` (metrics)
|
||||||
|
- Chain Gateway: `localhost:50070` (gRPC), `localhost:9404` (metrics)
|
||||||
|
- MNTX Gateway: `localhost:50075` (gRPC), `localhost:9405` (metrics), `localhost:8084` (HTTP)
|
||||||
|
- TGSettle Gateway: `localhost:50080` (gRPC), `localhost:9406` (metrics)
|
||||||
|
- Notification: `localhost:8081`
|
||||||
|
- BFF: `localhost:8080`
|
||||||
|
- Frontend: `localhost:3000`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Common Commands
|
||||||
|
|
||||||
|
### Lifecycle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make up # Start all services
|
||||||
|
make down # Stop all services
|
||||||
|
make restart # Restart all services
|
||||||
|
make status # Check status
|
||||||
|
make clean # Remove everything (containers + volumes)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View logs
|
||||||
|
make logs # All services
|
||||||
|
make logs SERVICE=dev-ledger # Specific service
|
||||||
|
|
||||||
|
# Rebuild after code changes
|
||||||
|
make rebuild SERVICE=dev-ledger
|
||||||
|
|
||||||
|
# Regenerate protobuf
|
||||||
|
make proto
|
||||||
|
```
|
||||||
|
|
||||||
|
### Selective Startup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start infrastructure only
|
||||||
|
make infra-up
|
||||||
|
|
||||||
|
# Then start services
|
||||||
|
make services-up
|
||||||
|
|
||||||
|
# Or start specific service groups
|
||||||
|
make build-core # discovery, ledger, billing-fees
|
||||||
|
make build-fx # fx-oracle, fx-ingestor
|
||||||
|
make build-payments # payments-orchestrator
|
||||||
|
make build-gateways # chain, mntx, tgsettle
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Vault Setup
|
||||||
|
|
||||||
|
Vault is **only for application data** (blockchain keys, external API keys).
|
||||||
|
Infrastructure credentials (MongoDB, NATS) are in `.env.dev`.
|
||||||
|
|
||||||
|
### Initialize Vault
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make vault-init
|
||||||
|
```
|
||||||
|
|
||||||
|
This will:
|
||||||
|
1. Initialize Vault with 1 key share
|
||||||
|
2. Unseal Vault automatically
|
||||||
|
3. Save keys to `vault-keys.txt` (NEVER commit this!)
|
||||||
|
4. Display root token
|
||||||
|
|
||||||
|
### Using Vault in Services
|
||||||
|
|
||||||
|
Services that need Vault (e.g., Chain Gateway for blockchain keys):
|
||||||
|
1. Set `VAULT_ADDR` in service environment
|
||||||
|
2. Use Vault client to fetch secrets at runtime
|
||||||
|
3. Store secrets in Vault: `kv/data/chain/ethereum/private_key`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Development Workflow
|
||||||
|
|
||||||
|
### Typical Day
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Morning: Start environment
|
||||||
|
make up
|
||||||
|
|
||||||
|
# Work on ledger service
|
||||||
|
vim api/ledger/internal/service/ledger/posting.go
|
||||||
|
|
||||||
|
# Rebuild ledger
|
||||||
|
make rebuild SERVICE=dev-ledger
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
make logs SERVICE=dev-ledger
|
||||||
|
|
||||||
|
# Test
|
||||||
|
curl http://localhost:9401/health
|
||||||
|
|
||||||
|
# End of day
|
||||||
|
make down
|
||||||
|
```
|
||||||
|
|
||||||
|
### After Changing Protos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Regenerate protos
|
||||||
|
make proto
|
||||||
|
|
||||||
|
# Rebuild affected services
|
||||||
|
make rebuild SERVICE=dev-ledger
|
||||||
|
make rebuild SERVICE=dev-payments-orchestrator
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend Development
|
||||||
|
|
||||||
|
For faster iteration, run frontend locally instead of Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start backend services only
|
||||||
|
make infra-up
|
||||||
|
make services-up
|
||||||
|
|
||||||
|
# Run frontend locally
|
||||||
|
cd frontend/pweb
|
||||||
|
flutter run -d chrome
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Debugging
|
||||||
|
|
||||||
|
### MongoDB Replica Set Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check replica set status
|
||||||
|
docker exec -it dev-mongo-1 mongosh -u dev_root -p dev_password_123 --eval "rs.status()"
|
||||||
|
|
||||||
|
# Reinitialize
|
||||||
|
make down
|
||||||
|
make up
|
||||||
|
docker logs dev-mongo-init
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Can't Connect to MongoDB
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if replica set is initialized
|
||||||
|
docker logs dev-mongo-init
|
||||||
|
|
||||||
|
# Check MongoDB is healthy
|
||||||
|
docker ps | grep mongo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vault Sealed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get unseal key from vault-keys.txt
|
||||||
|
UNSEAL_KEY=$(grep 'Unseal Key 1:' vault-keys.txt | awk '{print $NF}')
|
||||||
|
|
||||||
|
# Unseal
|
||||||
|
docker exec dev-vault vault operator unseal $UNSEAL_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Crash Loop
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
make logs SERVICE=dev-ledger
|
||||||
|
|
||||||
|
# Check environment variables
|
||||||
|
docker inspect dev-ledger | grep -A 20 Env
|
||||||
|
|
||||||
|
# Rebuild from scratch
|
||||||
|
make rebuild SERVICE=dev-ledger
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Docker Images
|
||||||
|
|
||||||
|
All images tagged as `sendico-dev/<service>:latest`:
|
||||||
|
- `sendico-dev/discovery:latest`
|
||||||
|
- `sendico-dev/ledger:latest`
|
||||||
|
- `sendico-dev/billing-fees:latest`
|
||||||
|
- `sendico-dev/fx-oracle:latest`
|
||||||
|
- `sendico-dev/fx-ingestor:latest`
|
||||||
|
- `sendico-dev/payments-orchestrator:latest`
|
||||||
|
- `sendico-dev/chain-gateway:latest`
|
||||||
|
- `sendico-dev/mntx-gateway:latest`
|
||||||
|
- `sendico-dev/tgsettle-gateway:latest`
|
||||||
|
- `sendico-dev/notification:latest`
|
||||||
|
- `sendico-dev/bff:latest`
|
||||||
|
- `sendico-dev/frontend:latest`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Testing Full Flow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Start everything
|
||||||
|
make up
|
||||||
|
|
||||||
|
# 2. Check all services are healthy
|
||||||
|
make status
|
||||||
|
|
||||||
|
# 3. Test discovery
|
||||||
|
curl http://localhost:9407/health
|
||||||
|
|
||||||
|
# 4. Test ledger
|
||||||
|
curl http://localhost:9401/health
|
||||||
|
|
||||||
|
# 5. Test BFF
|
||||||
|
curl http://localhost:8080/api/v1/health
|
||||||
|
|
||||||
|
# 6. Test frontend
|
||||||
|
open http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗑️ Cleanup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop everything
|
||||||
|
make down
|
||||||
|
|
||||||
|
# Remove volumes (fresh start)
|
||||||
|
make clean
|
||||||
|
|
||||||
|
# Remove images
|
||||||
|
docker rmi $(docker images 'sendico-dev/*' -q)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
sendico/
|
||||||
|
├── docker-compose.dev.yml # All service definitions
|
||||||
|
├── .env.dev # Plaintext credentials
|
||||||
|
├── Makefile # Build commands
|
||||||
|
├── SETUP.md # This file
|
||||||
|
├── vault-keys.txt # Vault keys (gitignored)
|
||||||
|
└── docker/
|
||||||
|
└── dev/
|
||||||
|
├── README.md # Detailed docs
|
||||||
|
├── mongo.key # MongoDB keyfile
|
||||||
|
├── vault/
|
||||||
|
│ └── config.hcl # Vault config
|
||||||
|
└── *.dockerfile # Service builds
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Getting Help
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show all available commands
|
||||||
|
make help
|
||||||
|
|
||||||
|
# List all services
|
||||||
|
make list-services
|
||||||
|
|
||||||
|
# Check service health
|
||||||
|
make health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎓 Next Steps
|
||||||
|
|
||||||
|
1. **Initialize Vault with secrets** for Chain Gateway
|
||||||
|
2. **Seed test data** into MongoDB
|
||||||
|
3. **Run integration tests**
|
||||||
|
4. **Add monitoring** (Prometheus/Grafana - optional)
|
||||||
|
5. **Document API endpoints** in each service
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Important Notes
|
||||||
|
|
||||||
|
- **Never commit `.env.dev`** - Contains credentials
|
||||||
|
- **Never commit `vault-keys.txt`** - Contains Vault keys
|
||||||
|
- **Vault is for app data only** - Not for infrastructure secrets
|
||||||
|
- **Use `dev-` prefix** for all service names to avoid conflicts
|
||||||
|
- **MongoDB keyfile** must have `400` permissions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Troubleshooting Checklist
|
||||||
|
|
||||||
|
- [ ] Docker is running
|
||||||
|
- [ ] Docker Compose v2 is installed (`docker compose version`)
|
||||||
|
- [ ] `.env.dev` exists and has correct values
|
||||||
|
- [ ] Vault is initialized and unsealed (`make vault-init`)
|
||||||
|
- [ ] MongoDB replica set is initialized (`docker logs dev-mongo-init`)
|
||||||
|
- [ ] All services are healthy (`make status`)
|
||||||
|
- [ ] No port conflicts on host machine
|
||||||
|
- [ ] Proto generation succeeded (`make proto`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ready to build? Run `make init && make up`** 🚀
|
||||||
1
api/server/tmp/build-errors.log
Normal file
1
api/server/tmp/build-errors.log
Normal file
@@ -0,0 +1 @@
|
|||||||
|
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
||||||
BIN
api/server/tmp/main
Executable file
BIN
api/server/tmp/main
Executable file
Binary file not shown.
46
ci/dev/.air.toml
Normal file
46
ci/dev/.air.toml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
args_bin = []
|
||||||
|
entrypoint = "./tmp/main"
|
||||||
|
cmd = "go build -o ./tmp/main ."
|
||||||
|
delay = 1000
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go", "_templ.go"]
|
||||||
|
exclude_unchanged = false
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||||
|
include_file = []
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
poll = false
|
||||||
|
poll_interval = 0
|
||||||
|
post_cmd = []
|
||||||
|
pre_cmd = []
|
||||||
|
rerun = false
|
||||||
|
rerun_delay = 500
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = false
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
main_only = false
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
||||||
|
keep_scroll = true
|
||||||
160
ci/dev/CHECKLIST.md
Normal file
160
ci/dev/CHECKLIST.md
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
# Development Environment - Implementation Checklist
|
||||||
|
|
||||||
|
## ✅ Completed
|
||||||
|
|
||||||
|
### Infrastructure (3/3)
|
||||||
|
- [x] MongoDB Replica Set (3 nodes with auto-init)
|
||||||
|
- [x] NATS with JetStream
|
||||||
|
- [x] Vault (single node for application data)
|
||||||
|
|
||||||
|
### Application Services (12/12)
|
||||||
|
- [x] Discovery Service
|
||||||
|
- [x] FX Oracle Service
|
||||||
|
- [x] FX Ingestor Service
|
||||||
|
- [x] Billing Fees Service
|
||||||
|
- [x] Ledger Service
|
||||||
|
- [x] Payments Orchestrator Service
|
||||||
|
- [x] Chain Gateway Service
|
||||||
|
- [x] MNTX Gateway Service
|
||||||
|
- [x] TGSettle Gateway Service
|
||||||
|
- [x] Notification Service
|
||||||
|
- [x] BFF (Server) Service
|
||||||
|
- [x] Frontend (Flutter Web)
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
- [x] docker-compose.dev.yml (complete with all services)
|
||||||
|
- [x] .env.dev (plaintext credentials template)
|
||||||
|
- [x] Makefile (full command suite)
|
||||||
|
- [x] .gitignore (updated with dev files)
|
||||||
|
|
||||||
|
### Dockerfiles (12/12)
|
||||||
|
- [x] ci/dev/discovery.dockerfile
|
||||||
|
- [x] ci/dev/ledger.dockerfile
|
||||||
|
- [x] ci/dev/billing-fees.dockerfile
|
||||||
|
- [x] ci/dev/fx-oracle.dockerfile
|
||||||
|
- [x] ci/dev/fx-ingestor.dockerfile
|
||||||
|
- [x] ci/dev/payments-orchestrator.dockerfile
|
||||||
|
- [x] ci/dev/chain-gateway.dockerfile
|
||||||
|
- [x] ci/dev/mntx-gateway.dockerfile
|
||||||
|
- [x] ci/dev/tgsettle-gateway.dockerfile
|
||||||
|
- [x] ci/dev/notification.dockerfile
|
||||||
|
- [x] ci/dev/bff.dockerfile
|
||||||
|
- [x] ci/dev/frontend.dockerfile
|
||||||
|
|
||||||
|
### Scripts & Utilities
|
||||||
|
- [x] ci/dev/mongo.key (MongoDB keyfile)
|
||||||
|
- [x] ci/dev/vault/config.hcl (Vault config)
|
||||||
|
- [x] Vault templates removed (not needed for dev)
|
||||||
|
- [x] Makefile commands for all operations
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- [x] SETUP.md (comprehensive setup guide)
|
||||||
|
- [x] ci/dev/README.md (quick reference)
|
||||||
|
- [x] ci/dev/CHECKLIST.md (this file)
|
||||||
|
- [x] CLAUDE.md (updated with dev commands)
|
||||||
|
|
||||||
|
## 🎯 Ready to Test
|
||||||
|
|
||||||
|
### Initial Setup
|
||||||
|
```bash
|
||||||
|
make init
|
||||||
|
```
|
||||||
|
|
||||||
|
### Start Environment
|
||||||
|
```bash
|
||||||
|
make up
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialize Vault (if needed)
|
||||||
|
```bash
|
||||||
|
make vault-init
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Status
|
||||||
|
```bash
|
||||||
|
make status
|
||||||
|
make list-services
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Service Dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
Infrastructure Layer:
|
||||||
|
├─ MongoDB (dev-mongo-1, dev-mongo-2, dev-mongo-3)
|
||||||
|
├─ NATS (dev-nats)
|
||||||
|
└─ Vault (dev-vault)
|
||||||
|
|
||||||
|
Service Layer:
|
||||||
|
├─ dev-discovery → [nats]
|
||||||
|
├─ dev-fx-oracle → [mongo, nats]
|
||||||
|
├─ dev-fx-ingestor → [mongo, nats]
|
||||||
|
├─ dev-billing-fees → [mongo, nats, fx-oracle]
|
||||||
|
├─ dev-ledger → [mongo, nats, discovery, billing-fees]
|
||||||
|
├─ dev-payments-orchestrator → [mongo, nats, ledger, billing-fees]
|
||||||
|
├─ dev-chain-gateway → [mongo, nats, discovery, vault]
|
||||||
|
├─ dev-mntx-gateway → [nats, discovery, vault]
|
||||||
|
├─ dev-tgsettle-gateway → [mongo, nats, discovery, vault]
|
||||||
|
├─ dev-notification → [nats]
|
||||||
|
├─ dev-bff → [mongo, nats, ledger, payments, chain-gateway]
|
||||||
|
└─ dev-frontend → [bff]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Validation Steps
|
||||||
|
|
||||||
|
### 1. Infrastructure
|
||||||
|
- [ ] MongoDB replica set initializes correctly
|
||||||
|
- [ ] NATS is accessible and healthy
|
||||||
|
- [ ] Vault starts and can be initialized
|
||||||
|
|
||||||
|
### 2. Core Services
|
||||||
|
- [ ] Discovery service starts and is healthy
|
||||||
|
- [ ] Ledger service connects to MongoDB and NATS
|
||||||
|
- [ ] Billing fees service can query FX oracle
|
||||||
|
- [ ] FX oracle provides quotes
|
||||||
|
|
||||||
|
### 3. Payment Flow
|
||||||
|
- [ ] Payments orchestrator can communicate with ledger
|
||||||
|
- [ ] Payments orchestrator can calculate fees
|
||||||
|
- [ ] Payment plan execution works
|
||||||
|
|
||||||
|
### 4. Gateways
|
||||||
|
- [ ] Chain gateway connects to Vault for keys
|
||||||
|
- [ ] MNTX gateway is reachable
|
||||||
|
- [ ] TGSettle gateway connects to Telegram
|
||||||
|
|
||||||
|
### 5. Frontend
|
||||||
|
- [ ] BFF serves API endpoints
|
||||||
|
- [ ] Frontend builds successfully
|
||||||
|
- [ ] Frontend connects to BFF
|
||||||
|
|
||||||
|
## 🐛 Known Considerations
|
||||||
|
|
||||||
|
1. **Vault Secrets**: Services using Vault (chain, mntx, tgsettle) need secrets populated
|
||||||
|
2. **External APIs**: MNTX and TGSettle need API credentials from Vault
|
||||||
|
3. **Blockchain**: Chain gateway needs blockchain node URLs and private keys
|
||||||
|
4. **Build Time**: Frontend build takes ~5-10 minutes (Flutter compile)
|
||||||
|
|
||||||
|
## 📝 Post-Setup Tasks
|
||||||
|
|
||||||
|
- [ ] Populate Vault with blockchain keys for Chain Gateway
|
||||||
|
- [ ] Add MNTX API credentials to Vault
|
||||||
|
- [ ] Add TGSettle (Telegram) credentials to Vault
|
||||||
|
- [ ] Seed test data into MongoDB
|
||||||
|
- [ ] Configure blockchain RPC endpoints
|
||||||
|
- [ ] Test full payment flow end-to-end
|
||||||
|
|
||||||
|
## 🚀 Next Development Steps
|
||||||
|
|
||||||
|
1. Test `make init && make up`
|
||||||
|
2. Verify all services start successfully
|
||||||
|
3. Check logs for any errors
|
||||||
|
4. Test service-to-service communication
|
||||||
|
5. Add seed data scripts
|
||||||
|
6. Create integration tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status**: ✅ COMPLETE - Ready for testing
|
||||||
|
**Date**: 2026-01-27
|
||||||
|
**Build System**: Docker Compose + Makefile
|
||||||
|
**Total Services**: 12 application + 3 infrastructure = 15 containers
|
||||||
101
ci/dev/Caddyfile.dev
Normal file
101
ci/dev/Caddyfile.dev
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
########################################
|
||||||
|
# Development Caddyfile for Sendico
|
||||||
|
########################################
|
||||||
|
{
|
||||||
|
# No ACME email needed for local dev
|
||||||
|
auto_https off
|
||||||
|
}
|
||||||
|
|
||||||
|
:80 {
|
||||||
|
vars static_root /usr/share/pweb
|
||||||
|
|
||||||
|
encode zstd gzip
|
||||||
|
|
||||||
|
route {
|
||||||
|
########################################
|
||||||
|
# Backend API - proxy to dev-bff
|
||||||
|
########################################
|
||||||
|
handle /api/v1/* {
|
||||||
|
reverse_proxy dev-bff:8080 {
|
||||||
|
health_uri /api/v1/health
|
||||||
|
health_interval 15s
|
||||||
|
health_timeout 4s
|
||||||
|
health_status 2xx
|
||||||
|
}
|
||||||
|
header Cache-Control "no-cache, no-store, must-revalidate"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Telegram webhook -> notification service
|
||||||
|
handle /telegram/webhook {
|
||||||
|
reverse_proxy dev-notification:8081
|
||||||
|
}
|
||||||
|
|
||||||
|
# Monetix callbacks -> mntx gateway
|
||||||
|
handle /gateway/m/* {
|
||||||
|
rewrite * /monetix/callback
|
||||||
|
reverse_proxy dev-mntx-gateway:8084
|
||||||
|
header Cache-Control "no-cache, no-store, must-revalidate"
|
||||||
|
}
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# Static assets
|
||||||
|
########################################
|
||||||
|
handle /version.json {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "no-cache"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /*.js {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "public, max-age=3600"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /assets/* {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "public, max-age=86400"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /canvaskit/* {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "public, max-age=86400"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /icons/* {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "public, max-age=86400"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /*.html {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "no-cache"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /*.css {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "public, max-age=3600"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /*.json {
|
||||||
|
root * {vars.static_root}
|
||||||
|
file_server
|
||||||
|
header Cache-Control "public, max-age=3600"
|
||||||
|
}
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# SPA fallback - serves index.html for all routes
|
||||||
|
########################################
|
||||||
|
handle {
|
||||||
|
root * {vars.static_root}
|
||||||
|
try_files {path} /index.html
|
||||||
|
file_server
|
||||||
|
header Cache-Control "no-cache"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
124
ci/dev/README.md
Normal file
124
ci/dev/README.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# Sendico Development Environment
|
||||||
|
|
||||||
|
Docker Compose + Makefile build system for local development.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
**Infrastructure:**
|
||||||
|
- MongoDB replica set (3 nodes) - credentials in `.env.dev`
|
||||||
|
- NATS with JetStream - credentials in `.env.dev`
|
||||||
|
- Vault (single node) - for application data ONLY (blockchain keys, external API keys)
|
||||||
|
|
||||||
|
**Services:**
|
||||||
|
- Discovery, Ledger, Billing Fees, Billing Documents, FX Oracle, Payments Orchestrator
|
||||||
|
- Chain Gateway, MNTX Gateway, TGSettle Gateway
|
||||||
|
- FX Ingestor, Notification, BFF (Server), Frontend
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Initialize environment (first time)
|
||||||
|
make init
|
||||||
|
|
||||||
|
# 2. Start all services
|
||||||
|
make up
|
||||||
|
|
||||||
|
# 3. Initialize Vault (if services need it for application data)
|
||||||
|
make vault-init
|
||||||
|
|
||||||
|
# 4. View logs
|
||||||
|
make logs SERVICE=ledger
|
||||||
|
|
||||||
|
# 5. Stop everything
|
||||||
|
make down
|
||||||
|
```
|
||||||
|
|
||||||
|
## Credentials
|
||||||
|
|
||||||
|
All in `.env.dev` (plaintext for dev):
|
||||||
|
- MongoDB: `dev_root` / `dev_password_123`
|
||||||
|
- NATS: `dev_nats` / `nats_password_123`
|
||||||
|
- Vault: Run `make vault-init` to get root token
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build # Build all images
|
||||||
|
make up # Start environment
|
||||||
|
make down # Stop environment
|
||||||
|
make logs SERVICE=ledger # View service logs
|
||||||
|
make rebuild SERVICE=ledger # Rebuild specific service
|
||||||
|
make proto # Regenerate protobuf
|
||||||
|
make clean # Remove everything
|
||||||
|
make status # Check service status
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vault Usage
|
||||||
|
|
||||||
|
**Vault is ONLY for application data**, not infrastructure secrets!
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- Blockchain private keys (Chain Gateway)
|
||||||
|
- External API keys (MNTX, TGSettle)
|
||||||
|
- Production-like secrets
|
||||||
|
|
||||||
|
Infrastructure (MongoDB, NATS) uses plain `.env.dev` credentials.
|
||||||
|
|
||||||
|
## Network
|
||||||
|
|
||||||
|
All services on `sendico-dev` network. Vault also on `cicd` network to connect to infra Vault if needed.
|
||||||
|
|
||||||
|
## Rebuilding Services
|
||||||
|
|
||||||
|
After code changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebuild specific service
|
||||||
|
make rebuild SERVICE=ledger
|
||||||
|
|
||||||
|
# Or manually
|
||||||
|
docker compose -f docker-compose.dev.yml build ledger
|
||||||
|
docker compose -f docker-compose.dev.yml up -d --force-recreate ledger
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding New Services
|
||||||
|
|
||||||
|
1. Create Dockerfile: `ci/dev/yourservice.dockerfile`
|
||||||
|
2. Add service to `docker-compose.dev.yml`
|
||||||
|
3. Use environment variables from `.env.dev`
|
||||||
|
4. Connect to `sendico-dev` network
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**MongoDB replica set not initializing:**
|
||||||
|
```bash
|
||||||
|
make down
|
||||||
|
make up
|
||||||
|
# Wait for health checks, then:
|
||||||
|
docker logs dev-mongo-init
|
||||||
|
```
|
||||||
|
|
||||||
|
**Vault sealed:**
|
||||||
|
```bash
|
||||||
|
make vault-init
|
||||||
|
# Save the unseal key and root token from vault-keys.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Service can't connect to MongoDB:**
|
||||||
|
- Check replica set: `docker exec -it dev-mongo-1 mongosh -u dev_root -p dev_password_123 --eval "rs.status()"`
|
||||||
|
- Ensure `dev-mongo-init` completed: `docker ps -a | grep init`
|
||||||
|
|
||||||
|
**Proto generation errors:**
|
||||||
|
```bash
|
||||||
|
make proto
|
||||||
|
# Check output for missing dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `docker-compose.dev.yml` - All services
|
||||||
|
- `.env.dev` - Plaintext credentials
|
||||||
|
- `Makefile` - Build commands
|
||||||
|
- `ci/dev/*.dockerfile` - Service builds
|
||||||
|
- `ci/dev/mongo.key` - MongoDB replica set key
|
||||||
|
- `ci/dev/vault/config.hcl` - Vault config
|
||||||
52
ci/dev/bff.dockerfile
Normal file
52
ci/dev/bff.dockerfile
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Development Dockerfile for BFF (Server) Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Copy service dependencies (needed for go.mod replace directives)
|
||||||
|
COPY api/ledger ./api/ledger
|
||||||
|
COPY api/payments/orchestrator ./api/payments/orchestrator
|
||||||
|
COPY api/gateway/chain ./api/gateway/chain
|
||||||
|
COPY api/billing/fees ./api/billing/fees
|
||||||
|
COPY api/fx/oracle ./api/fx/oracle
|
||||||
|
COPY api/fx/storage ./api/fx/storage
|
||||||
|
COPY api/gateway/mntx ./api/gateway/mntx
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy service dependencies
|
||||||
|
COPY --from=builder /src/api/ledger ./api/ledger
|
||||||
|
COPY --from=builder /src/api/payments/orchestrator ./api/payments/orchestrator
|
||||||
|
COPY --from=builder /src/api/gateway/chain ./api/gateway/chain
|
||||||
|
COPY --from=builder /src/api/billing/fees ./api/billing/fees
|
||||||
|
COPY --from=builder /src/api/fx/oracle ./api/fx/oracle
|
||||||
|
COPY --from=builder /src/api/fx/storage ./api/fx/storage
|
||||||
|
COPY --from=builder /src/api/gateway/mntx ./api/gateway/mntx
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/server
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
39
ci/dev/billing-documents.dockerfile
Normal file
39
ci/dev/billing-documents.dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Development Dockerfile for Billing Documents Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy proto and pkg first (changes less frequently)
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
|
||||||
|
# Generate protos (cached if proto files unchanged)
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime to /src/api/billing/documents
|
||||||
|
WORKDIR /src/api/billing/documents
|
||||||
|
|
||||||
|
EXPOSE 50061 9409
|
||||||
|
|
||||||
|
# Use Air for hot reload
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
42
ci/dev/billing-fees.dockerfile
Normal file
42
ci/dev/billing-fees.dockerfile
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Development Dockerfile for Billing Fees Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Copy service dependencies (needed for go.mod replace directives)
|
||||||
|
COPY api/fx/oracle ./api/fx/oracle
|
||||||
|
COPY api/fx/storage ./api/fx/storage
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy service dependencies
|
||||||
|
COPY --from=builder /src/api/fx/oracle ./api/fx/oracle
|
||||||
|
COPY --from=builder /src/api/fx/storage ./api/fx/storage
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/billing/fees
|
||||||
|
|
||||||
|
EXPOSE 50060 9402
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
40
ci/dev/chain-gateway.dockerfile
Normal file
40
ci/dev/chain-gateway.dockerfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Development Dockerfile for chain-gateway Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy dev-specific entrypoint script
|
||||||
|
COPY ci/dev/entrypoints/chain-gateway.sh /app/entrypoint.sh
|
||||||
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/gateway/chain
|
||||||
|
|
||||||
|
EXPOSE 50070 9404
|
||||||
|
|
||||||
|
# Use entrypoint wrapper to load vault token
|
||||||
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
34
ci/dev/discovery.dockerfile
Normal file
34
ci/dev/discovery.dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Development Dockerfile for discovery Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/discovery
|
||||||
|
|
||||||
|
EXPOSE 9407
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
17
ci/dev/entrypoints/chain-gateway.sh
Normal file
17
ci/dev/entrypoints/chain-gateway.sh
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# Load Vault token from file if VAULT_TOKEN_FILE is set
|
||||||
|
if [ -n "${VAULT_TOKEN_FILE:-}" ] && [ -f "${VAULT_TOKEN_FILE}" ]; then
|
||||||
|
token="$(cat "${VAULT_TOKEN_FILE}" 2>/dev/null | tr -d '[:space:]')"
|
||||||
|
if [ -n "${token}" ]; then
|
||||||
|
export VAULT_TOKEN="${token}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VAULT_TOKEN:-}" ]; then
|
||||||
|
echo "[entrypoint] VAULT_TOKEN is not set; expected Vault Agent sink to write a token to ${VAULT_TOKEN_FILE:-/run/vault/token}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute the command passed as arguments (e.g., air)
|
||||||
|
exec "$@"
|
||||||
17
ci/dev/entrypoints/tron-gateway.sh
Executable file
17
ci/dev/entrypoints/tron-gateway.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# Load Vault token from file if VAULT_TOKEN_FILE is set
|
||||||
|
if [ -n "${VAULT_TOKEN_FILE:-}" ] && [ -f "${VAULT_TOKEN_FILE}" ]; then
|
||||||
|
token="$(cat "${VAULT_TOKEN_FILE}" 2>/dev/null | tr -d '[:space:]')"
|
||||||
|
if [ -n "${token}" ]; then
|
||||||
|
export VAULT_TOKEN="${token}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VAULT_TOKEN:-}" ]; then
|
||||||
|
echo "[entrypoint] VAULT_TOKEN is not set; expected Vault Agent sink to write a token to ${VAULT_TOKEN_FILE:-/run/vault/token}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute the command passed as arguments (e.g., air)
|
||||||
|
exec "$@"
|
||||||
57
ci/dev/frontend.dockerfile
Normal file
57
ci/dev/frontend.dockerfile
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Development Dockerfile for Frontend (Flutter Web)
|
||||||
|
|
||||||
|
FROM dart:stable AS web_builder
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
unzip \
|
||||||
|
xz-utils \
|
||||||
|
libglu1-mesa \
|
||||||
|
ca-certificates \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN useradd -ms /bin/bash flutteruser
|
||||||
|
|
||||||
|
ENV PATH="/home/flutteruser/flutter/bin:${PATH}"
|
||||||
|
|
||||||
|
USER flutteruser
|
||||||
|
WORKDIR /home/flutteruser
|
||||||
|
|
||||||
|
# Install Flutter
|
||||||
|
RUN git clone --branch stable --depth 1 https://github.com/flutter/flutter.git \
|
||||||
|
&& flutter config --enable-web \
|
||||||
|
&& flutter precache --web \
|
||||||
|
&& flutter upgrade
|
||||||
|
|
||||||
|
COPY --chown=flutteruser:flutteruser frontend /home/flutteruser/app
|
||||||
|
|
||||||
|
# Replace production config with dev config
|
||||||
|
WORKDIR /home/flutteruser/app/pshared
|
||||||
|
RUN cp lib/config/common_dev.dart lib/config/common.dart
|
||||||
|
|
||||||
|
# Build shared package with code generation
|
||||||
|
RUN flutter clean \
|
||||||
|
&& flutter pub get \
|
||||||
|
&& dart run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
|
# Build the web client
|
||||||
|
WORKDIR /home/flutteruser/app/pweb
|
||||||
|
RUN flutter clean \
|
||||||
|
&& flutter pub get \
|
||||||
|
&& flutter build web --release --no-tree-shake-icons
|
||||||
|
|
||||||
|
# Runtime stage with Caddy
|
||||||
|
FROM caddy:alpine AS runtime
|
||||||
|
|
||||||
|
WORKDIR /usr/share/pweb
|
||||||
|
|
||||||
|
COPY --from=web_builder /home/flutteruser/app/pweb/build/web /usr/share/pweb
|
||||||
|
|
||||||
|
# Copy Caddy config (will be mounted from host)
|
||||||
|
# COPY frontend/pweb/caddy/Caddyfile /etc/caddy/Caddyfile
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
|
||||||
40
ci/dev/fx-ingestor.dockerfile
Normal file
40
ci/dev/fx-ingestor.dockerfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Development Dockerfile for fx-ingestor Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Copy service dependencies (needed for go.mod replace directives)
|
||||||
|
COPY api/fx/storage ./api/fx/storage
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy service dependencies
|
||||||
|
COPY --from=builder /src/api/fx/storage ./api/fx/storage
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/fx/ingestor
|
||||||
|
|
||||||
|
EXPOSE 9102
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
40
ci/dev/fx-oracle.dockerfile
Normal file
40
ci/dev/fx-oracle.dockerfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Development Dockerfile for fx-oracle Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Copy service dependencies (needed for go.mod replace directives)
|
||||||
|
COPY api/fx/storage ./api/fx/storage
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy service dependencies
|
||||||
|
COPY --from=builder /src/api/fx/storage ./api/fx/storage
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/fx/oracle
|
||||||
|
|
||||||
|
EXPOSE 50051 9400
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
39
ci/dev/ledger.dockerfile
Normal file
39
ci/dev/ledger.dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Development Dockerfile for Ledger Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy proto and pkg first (changes less frequently)
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
|
||||||
|
# Generate protos (cached if proto files unchanged)
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime to /src/api/ledger
|
||||||
|
WORKDIR /src/api/ledger
|
||||||
|
|
||||||
|
EXPOSE 50052 9401
|
||||||
|
|
||||||
|
# Use Air for hot reload
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
34
ci/dev/mntx-gateway.dockerfile
Normal file
34
ci/dev/mntx-gateway.dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Development Dockerfile for mntx-gateway Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/gateway/mntx
|
||||||
|
|
||||||
|
EXPOSE 50075 9405 8084
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
1
ci/dev/mongo.key
Normal file
1
ci/dev/mongo.key
Normal file
@@ -0,0 +1 @@
|
|||||||
|
FyzfUWK+e1eja+tKfkBhLBPHK34pQgsTkgsq8jxocQCt95k5dxbhw8loB+wyZ2LijIXRjGqraurKEHIl4bF12C05pRlazIyiJXA7T2iQzFtEnJW7IQM1rRWcnm5ZKwxlnnjF4t+5E48SUnXUq587iZV+osrHpGxIHu7WKMtRXE6kD+allogQ+6TCcFu8dDg4ruyC1WUkXh/5ivoFyzFE9hK5WDPo8/dURPav8j+rhaP6+ZWKisfzvssVNiLA3jyb+NYiTBgWkVXk9RXH1SpyrQZOHaOon7Kr57KQnksBrv/yJa75FfwZJagpWUkSbqtpz20e8Jimh/1c+fzE8JR0wFd0eprMQQbZ0WM1hadi5FP5I0e883nLh2brUUI9MUC0sO/+qAL7Giv6+eNhrVWfrJBA0TNQ09AygqBrgM0JJGxHe8OBtlQWWcAI58rtSU2eJmNiwMkyzccv3Z7zknjZ4Y/dGTNQ7ckzEyRQE2u+Ujgs1bje/IS+geFieVpwGoRuKyBqQsnH2uKO/M1wrMwGyPo+5AMKhXtYuMCQoz5jNuRFmOxQq/8Jykg07Z2hntoky3nvWAlDgh3B/mXJmZzi4KfXIW1xnNGzxDMnHeuNcCxAe7vlHkLX6xU74DuWUYYi92Sd6oLeyfxZqoqwgO3SEqfErDC3bOIAQBiJHKs+8UwhbfUoEdX/pLenAOPIcq1fcRQIOd/PKE/USlYGFao8mluBqJuXkw8iPeMQEBepuovebTDxIM4whzWQmMqKm/Xn/CZNhv3CISQvGg0IIqNL6q8FxFSRc7aa0ezUMpMFQBt20muL0xz8DGxdzTOqUWXr8ac2JQH0A66UXYW8iBlP3ZPh37BURBVQTB+++uF2p72jGhWHcE873ELV5Xq7LeextIDcz4L8O+C0K8v7v9tsI35PJR93+jNOS8phEkanvN2Yo6v4W1GQ8oBqbFd9R0KIwxgL7iK1H9pfA7lIeBavHjEjz8FqFxltpqz9mHvop41Sybp6
|
||||||
34
ci/dev/notification.dockerfile
Normal file
34
ci/dev/notification.dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Development Dockerfile for notification Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/notification
|
||||||
|
|
||||||
|
EXPOSE 8081
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
50
ci/dev/payments-orchestrator.dockerfile
Normal file
50
ci/dev/payments-orchestrator.dockerfile
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Development Dockerfile for Payments Orchestrator Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Copy service dependencies (needed for go.mod replace directives)
|
||||||
|
COPY api/ledger ./api/ledger
|
||||||
|
COPY api/billing/fees ./api/billing/fees
|
||||||
|
COPY api/fx/oracle ./api/fx/oracle
|
||||||
|
COPY api/fx/storage ./api/fx/storage
|
||||||
|
COPY api/gateway/chain ./api/gateway/chain
|
||||||
|
COPY api/gateway/mntx ./api/gateway/mntx
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy service dependencies
|
||||||
|
COPY --from=builder /src/api/ledger ./api/ledger
|
||||||
|
COPY --from=builder /src/api/billing/fees ./api/billing/fees
|
||||||
|
COPY --from=builder /src/api/fx/oracle ./api/fx/oracle
|
||||||
|
COPY --from=builder /src/api/fx/storage ./api/fx/storage
|
||||||
|
COPY --from=builder /src/api/gateway/chain ./api/gateway/chain
|
||||||
|
COPY --from=builder /src/api/gateway/mntx ./api/gateway/mntx
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/payments/orchestrator
|
||||||
|
|
||||||
|
EXPOSE 50062 9403
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
13
ci/dev/scripts/mongo-entrypoint.sh
Normal file
13
ci/dev/scripts/mongo-entrypoint.sh
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# MongoDB entrypoint wrapper for dev environment
|
||||||
|
# Reads credentials from Vault secrets and initializes MongoDB
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Read credentials from Vault Agent-rendered files
|
||||||
|
if [ -s /vault/secrets/MONGO_ROOT_USER ] && [ -s /vault/secrets/MONGO_ROOT_PASSWORD ]; then
|
||||||
|
export MONGO_INITDB_ROOT_USERNAME="$(cat /vault/secrets/MONGO_ROOT_USER)"
|
||||||
|
export MONGO_INITDB_ROOT_PASSWORD="$(cat /vault/secrets/MONGO_ROOT_PASSWORD)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute original MongoDB entrypoint
|
||||||
|
exec docker-entrypoint.sh "$@"
|
||||||
18
ci/dev/scripts/nats-entrypoint.sh
Normal file
18
ci/dev/scripts/nats-entrypoint.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# NATS entrypoint wrapper for dev environment
|
||||||
|
# Reads credentials from Vault secrets and starts NATS
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Read NATS credentials from Vault Agent-rendered files
|
||||||
|
NATS_USER="$(cat /vault/secrets/NATS_USER)"
|
||||||
|
NATS_PASSWORD="$(cat /vault/secrets/NATS_PASSWORD)"
|
||||||
|
|
||||||
|
# Start NATS with JetStream
|
||||||
|
exec nats-server \
|
||||||
|
--jetstream \
|
||||||
|
--store_dir=/data \
|
||||||
|
--http_port=8222 \
|
||||||
|
--port=4222 \
|
||||||
|
--server_name=dev-nats \
|
||||||
|
--user="${NATS_USER}" \
|
||||||
|
--pass="${NATS_PASSWORD}"
|
||||||
112
ci/dev/scripts/vault-setup.sh
Normal file
112
ci/dev/scripts/vault-setup.sh
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Vault Setup Script for Development Environment
|
||||||
|
# Creates AppRole, policies, and secrets for dev services
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||||||
|
|
||||||
|
# Source the vlt helper
|
||||||
|
VLT="${REPO_ROOT}/ci/vlt"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log() { echo -e "${GREEN}[vault-setup]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[vault-setup]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[vault-setup]${NC} $*" >&2; }
|
||||||
|
|
||||||
|
# Check prerequisites
|
||||||
|
if [ ! -f "$VLT" ]; then
|
||||||
|
error "Vault helper not found at $VLT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VAULT_ADDR:-}" ]; then
|
||||||
|
error "VAULT_ADDR is not set"
|
||||||
|
error "Please ensure Vault is running: cd infra/vault && docker compose up -d"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Checking Vault connection..."
|
||||||
|
if ! curl -sf "${VAULT_ADDR}/v1/sys/health" > /dev/null; then
|
||||||
|
error "Cannot connect to Vault at ${VAULT_ADDR}"
|
||||||
|
error "Please ensure Vault is running: cd infra/vault && docker compose up -d"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "✓ Vault is reachable at ${VAULT_ADDR}"
|
||||||
|
|
||||||
|
# You need to be authenticated to Vault to run this script
|
||||||
|
# Either set VAULT_TOKEN or VAULT_ROLE_ID + VAULT_SECRET_ID
|
||||||
|
if [ -z "${VAULT_TOKEN:-}" ]; then
|
||||||
|
warn "VAULT_TOKEN not set. Attempting AppRole login..."
|
||||||
|
if [ -z "${VAULT_ROLE_ID:-}" ] || [ -z "${VAULT_SECRET_ID:-}" ]; then
|
||||||
|
error "Neither VAULT_TOKEN nor VAULT_ROLE_ID/VAULT_SECRET_ID are set"
|
||||||
|
error "Please authenticate to Vault first:"
|
||||||
|
error " export VAULT_TOKEN=<your-vault-token>"
|
||||||
|
error "Or use AppRole:"
|
||||||
|
error " export VAULT_ROLE_ID=<role-id>"
|
||||||
|
error " export VAULT_SECRET_ID=<secret-id>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
"${VLT}" login
|
||||||
|
VAULT_TOKEN="$(cat .vault_token)"
|
||||||
|
export VAULT_TOKEN
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Creating dev environment policy..."
|
||||||
|
cat <<'EOF' | curl -sf -X PUT -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
||||||
|
--data-binary @- "${VAULT_ADDR}/v1/sys/policy/dev-services" > /dev/null
|
||||||
|
{
|
||||||
|
"policy": "path \"kv/data/sendico/dev\" { capabilities = [\"read\"] }"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log "Creating dev-services AppRole..."
|
||||||
|
curl -sf -X POST -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
||||||
|
-d '{"policies": ["dev-services"], "bind_secret_id": true, "token_ttl": "24h", "token_max_ttl": "720h"}' \
|
||||||
|
"${VAULT_ADDR}/v1/auth/approle/role/dev-services" > /dev/null
|
||||||
|
|
||||||
|
log "Fetching AppRole credentials..."
|
||||||
|
ROLE_ID=$(curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
||||||
|
"${VAULT_ADDR}/v1/auth/approle/role/dev-services/role-id" | \
|
||||||
|
grep -o '"role_id":"[^"]*' | cut -d'"' -f4)
|
||||||
|
|
||||||
|
SECRET_ID=$(curl -sf -X POST -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
||||||
|
"${VAULT_ADDR}/v1/auth/approle/role/dev-services/secret-id" | \
|
||||||
|
grep -o '"secret_id":"[^"]*' | cut -d'"' -f4)
|
||||||
|
|
||||||
|
log "Creating/updating dev secrets in Vault..."
|
||||||
|
|
||||||
|
# Generate random credentials if they don't exist
|
||||||
|
MONGO_USER="sendico_dev"
|
||||||
|
MONGO_PASSWORD="$(openssl rand -base64 32 | tr -d '/+=' | cut -c1-24)"
|
||||||
|
MONGO_KEYFILE="$(openssl rand -base64 756 | tr -d '\n')"
|
||||||
|
NATS_USER="sendico_dev"
|
||||||
|
NATS_PASSWORD="$(openssl rand -base64 32 | tr -d '/+=' | cut -c1-24)"
|
||||||
|
|
||||||
|
curl -sf -X POST -H "X-Vault-Token: ${VAULT_TOKEN}" \
|
||||||
|
-d "{
|
||||||
|
\"data\": {
|
||||||
|
\"mongo_user\": \"${MONGO_USER}\",
|
||||||
|
\"mongo_password\": \"${MONGO_PASSWORD}\",
|
||||||
|
\"mongo_keyfile\": \"${MONGO_KEYFILE}\",
|
||||||
|
\"nats_user\": \"${NATS_USER}\",
|
||||||
|
\"nats_password\": \"${NATS_PASSWORD}\"
|
||||||
|
}
|
||||||
|
}" \
|
||||||
|
"${VAULT_ADDR}/v1/kv/data/sendico/dev" > /dev/null
|
||||||
|
|
||||||
|
log "✅ Vault setup complete!"
|
||||||
|
echo ""
|
||||||
|
log "AppRole Credentials (add these to .env.dev):"
|
||||||
|
echo ""
|
||||||
|
echo "VAULT_ROLE_ID=${ROLE_ID}"
|
||||||
|
echo "VAULT_SECRET_ID=${SECRET_ID}"
|
||||||
|
echo ""
|
||||||
|
warn "IMPORTANT: Save these credentials in .env.dev"
|
||||||
|
warn "They will be needed to start the dev environment"
|
||||||
34
ci/dev/tgsettle-gateway.dockerfile
Normal file
34
ci/dev/tgsettle-gateway.dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Development Dockerfile for tgsettle-gateway Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/gateway/tgsettle
|
||||||
|
|
||||||
|
EXPOSE 50080 9406
|
||||||
|
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
40
ci/dev/tron-gateway.dockerfile
Normal file
40
ci/dev/tron-gateway.dockerfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Development Dockerfile for tron-gateway Service with Air hot reload
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY api/proto ./api/proto
|
||||||
|
COPY api/pkg ./api/pkg
|
||||||
|
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
|
||||||
|
RUN bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
# Runtime stage for development with Air
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash git build-base && \
|
||||||
|
go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy generated proto and pkg from builder
|
||||||
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
|
# Copy dev-specific entrypoint script
|
||||||
|
COPY ci/dev/entrypoints/tron-gateway.sh /app/entrypoint.sh
|
||||||
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
|
# Source code will be mounted at runtime
|
||||||
|
WORKDIR /src/api/gateway/tron
|
||||||
|
|
||||||
|
EXPOSE 50071 9407
|
||||||
|
|
||||||
|
# Use entrypoint wrapper to load vault token
|
||||||
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
|
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]
|
||||||
20
ci/dev/vault-agent/chain-gateway.hcl
Normal file
20
ci/dev/vault-agent/chain-gateway.hcl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
vault {
|
||||||
|
address = "http://dev-vault:8200"
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_auth {
|
||||||
|
method "approle" {
|
||||||
|
mount_path = "auth/approle"
|
||||||
|
config = {
|
||||||
|
role_id_file_path = "/run/vault/role_id"
|
||||||
|
secret_id_file_path = "/run/vault/secret_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sink "file" {
|
||||||
|
config = {
|
||||||
|
path = "/run/vault/token"
|
||||||
|
mode = 0600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
ci/dev/vault-agent/tron-gateway.hcl
Normal file
20
ci/dev/vault-agent/tron-gateway.hcl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
vault {
|
||||||
|
address = "http://dev-vault:8200"
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_auth {
|
||||||
|
method "approle" {
|
||||||
|
mount_path = "auth/approle"
|
||||||
|
config = {
|
||||||
|
role_id_file_path = "/run/vault/role_id"
|
||||||
|
secret_id_file_path = "/run/vault/secret_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sink "file" {
|
||||||
|
config = {
|
||||||
|
path = "/run/vault/token"
|
||||||
|
mode = 0600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
ci/dev/vault/agent.hcl
Normal file
49
ci/dev/vault/agent.hcl
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Vault Agent for Development Environment
|
||||||
|
# AppRole credentials are injected as files from environment variables
|
||||||
|
pid_file = "/tmp/vault-agent.pid"
|
||||||
|
|
||||||
|
auto_auth {
|
||||||
|
method "approle" {
|
||||||
|
mount_path = "auth/approle"
|
||||||
|
config = {
|
||||||
|
role_id_file_path = "/vault/secrets/role_id"
|
||||||
|
secret_id_file_path = "/vault/secrets/secret_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sink "file" {
|
||||||
|
config = { path = "/vault/token" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vault {
|
||||||
|
address = "{{ env `VAULT_ADDR` }}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# MongoDB root credentials
|
||||||
|
template {
|
||||||
|
source = "/etc/vault/templates/mongo/user.ctmpl"
|
||||||
|
destination = "/vault/secrets/MONGO_ROOT_USER"
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
source = "/etc/vault/templates/mongo/pass.ctmpl"
|
||||||
|
destination = "/vault/secrets/MONGO_ROOT_PASSWORD"
|
||||||
|
}
|
||||||
|
|
||||||
|
# MongoDB replica set keyFile (strict perms for MongoDB)
|
||||||
|
template {
|
||||||
|
source = "/etc/vault/templates/mongo/keyfile.ctmpl"
|
||||||
|
destination = "/vault/secrets/mongo.kf"
|
||||||
|
command = "sh -lc 'chmod 0400 /vault/secrets/mongo.kf'"
|
||||||
|
}
|
||||||
|
|
||||||
|
# NATS credentials
|
||||||
|
template {
|
||||||
|
source = "/etc/vault/templates/nats/user.ctmpl"
|
||||||
|
destination = "/vault/secrets/NATS_USER"
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
source = "/etc/vault/templates/nats/pass.ctmpl"
|
||||||
|
destination = "/vault/secrets/NATS_PASSWORD"
|
||||||
|
}
|
||||||
17
ci/dev/vault/config.hcl
Normal file
17
ci/dev/vault/config.hcl
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Vault Configuration for Development
|
||||||
|
# Single node, file storage backend
|
||||||
|
|
||||||
|
storage "file" {
|
||||||
|
path = "/vault/file"
|
||||||
|
}
|
||||||
|
|
||||||
|
listener "tcp" {
|
||||||
|
address = "0.0.0.0:8200"
|
||||||
|
tls_disable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
api_addr = "http://0.0.0.0:8200"
|
||||||
|
ui = true
|
||||||
|
|
||||||
|
# Disable mlock for dev (no need for memory protection)
|
||||||
|
disable_mlock = true
|
||||||
3
ci/dev/vault/templates/mongo/keyfile.ctmpl
Normal file
3
ci/dev/vault/templates/mongo/keyfile.ctmpl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{{ with secret "kv/data/sendico/dev" -}}
|
||||||
|
{{ .Data.data.mongo_keyfile }}
|
||||||
|
{{- end }}
|
||||||
3
ci/dev/vault/templates/mongo/pass.ctmpl
Normal file
3
ci/dev/vault/templates/mongo/pass.ctmpl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{{ with secret "kv/data/sendico/dev" -}}
|
||||||
|
{{ .Data.data.mongo_password }}
|
||||||
|
{{- end }}
|
||||||
3
ci/dev/vault/templates/mongo/user.ctmpl
Normal file
3
ci/dev/vault/templates/mongo/user.ctmpl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{{ with secret "kv/data/sendico/dev" -}}
|
||||||
|
{{ .Data.data.mongo_user }}
|
||||||
|
{{- end }}
|
||||||
3
ci/dev/vault/templates/nats/pass.ctmpl
Normal file
3
ci/dev/vault/templates/nats/pass.ctmpl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{{ with secret "kv/data/sendico/dev" -}}
|
||||||
|
{{ .Data.data.nats_password }}
|
||||||
|
{{- end }}
|
||||||
3
ci/dev/vault/templates/nats/user.ctmpl
Normal file
3
ci/dev/vault/templates/nats/user.ctmpl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{{ with secret "kv/data/sendico/dev" -}}
|
||||||
|
{{ .Data.data.nats_user }}
|
||||||
|
{{- end }}
|
||||||
@@ -90,6 +90,13 @@ FEES_SERVICE_NAME=sendico_billing_fees
|
|||||||
FEES_GRPC_PORT=50060
|
FEES_GRPC_PORT=50060
|
||||||
FEES_METRICS_PORT=9402
|
FEES_METRICS_PORT=9402
|
||||||
|
|
||||||
|
# Billing documents stack
|
||||||
|
DOCUMENTS_DIR=billing_documents
|
||||||
|
DOCUMENTS_COMPOSE_PROJECT=sendico-billing-documents
|
||||||
|
DOCUMENTS_SERVICE_NAME=sendico_billing_documents
|
||||||
|
DOCUMENTS_GRPC_PORT=50061
|
||||||
|
DOCUMENTS_METRICS_PORT=9409
|
||||||
|
|
||||||
# Billing fees Mongo settings
|
# Billing fees Mongo settings
|
||||||
FEES_MONGO_HOST=sendico_db1
|
FEES_MONGO_HOST=sendico_db1
|
||||||
FEES_MONGO_PORT=27017
|
FEES_MONGO_PORT=27017
|
||||||
|
|||||||
40
ci/prod/compose/billing_documents.dockerfile
Normal file
40
ci/prod/compose/billing_documents.dockerfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
|
ARG TARGETOS=linux
|
||||||
|
ARG TARGETARCH=amd64
|
||||||
|
|
||||||
|
FROM golang:alpine AS build
|
||||||
|
ARG APP_VERSION=dev
|
||||||
|
ARG GIT_REV=unknown
|
||||||
|
ARG BUILD_BRANCH=unknown
|
||||||
|
ARG BUILD_DATE=unknown
|
||||||
|
ARG BUILD_USER=ci
|
||||||
|
ENV GO111MODULE=on
|
||||||
|
ENV PATH="/go/bin:${PATH}"
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev \
|
||||||
|
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
|
||||||
|
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
|
||||||
|
&& bash ci/scripts/proto/generate.sh
|
||||||
|
WORKDIR /src/api/billing/documents
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
|
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
|
||||||
|
go build -trimpath -ldflags "\
|
||||||
|
-s -w \
|
||||||
|
-X github.com/tech/sendico/billing/documents/internal/appversion.Version=${APP_VERSION} \
|
||||||
|
-X github.com/tech/sendico/billing/documents/internal/appversion.Revision=${GIT_REV} \
|
||||||
|
-X github.com/tech/sendico/billing/documents/internal/appversion.Branch=${BUILD_BRANCH} \
|
||||||
|
-X github.com/tech/sendico/billing/documents/internal/appversion.BuildUser=${BUILD_USER} \
|
||||||
|
-X github.com/tech/sendico/billing/documents/internal/appversion.BuildDate=${BUILD_DATE}" \
|
||||||
|
-o /out/billing-documents .
|
||||||
|
|
||||||
|
FROM alpine:latest AS runtime
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata wget
|
||||||
|
WORKDIR /app
|
||||||
|
COPY api/billing/documents/config.yml /app/config.yml
|
||||||
|
COPY --from=build /out/billing-documents /app/billing-documents
|
||||||
|
EXPOSE 50061 9409
|
||||||
|
ENTRYPOINT ["/app/billing-documents"]
|
||||||
|
CMD ["--config.file", "/app/config.yml"]
|
||||||
39
ci/prod/compose/billing_documents.yml
Normal file
39
ci/prod/compose/billing_documents.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Compose v2 - Billing documents
|
||||||
|
|
||||||
|
x-common-env: &common-env
|
||||||
|
env_file:
|
||||||
|
- ../env/.env.runtime
|
||||||
|
- ../env/.env.version
|
||||||
|
|
||||||
|
networks:
|
||||||
|
sendico-net:
|
||||||
|
external: true
|
||||||
|
name: sendico-net
|
||||||
|
|
||||||
|
services:
|
||||||
|
sendico_billing_documents:
|
||||||
|
<<: *common-env
|
||||||
|
container_name: sendico-billing-documents
|
||||||
|
restart: unless-stopped
|
||||||
|
image: ${REGISTRY_URL}/billing/documents:${APP_V}
|
||||||
|
pull_policy: always
|
||||||
|
environment:
|
||||||
|
DOCUMENTS_GRPC_PORT: ${DOCUMENTS_GRPC_PORT}
|
||||||
|
DOCUMENTS_METRICS_PORT: ${DOCUMENTS_METRICS_PORT}
|
||||||
|
NATS_URL: ${NATS_URL}
|
||||||
|
NATS_HOST: ${NATS_HOST}
|
||||||
|
NATS_PORT: ${NATS_PORT}
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
command: ["--config.file", "/app/config.yml"]
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${DOCUMENTS_GRPC_PORT}:50061"
|
||||||
|
- "0.0.0.0:${DOCUMENTS_METRICS_PORT}:${DOCUMENTS_METRICS_PORT}"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL","wget -qO- http://localhost:${DOCUMENTS_METRICS_PORT}/health | grep -q '\"status\":\"ok\"'"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 60s
|
||||||
|
networks:
|
||||||
|
- sendico-net
|
||||||
43
ci/prod/compose/tron_gateway.dockerfile
Normal file
43
ci/prod/compose/tron_gateway.dockerfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
|
ARG TARGETOS=linux
|
||||||
|
ARG TARGETARCH=amd64
|
||||||
|
|
||||||
|
FROM golang:alpine AS build
|
||||||
|
ARG APP_VERSION=dev
|
||||||
|
ARG GIT_REV=unknown
|
||||||
|
ARG BUILD_BRANCH=unknown
|
||||||
|
ARG BUILD_DATE=unknown
|
||||||
|
ARG BUILD_USER=ci
|
||||||
|
ENV GO111MODULE=on
|
||||||
|
ENV PATH="/go/bin:${PATH}"
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
RUN apk add --no-cache bash git build-base protoc protobuf-dev \
|
||||||
|
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
|
||||||
|
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
|
||||||
|
&& bash ci/scripts/proto/generate.sh
|
||||||
|
WORKDIR /src/api/gateway/tron
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||||
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
|
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
|
||||||
|
go build -trimpath -ldflags "\
|
||||||
|
-s -w \
|
||||||
|
-X github.com/tech/sendico/gateway/tron/internal/appversion.Version=${APP_VERSION} \
|
||||||
|
-X github.com/tech/sendico/gateway/tron/internal/appversion.Revision=${GIT_REV} \
|
||||||
|
-X github.com/tech/sendico/gateway/tron/internal/appversion.Branch=${BUILD_BRANCH} \
|
||||||
|
-X github.com/tech/sendico/gateway/tron/internal/appversion.BuildUser=${BUILD_USER} \
|
||||||
|
-X github.com/tech/sendico/gateway/tron/internal/appversion.BuildDate=${BUILD_DATE}" \
|
||||||
|
-o /out/tron-gateway .
|
||||||
|
|
||||||
|
FROM alpine:latest AS runtime
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata wget
|
||||||
|
WORKDIR /app
|
||||||
|
COPY api/gateway/tron/config.yml /app/config.yml
|
||||||
|
COPY api/gateway/tron/env /app/env
|
||||||
|
COPY api/gateway/tron/entrypoint.sh /app/entrypoint.sh
|
||||||
|
COPY --from=build /out/tron-gateway /app/tron-gateway
|
||||||
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
EXPOSE 50071 9407
|
||||||
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
|
CMD ["/app/tron-gateway","--config.file","/app/config.yml"]
|
||||||
20
ci/prod/compose/vault-agent/tron-gateway.hcl
Normal file
20
ci/prod/compose/vault-agent/tron-gateway.hcl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
vault {
|
||||||
|
address = "https://vault.sendico.io"
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_auth {
|
||||||
|
method "approle" {
|
||||||
|
mount_path = "auth/approle"
|
||||||
|
config = {
|
||||||
|
role_id_file_path = "/run/vault/role_id"
|
||||||
|
secret_id_file_path = "/run/vault/secret_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sink "file" {
|
||||||
|
config = {
|
||||||
|
path = "/run/vault/token"
|
||||||
|
mode = 0600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
ci/prod/scripts/deploy/billing_documents.sh
Executable file
139
ci/prod/scripts/deploy/billing_documents.sh
Executable file
@@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
[[ "${DEBUG_DEPLOY:-0}" = "1" ]] && set -x
|
||||||
|
trap 'echo "[deploy-billing-documents] error at line $LINENO" >&2' ERR
|
||||||
|
|
||||||
|
: "${REMOTE_BASE:?missing REMOTE_BASE}"
|
||||||
|
: "${SSH_USER:?missing SSH_USER}"
|
||||||
|
: "${SSH_HOST:?missing SSH_HOST}"
|
||||||
|
: "${DOCUMENTS_DIR:?missing DOCUMENTS_DIR}"
|
||||||
|
: "${DOCUMENTS_COMPOSE_PROJECT:?missing DOCUMENTS_COMPOSE_PROJECT}"
|
||||||
|
: "${DOCUMENTS_SERVICE_NAME:?missing DOCUMENTS_SERVICE_NAME}"
|
||||||
|
|
||||||
|
REMOTE_DIR="${REMOTE_BASE%/}/${DOCUMENTS_DIR}"
|
||||||
|
REMOTE_TARGET="${SSH_USER}@${SSH_HOST}"
|
||||||
|
COMPOSE_FILE="billing_documents.yml"
|
||||||
|
SERVICE_NAMES="${DOCUMENTS_SERVICE_NAME}"
|
||||||
|
|
||||||
|
REQUIRED_SECRETS=(
|
||||||
|
NATS_USER
|
||||||
|
NATS_PASSWORD
|
||||||
|
NATS_URL
|
||||||
|
)
|
||||||
|
|
||||||
|
for var in "${REQUIRED_SECRETS[@]}"; do
|
||||||
|
if [[ -z "${!var:-}" ]]; then
|
||||||
|
echo "missing required secret env: ${var}" >&2
|
||||||
|
exit 65
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ! -s .env.version ]]; then
|
||||||
|
echo ".env.version is missing; run version step first" >&2
|
||||||
|
exit 66
|
||||||
|
fi
|
||||||
|
|
||||||
|
b64enc() {
|
||||||
|
printf '%s' "$1" | base64 | tr -d '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
NATS_USER_B64="$(b64enc "${NATS_USER}")"
|
||||||
|
NATS_PASSWORD_B64="$(b64enc "${NATS_PASSWORD}")"
|
||||||
|
NATS_URL_B64="$(b64enc "${NATS_URL}")"
|
||||||
|
|
||||||
|
SSH_OPTS=(
|
||||||
|
-i /root/.ssh/id_rsa
|
||||||
|
-o StrictHostKeyChecking=no
|
||||||
|
-o UserKnownHostsFile=/dev/null
|
||||||
|
-o LogLevel=ERROR
|
||||||
|
-q
|
||||||
|
)
|
||||||
|
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then
|
||||||
|
SSH_OPTS=("${SSH_OPTS[@]/-q/}" -vv)
|
||||||
|
fi
|
||||||
|
|
||||||
|
RSYNC_FLAGS=(-az --delete)
|
||||||
|
[[ "${DEBUG_DEPLOY:-0}" = "1" ]] && RSYNC_FLAGS=(-avz --delete)
|
||||||
|
|
||||||
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "mkdir -p ${REMOTE_DIR}/{compose,env}"
|
||||||
|
|
||||||
|
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/compose/ "$REMOTE_TARGET:${REMOTE_DIR}/compose/"
|
||||||
|
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/.env.runtime "$REMOTE_TARGET:${REMOTE_DIR}/env/.env.runtime"
|
||||||
|
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" .env.version "$REMOTE_TARGET:${REMOTE_DIR}/env/.env.version"
|
||||||
|
|
||||||
|
SERVICES_LINE="${SERVICE_NAMES}"
|
||||||
|
|
||||||
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" \
|
||||||
|
REMOTE_DIR="$REMOTE_DIR" \
|
||||||
|
COMPOSE_FILE="$COMPOSE_FILE" \
|
||||||
|
COMPOSE_PROJECT="$DOCUMENTS_COMPOSE_PROJECT" \
|
||||||
|
SERVICES_LINE="$SERVICES_LINE" \
|
||||||
|
NATS_USER_B64="$NATS_USER_B64" \
|
||||||
|
NATS_PASSWORD_B64="$NATS_PASSWORD_B64" \
|
||||||
|
NATS_URL_B64="$NATS_URL_B64" \
|
||||||
|
bash -s <<'EOSSH'
|
||||||
|
set -euo pipefail
|
||||||
|
cd "${REMOTE_DIR}/compose"
|
||||||
|
set -a
|
||||||
|
. ../env/.env.runtime
|
||||||
|
load_kv_file() {
|
||||||
|
local file="$1"
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
case "$line" in
|
||||||
|
''|\#*) continue ;;
|
||||||
|
esac
|
||||||
|
if printf '%s' "$line" | grep -Eq '^[[:alpha:]_][[:alnum:]_]*='; then
|
||||||
|
local key="${line%%=*}"
|
||||||
|
local value="${line#*=}"
|
||||||
|
key="$(printf '%s' "$key" | tr -d '[:space:]')"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
if [[ -n "$key" ]]; then
|
||||||
|
export "$key=$value"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done <"$file"
|
||||||
|
}
|
||||||
|
load_kv_file ../env/.env.version
|
||||||
|
set +a
|
||||||
|
|
||||||
|
if base64 -d >/dev/null 2>&1 <<<'AA=='; then
|
||||||
|
BASE64_DECODE_FLAG='-d'
|
||||||
|
else
|
||||||
|
BASE64_DECODE_FLAG='--decode'
|
||||||
|
fi
|
||||||
|
|
||||||
|
decode_b64() {
|
||||||
|
val="$1"
|
||||||
|
if [[ -z "$val" ]]; then
|
||||||
|
printf ''
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
printf '%s' "$val" | base64 "${BASE64_DECODE_FLAG}"
|
||||||
|
}
|
||||||
|
|
||||||
|
NATS_USER="$(decode_b64 "$NATS_USER_B64")"
|
||||||
|
NATS_PASSWORD="$(decode_b64 "$NATS_PASSWORD_B64")"
|
||||||
|
NATS_URL="$(decode_b64 "$NATS_URL_B64")"
|
||||||
|
|
||||||
|
export NATS_USER NATS_PASSWORD NATS_URL
|
||||||
|
COMPOSE_PROJECT_NAME="$COMPOSE_PROJECT"
|
||||||
|
export COMPOSE_PROJECT_NAME
|
||||||
|
read -r -a SERVICES <<<"${SERVICES_LINE}"
|
||||||
|
|
||||||
|
pull_cmd=(docker compose -f "$COMPOSE_FILE" pull)
|
||||||
|
up_cmd=(docker compose -f "$COMPOSE_FILE" up -d --remove-orphans)
|
||||||
|
ps_cmd=(docker compose -f "$COMPOSE_FILE" ps)
|
||||||
|
if [[ "${#SERVICES[@]}" -gt 0 ]]; then
|
||||||
|
pull_cmd+=("${SERVICES[@]}")
|
||||||
|
up_cmd+=("${SERVICES[@]}")
|
||||||
|
ps_cmd+=("${SERVICES[@]}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${pull_cmd[@]}"
|
||||||
|
"${up_cmd[@]}"
|
||||||
|
"${ps_cmd[@]}"
|
||||||
|
|
||||||
|
date -Is > .last_deploy
|
||||||
|
logger -t "deploy-${COMPOSE_PROJECT_NAME}" "${COMPOSE_PROJECT_NAME} deployed at $(date -Is) in ${REMOTE_DIR}"
|
||||||
|
EOSSH
|
||||||
175
ci/prod/scripts/deploy/tron_gateway.sh
Executable file
175
ci/prod/scripts/deploy/tron_gateway.sh
Executable file
@@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
[[ "${DEBUG_DEPLOY:-0}" = "1" ]] && set -x
|
||||||
|
trap 'echo "[deploy-tron-gateway] error at line $LINENO" >&2' ERR
|
||||||
|
|
||||||
|
: "${REMOTE_BASE:?missing REMOTE_BASE}"
|
||||||
|
: "${SSH_USER:?missing SSH_USER}"
|
||||||
|
: "${SSH_HOST:?missing SSH_HOST}"
|
||||||
|
: "${TRON_GATEWAY_DIR:?missing TRON_GATEWAY_DIR}"
|
||||||
|
: "${TRON_GATEWAY_COMPOSE_PROJECT:?missing TRON_GATEWAY_COMPOSE_PROJECT}"
|
||||||
|
: "${TRON_GATEWAY_SERVICE_NAME:?missing TRON_GATEWAY_SERVICE_NAME}"
|
||||||
|
|
||||||
|
REMOTE_DIR="${REMOTE_BASE%/}/${TRON_GATEWAY_DIR}"
|
||||||
|
REMOTE_TARGET="${SSH_USER}@${SSH_HOST}"
|
||||||
|
COMPOSE_FILE="tron_gateway.yml"
|
||||||
|
SERVICE_NAMES="${TRON_GATEWAY_SERVICE_NAME}"
|
||||||
|
|
||||||
|
REQUIRED_SECRETS=(
|
||||||
|
TRON_GATEWAY_MONGO_USER
|
||||||
|
TRON_GATEWAY_MONGO_PASSWORD
|
||||||
|
TRON_GATEWAY_RPC_URL
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_KEY
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_ADDRESS
|
||||||
|
TRON_GATEWAY_VAULT_ROLE_ID
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_ID
|
||||||
|
NATS_USER
|
||||||
|
NATS_PASSWORD
|
||||||
|
NATS_URL
|
||||||
|
)
|
||||||
|
|
||||||
|
for var in "${REQUIRED_SECRETS[@]}"; do
|
||||||
|
if [[ -z "${!var:-}" ]]; then
|
||||||
|
echo "missing required secret env: ${var}" >&2
|
||||||
|
exit 65
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ! -s .env.version ]]; then
|
||||||
|
echo ".env.version is missing; run version step first" >&2
|
||||||
|
exit 66
|
||||||
|
fi
|
||||||
|
|
||||||
|
b64enc() {
|
||||||
|
printf '%s' "$1" | base64 | tr -d '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
TRON_GATEWAY_MONGO_USER_B64="$(b64enc "${TRON_GATEWAY_MONGO_USER}")"
|
||||||
|
TRON_GATEWAY_MONGO_PASSWORD_B64="$(b64enc "${TRON_GATEWAY_MONGO_PASSWORD}")"
|
||||||
|
TRON_GATEWAY_RPC_URL_B64="$(b64enc "${TRON_GATEWAY_RPC_URL}")"
|
||||||
|
TRON_GATEWAY_GRPC_URL_B64="$(b64enc "${TRON_GATEWAY_GRPC_URL:-}")"
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_KEY_B64="$(b64enc "${TRON_GATEWAY_SERVICE_WALLET_KEY}")"
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_ADDRESS_B64="$(b64enc "${TRON_GATEWAY_SERVICE_WALLET_ADDRESS}")"
|
||||||
|
TRON_GATEWAY_VAULT_ROLE_ID_B64="$(b64enc "${TRON_GATEWAY_VAULT_ROLE_ID}")"
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_ID_B64="$(b64enc "${TRON_GATEWAY_VAULT_SECRET_ID}")"
|
||||||
|
NATS_USER_B64="$(b64enc "${NATS_USER}")"
|
||||||
|
NATS_PASSWORD_B64="$(b64enc "${NATS_PASSWORD}")"
|
||||||
|
NATS_URL_B64="$(b64enc "${NATS_URL}")"
|
||||||
|
|
||||||
|
SSH_OPTS=(
|
||||||
|
-i /root/.ssh/id_rsa
|
||||||
|
-o StrictHostKeyChecking=no
|
||||||
|
-o UserKnownHostsFile=/dev/null
|
||||||
|
-o LogLevel=ERROR
|
||||||
|
-q
|
||||||
|
)
|
||||||
|
if [[ "${DEBUG_DEPLOY:-0}" = "1" ]]; then
|
||||||
|
SSH_OPTS=("${SSH_OPTS[@]/-q/}" -vv)
|
||||||
|
fi
|
||||||
|
|
||||||
|
RSYNC_FLAGS=(-az --delete)
|
||||||
|
[[ "${DEBUG_DEPLOY:-0}" = "1" ]] && RSYNC_FLAGS=(-avz --delete)
|
||||||
|
|
||||||
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "mkdir -p ${REMOTE_DIR}/compose/secrets ${REMOTE_DIR}/env"
|
||||||
|
|
||||||
|
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/compose/ "$REMOTE_TARGET:${REMOTE_DIR}/compose/"
|
||||||
|
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/.env.runtime "$REMOTE_TARGET:${REMOTE_DIR}/env/.env.runtime"
|
||||||
|
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" .env.version "$REMOTE_TARGET:${REMOTE_DIR}/env/.env.version"
|
||||||
|
|
||||||
|
SERVICES_LINE="${SERVICE_NAMES}"
|
||||||
|
|
||||||
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" \
|
||||||
|
REMOTE_DIR="$REMOTE_DIR" \
|
||||||
|
COMPOSE_FILE="$COMPOSE_FILE" \
|
||||||
|
COMPOSE_PROJECT="$TRON_GATEWAY_COMPOSE_PROJECT" \
|
||||||
|
SERVICES_LINE="$SERVICES_LINE" \
|
||||||
|
TRON_GATEWAY_MONGO_USER_B64="$TRON_GATEWAY_MONGO_USER_B64" \
|
||||||
|
TRON_GATEWAY_MONGO_PASSWORD_B64="$TRON_GATEWAY_MONGO_PASSWORD_B64" \
|
||||||
|
TRON_GATEWAY_RPC_URL_B64="$TRON_GATEWAY_RPC_URL_B64" \
|
||||||
|
TRON_GATEWAY_GRPC_URL_B64="$TRON_GATEWAY_GRPC_URL_B64" \
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_KEY_B64="$TRON_GATEWAY_SERVICE_WALLET_KEY_B64" \
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_ADDRESS_B64="$TRON_GATEWAY_SERVICE_WALLET_ADDRESS_B64" \
|
||||||
|
TRON_GATEWAY_VAULT_ROLE_ID_B64="$TRON_GATEWAY_VAULT_ROLE_ID_B64" \
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_ID_B64="$TRON_GATEWAY_VAULT_SECRET_ID_B64" \
|
||||||
|
NATS_USER_B64="$NATS_USER_B64" \
|
||||||
|
NATS_PASSWORD_B64="$NATS_PASSWORD_B64" \
|
||||||
|
NATS_URL_B64="$NATS_URL_B64" \
|
||||||
|
bash -s <<'EOSSH'
|
||||||
|
set -euo pipefail
|
||||||
|
cd "${REMOTE_DIR}/compose"
|
||||||
|
set -a
|
||||||
|
. ../env/.env.runtime
|
||||||
|
load_kv_file() {
|
||||||
|
local file="$1"
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
case "$line" in
|
||||||
|
''|\#*) continue ;;
|
||||||
|
esac
|
||||||
|
if printf '%s' "$line" | grep -Eq '^[[:alpha:]_][[:alnum:]_]*='; then
|
||||||
|
local key="${line%%=*}"
|
||||||
|
local value="${line#*=}"
|
||||||
|
key="$(printf '%s' "$key" | tr -d '[:space:]')"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
if [[ -n "$key" ]]; then
|
||||||
|
export "$key=$value"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done <"$file"
|
||||||
|
}
|
||||||
|
load_kv_file ../env/.env.version
|
||||||
|
set +a
|
||||||
|
|
||||||
|
if base64 -d >/dev/null 2>&1 <<<'AA=='; then
|
||||||
|
BASE64_DECODE_FLAG='-d'
|
||||||
|
else
|
||||||
|
BASE64_DECODE_FLAG='--decode'
|
||||||
|
fi
|
||||||
|
|
||||||
|
decode_b64() {
|
||||||
|
val="$1"
|
||||||
|
if [[ -z "$val" ]]; then
|
||||||
|
printf ''
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
printf '%s' "$val" | base64 "${BASE64_DECODE_FLAG}"
|
||||||
|
}
|
||||||
|
|
||||||
|
TRON_GATEWAY_MONGO_USER="$(decode_b64 "$TRON_GATEWAY_MONGO_USER_B64")"
|
||||||
|
TRON_GATEWAY_MONGO_PASSWORD="$(decode_b64 "$TRON_GATEWAY_MONGO_PASSWORD_B64")"
|
||||||
|
TRON_GATEWAY_RPC_URL="$(decode_b64 "$TRON_GATEWAY_RPC_URL_B64")"
|
||||||
|
TRON_GATEWAY_GRPC_URL="$(decode_b64 "$TRON_GATEWAY_GRPC_URL_B64")"
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_KEY="$(decode_b64 "$TRON_GATEWAY_SERVICE_WALLET_KEY_B64")"
|
||||||
|
TRON_GATEWAY_SERVICE_WALLET_ADDRESS="$(decode_b64 "$TRON_GATEWAY_SERVICE_WALLET_ADDRESS_B64")"
|
||||||
|
TRON_GATEWAY_VAULT_ROLE_ID="$(decode_b64 "$TRON_GATEWAY_VAULT_ROLE_ID_B64")"
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_ID="$(decode_b64 "$TRON_GATEWAY_VAULT_SECRET_ID_B64")"
|
||||||
|
NATS_USER="$(decode_b64 "$NATS_USER_B64")"
|
||||||
|
NATS_PASSWORD="$(decode_b64 "$NATS_PASSWORD_B64")"
|
||||||
|
NATS_URL="$(decode_b64 "$NATS_URL_B64")"
|
||||||
|
|
||||||
|
export TRON_GATEWAY_MONGO_USER TRON_GATEWAY_MONGO_PASSWORD
|
||||||
|
export TRON_GATEWAY_RPC_URL TRON_GATEWAY_GRPC_URL
|
||||||
|
export TRON_GATEWAY_SERVICE_WALLET_KEY TRON_GATEWAY_SERVICE_WALLET_ADDRESS
|
||||||
|
export TRON_GATEWAY_VAULT_ROLE_ID TRON_GATEWAY_VAULT_SECRET_ID
|
||||||
|
export NATS_USER NATS_PASSWORD NATS_URL
|
||||||
|
|
||||||
|
COMPOSE_PROJECT_NAME="$COMPOSE_PROJECT"
|
||||||
|
export COMPOSE_PROJECT_NAME
|
||||||
|
read -r -a SERVICES <<<"${SERVICES_LINE}"
|
||||||
|
|
||||||
|
pull_cmd=(docker compose -f "$COMPOSE_FILE" pull)
|
||||||
|
up_cmd=(docker compose -f "$COMPOSE_FILE" up -d --remove-orphans)
|
||||||
|
ps_cmd=(docker compose -f "$COMPOSE_FILE" ps)
|
||||||
|
if [[ "${#SERVICES[@]}" -gt 0 ]]; then
|
||||||
|
pull_cmd+=("${SERVICES[@]}")
|
||||||
|
up_cmd+=("${SERVICES[@]}")
|
||||||
|
ps_cmd+=("${SERVICES[@]}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${pull_cmd[@]}"
|
||||||
|
"${up_cmd[@]}"
|
||||||
|
"${ps_cmd[@]}"
|
||||||
|
|
||||||
|
date -Is > .last_deploy
|
||||||
|
logger -t "deploy-${COMPOSE_PROJECT_NAME}" "${COMPOSE_PROJECT_NAME} deployed at $(date -Is) in ${REMOTE_DIR}"
|
||||||
|
EOSSH
|
||||||
85
ci/scripts/billing_documents/build-image.sh
Executable file
85
ci/scripts/billing_documents/build-image.sh
Executable file
@@ -0,0 +1,85 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if ! set -o pipefail 2>/dev/null; then
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
cd "${REPO_ROOT}"
|
||||||
|
|
||||||
|
sh ci/scripts/common/ensure_env_version.sh
|
||||||
|
|
||||||
|
normalize_env_file() {
|
||||||
|
file="$1"
|
||||||
|
tmp="${file}.tmp.$$"
|
||||||
|
tr -d '\r' <"$file" >"$tmp"
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_env_file() {
|
||||||
|
file="$1"
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
case "$line" in
|
||||||
|
''|\#*) continue ;;
|
||||||
|
esac
|
||||||
|
key="${line%%=*}"
|
||||||
|
value="${line#*=}"
|
||||||
|
key="$(printf '%s' "$key" | tr -d '[:space:]')"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
export "$key=$value"
|
||||||
|
done <"$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
DOCUMENTS_ENV_NAME="${DOCUMENTS_ENV:-prod}"
|
||||||
|
RUNTIME_ENV_FILE="./ci/${DOCUMENTS_ENV_NAME}/.env.runtime"
|
||||||
|
|
||||||
|
if [ ! -f "${RUNTIME_ENV_FILE}" ]; then
|
||||||
|
echo "[billing-documents-build] runtime env file not found: ${RUNTIME_ENV_FILE}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalize_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
normalize_env_file ./.env.version
|
||||||
|
|
||||||
|
load_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
load_env_file ./.env.version
|
||||||
|
|
||||||
|
REGISTRY_URL="${REGISTRY_URL:?missing REGISTRY_URL}"
|
||||||
|
APP_V="${APP_V:?missing APP_V}"
|
||||||
|
DOCUMENTS_DOCKERFILE="${DOCUMENTS_DOCKERFILE:?missing DOCUMENTS_DOCKERFILE}"
|
||||||
|
DOCUMENTS_IMAGE_PATH="${DOCUMENTS_IMAGE_PATH:?missing DOCUMENTS_IMAGE_PATH}"
|
||||||
|
|
||||||
|
REGISTRY_HOST="${REGISTRY_URL#http://}"
|
||||||
|
REGISTRY_HOST="${REGISTRY_HOST#https://}"
|
||||||
|
REGISTRY_USER="$(cat secrets/REGISTRY_USER)"
|
||||||
|
REGISTRY_PASSWORD="$(cat secrets/REGISTRY_PASSWORD)"
|
||||||
|
: "${REGISTRY_USER:?missing registry user}"
|
||||||
|
: "${REGISTRY_PASSWORD:?missing registry password}"
|
||||||
|
|
||||||
|
mkdir -p /kaniko/.docker
|
||||||
|
AUTH_B64="$(printf '%s:%s' "$REGISTRY_USER" "$REGISTRY_PASSWORD" | base64 | tr -d '\n')"
|
||||||
|
cat <<EOF_JSON >/kaniko/.docker/config.json
|
||||||
|
{
|
||||||
|
"auths": {
|
||||||
|
"https://${REGISTRY_HOST}": { "auth": "${AUTH_B64}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF_JSON
|
||||||
|
|
||||||
|
BUILD_CONTEXT="${DOCUMENTS_BUILD_CONTEXT:-${WOODPECKER_WORKSPACE:-${CI_WORKSPACE:-${PWD:-/workspace}}}}"
|
||||||
|
if [ ! -d "${BUILD_CONTEXT}" ]; then
|
||||||
|
BUILD_CONTEXT="/workspace"
|
||||||
|
fi
|
||||||
|
|
||||||
|
/kaniko/executor \
|
||||||
|
--context "${BUILD_CONTEXT}" \
|
||||||
|
--dockerfile "${DOCUMENTS_DOCKERFILE}" \
|
||||||
|
--destination "${REGISTRY_URL}/${DOCUMENTS_IMAGE_PATH}:${APP_V}" \
|
||||||
|
--build-arg APP_VERSION="${APP_V}" \
|
||||||
|
--build-arg GIT_REV="${GIT_REV}" \
|
||||||
|
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
|
||||||
|
--build-arg BUILD_DATE="${BUILD_DATE}" \
|
||||||
|
--build-arg BUILD_USER="${BUILD_USER}" \
|
||||||
|
--single-snapshot
|
||||||
54
ci/scripts/billing_documents/deploy.sh
Executable file
54
ci/scripts/billing_documents/deploy.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if ! set -o pipefail 2>/dev/null; then
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
cd "${REPO_ROOT}"
|
||||||
|
|
||||||
|
sh ci/scripts/common/ensure_env_version.sh
|
||||||
|
|
||||||
|
normalize_env_file() {
|
||||||
|
file="$1"
|
||||||
|
tmp="${file}.tmp.$$"
|
||||||
|
tr -d '\r' <"$file" >"$tmp"
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_env_file() {
|
||||||
|
file="$1"
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
case "$line" in
|
||||||
|
''|\#*) continue ;;
|
||||||
|
esac
|
||||||
|
key="${line%%=*}"
|
||||||
|
value="${line#*=}"
|
||||||
|
key="$(printf '%s' "$key" | tr -d '[:space:]')"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
export "$key=$value"
|
||||||
|
done <"$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
. ci/scripts/common/nats_env.sh
|
||||||
|
|
||||||
|
DOCUMENTS_ENV_NAME="${DOCUMENTS_ENV:-prod}"
|
||||||
|
RUNTIME_ENV_FILE="./ci/${DOCUMENTS_ENV_NAME}/.env.runtime"
|
||||||
|
|
||||||
|
if [ ! -f "${RUNTIME_ENV_FILE}" ]; then
|
||||||
|
echo "[billing-documents-deploy] runtime env file not found: ${RUNTIME_ENV_FILE}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalize_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
normalize_env_file ./.env.version
|
||||||
|
|
||||||
|
load_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
load_env_file ./.env.version
|
||||||
|
|
||||||
|
load_nats_env
|
||||||
|
|
||||||
|
bash ci/prod/scripts/bootstrap/network.sh
|
||||||
|
bash ci/prod/scripts/deploy/billing_documents.sh
|
||||||
@@ -134,4 +134,10 @@ if [ -f "${PROTO_DIR}/billing/fees/v1/fees.proto" ]; then
|
|||||||
generate_go_with_grpc "${PROTO_DIR}/billing/fees/v1/fees.proto"
|
generate_go_with_grpc "${PROTO_DIR}/billing/fees/v1/fees.proto"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -f "${PROTO_DIR}/billing/documents/v1/documents.proto" ]; then
|
||||||
|
info "Compiling billing documents protos"
|
||||||
|
clean_pb_files "./pkg/proto/billing/documents"
|
||||||
|
generate_go_with_grpc "${PROTO_DIR}/billing/documents/v1/documents.proto"
|
||||||
|
fi
|
||||||
|
|
||||||
info "Protobuf generation completed"
|
info "Protobuf generation completed"
|
||||||
|
|||||||
85
ci/scripts/tron_gateway/build-image.sh
Executable file
85
ci/scripts/tron_gateway/build-image.sh
Executable file
@@ -0,0 +1,85 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if ! set -o pipefail 2>/dev/null; then
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
cd "${REPO_ROOT}"
|
||||||
|
|
||||||
|
sh ci/scripts/common/ensure_env_version.sh
|
||||||
|
|
||||||
|
normalize_env_file() {
|
||||||
|
file="$1"
|
||||||
|
tmp="${file}.tmp.$$"
|
||||||
|
tr -d '\r' <"$file" >"$tmp"
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_env_file() {
|
||||||
|
file="$1"
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
case "$line" in
|
||||||
|
''|\#*) continue ;;
|
||||||
|
esac
|
||||||
|
key="${line%%=*}"
|
||||||
|
value="${line#*=}"
|
||||||
|
key="$(printf '%s' "$key" | tr -d '[:space:]')"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
export "$key=$value"
|
||||||
|
done <"$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
TRON_GATEWAY_ENV_NAME="${TRON_GATEWAY_ENV:-prod}"
|
||||||
|
RUNTIME_ENV_FILE="./ci/${TRON_GATEWAY_ENV_NAME}/.env.runtime"
|
||||||
|
|
||||||
|
if [ ! -f "${RUNTIME_ENV_FILE}" ]; then
|
||||||
|
echo "[tron-gateway-build] runtime env file not found: ${RUNTIME_ENV_FILE}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalize_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
normalize_env_file ./.env.version
|
||||||
|
|
||||||
|
load_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
load_env_file ./.env.version
|
||||||
|
|
||||||
|
REGISTRY_URL="${REGISTRY_URL:?missing REGISTRY_URL}"
|
||||||
|
APP_V="${APP_V:?missing APP_V}"
|
||||||
|
TRON_GATEWAY_DOCKERFILE="${TRON_GATEWAY_DOCKERFILE:?missing TRON_GATEWAY_DOCKERFILE}"
|
||||||
|
TRON_GATEWAY_IMAGE_PATH="${TRON_GATEWAY_IMAGE_PATH:?missing TRON_GATEWAY_IMAGE_PATH}"
|
||||||
|
|
||||||
|
REGISTRY_HOST="${REGISTRY_URL#http://}"
|
||||||
|
REGISTRY_HOST="${REGISTRY_HOST#https://}"
|
||||||
|
REGISTRY_USER="$(cat secrets/REGISTRY_USER)"
|
||||||
|
REGISTRY_PASSWORD="$(cat secrets/REGISTRY_PASSWORD)"
|
||||||
|
: "${REGISTRY_USER:?missing registry user}"
|
||||||
|
: "${REGISTRY_PASSWORD:?missing registry password}"
|
||||||
|
|
||||||
|
mkdir -p /kaniko/.docker
|
||||||
|
AUTH_B64="$(printf '%s:%s' "$REGISTRY_USER" "$REGISTRY_PASSWORD" | base64 | tr -d '\n')"
|
||||||
|
cat <<EOF >/kaniko/.docker/config.json
|
||||||
|
{
|
||||||
|
"auths": {
|
||||||
|
"https://${REGISTRY_HOST}": { "auth": "${AUTH_B64}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
BUILD_CONTEXT="${TRON_GATEWAY_BUILD_CONTEXT:-${WOODPECKER_WORKSPACE:-${CI_WORKSPACE:-${PWD:-/workspace}}}}"
|
||||||
|
if [ ! -d "${BUILD_CONTEXT}" ]; then
|
||||||
|
BUILD_CONTEXT="/workspace"
|
||||||
|
fi
|
||||||
|
|
||||||
|
/kaniko/executor \
|
||||||
|
--context "${BUILD_CONTEXT}" \
|
||||||
|
--dockerfile "${TRON_GATEWAY_DOCKERFILE}" \
|
||||||
|
--destination "${REGISTRY_URL}/${TRON_GATEWAY_IMAGE_PATH}:${APP_V}" \
|
||||||
|
--build-arg APP_VERSION="${APP_V}" \
|
||||||
|
--build-arg GIT_REV="${GIT_REV}" \
|
||||||
|
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
|
||||||
|
--build-arg BUILD_DATE="${BUILD_DATE}" \
|
||||||
|
--build-arg BUILD_USER="${BUILD_USER}" \
|
||||||
|
--single-snapshot
|
||||||
75
ci/scripts/tron_gateway/deploy.sh
Executable file
75
ci/scripts/tron_gateway/deploy.sh
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if ! set -o pipefail 2>/dev/null; then
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
cd "${REPO_ROOT}"
|
||||||
|
|
||||||
|
sh ci/scripts/common/ensure_env_version.sh
|
||||||
|
|
||||||
|
normalize_env_file() {
|
||||||
|
file="$1"
|
||||||
|
tmp="${file}.tmp.$$"
|
||||||
|
tr -d '\r' <"$file" >"$tmp"
|
||||||
|
mv "$tmp" "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_env_file() {
|
||||||
|
file="$1"
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
case "$line" in
|
||||||
|
''|\#*) continue ;;
|
||||||
|
esac
|
||||||
|
key="${line%%=*}"
|
||||||
|
value="${line#*=}"
|
||||||
|
key="$(printf '%s' "$key" | tr -d '[:space:]')"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
export "$key=$value"
|
||||||
|
done <"$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
. ci/scripts/common/nats_env.sh
|
||||||
|
|
||||||
|
TRON_GATEWAY_ENV_NAME="${TRON_GATEWAY_ENV:-prod}"
|
||||||
|
RUNTIME_ENV_FILE="./ci/${TRON_GATEWAY_ENV_NAME}/.env.runtime"
|
||||||
|
|
||||||
|
if [ ! -f "${RUNTIME_ENV_FILE}" ]; then
|
||||||
|
echo "[tron-gateway-deploy] runtime env file not found: ${RUNTIME_ENV_FILE}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalize_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
normalize_env_file ./.env.version
|
||||||
|
|
||||||
|
load_env_file "${RUNTIME_ENV_FILE}"
|
||||||
|
load_env_file ./.env.version
|
||||||
|
|
||||||
|
TRON_GATEWAY_MONGO_SECRET_PATH="${TRON_GATEWAY_MONGO_SECRET_PATH:?missing TRON_GATEWAY_MONGO_SECRET_PATH}"
|
||||||
|
TRON_GATEWAY_RPC_SECRET_PATH="${TRON_GATEWAY_RPC_SECRET_PATH:?missing TRON_GATEWAY_RPC_SECRET_PATH}"
|
||||||
|
TRON_GATEWAY_WALLET_SECRET_PATH="${TRON_GATEWAY_WALLET_SECRET_PATH:?missing TRON_GATEWAY_WALLET_SECRET_PATH}"
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_PATH="${TRON_GATEWAY_VAULT_SECRET_PATH:?missing TRON_GATEWAY_VAULT_SECRET_PATH}"
|
||||||
|
|
||||||
|
export TRON_GATEWAY_MONGO_USER="$(./ci/vlt kv_get kv "${TRON_GATEWAY_MONGO_SECRET_PATH}" user)"
|
||||||
|
export TRON_GATEWAY_MONGO_PASSWORD="$(./ci/vlt kv_get kv "${TRON_GATEWAY_MONGO_SECRET_PATH}" password)"
|
||||||
|
|
||||||
|
export TRON_GATEWAY_RPC_URL="$(./ci/vlt kv_get kv "${TRON_GATEWAY_RPC_SECRET_PATH}" tron_rpc_url)"
|
||||||
|
export TRON_GATEWAY_GRPC_URL="$(./ci/vlt kv_get kv "${TRON_GATEWAY_RPC_SECRET_PATH}" tron_grpc_url || true)"
|
||||||
|
|
||||||
|
export TRON_GATEWAY_SERVICE_WALLET_KEY="$(./ci/vlt kv_get kv "${TRON_GATEWAY_WALLET_SECRET_PATH}" private_key)"
|
||||||
|
export TRON_GATEWAY_SERVICE_WALLET_ADDRESS="$(./ci/vlt kv_get kv "${TRON_GATEWAY_WALLET_SECRET_PATH}" address || true)"
|
||||||
|
|
||||||
|
export TRON_GATEWAY_VAULT_ROLE_ID="$(./ci/vlt kv_get kv "${TRON_GATEWAY_VAULT_SECRET_PATH}" role_id)"
|
||||||
|
export TRON_GATEWAY_VAULT_SECRET_ID="$(./ci/vlt kv_get kv "${TRON_GATEWAY_VAULT_SECRET_PATH}" secret_id)"
|
||||||
|
if [ -z "${TRON_GATEWAY_VAULT_ROLE_ID}" ] || [ -z "${TRON_GATEWAY_VAULT_SECRET_ID}" ]; then
|
||||||
|
echo "[tron-gateway-deploy] vault approle creds are empty for path ${TRON_GATEWAY_VAULT_SECRET_PATH}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
load_nats_env
|
||||||
|
|
||||||
|
bash ci/prod/scripts/bootstrap/network.sh
|
||||||
|
bash ci/prod/scripts/deploy/tron_gateway.sh
|
||||||
807
docker-compose.dev.yml
Normal file
807
docker-compose.dev.yml
Normal file
@@ -0,0 +1,807 @@
|
|||||||
|
# Sendico Development Environment
|
||||||
|
# Vault is ONLY used for application data (blockchain keys, external API keys)
|
||||||
|
# NOT for infrastructure credentials (MongoDB, NATS use plain .env)
|
||||||
|
|
||||||
|
x-common-env: &common-env
|
||||||
|
env_file:
|
||||||
|
- .env.dev
|
||||||
|
|
||||||
|
networks:
|
||||||
|
sendico-dev:
|
||||||
|
name: sendico-dev
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
dev-mongo1-data:
|
||||||
|
dev-mongo2-data:
|
||||||
|
dev-mongo3-data:
|
||||||
|
dev-nats-data:
|
||||||
|
dev-vault-data:
|
||||||
|
dev-chain-gateway-vault-run:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: tmpfs
|
||||||
|
device: tmpfs
|
||||||
|
o: size=8m,uid=0,gid=0,mode=0700
|
||||||
|
dev-tron-gateway-vault-run:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: tmpfs
|
||||||
|
device: tmpfs
|
||||||
|
o: size=8m,uid=0,gid=0,mode=0700
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# INFRASTRUCTURE SERVICES
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Vault (Single Node) - for application data ONLY
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-vault:
|
||||||
|
image: hashicorp/vault:latest
|
||||||
|
container_name: dev-vault
|
||||||
|
restart: unless-stopped
|
||||||
|
cap_add: [IPC_LOCK]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: http://0.0.0.0:8200
|
||||||
|
volumes:
|
||||||
|
- dev-vault-data:/vault/file
|
||||||
|
- ./ci/dev/vault/config.hcl:/vault/config/vault.hcl:ro
|
||||||
|
command: vault server -config=/vault/config/vault.hcl
|
||||||
|
ports:
|
||||||
|
- "8200:8200"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget --spider --proxy off http://127.0.0.1:8200/v1/sys/health || [ $? -eq 1 ]"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# MongoDB Replica Set (3 nodes) - plain credentials from .env
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-mongo-1:
|
||||||
|
<<: *common-env
|
||||||
|
image: mongo:latest
|
||||||
|
container_name: dev-mongo-1
|
||||||
|
restart: unless-stopped
|
||||||
|
command: >
|
||||||
|
mongod --replSet dev-rs --bind_ip_all --auth
|
||||||
|
--keyFile /data/mongo.key --port 27017
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- dev-mongo1-data:/data/db
|
||||||
|
- ./ci/dev/mongo.key:/data/mongo.key:ro
|
||||||
|
ports:
|
||||||
|
- "27017:27017"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "mongosh --quiet --host localhost --port 27017 --eval 'db.runCommand({ ping: 1 }).ok' || exit 1"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
dev-mongo-2:
|
||||||
|
<<: *common-env
|
||||||
|
image: mongo:latest
|
||||||
|
container_name: dev-mongo-2
|
||||||
|
restart: unless-stopped
|
||||||
|
command: >
|
||||||
|
mongod --replSet dev-rs --bind_ip_all --auth
|
||||||
|
--keyFile /data/mongo.key --port 27017
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- dev-mongo2-data:/data/db
|
||||||
|
- ./ci/dev/mongo.key:/data/mongo.key:ro
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "mongosh --quiet --host localhost --port 27017 --eval 'db.runCommand({ ping: 1 }).ok' || exit 1"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
dev-mongo-3:
|
||||||
|
<<: *common-env
|
||||||
|
image: mongo:latest
|
||||||
|
container_name: dev-mongo-3
|
||||||
|
restart: unless-stopped
|
||||||
|
command: >
|
||||||
|
mongod --replSet dev-rs --bind_ip_all --auth
|
||||||
|
--keyFile /data/mongo.key --port 27017
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- dev-mongo3-data:/data/db
|
||||||
|
- ./ci/dev/mongo.key:/data/mongo.key:ro
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "mongosh --quiet --host localhost --port 27017 --eval 'db.runCommand({ ping: 1 }).ok' || exit 1"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# MongoDB Replica Set Initialization
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-mongo-init:
|
||||||
|
<<: *common-env
|
||||||
|
image: mongo:latest
|
||||||
|
container_name: dev-mongo-init
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-1: { condition: service_healthy }
|
||||||
|
dev-mongo-2: { condition: service_healthy }
|
||||||
|
dev-mongo-3: { condition: service_healthy }
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
entrypoint: |
|
||||||
|
bash -c '
|
||||||
|
set -euo pipefail
|
||||||
|
echo "Waiting for MongoDB nodes..."
|
||||||
|
until mongosh --quiet --host dev-mongo-1 --port 27017 --eval "db.adminCommand({ ping: 1 })"; do
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Initializing replica set..."
|
||||||
|
mongosh --host dev-mongo-1 --port 27017 -u "${MONGO_USER}" -p "${MONGO_PASSWORD}" --authenticationDatabase admin <<EOF || echo "Replica set already initialized"
|
||||||
|
try {
|
||||||
|
rs.status()
|
||||||
|
print("Replica set already initialized")
|
||||||
|
} catch (e) {
|
||||||
|
rs.initiate({
|
||||||
|
_id: "dev-rs",
|
||||||
|
members: [
|
||||||
|
{ _id: 0, host: "dev-mongo-1:27017", priority: 2 },
|
||||||
|
{ _id: 1, host: "dev-mongo-2:27017", priority: 1 },
|
||||||
|
{ _id: 2, host: "dev-mongo-3:27017", priority: 1 }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
print("Replica set initialized")
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "✅ MongoDB replica set ready"
|
||||||
|
'
|
||||||
|
restart: "no"
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# NATS with JetStream - plain credentials from .env
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-nats:
|
||||||
|
<<: *common-env
|
||||||
|
image: nats:latest
|
||||||
|
container_name: dev-nats
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- --jetstream
|
||||||
|
- --store_dir=/data
|
||||||
|
- --http_port=8222
|
||||||
|
- --port=4222
|
||||||
|
- --server_name=dev-nats
|
||||||
|
- --user=${NATS_USER}
|
||||||
|
- --pass=${NATS_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- dev-nats-data:/data
|
||||||
|
ports:
|
||||||
|
- "4222:4222"
|
||||||
|
- "8222:8222"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# APPLICATION SERVICES
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Discovery Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-discovery:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/discovery.dockerfile
|
||||||
|
image: sendico-dev/discovery:latest
|
||||||
|
container_name: dev-discovery
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/discovery:/src/api/discovery
|
||||||
|
- ./api/discovery/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "9407:9407"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
DISCOVERY_METRICS_PORT: 9407
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# FX Oracle Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-fx-oracle:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/fx-oracle.dockerfile
|
||||||
|
image: sendico-dev/fx-oracle:latest
|
||||||
|
container_name: dev-fx-oracle
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/fx/oracle:/src/api/fx/oracle
|
||||||
|
- ./api/fx/oracle/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50051:50051"
|
||||||
|
- "9400:9400"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
FX_MONGO_HOST: dev-mongo-1
|
||||||
|
FX_MONGO_PORT: 27017
|
||||||
|
FX_MONGO_DATABASE: fx
|
||||||
|
FX_MONGO_USER: ${MONGO_USER}
|
||||||
|
FX_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
FX_MONGO_AUTH_SOURCE: admin
|
||||||
|
FX_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
FX_ORACLE_GRPC_PORT: 50051
|
||||||
|
FX_ORACLE_METRICS_PORT: 9400
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Billing Fees Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-billing-fees:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/billing-fees.dockerfile
|
||||||
|
image: sendico-dev/billing-fees:latest
|
||||||
|
container_name: dev-billing-fees
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-fx-oracle: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/billing/fees:/src/api/billing/fees
|
||||||
|
- ./api/billing/fees/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50060:50060"
|
||||||
|
- "9402:9402"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
FEES_MONGO_HOST: dev-mongo-1
|
||||||
|
FEES_MONGO_PORT: 27017
|
||||||
|
FEES_MONGO_DATABASE: billing_fees
|
||||||
|
FEES_MONGO_USER: ${MONGO_USER}
|
||||||
|
FEES_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
FEES_MONGO_AUTH_SOURCE: admin
|
||||||
|
FEES_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
FEES_GRPC_PORT: 50060
|
||||||
|
FEES_METRICS_PORT: 9402
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Billing Documents Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-billing-documents:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/billing-documents.dockerfile
|
||||||
|
image: sendico-dev/billing-documents:latest
|
||||||
|
container_name: dev-billing-documents
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/billing/documents:/src/api/billing/documents
|
||||||
|
- ./api/billing/documents/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50061:50061"
|
||||||
|
- "9409:9409"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
DOCUMENTS_GRPC_PORT: 50061
|
||||||
|
DOCUMENTS_METRICS_PORT: 9409
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Ledger Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-ledger:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/ledger.dockerfile
|
||||||
|
image: sendico-dev/ledger:latest
|
||||||
|
container_name: dev-ledger
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-discovery: { condition: service_started }
|
||||||
|
dev-billing-fees: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/ledger:/src/api/ledger
|
||||||
|
- ./api/ledger/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50052:50052"
|
||||||
|
- "9401:9401"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
LEDGER_MONGO_HOST: dev-mongo-1
|
||||||
|
LEDGER_MONGO_PORT: 27017
|
||||||
|
LEDGER_MONGO_DATABASE: ledger
|
||||||
|
LEDGER_MONGO_USER: ${MONGO_USER}
|
||||||
|
LEDGER_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
LEDGER_MONGO_AUTH_SOURCE: admin
|
||||||
|
LEDGER_MONGO_REPLICA_SET: dev-rs
|
||||||
|
MONGO_HOSTS_0: dev-mongo-1
|
||||||
|
MONGO_PORTS_0: 27017
|
||||||
|
MONGO_HOSTS_1: dev-mongo-2
|
||||||
|
MONGO_PORTS_1: 27017
|
||||||
|
MONGO_HOSTS_2: dev-mongo-3
|
||||||
|
MONGO_PORTS_2: 27017
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
LEDGER_GRPC_PORT: 50052
|
||||||
|
LEDGER_METRICS_PORT: 9401
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# FX Ingestor Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-fx-ingestor:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/fx-ingestor.dockerfile
|
||||||
|
image: sendico-dev/fx-ingestor:latest
|
||||||
|
container_name: dev-fx-ingestor
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/fx/ingestor:/src/api/fx/ingestor
|
||||||
|
- ./api/fx/ingestor/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "9102:9102"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
FX_MONGO_HOST: dev-mongo-1
|
||||||
|
FX_MONGO_PORT: 27017
|
||||||
|
FX_MONGO_DATABASE: fx
|
||||||
|
FX_MONGO_USER: ${MONGO_USER}
|
||||||
|
FX_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
FX_MONGO_AUTH_SOURCE: admin
|
||||||
|
FX_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
FX_INGESTOR_METRICS_PORT: 9102
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Payments Orchestrator Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-payments-orchestrator:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/payments-orchestrator.dockerfile
|
||||||
|
image: sendico-dev/payments-orchestrator:latest
|
||||||
|
container_name: dev-payments-orchestrator
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-ledger: { condition: service_started }
|
||||||
|
dev-billing-fees: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/payments/orchestrator:/src/api/payments/orchestrator
|
||||||
|
- ./api/payments/orchestrator/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50062:50062"
|
||||||
|
- "9403:9403"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
PAYMENTS_MONGO_HOST: dev-mongo-1
|
||||||
|
PAYMENTS_MONGO_PORT: 27017
|
||||||
|
PAYMENTS_MONGO_DATABASE: payments_orchestrator
|
||||||
|
PAYMENTS_MONGO_USER: ${MONGO_USER}
|
||||||
|
PAYMENTS_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
PAYMENTS_MONGO_AUTH_SOURCE: admin
|
||||||
|
PAYMENTS_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
PAYMENTS_GRPC_PORT: 50062
|
||||||
|
PAYMENTS_METRICS_PORT: 9403
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Chain Gateway Vault Agent (sidecar for AppRole authentication)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-chain-gateway-vault-agent:
|
||||||
|
<<: *common-env
|
||||||
|
image: hashicorp/vault:latest
|
||||||
|
container_name: dev-chain-gateway-vault-agent
|
||||||
|
restart: unless-stopped
|
||||||
|
cap_add: ["IPC_LOCK"]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: ${VAULT_ADDR}
|
||||||
|
CHAIN_GATEWAY_VAULT_ROLE_ID: ${CHAIN_GATEWAY_VAULT_ROLE_ID}
|
||||||
|
CHAIN_GATEWAY_VAULT_SECRET_ID: ${CHAIN_GATEWAY_VAULT_SECRET_ID}
|
||||||
|
command: >
|
||||||
|
sh -c 'set -eu; umask 077;
|
||||||
|
echo "$$CHAIN_GATEWAY_VAULT_ROLE_ID" > /run/vault/role_id;
|
||||||
|
echo "$$CHAIN_GATEWAY_VAULT_SECRET_ID" > /run/vault/secret_id;
|
||||||
|
unset CHAIN_GATEWAY_VAULT_ROLE_ID CHAIN_GATEWAY_VAULT_SECRET_ID;
|
||||||
|
exec vault agent -config=/etc/vault/agent/chain-gateway.hcl'
|
||||||
|
volumes:
|
||||||
|
- ./ci/dev/vault-agent/chain-gateway.hcl:/etc/vault/agent/chain-gateway.hcl:ro
|
||||||
|
- dev-chain-gateway-vault-run:/run/vault
|
||||||
|
depends_on:
|
||||||
|
dev-vault: { condition: service_healthy }
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "test", "-s", "/run/vault/token"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 6
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Chain Gateway Service (blockchain - connects to Vault for keys)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-chain-gateway:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/chain-gateway.dockerfile
|
||||||
|
image: sendico-dev/chain-gateway:latest
|
||||||
|
container_name: dev-chain-gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-discovery: { condition: service_started }
|
||||||
|
dev-vault: { condition: service_healthy }
|
||||||
|
dev-chain-gateway-vault-agent: { condition: service_healthy }
|
||||||
|
volumes:
|
||||||
|
- ./api/gateway/chain:/src/api/gateway/chain
|
||||||
|
- ./api/gateway/chain/config.dev.yml:/app/config.yml:ro
|
||||||
|
- dev-chain-gateway-vault-run:/run/vault:ro
|
||||||
|
ports:
|
||||||
|
- "50070:50070"
|
||||||
|
- "9404:9404"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
CHAIN_GATEWAY_MONGO_HOST: dev-mongo-1
|
||||||
|
CHAIN_GATEWAY_MONGO_PORT: 27017
|
||||||
|
CHAIN_GATEWAY_MONGO_DATABASE: chain_gateway
|
||||||
|
CHAIN_GATEWAY_MONGO_USER: ${MONGO_USER}
|
||||||
|
CHAIN_GATEWAY_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
CHAIN_GATEWAY_MONGO_AUTH_SOURCE: admin
|
||||||
|
CHAIN_GATEWAY_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
CHAIN_GATEWAY_GRPC_PORT: 50070
|
||||||
|
CHAIN_GATEWAY_METRICS_PORT: 9404
|
||||||
|
VAULT_ADDR: ${VAULT_ADDR}
|
||||||
|
VAULT_TOKEN_FILE: /run/vault/token
|
||||||
|
CHAIN_GATEWAY_RPC_URL: ${CHAIN_GATEWAY_RPC_URL}
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# TRON Gateway Vault Agent (sidecar for AppRole authentication)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-tron-gateway-vault-agent:
|
||||||
|
<<: *common-env
|
||||||
|
image: hashicorp/vault:latest
|
||||||
|
container_name: dev-tron-gateway-vault-agent
|
||||||
|
restart: unless-stopped
|
||||||
|
cap_add: ["IPC_LOCK"]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: ${VAULT_ADDR}
|
||||||
|
TRON_GATEWAY_VAULT_ROLE_ID: ${TRON_GATEWAY_VAULT_ROLE_ID}
|
||||||
|
TRON_GATEWAY_VAULT_SECRET_ID: ${TRON_GATEWAY_VAULT_SECRET_ID}
|
||||||
|
command: >
|
||||||
|
sh -c 'set -eu; umask 077;
|
||||||
|
echo "$$TRON_GATEWAY_VAULT_ROLE_ID" > /run/vault/role_id;
|
||||||
|
echo "$$TRON_GATEWAY_VAULT_SECRET_ID" > /run/vault/secret_id;
|
||||||
|
unset TRON_GATEWAY_VAULT_ROLE_ID TRON_GATEWAY_VAULT_SECRET_ID;
|
||||||
|
exec vault agent -config=/etc/vault/agent/tron-gateway.hcl'
|
||||||
|
volumes:
|
||||||
|
- ./ci/dev/vault-agent/tron-gateway.hcl:/etc/vault/agent/tron-gateway.hcl:ro
|
||||||
|
- dev-tron-gateway-vault-run:/run/vault
|
||||||
|
depends_on:
|
||||||
|
dev-vault: { condition: service_healthy }
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "test", "-s", "/run/vault/token"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 6
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# TRON Gateway Service (TRON blockchain - connects to Vault for keys)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-tron-gateway:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/tron-gateway.dockerfile
|
||||||
|
image: sendico-dev/tron-gateway:latest
|
||||||
|
container_name: dev-tron-gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-discovery: { condition: service_started }
|
||||||
|
dev-vault: { condition: service_healthy }
|
||||||
|
dev-tron-gateway-vault-agent: { condition: service_healthy }
|
||||||
|
volumes:
|
||||||
|
- ./api/gateway/tron:/src/api/gateway/tron
|
||||||
|
- ./api/gateway/tron/config.dev.yml:/app/config.yml:ro
|
||||||
|
- dev-tron-gateway-vault-run:/run/vault:ro
|
||||||
|
ports:
|
||||||
|
- "50071:50071"
|
||||||
|
- "9408:9407"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
TRON_GATEWAY_MONGO_HOST: dev-mongo-1
|
||||||
|
TRON_GATEWAY_MONGO_PORT: 27017
|
||||||
|
TRON_GATEWAY_MONGO_DATABASE: tron_gateway
|
||||||
|
TRON_GATEWAY_MONGO_USER: ${MONGO_USER}
|
||||||
|
TRON_GATEWAY_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
TRON_GATEWAY_MONGO_AUTH_SOURCE: admin
|
||||||
|
TRON_GATEWAY_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
TRON_GATEWAY_GRPC_PORT: 50071
|
||||||
|
TRON_GATEWAY_METRICS_PORT: 9407
|
||||||
|
VAULT_ADDR: ${VAULT_ADDR}
|
||||||
|
VAULT_TOKEN_FILE: /run/vault/token
|
||||||
|
TRON_GATEWAY_RPC_URL: ${TRON_GATEWAY_RPC_URL:-}
|
||||||
|
TRON_GATEWAY_GRPC_URL: ${TRON_GATEWAY_GRPC_URL:-}
|
||||||
|
TRON_GATEWAY_GRPC_TOKEN: ${TRON_GATEWAY_GRPC_TOKEN:-}
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# MNTX Gateway Service (card payouts)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-mntx-gateway:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/mntx-gateway.dockerfile
|
||||||
|
image: sendico-dev/mntx-gateway:latest
|
||||||
|
container_name: dev-mntx-gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-discovery: { condition: service_started }
|
||||||
|
dev-vault: { condition: service_healthy }
|
||||||
|
volumes:
|
||||||
|
- ./api/gateway/mntx:/src/api/gateway/mntx
|
||||||
|
- ./api/gateway/mntx/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50075:50075"
|
||||||
|
- "9405:9405"
|
||||||
|
- "8084:8084"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
MNTX_GATEWAY_GRPC_PORT: 50075
|
||||||
|
MNTX_GATEWAY_METRICS_PORT: 9405
|
||||||
|
MNTX_GATEWAY_HTTP_PORT: 8084
|
||||||
|
VAULT_ADDR: ${VAULT_ADDR}
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# TGSettle Gateway Service (Telegram settlements)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-tgsettle-gateway:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/tgsettle-gateway.dockerfile
|
||||||
|
image: sendico-dev/tgsettle-gateway:latest
|
||||||
|
container_name: dev-tgsettle-gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-discovery: { condition: service_started }
|
||||||
|
dev-vault: { condition: service_healthy }
|
||||||
|
volumes:
|
||||||
|
- ./api/gateway/tgsettle:/src/api/gateway/tgsettle
|
||||||
|
- ./api/gateway/tgsettle/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "50080:50080"
|
||||||
|
- "9406:9406"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
TGSETTLE_GATEWAY_MONGO_HOST: dev-mongo-1
|
||||||
|
TGSETTLE_GATEWAY_MONGO_PORT: 27017
|
||||||
|
TGSETTLE_GATEWAY_MONGO_DATABASE: tgsettle_gateway
|
||||||
|
TGSETTLE_GATEWAY_MONGO_USER: ${MONGO_USER}
|
||||||
|
TGSETTLE_GATEWAY_MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
TGSETTLE_GATEWAY_MONGO_AUTH_SOURCE: admin
|
||||||
|
TGSETTLE_GATEWAY_MONGO_REPLICA_SET: dev-rs
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
TGSETTLE_GATEWAY_GRPC_PORT: 50080
|
||||||
|
TGSETTLE_GATEWAY_METRICS_PORT: 9406
|
||||||
|
VAULT_ADDR: ${VAULT_ADDR}
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Notification Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-notification:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/notification.dockerfile
|
||||||
|
image: sendico-dev/notification:latest
|
||||||
|
container_name: dev-notification
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/notification:/src/api/notification
|
||||||
|
- ./api/notification/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
NOTIFICATION_HTTP_PORT: 8081
|
||||||
|
MONGO_HOST: dev-mongo-1
|
||||||
|
MONGO_PORT: 27017
|
||||||
|
MONGO_DATABASE: sendico
|
||||||
|
MONGO_USER: ${MONGO_USER}
|
||||||
|
MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
MONGO_AUTH_SOURCE: admin
|
||||||
|
MONGO_REPLICA_SET: dev-rs
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# BFF (Backend for Frontend / Server) Service
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-bff:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/bff.dockerfile
|
||||||
|
image: sendico-dev/bff:latest
|
||||||
|
container_name: dev-bff
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-mongo-init: { condition: service_completed_successfully }
|
||||||
|
dev-nats: { condition: service_started }
|
||||||
|
dev-ledger: { condition: service_started }
|
||||||
|
dev-payments-orchestrator: { condition: service_started }
|
||||||
|
dev-chain-gateway: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./api/server:/src/api/server
|
||||||
|
- ./api/server/config.dev.yml:/app/config.yml:ro
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
MONGO_HOST: dev-mongo-1
|
||||||
|
MONGO_PORT: 27017
|
||||||
|
MONGO_DATABASE: sendico
|
||||||
|
MONGO_USER: ${MONGO_USER}
|
||||||
|
MONGO_PASSWORD: ${MONGO_PASSWORD}
|
||||||
|
MONGO_AUTH_SOURCE: admin
|
||||||
|
MONGO_REPLICA_SET: dev-rs
|
||||||
|
MONGO_HOSTS_0: dev-mongo-1
|
||||||
|
MONGO_PORTS_0: 27017
|
||||||
|
MONGO_HOSTS_1: dev-mongo-2
|
||||||
|
MONGO_PORTS_1: 27017
|
||||||
|
MONGO_HOSTS_2: dev-mongo-3
|
||||||
|
MONGO_PORTS_2: 27017
|
||||||
|
NATS_HOST: dev-nats
|
||||||
|
NATS_PORT: 4222
|
||||||
|
NATS_USER: ${NATS_USER}
|
||||||
|
NATS_PASSWORD: ${NATS_PASSWORD}
|
||||||
|
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
|
||||||
|
LEDGER_ADDRESS: dev-ledger:50052
|
||||||
|
PAYMENTS_ADDRESS: dev-payments-orchestrator:50062
|
||||||
|
CHAIN_GATEWAY_ADDRESS: dev-chain-gateway:50070
|
||||||
|
BFF_HTTP_PORT: 8080
|
||||||
|
API_PROTOCOL: http
|
||||||
|
SERVICE_HOST: localhost
|
||||||
|
API_ENDPOINT: /api/v1
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Frontend (Flutter Web)
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
dev-frontend:
|
||||||
|
<<: *common-env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ci/dev/frontend.dockerfile
|
||||||
|
image: sendico-dev/frontend:latest
|
||||||
|
container_name: dev-frontend
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
dev-bff: { condition: service_started }
|
||||||
|
volumes:
|
||||||
|
- ./ci/dev/Caddyfile.dev:/etc/caddy/Caddyfile:ro
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
networks:
|
||||||
|
- sendico-dev
|
||||||
|
environment:
|
||||||
|
BFF_URL: http://dev-bff:8080
|
||||||
Reference in New Issue
Block a user