- sogoctl: supervisor avec health checks et restart auto - sogoway: gateway HTTP, auth JWT, routing par hostname - sogoms-db: microservice MariaDB avec pool par application - Protocol IPC Unix socket JSON length-prefixed - Config YAML multi-application (prokov) - Deploy script pour container Alpine gw3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
33 KiB
Executable File
SOGOMS - Service Oriented GO MicroServices
Architecture modulaire, configurable et multi-tenant pour plateformes SaaS
Website : https://sogoms.com
1. Vision et Principes
1.1 Concept
SOGOMS est une architecture de plateforme permettant de construire des applications SaaS modulaires, hautement configurables et multi-tenant.
L'idée centrale : une seule plateforme, plusieurs services, plusieurs clients, configurations illimitées.
1.2 Principes fondamentaux
| Principe | Description |
|---|---|
| Modularité | Chaque fonctionnalité = un binaire Go indépendant |
| Configuration over Code | Comportements définis en YAML, pas en dur |
| Multi-tenant natif | Isolation des données et configs par client |
| Orchestration | Workflows complexes via scénarios paramétrables |
| Scalabilité horizontale | Chaque binaire peut avoir N instances |
| Simplicité | Un container, plusieurs processus supervisés |
1.3 Cas d'usage cibles
- Plateformes SaaS B2B multi-clients
- Applications métier avec workflows personnalisables
- Systèmes de gestion documentaire (PDF, signatures, archivage)
- Plateformes de communication (emails, notifications, SMS)
- Back-offices d'applications mobiles Flutter
1.4 Composants de l'écosystème
| Composant | Description |
|---|---|
| SOGOMS | Plateforme principale (ce document) |
| SOGOMS Vigil | Extension monitoring (voir sogoms-vigil.md) |
2. Architecture Globale
2.1 Infrastructure
Internet
│
▼
┌────────────────────────────────────────────────────────────────────────────┐
│ IN3 (Dev/Recette) ou IN4 (Prod) │
│ Debian 13 - Host │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ Nginx Host (:443 TLS → :80 HTTP) │
│ │ │
│ ├── api-dev.sogoms.com ──→ gw3:8080 (Dev) │
│ ├── api.sogoms.com ──────→ gw4:8080 (Prod) │
│ └── (autres sites) ──────→ [containers PHP existants] │
│ │
├────────────────────────────────────────────────────────────────────────────┤
│ Bridge Incus : 13.23.33.0/24 │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ gw3 - 13.23.33.5 (ou gw4) │ │
│ │ Alpine 3.21 │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────────┐ │ │
│ │ │ Sogoctl (superviseur) │ │ │
│ │ │ PID 1 - Admin :9000 │ │ │
│ │ └────────────────────────┬───────────────────────────────┘ │ │
│ │ │ supervise │ │
│ │ ┌────────────────────────┴───────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ Sogoway (:8080) │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ unix socket │ │ │
│ │ │ Sogorch (N instances) │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ unix sockets │ │ │
│ │ │ ┌──────────┬──────────┬──────────┬──────────┐ │ │ │
│ │ │ │sogoms-db │sogoms-pdf│sogoms- │sogoms- │ │ │ │
│ │ │ │ (N) │ (N) │ email(N) │ stor.(N) │ │ │ │
│ │ │ └──────────┴──────────┴──────────┴──────────┘ │ │ │
│ │ │ │ │ │
│ │ └────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ /run/ /config/ /data/storage/ │ │
│ │ └── *.sock ├── sogoctl.yaml └── tenants/ │ │
│ │ ├── routes/ └── {tenant}/ │ │
│ │ └── scenarios/ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ maria3 │ │ redis3 │ │
│ │ 13.23.33.4 │ │ 13.23.33.6 │ │
│ │ MariaDB :3306 │ │ Redis :6379 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
2.2 Containers Incus
| Container | IP | Rôle | Base |
|---|---|---|---|
| gw3 (dev) / gw4 (prod) | 13.23.33.5 | Gateway + Orchestrateur + Microservices | Alpine |
| maria3 / maria4 | 13.23.33.4 | MariaDB (existant) | Alpine |
| redis3 / redis4 | 13.23.33.6 | Cache, sessions, rate-limit (V2+) | Alpine |
2.3 Flux de données
1. Client HTTPS → Nginx Host (:443)
2. Nginx → Sogoway (:8080) via proxy HTTP
3. Sogoway → Valide JWT → Identifie tenant → Trouve route
4. Sogoway → Sogorch (unix socket)
5. Sogorch → Charge scénario YAML → Exécute steps
6. Sogorch → Sogoms-* (unix sockets) pour chaque step
7. Sogoms-* → Traite (DB, PDF, email...) → Retourne résultat
8. Sogorch → Agrège résultats → Retourne à Sogoway
9. Sogoway → Nginx → Client
2.4 Identification des Applications Clientes
Chaque application cliente de SOGOMS (Prokov, etc.) est identifiée par son hostname.
Flow d'identification
1. Requête arrive : GET https://prokov.unikoffice.com/api/auth/me
2. Nginx Host → Sogoway (:8080) avec Header "Host: prokov.unikoffice.com"
3. Sogoway parcourt config/routes/*.yaml
4. Sogoway trouve prokov.yaml car "prokov.unikoffice.com" est dans ses "hosts"
5. Sogoway identifie app_id = "prokov"
6. Pour chaque appel à sogoms-db, Sogoway inclut app_id dans la requête
7. Sogoms-db charge config/routes/prokov.yaml → section "database"
8. Sogoms-db exécute la requête SQL sur la DB de l'application
Configuration obligatoire par application
Chaque fichier config/routes/{app}.yaml DOIT contenir :
app: prokov # Identifiant unique
hosts: # Hostnames associés
- prokov.unikoffice.com
- prokov.sogoms.com
database: # Config DB isolée
host: 13.23.33.4
port: 3306
user: prokov # User DB dédié
password_file: /secrets/prokov_db_pass
name: prokov # Base de données dédiée
Principe d'isolation
| Élément | Isolation |
|---|---|
| Base de données | Une DB par application |
| User MariaDB | Un user par application |
| Credentials | Fichier séparé par application |
| Données | Aucun partage entre applications |
3. Binaires Go
3.1 Vue d'ensemble
| Binaire | Rôle | Instances | Port/Socket |
|---|---|---|---|
| sogoctl | Superviseur, admin, monitoring | 1 | TCP :9000 |
| sogoway | HTTP Gateway, auth, routing | 1 | TCP :8080 |
| sogorch | Orchestrateur, exécute scénarios | N | Unix socket |
| sogoms-db | Service accès MariaDB | N | Unix socket |
| sogoms-pdf | Service génération PDF | N | Unix socket |
| sogoms-email | Service envoi emails | N | Unix socket |
| sogoms-storage | Service gestion fichiers | N | Unix socket |
3.2 Sogoctl (Superviseur)
Sogoctl est le processus principal (PID 1) qui supervise tous les autres binaires.
Responsabilités
- Démarrer/arrêter les binaires au boot
- Health checks périodiques
- Redémarrage automatique en cas de crash
- Load balancing round-robin entre instances
- API d'administration (stats, scaling, logs)
- Registry des instances actives
Configuration
# /config/sogoctl.yaml
supervisor:
socket: /run/sogoctl.sock
admin_port: 9000
health_interval: 5s
restart_delay: 1s
max_restarts: 5
logging:
level: info
output: /var/log/sogoms/sogoctl.log
services:
sogoway:
binary: /opt/sogoms/bin/sogoway
instances: 1
port: 8080
health_endpoint: /health
sogorch:
binary: /opt/sogoms/bin/sogorch
instances: 2
socket_pattern: /run/sogorch.{id}.sock
health_endpoint: /health
sogoms-db:
binary: /opt/sogoms/bin/sogoms-db
instances: 2
socket_pattern: /run/sogoms-db.{id}.sock
env:
MARIA_HOST: 13.23.33.4
MARIA_PORT: "3306"
MARIA_USER: sogoms
MARIA_PASS_FILE: /secrets/maria_password
sogoms-pdf:
binary: /opt/sogoms/bin/sogoms-pdf
instances: 1
socket_pattern: /run/sogoms-pdf.{id}.sock
autoscale:
enabled: true
min: 1
max: 5
metric: queue_depth
threshold: 10
sogoms-email:
binary: /opt/sogoms/bin/sogoms-email
instances: 1
socket_pattern: /run/sogoms-email.{id}.sock
env:
SMTP_HOST: smtp.example.com
SMTP_PORT: "587"
sogoms-storage:
binary: /opt/sogoms/bin/sogoms-storage
instances: 1
socket_pattern: /run/sogoms-storage.{id}.sock
env:
STORAGE_BASE: /data/storage
CLI Sogoctl
# Statut global
$ sogoctl status
SERVICE INSTANCE PID STATUS CPU MEM UPTIME
sogoway 1 1234 running 2% 45MB 2h15m
sogorch 1 1235 running 5% 32MB 2h15m
sogorch 2 1236 running 3% 30MB 2h15m
sogoms-db 1 1237 running 1% 28MB 2h15m
sogoms-db 2 1238 running 1% 27MB 2h15m
sogoms-pdf 1 1239 running 0% 52MB 2h15m
sogoms-email 1 1240 running 0% 25MB 2h15m
# Scaler un service
$ sogoctl scale sogoms-pdf 3
Scaling sogoms-pdf: 1 → 3
Starting sogoms-pdf.2 ... OK (PID 1241)
Starting sogoms-pdf.3 ... OK (PID 1242)
# Instances d'un service
$ sogoctl instances sogoms-pdf
INSTANCE PID SOCKET STATUS REQUESTS
1 1239 /run/sogoms-pdf.1.sock running 1,234
2 1241 /run/sogoms-pdf.2.sock running 156
3 1242 /run/sogoms-pdf.3.sock running 89
# Redémarrer un service
$ sogoctl restart sogorch
# Logs
$ sogoctl logs sogoms-pdf.1 --follow
$ sogoctl logs sogorch --all --since 1h
# Stats temps réel
$ sogoctl top
# Info d'un service
$ sogoctl info sogorch
3.3 Sogoway (Gateway HTTP)
Point d'entrée HTTP unique pour toutes les requêtes API.
Responsabilités
- Réception des requêtes HTTP
- Authentification (JWT, API Keys)
- Identification du tenant
- Routing vers les scénarios
- Rate limiting
- Logging des requêtes
Configuration
# /config/sogoway.yaml
server:
port: 8080
read_timeout: 30s
write_timeout: 30s
max_body_size: 10MB
auth:
jwt:
secret_env: JWT_SECRET
algorithm: HS256
expiration: 24h
claims:
tenant_id: tenant
user_id: sub
roles: roles
api_keys:
enabled: true
header: X-API-Key
storage: redis
tenant:
resolution:
- type: jwt_claim
claim: tenant_id
- type: header
name: X-Tenant-ID
- type: subdomain
pattern: "{tenant}.api.sogoms.com"
rate_limit:
enabled: true
storage: redis
default:
requests: 1000
window: 1m
by_tenant: true
orchestrator:
pool_size: 10
timeout: 30s
routes_path: /config/routes
logging:
level: info
format: json
output: stdout
metrics:
enabled: true
path: /metrics
Routes par application
# /config/routes/prokov.yaml
app: prokov
version: "1.0"
base_path: /api/prokov
auth:
required: true
roles: [user, admin]
routes:
# Liste des tâches
- path: /tasks
method: GET
scenario: list_tasks
cache:
enabled: true
ttl: 30s
# Créer une tâche
- path: /tasks
method: POST
scenario: create_task
rate_limit:
requests: 100
window: 1m
# Détail d'une tâche
- path: /tasks/{id}
method: GET
scenario: get_task
# Modifier une tâche
- path: /tasks/{id}
method: PUT
scenario: update_task
# Supprimer une tâche
- path: /tasks/{id}
method: DELETE
scenario: delete_task
auth:
roles: [admin]
3.4 Sogorch (Orchestrateur)
Exécute les scénarios YAML en appelant les microservices.
Responsabilités
- Charger et parser les scénarios YAML
- Exécuter les steps séquentiellement ou en parallèle
- Gérer le contexte et les variables
- Appeler les Sogoms via Unix sockets
- Gérer les erreurs, retry, conditions
- Retourner le résultat agrégé
Scénario type
# /config/scenarios/create_task.yaml
name: create_task
version: "1.0"
description: Créer une tâche et notifier l'assigné
input:
required:
- title
- assigned_to
optional:
- description
- priority
- notify
defaults:
priority: medium
notify: false
context:
created_at: "{{now}}"
created_by: "{{auth.user_id}}"
steps:
# Valider que l'utilisateur assigné existe
- id: validate_user
service: db
action: query_one
params:
query: "SELECT id, email FROM users WHERE id = ? AND tenant_id = ?"
args: ["{{input.assigned_to}}", "{{tenant.id}}"]
on_error: abort
error_message: "Utilisateur assigné non trouvé"
# Insérer la tâche
- id: insert_task
service: db
action: insert
params:
table: tasks
data:
tenant_id: "{{tenant.id}}"
title: "{{input.title}}"
description: "{{input.description}}"
priority: "{{input.priority}}"
assigned_to: "{{input.assigned_to}}"
status: "pending"
created_by: "{{context.created_by}}"
created_at: "{{context.created_at}}"
on_error: abort
# Notifier par email (optionnel, async)
- id: send_notification
service: email
action: send
condition: "{{input.notify == true}}"
async: true
params:
to: "{{steps.validate_user.result.email}}"
template: task_assigned
data:
task_id: "{{steps.insert_task.insert_id}}"
task_title: "{{input.title}}"
assigned_by: "{{auth.user_name}}"
output:
status: 201
body:
success: true
task:
id: "{{steps.insert_task.insert_id}}"
title: "{{input.title}}"
status: "pending"
created_at: "{{context.created_at}}"
Syntaxe des scénarios
# Conditions
- id: premium_only
service: billing
action: check_feature
condition: "{{tenant.plan == 'premium'}}"
# Boucles
- id: notify_all
service: email
action: send
foreach: "{{input.recipients}}"
foreach_as: recipient
params:
to: "{{recipient.email}}"
template: notification
# Parallélisme
- id: parallel_tasks
parallel:
- id: gen_pdf
service: pdf
action: generate
params: {...}
- id: send_copy
service: email
action: send
params: {...}
# Retry
- id: external_call
service: http
action: post
retry:
attempts: 3
delay: 2s
backoff: exponential
# Switch/case
- id: route_by_type
switch: "{{input.document_type}}"
cases:
invoice:
service: pdf
action: generate_invoice
contract:
service: pdf
action: generate_contract
default:
service: pdf
action: generate_generic
3.5 Microservices (Sogoms-*)
Chaque microservice est un binaire Go spécialisé.
Structure commune
// Chaque Sogoms implémente cette interface
type Service interface {
Name() string
Actions() map[string]ActionHandler
Health() error
}
type ActionHandler func(ctx context.Context, params map[string]any) (any, error)
Sogoms-db
# Actions disponibles
actions:
- query # SELECT avec plusieurs résultats
- query_one # SELECT avec un seul résultat
- insert # INSERT, retourne insert_id
- update # UPDATE, retourne affected_rows
- delete # DELETE, retourne affected_rows
- exec # Requête brute
- transaction # Groupe de requêtes transactionnelles
Sogoms-pdf
actions:
- generate # Générer un PDF depuis un template
- merge # Fusionner plusieurs PDFs
- split # Séparer un PDF
- extract_text # Extraire le texte
- add_signature # Ajouter une signature
Sogoms-email
actions:
- send # Envoyer un email
- send_bulk # Envoyer en masse
- validate # Valider une adresse email
Sogoms-storage
actions:
- put # Stocker un fichier
- get # Récupérer un fichier
- delete # Supprimer un fichier
- list # Lister les fichiers
- get_url # Obtenir une URL signée temporaire
4. Communication Inter-Processus
4.1 Protocole Unix Socket
Les binaires communiquent via Unix sockets avec un protocole simple basé sur JSON.
Format des messages
┌─────────────────────────────────────────────────────┐
│ 4 bytes │ N bytes │
│ Length │ JSON Payload │
└─────────────────────────────────────────────────────┘
Requête
{
"id": "req_abc123",
"action": "insert",
"tenant_id": "acme",
"params": {
"table": "tasks",
"data": {
"title": "Ma tâche",
"status": "pending"
}
},
"timeout_ms": 5000
}
Réponse
{
"id": "req_abc123",
"status": "success",
"result": {
"insert_id": 42,
"affected_rows": 1
}
}
{
"id": "req_abc123",
"status": "error",
"error": {
"code": "DB_ERROR",
"message": "Duplicate entry for key 'title'"
}
}
4.2 Load Balancing
Sogoctl maintient un pool de connexions pour chaque service :
type ServicePool struct {
name string
instances []*Instance
mu sync.RWMutex
counter uint64
}
func (p *ServicePool) Next() *Instance {
p.mu.RLock()
defer p.mu.RUnlock()
// Round-robin
idx := atomic.AddUint64(&p.counter, 1) % uint64(len(p.instances))
return p.instances[idx]
}
5. Multi-Tenancy
5.1 Identification du tenant
Le tenant est identifié dans cet ordre de priorité :
- Claim JWT
tenant_id - Header
X-Tenant-ID - Sous-domaine (
acme.api.sogoms.com) - API Key (lookup en base)
5.2 Configuration par tenant
# /config/tenants/acme.yaml
tenant:
id: acme
name: ACME Corporation
domain: acme.example.com
plan: premium
status: active
database:
prefix: acme_ # Tables préfixées ou schema séparé
limits:
rate_limit: 5000/min
storage: 50GB
users: 100
api_keys: 20
features:
- pdf
- email
- storage
- custom_workflows
storage:
type: local # local | s3 | minio
config:
base_path: /data/storage/tenants/acme
customization:
branding:
logo_url: https://acme.example.com/logo.png
primary_color: "#1a73e8"
email:
from_name: ACME Platform
from_email: noreply@acme.example.com
5.3 Isolation des données
-- Chaque table inclut tenant_id
CREATE TABLE tasks (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
tenant_id VARCHAR(50) NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
status ENUM('pending', 'in_progress', 'completed') DEFAULT 'pending',
assigned_to BIGINT,
created_by BIGINT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_tenant (tenant_id),
INDEX idx_tenant_status (tenant_id, status)
);
-- Sogoms-db ajoute automatiquement la clause tenant_id
6. Stockage Fichiers
6.1 Structure
/data/storage/
├── _system/ # Fichiers système SOGOMS
│ ├── templates/ # Templates PDF, email
│ │ ├── pdf/
│ │ │ ├── invoice.html
│ │ │ └── contract.html
│ │ └── email/
│ │ ├── welcome.html
│ │ └── task_assigned.html
│ └── tmp/ # Fichiers temporaires
│
└── tenants/
├── acme/
│ ├── documents/ # PDFs générés
│ ├── uploads/ # Fichiers uploadés
│ └── tmp/ # Temporaires du tenant
│
└── startup/
├── documents/
├── uploads/
└── tmp/
6.2 Interface Storage (évolutive)
type Storage interface {
Put(ctx context.Context, path string, data []byte) error
Get(ctx context.Context, path string) ([]byte, error)
Delete(ctx context.Context, path string) error
List(ctx context.Context, prefix string) ([]string, error)
GetURL(ctx context.Context, path string, expiry time.Duration) (string, error)
}
// Implémentations disponibles
// - LocalStorage : fichiers locaux
// - S3Storage : AWS S3 / Scaleway Object Storage
// - MinioStorage : MinIO self-hosted
7. Sécurité
7.1 Authentification JWT
# Structure du token JWT
header:
alg: HS256
typ: JWT
payload:
sub: "user_123" # User ID
tenant: "acme" # Tenant ID
roles: ["user", "admin"] # Rôles
exp: 1704067200 # Expiration
iat: 1703980800 # Issued at
7.2 Rate Limiting
# Par défaut
rate_limit:
default: 1000/min
# Par tenant (override)
rate_limit:
acme: 5000/min
startup: 500/min
# Par endpoint (override)
routes:
- path: /api/heavy-operation
rate_limit:
requests: 10
window: 1m
7.3 Validation des entrées
Chaque scénario valide ses inputs :
input:
required:
- email
- password
optional:
- name
validation:
email:
type: string
format: email
password:
type: string
min_length: 8
8. Structure du Projet
sogoms/
├── cmd/
│ ├── sogoctl/ # Superviseur
│ │ └── main.go
│ ├── sogoway/ # Gateway HTTP
│ │ └── main.go
│ ├── sogorch/ # Orchestrateur
│ │ └── main.go
│ └── sogoms/
│ ├── db/ # Microservice DB
│ │ └── main.go
│ ├── pdf/ # Microservice PDF
│ │ └── main.go
│ ├── email/ # Microservice Email
│ │ └── main.go
│ └── storage/ # Microservice Storage
│ └── main.go
│
├── internal/
│ ├── protocol/ # Protocole Unix socket
│ │ ├── message.go
│ │ ├── client.go
│ │ └── server.go
│ ├── pool/ # Load balancer interne
│ │ └── pool.go
│ ├── config/ # Lecture configs YAML
│ │ ├── config.go
│ │ ├── tenant.go
│ │ └── routes.go
│ ├── scenario/ # Exécution scénarios
│ │ ├── parser.go
│ │ ├── executor.go
│ │ └── context.go
│ ├── auth/ # JWT, API Keys
│ │ ├── jwt.go
│ │ └── apikey.go
│ └── registry/ # Registry des instances
│ └── registry.go
│
├── pkg/
│ └── logger/ # Logger partagé
│ └── logger.go
│
├── config/
│ ├── sogoctl.yaml # Config superviseur
│ ├── sogoway.yaml # Config gateway
│ ├── tenants/ # Configs tenants
│ │ ├── acme.yaml
│ │ └── startup.yaml
│ ├── routes/ # Routes par application
│ │ └── prokov.yaml
│ └── scenarios/ # Scénarios
│ ├── create_task.yaml
│ ├── update_task.yaml
│ └── delete_task.yaml
│
├── scripts/
│ ├── build.sh # Build tous les binaires
│ ├── install.sh # Installation dans container
│ └── dev.sh # Lancement dev local
│
├── deploy/
│ └── incus/
│ ├── setup-gw3.sh # Setup container gw3
│ └── setup-redis3.sh # Setup container redis3
│
├── go.mod
├── go.sum
├── Makefile
└── README.md
9. Déploiement
9.1 Build
# Makefile
BINARIES = sogoctl sogoway sogorch sogoms-db sogoms-pdf sogoms-email sogoms-storage
VERSION = $(shell git describe --tags --always)
LDFLAGS = -s -w -X main.version=$(VERSION)
.PHONY: all clean $(BINARIES)
all: $(BINARIES)
sogoctl:
CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogoctl ./cmd/sogoctl
sogoway:
CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogoway ./cmd/sogoway
sogorch:
CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogorch ./cmd/sogorch
sogoms-%:
CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o dist/sogoms-$* ./cmd/sogoms/$*
clean:
rm -rf dist/*
install: all
scp dist/* gw3:/opt/sogoms/bin/
ssh gw3 'sogoctl restart all'
9.2 Setup Container Incus
#!/bin/bash
# deploy/incus/setup-gw3.sh
# Créer le container
incus launch images:alpine/3.21 gw3
# Configurer l'IP fixe
incus config device override gw3 eth0 ipv4.address=13.23.33.5
# Créer les dossiers
incus exec gw3 -- mkdir -p /opt/sogoms/bin
incus exec gw3 -- mkdir -p /config
incus exec gw3 -- mkdir -p /data/storage/tenants
incus exec gw3 -- mkdir -p /run
incus exec gw3 -- mkdir -p /var/log/sogoms
# Installer les dépendances (pour sogoms-pdf notamment)
incus exec gw3 -- apk add --no-cache \
chromium \
font-noto \
font-noto-emoji
# Copier les binaires
incus file push dist/* gw3/opt/sogoms/bin/
# Copier les configs
incus file push -r config/* gw3/config/
# Configurer sogoctl comme service init
incus exec gw3 -- sh -c 'cat > /etc/init.d/sogoms << EOF
#!/sbin/openrc-run
command=/opt/sogoms/bin/sogoctl
command_args="--config /config/sogoctl.yaml"
pidfile=/run/sogoctl.pid
EOF'
incus exec gw3 -- chmod +x /etc/init.d/sogoms
incus exec gw3 -- rc-update add sogoms default
# Démarrer
incus exec gw3 -- rc-service sogoms start
9.3 Config Nginx Host
# /etc/nginx/sites-available/sogoms
upstream sogoms_gateway {
server 13.23.33.5:8080;
keepalive 16;
}
server {
listen 443 ssl http2;
server_name api.sogoms.com api-dev.sogoms.com;
ssl_certificate /etc/letsencrypt/live/sogoms.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sogoms.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
access_log /var/log/nginx/sogoms.access.log;
error_log /var/log/nginx/sogoms.error.log;
location / {
proxy_pass http://sogoms_gateway;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location /ws/ {
proxy_pass http://sogoms_gateway;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}
10. Monitoring
10.1 Métriques (via Sogoctl)
# API Admin :9000
GET /metrics # Prometheus format
GET /health # Health check global
GET /status # Status détaillé JSON
GET /services # Liste des services et instances
GET /services/{name} # Détail d'un service
10.2 Logs
# Logs centralisés par Sogoctl
/var/log/sogoms/
├── sogoctl.log
├── sogoway.log
├── sogorch.log
├── sogoms-db.log
├── sogoms-pdf.log
├── sogoms-email.log
└── sogoms-storage.log
10.3 SOGOMS Vigil
Pour un monitoring avancé multi-hosts avec agents, voir sogoms-vigil.md.
11. Roadmap
Phase 1 : Foundation (MVP)
- Sogoctl : superviseur basique (start/stop/restart)
- Sogoway : routing, auth JWT
- Sogorch : exécution scénarios simples
- Sogoms-db : CRUD MariaDB
- Protocole Unix socket
- Config YAML (routes + scénarios)
Phase 2 : Features
- Multi-tenant complet
- Sogoms-pdf : génération PDF
- Sogoms-email : envoi emails
- Sogoms-storage : gestion fichiers
- Rate limiting Redis
- Sogoctl : scaling dynamique
Phase 3 : Production
- Health checks avancés
- Métriques Prometheus
- Autoscaling basé sur métriques
- Hot reload des configs
- Dashboard admin
Phase 4 : Enterprise
- Workflows complexes (conditions, boucles, parallélisme)
- API Keys management
- Webhooks
- Multi-région
- Audit logs
12. Références
- Go Chi Router - HTTP routing
- Go YAML v3 - Parsing YAML
- Go MariaDB Driver - Accès MariaDB
- Chromedp - Génération PDF
- Incus Documentation - Containers
Website : https://sogoms.com Documentation : https://docs.sogoms.com API : https://api.sogoms.com
Document mis à jour le 2025-01-15 - Version 2.0.0