Compare commits

..

No commits in common. "main" and "v1.1.3" have entirely different histories.
main ... v1.1.3

40 changed files with 1801 additions and 308 deletions

18
.gitignore vendored
View File

@ -31,24 +31,8 @@ tests/reports/
# Sauvegardes locales # Sauvegardes locales
*.backup *.backup
*.conf
*.toml
*.yml
*.yaml
*.json
*.csv
*.txt
*.log
*.log.*
*.log.*.*
*.log.*.*.*
*.log.*.*.*.*
*.log.*.*.*.*.*
*.log.*.*.*.*.*.*
*.log.*.*.*.*.*.*.*
*.log.*.*.*.*.*.*.*.*
certs/ certs/
*.log *.log
# Ignore real configuration files, but keep example configs # Ignore real configuration files, but keep example configs
tor_data/ *.conf

View File

@ -81,10 +81,10 @@ cat ~/.ssh/id_ed25519_4nk.pub
### 📖 Guides Principaux ### 📖 Guides Principaux
- **[Index de la documentation](docs/INDEX.md)** - Table des matières centrale - **[Guide d'Installation](docs/INSTALLATION.md)** - Installation et configuration complète
- **[Guide d'Utilisation](docs/USAGE.md)** - Utilisation quotidienne et cas d'usage - **[Guide d'Utilisation](docs/USAGE.md)** - Utilisation quotidienne et cas d'usage
- **[Guide de Configuration](docs/CONFIGURATION.md)** - Configuration avancée - **[Guide de Configuration](docs/CONFIGURATION.md)** - Configuration avancée
- **[Architecture](docs/ARCHITECTURE.md)** - Architecture détaillée - **[Guide de Développement](docs/DEVELOPMENT.md)** - Développement et contribution
### 🔧 Guides Techniques ### 🔧 Guides Techniques
@ -101,7 +101,9 @@ cat ~/.ssh/id_ed25519_4nk.pub
### 🌐 Guides Réseau ### 🌐 Guides Réseau
- **[Réseau et cartographie](docs/NETWORK.md)** - Hostnames, IP, ports, montages et routes Nginx - **[Réseau de Relais](docs/RELAY_NETWORK.md)** - Configuration du réseau mesh
- **[Nœuds Externes](docs/EXTERNAL_NODES.md)** - Ajout et gestion de nœuds externes
- **[Synchronisation](docs/SYNCHRONIZATION.md)** - Protocole de synchronisation
## 🔧 Configuration ## 🔧 Configuration

320
conf/nginx.conf.exemple Normal file
View File

@ -0,0 +1,320 @@
# Configuration Nginx pour 4NK_node sur l'hôte Debian
# Reverse proxy et équilibreur de charge pour tous les services Docker
# Configuration globale
user www-data;
worker_processes auto;
error_log /var/log/nginx/4nk-node-error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging spécifique à 4NK_node
log_format 4nk_main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream: $upstream_addr';
access_log /var/log/nginx/4nk-node-access.log 4nk_main;
# Performance
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 100M;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Rate limiting
limit_req_zone $binary_remote_addr zone=4nk_api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=4nk_login:10m rate=1r/s;
# Upstream servers - ports Docker exposés sur l'hôte
upstream bitcoin_rpc {
server 127.0.0.1:38332;
keepalive 32;
}
upstream bitcoin_p2p {
server 127.0.0.1:38333;
keepalive 32;
}
upstream blindbit_api {
server 127.0.0.1:8000;
keepalive 32;
}
upstream sdk_storage_api {
server 127.0.0.1:8081;
keepalive 32;
}
upstream sdk_relay1_api {
server 127.0.0.1:8090;
keepalive 32;
}
upstream sdk_relay2_api {
server 127.0.0.1:8092;
keepalive 32;
}
upstream sdk_relay3_api {
server 127.0.0.1:8094;
keepalive 32;
}
upstream sdk_signer_api {
server 127.0.0.1:9090;
keepalive 32;
}
upstream ihm_client_web {
server 127.0.0.1:3003;
keepalive 32;
}
upstream ihm_client_http {
server 127.0.0.1:8080;
keepalive 32;
}
upstream grafana_dashboard {
server 127.0.0.1:3000;
keepalive 32;
}
upstream loki_api {
server 127.0.0.1:3100;
keepalive 32;
}
# Le coffre services (backend/frontend)
upstream coffre_backend {
server 127.0.0.1:8082;
keepalive 32;
}
upstream coffre_front {
server 127.0.0.1:8083;
keepalive 32;
}
# Main server block
server {
listen 80;
server_name 4nk-node.local localhost;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
# Health check endpoint
location /health {
access_log off;
return 200 "4NK Node healthy\n";
add_header Content-Type text/plain;
}
# Bitcoin RPC (JSON-RPC)
location /bitcoin/rpc/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://bitcoin_rpc/;
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;
# Bitcoin RPC specific
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# Bitcoin P2P (port 38333)
location /bitcoin/p2p/ {
proxy_pass http://bitcoin_p2p/;
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;
}
# BlindBit API
location /blindbit/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://blindbit_api/;
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_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# SDK Storage API
location /storage/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://sdk_storage_api/;
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;
}
# SDK Relay APIs
location /relay1/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://sdk_relay1_api/;
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;
}
location /relay2/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://sdk_relay2_api/;
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;
}
location /relay3/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://sdk_relay3_api/;
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;
}
# SDK Signer API
location /signer/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://sdk_signer_api/;
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;
}
# IHM Client Web (React)
location /ihm/ {
proxy_pass http://ihm_client_web/;
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;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# IHM Client HTTP
location /ihm-http/ {
proxy_pass http://ihm_client_http/;
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;
}
# Grafana Dashboard
location /grafana/ {
proxy_pass http://grafana_dashboard/;
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;
# Grafana specific
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Loki API (logs)
location /loki/ {
limit_req zone=4nk_api burst=20 nodelay;
proxy_pass http://loki_api/;
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;
}
# Default route - IHM Client
location / {
proxy_pass http://ihm_client_web/;
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;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# HTTPS server (commented out - uncomment and configure SSL for production)
# server {
# listen 443 ssl http2;
# server_name 4nk-node.local;
#
# ssl_certificate /etc/ssl/certs/4nk-node.crt;
# ssl_certificate_key /etc/ssl/private/4nk-node.key;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
# ssl_prefer_server_ciphers off;
#
# # Same location blocks as HTTP server
# # ... (copy from above)
# }
}

View File

@ -1,18 +0,0 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# Logs Nginx locaux (facultatif, peut être redirigé ailleurs)
access_log /var/log/nginx/4nk_node.access.log;
error_log /var/log/nginx/4nk_node.error.log;
include /etc/nginx/sites-enabled/*.conf;
}

View File

@ -1,90 +0,0 @@
server {
listen 80 default_server;
server_name _;
# Format de logs dédié Grafana/Promtail
access_log /var/log/nginx/4nk_node.access.log;
error_log /var/log/nginx/4nk_node.error.log;
# ihm_client (HTTP)
location / {
proxy_pass http://ihm-client.4nk.local:80/;
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;
}
# sdk_storage
location /sdk_storage/ {
proxy_pass http://sdk-storage.4nk.local:8081/;
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;
}
# blindbit
location /blindbit/ {
proxy_pass http://blindbit.4nk.local:8000/;
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;
}
# relais (HTTP API)
location /relay1/ { proxy_pass http://sdk-relay1.4nk.local:8091/; }
location /relay2/ { proxy_pass http://sdk-relay2.4nk.local:8093/; }
location /relay3/ { proxy_pass http://sdk-relay3.4nk.local:8095/; }
# relais (WebSocket)
location /relay1/ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://sdk-relay1.4nk.local:8090/;
}
location /relay2/ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://sdk-relay2.4nk.local:8092/;
}
location /relay3/ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://sdk-relay3.4nk.local:8094/;
}
# sdk_signer (WS et HTTP si exposés sur 9090/9092)
location /signer/ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://sdk-signer.4nk.local:9090/;
}
location /signer/ {
proxy_pass http://sdk-signer.4nk.local:9092/;
}
# lecoffre-front
location /coffre/ {
proxy_pass http://coffre-front.4nk.local:3003/;
}
# miniback (expose /logs si nécessaire)
location /miniback/ {
proxy_pass http://miniback.4nk.local:8081/;
}
# Grafana (sous-chemin /grafana)
location /grafana/ {
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_pass http://127.0.0.1:3000/;
}
}

View File

@ -0,0 +1,32 @@
NETWORK_NAME="4nk_network"
TOR_IMAGE="4nk-node-tor:docker-support-v2"
BITCOIN_IMAGE="4nk-node-bitcoin:docker-support-v2"
BLINDBIT_IMAGE="4nk-node-blindbit:docker-support-v2"
RELAY_IMAGE="4nk-node-sdk_relay1:docker-support-v2"
BITCOIN_VOLUME="bitcoin_data"
BLINDBIT_VOLUME="blindbit_data"
RELAY_1_VOLUME="sdk_relay_1_data"
RELAY_2_VOLUME="sdk_relay_2_data"
RELAY_3_VOLUME="sdk_relay_3_data"
TOR_PORTS=("9050:9050" "9051:9051")
BITCOIN_PORTS=("38333:38333" "18443:18443" "29000:29000")
BLINDBIT_PORTS=("8000:8000")
RELAY_1_PORTS=("8090:8090" "8091:8091")
RELAY_2_PORTS=("8092:8090" "8093:8091")
RELAY_3_PORTS=("8094:8090" "8095:8091")
BITCOIN_CONF="$PROJECT_DIR/conf/bitcoin.conf"
BLINDBIT_CONF="$PROJECT_DIR/conf/blindbit.toml"
RELAY_1_CONF="$PROJECT_DIR/conf/sdk_relay1.conf"
RELAY_2_CONF="$PROJECT_DIR/conf/sdk_relay2.conf"
RELAY_3_CONF="$PROJECT_DIR/conf/sdk_relay3.conf"
EXTERNAL_NODES_CONF="$PROJECT_DIR/sdk_relay/external_nodes.conf"
COMMON_ENV=(
"RUST_LOG=debug,bitcoincore_rpc=trace"
"HOME=/home/bitcoin"
"BITCOIN_COOKIE_PATH=/home/bitcoin/.bitcoin/signet/.cookie"
"ENABLE_SYNC_TEST=1"
)

View File

@ -277,21 +277,6 @@ services:
ipv4_address: 172.20.0.33 ipv4_address: 172.20.0.33
restart: unless-stopped restart: unless-stopped
nginx:
image: nginx:1.25
container_name: 4nk-nginx
hostname: nginx.4nk.local
ports:
- "80:80"
volumes:
- ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./conf/nginx/sites-enabled:/etc/nginx/sites-enabled:ro
- ./log/nginx:/var/log/nginx
networks:
4nk_network:
ipv4_address: 172.20.0.40
restart: unless-stopped
volumes: volumes:
miniback_pg_data: miniback_pg_data:

View File

@ -1,25 +0,0 @@
## Index de la documentation 4NK_node
### Guides principaux
- Configuration: `docs/CONFIGURATION.md`
- Architecture: `docs/ARCHITECTURE.md`
- Usage: `docs/USAGE.md`
- Réseau et cartographie: `docs/NETWORK.md`
### Monitoring et logs
- Stack monitoring (Loki/Promtail/Grafana): `log-monitoring.yml`
- Provisioning Grafana: `log/grafana-datasources.yml`, `log/grafana-dashboards.yml`
- Collecte Promtail: `log/promtail-config.yml`
### Reverse proxy
- Nginx conf: `conf/nginx/nginx.conf`
- Virtual host: `conf/nginx/sites-enabled/4nk_node.conf`
### Répertoires par service
- Modules: `modules/<service>/{conf,data,logs,scripts}`
- Projets: `projects/<projet>/<image>/{conf,data,logs,scripts}`
### Notes
- Les images internes référencées en `:dev` sont en cours de création.
- Grafana est servi sous `/grafana` via Nginx.

View File

@ -1,50 +1,13 @@
## Réseau et cartographie des services tor: hostname=tor.4nk.local, ip=172.20.0.10
bitcoin: hostname=bitcoin.4nk.local, ip=172.20.0.11
### Sous-réseaux blindbit: hostname=blindbit.4nk.local, ip=172.20.0.12
- 4nk_network: 172.20.0.0/16 (services applicatifs, IP statiques et hostnames fixés) sdk_storage: hostname=sdk-storage.4nk.local, ip=172.20.0.13
- 4nk_projects_net: 172.21.0.0/16 (réservé, aucun service attaché pour linstant) sdk_relay1: hostname=sdk-relay1.4nk.local, ip=172.20.0.14
sdk_relay2: hostname=sdk-relay2.4nk.local, ip=172.20.0.15
### Tableau de mapping sdk_relay3: hostname=sdk-relay3.4nk.local, ip=172.20.0.16
sdk_signer: hostname=sdk-signer.4nk.local, ip=172.20.0.17
| Service | Hostname | IP | Ports exposés | Montages conf/data/logs | Nginx (routes) | Dépendances | ihm_client: hostname=ihm-client.4nk.local, ip=172.20.0.18
|---|---|---|---|---|---|---| miniback-postgres: hostname=miniback-postgres.4nk.local, ip=172.20.0.30
| tor | tor.4nk.local | 172.20.0.10 | 9050, 9051 | conf:/etc/tor/torrc(ro), data:/var/lib/tor, logs:/var/log/tor | — | — | miniback: hostname=miniback.4nk.local, ip=172.20.0.31
| bitcoin | bitcoin.4nk.local | 172.20.0.11 | 38333, 38332, 29000 | conf:/home/bitcoin/.bitcoin/bitcoin.conf(ro), data:/home/bitcoin/.bitcoin, logs:/home/bitcoin/.bitcoin/logs | — | tor | coffre_front: hostname=coffre-front.4nk.local, ip=172.20.0.32
| blindbit | blindbit.4nk.local | 172.20.0.12 | 8000 | conf:/blindbit/blindbit.toml(ro), data:/blindbit, logs:/blindbit/logs | /blindbit/ → :8000 | bitcoin | coffre_back_mini: hostname=coffre-back-mini.4nk.local, ip=172.20.0.33
| sdk_storage | sdk-storage.4nk.local | 172.20.0.13 | 8081 | conf:/usr/local/bin/sdk_storage.conf(ro), logs:/app/logs | /sdk_storage/ → :8081 | blindbit |
| sdk_relay1 | sdk-relay1.4nk.local | 172.20.0.14 | 8090(ws), 8091(http) | conf:/home/bitcoin/.conf(ro), logs:/home/bitcoin/logs | /relay1/, /relay1/ws/ | sdk_storage |
| sdk_relay2 | sdk-relay2.4nk.local | 172.20.0.15 | 8092(ws), 8093(http) | conf:/home/bitcoin/.conf(ro), logs:/home/bitcoin/logs | /relay2/, /relay2/ws/ | sdk_storage |
| sdk_relay3 | sdk-relay3.4nk.local | 172.20.0.16 | 8094(ws), 8095(http) | conf:/home/bitcoin/.conf(ro), logs:/home/bitcoin/logs | /relay3/, /relay3/ws/ | sdk_storage |
| sdk_signer | sdk-signer.4nk.local | 172.20.0.17 | 9090(ws), 9092(http) | conf:/usr/local/bin/sdk_signer.conf(ro), data:/app/data, logs:/usr/src/app/logs | /signer/, /signer/ws/ | sdk_relay1/2/3 |
| ihm_client | ihm-client.4nk.local | 172.20.0.18 | 80, 3003 | logs:/var/log/ihm_client | / (→:80), /coffre/ (→coffre_front:3003) | sdk_signer |
| miniback-postgres | miniback-postgres.4nk.local | 172.20.0.30 | 5432 | data:/var/lib/postgresql/data(volume) | — | — |
| miniback | miniback.4nk.local | 172.20.0.31 | — | logs:/logs, env:.env(ro) | /miniback/ (si HTTP) | miniback-postgres |
| coffre_front | coffre-front.4nk.local | 172.20.0.32 | 3003 | logs:/logs | /coffre/ → :3003 | — |
| coffre_back_mini | coffre-back-mini.4nk.local | 172.20.0.33 | — | — | — | — |
| nginx | nginx.4nk.local | 172.20.0.40 | 80 | conf:/etc/nginx, logs:/var/log/nginx | reverse proxy + /grafana/ | — |
### Observabilité
- Promtail lit: `./log/**/*.log`, `./modules/*/logs/**/*.log`, `./projects/*/*/logs/**/*.log` et pousse vers Loki.
- Grafana est servi via Nginx sous `/grafana/` et provisionné avec datasources/dashboards.
### Liens entre services (flux réseau et dépendances)
- Tor → Bitcoin Core
- Bitcoin utilise Tor comme proxy (`proxy=tor.4nk.local:9050`) et active `listenonion=1`.
- Bitcoin Core → Blindbit
- Blindbit lit lendpoint RPC de Bitcoin (`http://bitcoin.4nk.local:38332`) et sappuie sur ZMQ (`tcp://bitcoin.4nk.local:29000`).
- Blindbit → SDK Storage
- SDK Storage consomme les index/infos de Blindbit (config via `sdk_storage.conf`).
- SDK Storage → SDK Relays (1/2/3)
- Les relais interrogent Storage côté API HTTP (8091/8093/8095) et exposent WS séparés (8090/8092/8094).
- SDK Relays (1/2/3) → SDK Signer
- Signer se connecte aux trois relais (WS et/ou HTTP) et à Storage; il consomme également Blindbit et Bitcoin RPC (pour certaines opérations).
- SDK Signer → IHM Client
- Lapplication front sappuie sur Signer (WS 9090, HTTP 9092) pour lorchestration fonctionnelle.
- Miniback → Postgres
- Miniback utilise `miniback-postgres` (5432) comme base de données.
- Nginx → Tous services HTTP/WS
- Reverseproxy vers: IHM (`/`), Storage (`/sdk_storage/`), Blindbit (`/blindbit/`), Relais (`/relayX/` + `/relayX/ws/`), Signer (`/signer/` + `/signer/ws/`), Coffre (`/coffre/`), Miniback (`/miniback/`), Grafana (`/grafana/`).
### Notes
- Les services internes utilisent des hostnames Docker `.4nk.local` résolus par le DNS du réseau `4nk_network`.
- Les tags dimages `:dev` sont en cours de création; voir `docs/CONFIGURATION.md`.

View File

@ -2,39 +2,10 @@
## Prérequis ## Prérequis
- Docker et docker compose installés
- Nginx utilisé via le service `nginx` de l'orchestrateur
## Installation locale ## Installation locale
- Cloner le dépôt et se placer à la racine
- Vérifier la présence des répertoires `modules/` et `projects/` avec `conf/`, `data/`, `logs/`, `scripts/`
- Vérifier la disponibilité des images taggées `:dev` (en cours de création) ou utiliser des tags stables le cas échéant
## Démarrage ## Démarrage
- Démarrer la stack applicative : `docker compose up -d`
- Démarrer la stack de monitoring (Loki/Promtail/Grafana) si souhaité : `docker compose -f log-monitoring.yml up -d`
- Accéder aux services via Nginx :
- IHM: `http://localhost/`
- Blindbit: `http://localhost/blindbit/`
- SDK Storage: `http://localhost/sdk_storage/`
- Relais HTTP: `http://localhost/relay1/`, `/relay2/`, `/relay3/`
- Relais WebSocket: `ws://localhost/relay1/ws/` (idem `relay2`, `relay3`)
- Signer WS: `ws://localhost/signer/ws/`; HTTP: `http://localhost/signer/`
- Coffre front: `http://localhost/coffre/`
- Grafana: `http://localhost/grafana/`
## Commandes utiles ## Commandes utiles
- Mettre à jour les images: `docker compose pull`
- Voir les logs Nginx: `tail -f log/nginx/4nk_node.access.log`
- Voir les logs des services (montés): `tail -f modules/<service>/logs/*`
- Logs Promtail/Loki/Grafana: voir `log/` et `log-monitoring.yml`
## Dépannage ## Dépannage
- Vérifier les hostnames Docker internes (DNS du réseau `4nk_network`): voir `docker-compose.yml`
- Les tags `:dev` sont en cours de création; en cas dindisponibilité, utiliser des tags stables temporaires
- Conf Tor: `modules/tor/conf/tor.conf` est montée si l'image Tor supporte `/etc/tor/torrc`
- Le reverse proxy Nginx sappuie sur les hostnames Docker (`*.4nk.local`); en cas de changement dIP/hostnames, mettre à jour `docker-compose.yml` et relancer `nginx`.

View File

@ -39,8 +39,6 @@ services:
environment: environment:
- GF_SECURITY_ADMIN_PASSWORD=admin - GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false - GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s/grafana
- GF_SERVER_SERVE_FROM_SUB_PATH=true
volumes: volumes:
- grafana_data:/var/lib/grafana - grafana_data:/var/lib/grafana
- ./log/grafana-datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml:ro - ./log/grafana-datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml:ro

View File

@ -16,4 +16,54 @@ zmqpubrawblock=tcp://bitcoin.4nk.local:29000
zmqpubrawtx=tcp://bitcoin.4nk.local:29000 zmqpubrawtx=tcp://bitcoin.4nk.local:29000
zmqpubhashblock=tcp://bitcoin.4nk.local:29000 zmqpubhashblock=tcp://bitcoin.4nk.local:29000
blockfilterindex=1 blockfilterindex=1
# 0.0.0.0:8000 to expose outside of localhost
# default: "127.0.0.1:8000"
host = "bitcoin.4nk.local:8000"
# Defines on which chain the wallet runs. Allowed values: main, testnet, signet, regtest.
# default: signet
chain = "signet"
# default: http://127.0.0.1:8332
rpc_endpoint = "http://bitcoin.4nk.local:38332"
# required, unless rpc_user and rpc_pass are set
cookie_path = "$HOME/.bitcoin/signet/.cookie"
# required, unless cookie_path is set
rpc_pass = ""
# required, unless cookie_path is set
rpc_user = ""
# required (has to be >= 1)
sync_start_height = 1
# the default for this is 1, but should be set to a higher value to increase performance,
# one should set this in accordance to how many cores one wants to use
max_parallel_tweak_computations = 4
# (depends on max-rpc-workers of the underlying full node)
max_parallel_requests = 4
# optional - will only generate tweaks (still both cut-through and full-index)
# default: 0
tweaks_only = 0
# The base index. Only includes the tweaks. No dust filtering or cut-through possible
# default: 1
tweaks_full_basic = 1
# if this is set a full non-cut-through index will be created.
# This index can be used to filter for dust (?dustLimit=). If this is active the base index will not be created.
# All full index queries will be served from this with or without (?dustLimit=) set in the query.
# default 0
tweaks_full_with_dust_filter = 0
# This index applies cut-through and dust filtering.
# Beware that it will be stored in addition to any full index (with or without dust) if activated.
# It has more storage requirements than the simple indices.
# Currently still requires tweaks_only=0.
# default: 0
tweaks_cut_through_with_dust_filter = 0

View File

@ -1,6 +1,6 @@
# 0.0.0.0:8000 to expose outside of localhost # 0.0.0.0:8000 to expose outside of localhost
# default: "127.0.0.1:8000" # default: "127.0.0.1:8000"
host = "blindbit.4nk.local:8000" host = "bitcoin.4nk.local:8000"
# Defines on which chain the wallet runs. Allowed values: main, testnet, signet, regtest. # Defines on which chain the wallet runs. Allowed values: main, testnet, signet, regtest.
# default: signet # default: signet

View File

@ -1,7 +1,43 @@
const U32_MAX = import.meta.env.U32_MAX; # Configuration ihm_client - Module 4NK_node
const BASEURL = import.meta.env.DEV.BASEURL;
const BOOTSTRAPURL = import.meta.env.DEV.BOOTSTRAPURL; # URLs des services
const STORAGEURL = import.meta.env.DEV.STORAGEURL; sdk_signer_url = "http://4nk-sdk-signer:9090"
const BLINDBITURL = import.meta.env.DEV.BLINDBITURL; sdk_storage_url = "http://4nk-sdk-storage:8081"
const DEFAULTAMOUNT = import.meta.env.DEV.DEFAULTAMOUNT; sdk_relay1_url = "http://4nk-sdk-relay1:8091"
const EMPTY32BYTES = import.meta.env.DEV.EMPTY32BYTES; sdk_relay2_url = "http://4nk-sdk-relay2:8093"
sdk_relay3_url = "http://4nk-sdk-relay3:8095"
# WebSocket URLs
sdk_relay1_ws = "ws://4nk-sdk-relay1:8090"
sdk_relay2_ws = "ws://4nk-sdk-relay2:8092"
sdk_relay3_ws = "ws://4nk-sdk-relay3:8094"
# Configuration réseau
network_type = "signet"
bitcoin_rpc_url = "http://4nk-bitcoin:18443"
# Ports
ui_port = 8080
api_port = 8080
# Sécurité
cors_enabled = true
cors_origins = ["*"]
rate_limit_enabled = true
rate_limit_requests = 100
rate_limit_window = 60
session_timeout = 3600
# Timeouts
request_timeout = 30
connection_timeout = 10
# Logging
log_level = "info"
log_file = "/app/logs/ihm_client.log"
log_max_size = "100MB"
log_max_files = 5
# Mode développement
dev_mode = true
debug_enabled = true

View File

@ -1,5 +1,5 @@
core_url="http://bitcoin.4nk.local:38332" core_url="http://bitcoin.4nk.local:38332"
ws_url="sdk-relay2.4nk.local:8090" ws_url="sdk-relay1.4nk.local:8090"
wallet_name="default" wallet_name="default"
network="signet" network="signet"
blindbit_url="http://blindbit.4nk.local:8000" blindbit_url="http://blindbit.4nk.local:8000"

View File

@ -1,5 +1,5 @@
core_url="http://bitcoin.4nk.local:38332" core_url="http://bitcoin.4nk.local:38332"
ws_url="sdk-relay3.4nk.local:8090" ws_url="sdk-relay1.4nk.local:8090"
wallet_name="default" wallet_name="default"
network="signet" network="signet"
blindbit_url="http://blindbit.4nk.local:8000" blindbit_url="http://blindbit.4nk.local:8000"

1
modules/sdk_signer/package-lock.json generated Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1 @@
{"name":"sdk_signer","version":"1.0.0"}

View File

@ -0,0 +1 @@
{"name":"sdk_signer_pkg","version":"0.0.1"}

View File

@ -0,0 +1,6 @@
export function sdkSignerInit(): void {
// Minimal placeholder to satisfy build during initial integration
}
export default sdkSignerInit;

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES2019",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true,
"strict": false
},
"include": ["src/**/*"]
}

View File

@ -4,13 +4,13 @@
http_port = 8081 http_port = 8081
# Base de données # Base de données
db_path = "$HOME/bitcoin/.4nk/storage.db" db_path = "/home/bitcoin/.4nk/storage.db"
# URLs des services # URLs des services
relay_urls = ["http://4nk-sdk-relay1:8091", "http://4nk-sdk-relay2:8093", "http://4nk-sdk-relay3:8095"] relay_urls = ["http://4nk-sdk-relay1:8091", "http://4nk-sdk-relay2:8093", "http://4nk-sdk-relay3:8095"]
bitcoin_rpc_url = "http://4nk-bitcoin:38332" bitcoin_rpc_url = "http://4nk-bitcoin:38332"
bitcoin_rpc_user = "bitcoin" bitcoin_rpc_user = "EXEMPLE"
bitcoin_rpc_password = "bitcoin" bitcoin_rpc_password = "EXEMPLE"
# Mode développement # Mode développement
dev_mode = true dev_mode = true
@ -22,10 +22,10 @@ timeout = 30
# Logging # Logging
log_level = "info" log_level = "info"
log_file = "$HOME/bitcoin/logs/sdk_storage.log" log_file = "/home/bitcoin/logs/sdk_storage.log"
# Stockage de fichiers # Stockage de fichiers
file_storage_path = "$HOME/bitcoin/.4nk/files" file_storage_path = "/home/bitcoin/.4nk/files"
max_file_size = "100MB" max_file_size = "100MB"
# Sécurité # Sécurité

View File

@ -1,16 +0,0 @@
# Configuration Tor pour 4NK_node (conteneur)
# Ports d\écoute
# Ports d\'écoute
SocksPort tor.4nk.local:9050
ControlPort tor.4nk.local:9051
# Répertoires
DataDirectory /var/lib/tor
# Logs (fichier monté par docker-compose)
Log notice file /var/log/tor/notices.log
# Exécution en avant-plan dans un conteneur
RunAsDaemon 0

View File

@ -2,8 +2,8 @@
# Écoute sur toutes les interfaces pour permettre la connexion depuis d'autres conteneurs # Écoute sur toutes les interfaces pour permettre la connexion depuis d'autres conteneurs
# Ports SOCKS et contrôle # Ports SOCKS et contrôle
SocksPort tor.4nk.local:9050 SocksPort 0.0.0.0:9050
ControlPort tor.4nk.local:9051 ControlPort 0.0.0.0:9051
# Répertoire de données # Répertoire de données
DataDirectory /var/lib/tor DataDirectory /var/lib/tor

View File

@ -1,50 +1,48 @@
# Configuration OVH # Configuration OVH
OVH_APP_KEY=5ab0709bbb65ef26 OVH_APP_KEY=EXEMPLE
OVH_APP_SECRET=de1fac1779d707d263a611a557cd5766 OVH_APP_SECRET=EXEMPLE
OVH_CONSUMER_KEY=5fe817829b8a9c780cfa2354f8312ece OVH_CONSUMER_KEY=EXEMPLE
OVH_SMS_SERVICE_NAME=sms-tt802880-1 OVH_SMS_SERVICE_NAME=sms-tt802880-1
# Configuration SMS Factor # Configuration SMS Factor
SMS_FACTOR_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI4NzgzNiIsImlhdCI6MTcwMTMzOTY1Mi45NDUzOH0.GNoqLb5MDBWuniNlQjbr1PKolwxGqBZe_tf4IMObvHw SMS_FACTOR_TOKEN=EXEMPLE
#Configuration Mailchimp #Configuration Mailchimp
MAILCHIMP_API_KEY=md-VVfaml-ApIV4nsGgaJKl0A MAILCHIMP_API_KEY=EXEMPLE
MAILCHIMP_KEY=3fa54304bc766dfd0b8043a827b28a3a-us17 MAILCHIMP_KEY=EXEMPLE
MAILCHIMP_LIST_ID=a48d9ad852 MAILCHIMP_LIST_ID=a48d9ad852
#Configuration Stripe #Configuration Stripe
STRIPE_SECRET_KEY=sk_test_51OwKmMP5xh1u9BqSeFpqw0Yr15hHtFsh0pvRGaE0VERhlYtvw33ND1qiGA6Dy1DPmmV61B6BqIimlhuv7bwElhjF00PLQwD60n STRIPE_SECRET_KEY=EXEMPLE
STRIPE_WEBHOOK_SECRET= STRIPE_WEBHOOK_SECRET=EXEMPLE
STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1P66fuP5xh1u9BqSHj0O6Uy3 STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1P66fuP5xh1u9BqSHj0O6Uy3
STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NsRP5xh1u9BqSFgkUDbQY STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NsRP5xh1u9BqSFgkUDbQY
STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1P66RqP5xh1u9BqSuUzkQNac STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1P66RqP5xh1u9BqSuUzkQNac
STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NpKP5xh1u9BqSApFogvUB STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NpKP5xh1u9BqSApFogvUB
# Configuration serveur # Configuration serveur
APP_HOST=http://miniback.4nk.local APP_HOST=http://localhost
PORT=8080 PORT=8080
# Configuration front-end # Configuration front-end
NEXT_PUBLIC_4NK_URL=https://ihm-client.4nk.local NEXT_PUBLIC_4NK_URL=https://dev3.4nkweb.com
NEXT_PUBLIC_FRONT_APP_HOST=http://coffre-front.4nk.local:3000 NEXT_PUBLIC_FRONT_APP_HOST=http://localhost:3000
NEXT_PUBLIC_IDNOT_BASE_URL=https://qual-connexion.idnot.fr NEXT_PUBLIC_IDNOT_BASE_URL=https://qual-connexion.idnot.fr
NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT=/IdPOAuth2/authorize/idnot_idp_v1 NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT=/IdPOAuth2/authorize/idnot_idp_v1
NEXT_PUBLIC_IDNOT_CLIENT_ID=4501646203F3EF67 NEXT_PUBLIC_IDNOT_CLIENT_ID=4501646203F3EF67
NEXT_PUBLIC_BACK_API_PROTOCOL=http NEXT_PUBLIC_BACK_API_PROTOCOL=http
NEXT_PUBLIC_BACK_API_HOST=miniback.4nk.local NEXT_PUBLIC_BACK_API_HOST=localhost
BACK_API_PORT=8080 BACK_API_PORT=8080
BACK_API_ROOT_URL=/api BACK_API_ROOT_URL=/api
BACK_API_VERSION=/v1 BACK_API_VERSION=/v1
# Configuration idnot # Configuration idnot
IDNOT_ANNUARY_BASE_URL='https://qual-api.notaires.fr/annuaire' IDNOT_ANNUARY_BASE_URL='https://qual-api.notaires.fr/annuaire'
IDNOT_API_KEY='ba557f84-0bf6-4dbf-844f-df2767555e3e' IDNOT_API_KEY='EXEMPLE'
# Configuration PostgreSQL # Configuration PostgreSQL
DB_HOST= DB_HOST=miniback-postgres
DB_PORT= DB_PORT=5432
DB_NAME= DB_NAME=miniback
DB_USER= DB_USER=EXEMPLE
DB_PASSWORD= DB_PASSWORD=EXEMPLE
LOG_LEVEL="debug"

View File

@ -1,10 +1,17 @@
EXT_PUBLIC_4NK_URL="http://ihm-client.4nk.local:3003" # Configuration IHM_client
NEXT_PUBLIC_FRONT_APP_HOST="http://coffre-front.4nk.local:3000" NEXT_PUBLIC_4NK_URL="http://localhost:3003"
# Configuration lecoffre-front
NEXT_PUBLIC_FRONT_APP_HOST="http://localhost:3000"
# Configuration IDNOT
NEXT_PUBLIC_IDNOT_BASE_URL="https://qual-connexion.idnot.fr" NEXT_PUBLIC_IDNOT_BASE_URL="https://qual-connexion.idnot.fr"
NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT="/IdPOAuth2/authorize/idnot_idp_v1" NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT="/IdPOAuth2/authorize/idnot_idp_v1"
NEXT_PUBLIC_IDNOT_CLIENT_ID="4501646203F3EF67" NEXT_PUBLIC_IDNOT_CLIENT_ID="EXEMPLE"
# Configuration mini-back
NEXT_PUBLIC_BACK_API_PROTOCOL=http:// NEXT_PUBLIC_BACK_API_PROTOCOL=http://
NEXT_PUBLIC_BACK_API_HOST=miniback.4nk.local NEXT_PUBLIC_BACK_API_HOST=localhost
NEXT_PUBLIC_BACK_API_PORT=8080 NEXT_PUBLIC_BACK_API_PORT=8080
NEXT_PUBLIC_BACK_API_ROOT_URL=/api NEXT_PUBLIC_BACK_API_ROOT_URL=/api
NEXT_PUBLIC_BACK_API_VERSION=/v1 NEXT_PUBLIC_BACK_API_VERSION=/v1

View File

@ -4,7 +4,7 @@ set -e
# Configuration # Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/external_nodes.conf" CONFIG_FILE="$SCRIPT_DIR/sdk_relay/external_nodes.conf"
# Couleurs pour l'affichage # Couleurs pour l'affichage
RED='\033[0;31m' RED='\033[0;31m'

16
scripts/build_all_images.sh Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/home/debian/code/4NK_dev/4NK_node"
echo "Building all local Docker images from Dockerfiles under modules/ and projects/ ..."
while IFS= read -r df; do
dir=$(dirname "$df")
rel=${dir#"$BASE_DIR/"}
img_tag="4nk-node-"$(echo "$rel" | tr '/' '-')":latest"
echo "Building $img_tag from $dir"
# signer image will always be built
docker build -t "$img_tag" "$dir"
done < <(find "$BASE_DIR" -name Dockerfile -print)
echo "All images built."

90
scripts/build_modules.sh Executable file
View File

@ -0,0 +1,90 @@
#!/bin/bash
# Script de construction des modules 4NK_node et des projets 4NK_node
set -e
echo "🏗️ Construction des modules 4NK_node et projets 4NK_node..."
# Fonction pour construire un module spécifique
build_module() {
local module_name="$1"
local module_dir="modules/$module_name"
if [ ! -d "$module_dir" ]; then
echo "❌ Module $module_name non trouvé dans $module_dir"
return 1
fi
echo "🔨 Construction de $module_name..."
# Construire l'image Docker
docker build -t "4nk-node-$module_name:latest" "$module_dir"
if [ $? -eq 0 ]; then
echo "✅ Module $module_name construit avec succès"
else
echo "❌ Échec de la construction du module $module_name"
return 1
fi
}
build_project() {
local project_name="$1"
local project_dir="projects/$project_name"
if [ ! -d "$project_dir" ]; then
echo "❌ Project $project_name non trouvé dans $project_dir"
return 1
fi
echo "🔨 Construction de $project_name (project)..."
docker build -t "4nk-node-$project_name:latest" "$project_dir"
if [ $? -eq 0 ]; then
echo "✅ Project $project_name construit avec succès"
else
echo "❌ Échec de la construction du project $project_name"
return 1
fi
}
# Construction de tous les modules si aucun argument n'est fourni
if [ $# -eq 0 ]; then
echo "📦 Construction de tous les modules et projets..."
# Modules de base (existence check pour éviter les erreurs sur des dépôts partiels)
if [ -d "modules/tor" ]; then
build_module "tor"
else
echo "⚠️ Tor module absent, skipping"
fi
if [ -d "modules/bitcoin" ]; then
build_module "bitcoin"
else
echo "⚠️ Bitcoin module absent, skipping"
fi
# Modules applicatifs
if [ -d "modules/blindbit" ]; then build_module "blindbit"; else echo "⚠️ blindbit module absent"; fi
if [ -d "modules/sdk_relay1" ]; then build_module "sdk_relay1"; fi
if [ -d "modules/sdk_relay2" ]; then build_module "sdk_relay2"; fi
if [ -d "modules/sdk_relay3" ]; then build_module "sdk_relay3"; fi
if [ -d "modules/sdk_storage" ]; then build_module "sdk_storage"; fi
if [ -d "modules/sdk_signer" ]; then build_module "sdk_signer"; fi
if [ -d "modules/ihm_client" ]; then build_module "ihm_client"; fi
# Projets nouvellement ajoutés (Le coffre)
# Le coffre-back et le coffre-front dans 4NK_node/projects
if [ -d "projects/lecoffre-back" ]; then build_project "lecoffre-back"; else echo "⚠️ lecoffre-back project absent"; fi
if [ -d "projects/lecoffre-front" ]; then build_project "lecoffre-front"; else echo "⚠️ lecoffre-front project absent"; fi
echo "🎉 Tous les modules et projets ont été construits !"
else
# Construction d'un module ou d'un projet spécifique
if [ -d "modules/$1" ]; then
build_module "$1"
elif [ -d "projects/$1" ]; then
build_project "$1"
else
echo "Module ou projet inconnu: $1"
exit 1
fi
fi

16
scripts/disable_nginx_docker.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
set -euo pipefail
# Désactiver l'exécution de nginx docker
CONTAINER_NAME="4nk-nginx"
# Arrêter et supprimer le conteneur s'il est présent
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Arrêt et suppression du conteneur Docker '$CONTAINER_NAME'..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
else
echo "Aucun conteneur '$CONTAINER_NAME' trouvé; pas d'action nécessaire."
fi
echo "Désactivation Nginx Docker terminée."

59
scripts/health_after_ibd.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/bash
set -euo pipefail
BTC_CONTAINER="4nk-bitcoin"
RELAY_CONTAINERS=("4nk-sdk-relay1" "4nk-sdk-relay2" "4nk-sdk-relay3")
STORAGE_CONTAINER="4nk-sdk-storage"
SIGNER_CONTAINER="4nk-sdk-signer"
IHMSERVER_CONTAINER="4nk-node-ihm-client"
TOR_CONTAINER="4nk-node-tor"
NGINX_CONTAINER="4nk-nginx" # si présent
# Attendre la fin de l'IBD du Bitcoin Core
echo "Relancer les healthchecks après l'IBD terminé..."
while true; do
if docker ps -q -f name="^${BTC_CONTAINER}$" >/dev/null 2>&1; then
INFO=$(docker exec "$BTC_CONTAINER" bitcoin-cli -signet getblockchaininfo 2>/dev/null || true)
if echo "$INFO" | grep -q '"initialblockdownload":false'; then
echo "IBD terminé sur $BTC_CONTAINER"
break
else
echo "IBD en cours sur $BTC_CONTAINER...";
fi
else
echo "Bitcoin container non trouvé, tentative de reprise..."
fi
sleep 60
done
# Redémarrer les conteneurs critiques pour relancer les healthchecks
RESTART_LIST=("$BTC_CONTAINER" "${RELAY_CONTAINERS[@]}" "$STORAGE_CONTAINER" "$SIGNER_CONTAINER" "$IHMSERVER_CONTAINER" "$TOR_CONTAINER")
for c in "${RESTART_LIST[@]}"; do
if docker ps -a | awk '{print $NF}' | tail -n +2 | grep -qx "$c"; then
echo "Redémarrage de $c ..."
docker restart "$c" >/dev/null 2>&1 || true
fi
done
# Vérification rapide des conteneurs
echo "État des conteneurs après redémarrage:"
docker ps -a
# Vérifier des endpoints simples si accessibles
echo "Vérification rapide des endpoints (si disponibles) :"
ENDPOINTS=(
"http://localhost:8081/" # storage
"http://localhost:8000/" # blindbit
"http://localhost:9090/" # signer
"http://localhost:3003/" # ihm web
"http://localhost:8091/" # relay1
"http://localhost:8093/" # relay2
"http://localhost:8095/" # relay3
)
for url in "${ENDPOINTS[@]}"; do
if curl -sS --max-time 5 "$url" >/dev/null 2>&1; then
echo "OK: $url reachable"
else
echo "WARN: $url not reachable"
fi
done

View File

@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
echo "[Grafana setup] starting local Grafana and Loki/Promtail integration"
# Install Grafana if not present
if ! command -v grafana-server >/dev/null 2>&1; then
echo "Grafana not found. Please install Grafana manually or enable the apt repository and run this script again."
exit 1
fi
echo "Grafana is installed. Ensuring service is running..."
sudo systemctl enable grafana-server
sudo systemctl start grafana-server || true
echo "Grafana service status:"
sudo systemctl is-active grafana-server || true
# Try to install Loki/Promtail if helper script exists
HELPER="/home/debian/code/4NK_dev/4NK_node/scripts/install_loki_promtail_local.sh"
if [ -x "$HELPER" ]; then
echo "Running Loki/Promtail installer..."
bash "$HELPER"
else
echo "No Loki/Promtail installer found at $HELPER; skipping."
fi
echo "[Grafana setup] completed."
#!/usr/bin/env bash
set -euo pipefail
echo "[ Grafana setup ]: starting local Grafana installation and Loki/Promtail integration"
# Install Grafana if not present
if ! command -v grafana-server >/dev/null 2>&1; then
echo "Installing Grafana..."
sudo apt-get update
sudo apt-get install -y software-properties-common wget apt-transport-https
wget -q -O - https://packages.grafana.com/grafana.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install -y grafana
sudo systemctl enable grafana-server
sudo systemctl start grafana-server
else
echo "Grafana is already installed."
fi
echo "[ Grafana setup ]: Grafana service status ready."
# Try to install Loki/Promtail using existing helper script if present
if [ -x "/home/debian/code/4NK_dev/4NK_node/scripts/install_loki_promtail_local.sh" ]; then
echo "Running Loki/Promtail installer..."
bash /home/debian/code/4NK_dev/4NK_node/scripts/install_loki_promtail_local.sh
else
echo "Loki/Promtail installer script not found; skipping. Please install Loki/Promtail manually if needed."
fi
echo "[ Grafana setup ]: completed."

View File

@ -0,0 +1,109 @@
#!/bin/bash
set -euo pipefail
# Version et URLs
LOKI_VER="2.9.0"
PROMTAIL_VER="2.9.0"
LOKI_URL="https://github.com/grafana/loki/releases/download/v${LOKI_VER}/loki-linux-amd64.zip"
PROMTAIL_URL="https://github.com/grafana/loki/releases/download/v${PROMTAIL_VER}/promtail-linux-amd64.zip"
# Détection Distro et dépendances
if [ -f /etc/os-release ]; then
. /etc/os-release
fi
OS_ID=${ID:-debian}
sudo apt-get update
sudo apt-get install -y curl unzip
# Installer Loki
sudo mkdir -p /usr/local/bin /etc/loki /var/lib/loki
sudo curl -L -o /tmp/loki-linux-amd64.zip "$LOKI_URL"
sudo unzip -o /tmp/loki-linux-amd64.zip -d /usr/local/bin
sudo bash -lc 'cat > /etc/systemd/system/loki.service <<EOF
[Unit]
Description=Loki service
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/loki-linux-amd64 -config.file=/etc/loki/local-config.yaml
Restart=always
User=root
Group=root
[Install]
WantedBy=multi-user.target
EOF'
sudo mkdir -p /etc/loki /var/lib/loki
sudo tee /etc/loki/local-config.yaml >/dev/null << 'EOF'
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9095
ingester:
wal:
enabled: true
storage_config:
boltdb:
directory: /var/lib/loki/chunks
limits_config:
enforce_metric_name: false
EOF
sudo systemctl daemon-reload
sudo systemctl enable loki
sudo systemctl start loki
# Installer Promtail
sudo mkdir -p /usr/local/bin /etc/promtail /var/log/promtail
sudo curl -L -o /tmp/promtail-linux-amd64.zip "$PROMTAIL_URL"
sudo unzip -o /tmp/promtail-linux-amd64.zip -d /usr/local/bin
sudo bash -lc 'cat > /etc/systemd/system/promtail.service <<EOF
[Unit]
Description=Promtail service
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/promtail-linux-amd64 -config.file=/etc/promtail/promtail.yaml
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF'
sudo mkdir -p /etc/promtail
sudo tee /etc/promtail/promtail.yaml >/dev/null << 'EOF'
server:
http_listen_port: 9080
positions:
filename: /var/log/promtail/positions.yaml
clients:
- url: http://localhost:3100/loki/api/v1/push
scrape_configs:
- job: grafana-logs
static_configs:
- targets: [localhost]
labels:
__path__: /home/debian/code/logs/*.log
job: logs
- job: coffre-logs
static_configs:
- targets: [localhost]
labels:
__path__: /home/debian/code/4NK_dev/4NK_node/log/*.log
job: coffre_logs
EOF
sudo systemctl daemon-reload
sudo systemctl enable promtail
sudo systemctl start promtail
# Vérifications simples
echo
echo "Grafana Loki Promtail local install terminé. Vérifications:"
echo " - Grafana: http://localhost:3000"
echo " - Loki: http://localhost:3100"
echo " - Promtail: service actif (Promtail)"

177
scripts/manage_auth.sh Executable file
View File

@ -0,0 +1,177 @@
#!/bin/bash
# Script de gestion de l'authentification et des fichiers partagés
# pour la stack 4NK_node
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
echo "🔐 Gestion de l'authentification et des fichiers partagés 4NK_node"
# Fonction pour vérifier si un conteneur est en cours d'exécution
container_running() {
docker ps --format "table {{.Names}}" | grep -q "$1"
}
# Fonction pour attendre qu'un conteneur soit prêt
wait_for_container() {
local container_name="$1"
local max_wait=60
local wait_time=0
echo "⏳ Attente que le conteneur $container_name soit prêt..."
while [ $wait_time -lt $max_wait ]; do
if container_running "$container_name"; then
echo "✅ Conteneur $container_name est prêt"
return 0
fi
sleep 2
wait_time=$((wait_time + 2))
done
echo "❌ Timeout en attendant le conteneur $container_name"
return 1
}
# Fonction pour vérifier et créer le fichier .cookie
setup_bitcoin_cookie() {
echo "🔍 Configuration du fichier .cookie Bitcoin..."
if ! container_running "4nk-bitcoin"; then
echo "❌ Le conteneur Bitcoin n'est pas en cours d'exécution"
return 1
fi
# Attendre que Bitcoin soit complètement démarré
wait_for_container "4nk-bitcoin"
sleep 10
# Vérifier si le fichier .cookie existe
if docker exec 4nk-bitcoin test -f /home/bitcoin/.bitcoin/signet/.cookie; then
echo "✅ Fichier .cookie Bitcoin trouvé"
# Afficher les informations du cookie
echo "📋 Informations du fichier .cookie :"
docker exec 4nk-bitcoin ls -la /home/bitcoin/.bitcoin/signet/.cookie
docker exec 4nk-bitcoin cat /home/bitcoin/.bitcoin/signet/.cookie | head -1
# Vérifier les permissions
local perms=$(docker exec 4nk-bitcoin stat -c "%a" /home/bitcoin/.bitcoin/signet/.cookie)
echo "🔐 Permissions du fichier .cookie : $perms"
# S'assurer que les permissions sont correctes (600)
if [ "$perms" != "600" ]; then
echo "🔧 Correction des permissions du fichier .cookie..."
docker exec 4nk-bitcoin chmod 600 /home/bitcoin/.bitcoin/signet/.cookie
fi
return 0
else
echo "❌ Fichier .cookie Bitcoin non trouvé"
echo "📋 Logs Bitcoin récents :"
docker logs 4nk-bitcoin --tail 10
return 1
fi
}
# Fonction pour vérifier l'accès au fichier .cookie depuis d'autres services
verify_cookie_access() {
echo "🔍 Vérification de l'accès au fichier .cookie depuis d'autres services..."
local services=("4nk-blindbit" "4nk-sdk-relay1" "4nk-sdk-relay2" "4nk-sdk-relay3" "4nk-sdk-storage" "4nk-sdk-signer")
for service in "${services[@]}"; do
if container_running "$service"; then
echo "🔍 Vérification de $service..."
if docker exec "$service" test -f /home/bitcoin/.bitcoin/signet/.cookie; then
echo "$service peut accéder au fichier .cookie"
# Vérifier les permissions
local perms=$(docker exec "$service" stat -c "%a" /home/bitcoin/.bitcoin/signet/.cookie)
echo " Permissions : $perms"
# Vérifier la lisibilité
if docker exec "$service" test -r /home/bitcoin/.bitcoin/signet/.cookie; then
echo " ✅ Fichier lisible"
else
echo " ❌ Fichier non lisible"
fi
else
echo "$service ne peut pas accéder au fichier .cookie"
fi
else
echo "⏸️ $service n'est pas en cours d'exécution"
fi
done
}
# Fonction pour tester la connectivité RPC
test_rpc_connectivity() {
echo "🔍 Test de la connectivité RPC..."
if ! container_running "4nk-bitcoin"; then
echo "❌ Bitcoin n'est pas en cours d'exécution"
return 1
fi
# Attendre que Bitcoin soit prêt
sleep 5
# Test de la connectivité RPC via curl
echo "📡 Test de la connectivité RPC via HTTP..."
if docker exec 4nk-bitcoin curl -s --connect-timeout 5 http://localhost:18443 > /dev/null 2>&1; then
echo "✅ Connectivité RPC HTTP OK"
return 0
else
echo "❌ Connectivité RPC HTTP échouée"
return 1
fi
}
# Fonction pour afficher le statut des volumes partagés
show_shared_volumes() {
echo "🔍 Statut des volumes partagés..."
echo "📊 Volumes Docker :"
docker volume ls | grep 4nk_node || echo "Aucun volume 4nk_node trouvé"
echo "📊 Volumes partagés dans docker-compose :"
if [ -f "$PROJECT_DIR/docker-compose.yml" ]; then
grep -A 5 -B 5 "shared_auth" "$PROJECT_DIR/docker-compose.yml" || echo "Volume shared_auth non trouvé"
fi
}
# Fonction principale
main() {
case "${1:-all}" in
"cookie")
setup_bitcoin_cookie
;;
"access")
verify_cookie_access
;;
"rpc")
test_rpc_connectivity
;;
"volumes")
show_shared_volumes
;;
"all"|*)
echo "🚀 Exécution de toutes les vérifications..."
setup_bitcoin_cookie
verify_cookie_access
test_rpc_connectivity
show_shared_volumes
;;
esac
echo "✅ Gestion de l'authentification terminée"
}
# Exécution du script
main "$@"

View File

@ -0,0 +1 @@
#!/bin/bash

99
scripts/monitor_sync.sh Executable file
View File

@ -0,0 +1,99 @@
#!/bin/bash
set -e
echo "🔍 Surveillance de la synchronisation entre 3 relais"
echo "=================================================="
echo ""
# Fonction pour vérifier si Bitcoin Core a terminé l'IBD
check_bitcoin_ready() {
local bitcoin_status=$(docker exec bitcoin-signet bitcoin-cli -signet getblockchaininfo 2>/dev/null | grep -o '"initialblockdownload":false' || echo "still_downloading")
if [[ "$bitcoin_status" == "still_downloading" ]]; then
return 1
else
return 0
fi
}
# Fonction pour afficher les logs de synchronisation
show_sync_logs() {
echo "📡 Logs de synchronisation des relais :"
echo "----------------------------------------"
for i in {1..3}; do
echo "🔸 Relais $i :"
docker logs sdk_relay_$i 2>&1 | grep -E "(🧪|📊|🏥|📈|🔄|🎉|❌|Relay|Sync|Mesh|Topology|🔍|✅|discover|relay)" | tail -3 || echo " Aucun message de synchronisation trouvé"
echo ""
done
}
# Fonction pour vérifier la connectivité entre relais
check_relay_connectivity() {
echo "🌐 Vérification de la connectivité entre relais :"
echo "------------------------------------------------"
for i in {1..3}; do
echo "🔸 Relais $i (port $((8090 + i - 1))) :"
if curl -s http://localhost:$((8090 + i - 1)) >/dev/null 2>&1; then
echo " ✅ Port WebSocket accessible"
else
echo " ❌ Port WebSocket non accessible"
fi
done
echo ""
}
# Fonction pour afficher les métriques de synchronisation
show_sync_metrics() {
echo "📊 Métriques de synchronisation :"
echo "--------------------------------"
for i in {1..3}; do
echo "🔸 Relais $i :"
docker logs sdk_relay_$i 2>&1 | grep -E "(SyncMetrics|known_relays|mesh_connections|sync_cache)" | tail -2 || echo " Aucune métrique trouvée"
echo ""
done
}
# Attendre que Bitcoin Core soit prêt
echo "⏳ Attente que Bitcoin Core termine le téléchargement initial..."
while ! check_bitcoin_ready; do
echo " Bitcoin Core télécharge encore les blocs..."
sleep 30
done
echo "✅ Bitcoin Core est prêt !"
echo ""
# Attendre un peu pour que les relais se stabilisent
echo "⏳ Attente de stabilisation des relais..."
sleep 10
# Boucle de surveillance
echo "🚀 Démarrage de la surveillance de synchronisation..."
echo "Appuyez sur Ctrl+C pour arrêter"
echo ""
while true; do
clear
echo "🔍 Surveillance de la synchronisation entre 3 relais"
echo "=================================================="
echo "$(date)"
echo ""
# Vérifier la connectivité
check_relay_connectivity
# Afficher les logs de synchronisation
show_sync_logs
# Afficher les métriques
show_sync_metrics
echo "🔄 Actualisation dans 30 secondes..."
sleep 30
done

69
scripts/orchestrate_start.sh Executable file
View File

@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/home/debian/code/4NK_dev/4NK_node"
cd "$BASE_DIR" || exit 1
echo "== Début de lorchestration de démarrage des modules =="
SERVICES=(
tor
bitcoin
blindbit
sdk_storage
sdk_relay1
sdk_relay2
sdk_relay3
ihm_client
sdk_signer
coffre_back_mini
coffre_front
)
wait_for_service() {
local svc="$1"; local timeout=${2:-120}; local waited=0
while :; do
if docker compose ps "$svc" 2>/dev/null | grep -q "Up"; then
return 0
fi
if [ "$waited" -ge "$timeout" ]; then
echo "[WARN] Service '$svc' n'est pas en état 'Up' après ${timeout}s" >&2
return 1
fi
waited=$((waited+2))
sleep 2
done
}
for svc in "${SERVICES[@]}"; do
# Determine corresponding image to verify availability
case "$svc" in
tor) img="4nk-node-tor:docker-support-v2" ;;
bitcoin) img="4nk-node-bitcoin:docker-support-v2" ;;
blindbit) img="4nk-node-blindbit:docker-support-v2" ;;
sdk_storage) img="4nk-node-sdk_storage:docker-support-v2" ;;
sdk_relay1) img="4nk-node-sdk_relay1:docker-support-v2" ;;
sdk_relay2) img="4nk-node-sdk_relay2:docker-support-v2" ;;
sdk_relay3) img="4nk-node-sdk_relay3:docker-support-v2" ;;
ihm_client) img="4nk-node-ihm_client:docker-support-v2" ;;
sdk_signer) img="4nk-node-sdk_signer:docker-support-v2" ;;
coffre_back_mini) img="4nk-node-lecoffre-back-mini:latest" ;;
coffre_front) img="lecoffre-front:latest" ;;
miniback) img="4nk-node-miniback:latest" ;;
*) img="" ;;
esac
if [[ -n "$img" ]]; then
if ! docker image inspect "$img" >/dev/null 2>&1; then
echo "[WARN] Image '$img' for service '$svc' not found; skipping." >&2
continue
fi
fi
echo "Starting service: $svc"
docker compose up -d "$svc"
wait_for_service "$svc" 180 || echo "Continuing malgré l'état potentiellement non Up pour $svc"
echo "Service $svc démarré (ou état final vérifié)."
done
echo "== Ordre dorchestration terminé =="

36
scripts/pull_repos_in_order.sh Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
# Pull repos in a defined order to prepare images for docker-compose
BASE_DIR="/home/debian/code/4NK_dev/4NK_node"
ORDER=(
modules/tor
modules/bitcoin-core
modules/blindbit-oracle
modules/sp-client
modules/sdk_common
modules/sdk_client
modules/sdk_relay
modules/sdk_storage
modules/sdk_signer_client
modules/sdk_signer
modules/ihm_client
modules/4NK_template
projects/lecoffre-back-mini
projects/lecoffre-front
)
echo "=== Pull order start ==="
for path in "${ORDER[@]}"; do
full_path="$BASE_DIR/$path"
if [ -d "$full_path" ]; then
echo "-> pulling $path"
(cd "$full_path" && git fetch --all --prune || true && git reset --hard origin/docker-support-v2 || true)
else
echo "-- skipping missing path $path"
fi
done
echo "=== Pull order finished ==="

522
scripts/restart_4nk_node.sh Executable file
View File

@ -0,0 +1,522 @@
#!/bin/bash
# =============================================================================
# Script de Redémarrage Complet 4NK Node
# =============================================================================
# Date: $(date)
# Motif: Redémarrage propre pour intégrer dev3.4nkweb.com
# =============================================================================
set -e # Arrêter en cas d'erreur
# =============================================================================
# CONFIGURATION
# =============================================================================
# Couleurs pour l'affichage
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Configuration du projet
PROJECT_NAME="4NK Node"
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT_DIR="${PROJECT_DIR}"
CONFIG_FILE="$SCRIPT_DIR/conf/restart_config.conf"
if [ -f "$CONFIG_FILE" ]; then
# Import restart configuration from external file
# shellcheck disable=SC1091
# shellcheck source=/home/debian/code/4NK_dev/4NK_node/conf/restart_config.conf
source "$CONFIG_FILE"
fi
# Réseau Docker
NETWORK_NAME="4nk_network"
# Images Docker
TOR_IMAGE="4nk-node-tor:docker-support-v2"
BITCOIN_IMAGE="4nk-node-bitcoin:docker-support-v2"
BLINDBIT_IMAGE="4nk-node-blindbit:docker-support-v2"
RELAY_IMAGE="4nk-node-sdk_relay1:docker-support-v2"
# Volumes
BITCOIN_VOLUME="bitcoin_data"
BLINDBIT_VOLUME="blindbit_data"
RELAY_1_VOLUME="sdk_relay_1_data"
RELAY_2_VOLUME="sdk_relay_2_data"
RELAY_3_VOLUME="sdk_relay_3_data"
# Ports
TOR_PORTS=("9050:9050" "9051:9051")
BITCOIN_PORTS=("38333:38333" "18443:18443" "29000:29000")
BLINDBIT_PORTS=("8000:8000")
RELAY_1_PORTS=("8090:8090" "8091:8091")
RELAY_2_PORTS=("8092:8090" "8093:8091")
RELAY_3_PORTS=("8094:8090" "8095:8091")
# Chemins de configuration
BITCOIN_CONF="$PROJECT_DIR/conf/bitcoin.conf"
BLINDBIT_CONF="$PROJECT_DIR/conf/blindbit.toml"
RELAY_1_CONF="$PROJECT_DIR/conf/sdk_relay1.conf"
RELAY_2_CONF="$PROJECT_DIR/conf/sdk_relay2.conf"
RELAY_3_CONF="$PROJECT_DIR/conf/sdk_relay3.conf"
EXTERNAL_NODES_CONF="$PROJECT_DIR/scripts/sdk_relay/external_nodes.conf"
# Variables d'environnement communes
COMMON_ENV=(
"RUST_LOG=debug,bitcoincore_rpc=trace"
"HOME=/home/bitcoin"
"BITCOIN_COOKIE_PATH=/home/bitcoin/.bitcoin/signet/.cookie"
"ENABLE_SYNC_TEST=1"
)
# Silence potential linter warnings about unused variables from imported config
: "${RELAY_1_VOLUME}"
: "${RELAY_2_VOLUME}"
: "${RELAY_3_VOLUME}"
: "${RELAY_1_PORTS[@]}"
: "${RELAY_2_PORTS[@]}"
: "${RELAY_3_PORTS[@]}"
: "${RELAY_1_CONF}"
: "${RELAY_2_CONF}"
: "${RELAY_3_CONF}"
# =============================================================================
# FONCTIONS UTILITAIRES
# =============================================================================
print_header() {
echo -e "${BLUE}=============================================================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}=============================================================================${NC}"
}
print_step() {
echo -e "${CYAN}🔄 $1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
print_info() {
echo -e "${PURPLE} $1${NC}"
}
wait_for_container() {
local container_name=$1
local max_attempts=${2:-30}
local attempt=1
print_info "Attente du démarrage de $container_name..."
while [ $attempt -le $max_attempts ]; do
if docker ps --format "table {{.Names}}" | grep -q "^$container_name$"; then
if docker ps --format "table {{.Status}}" --filter "name=$container_name" | grep -q "Up"; then
print_success "$container_name est démarré"
return 0
fi
fi
echo -n "."
sleep 2
((attempt++))
done
print_error "Timeout: $container_name n'a pas démarré dans les temps"
return 1
}
check_file_exists() {
local file_path=$1
local description=$2
if [ ! -f "$file_path" ]; then
print_error "Fichier manquant: $description ($file_path)"
return 1
fi
print_success "Fichier trouvé: $description"
return 0
}
build_port_mapping() {
local ports=("$@")
local mapping=""
for port in "${ports[@]}"; do
if [ -n "$mapping" ]; then
mapping="$mapping -p $port"
else
mapping="-p $port"
fi
done
echo "$mapping"
}
build_env_vars() {
local env_vars=""
for env_var in "${COMMON_ENV[@]}"; do
if [ -n "$env_vars" ]; then
env_vars="$env_vars -e $env_var"
else
env_vars="-e $env_var"
fi
done
echo "$env_vars"
}
# =============================================================================
# FONCTIONS PRINCIPALES
# =============================================================================
stop_all_services() {
print_header "ARRÊT DE TOUS LES SERVICES"
print_step "Arrêt de tous les conteneurs"
local _running_ids
_running_ids=$(docker ps -q 2>/dev/null || true)
if [ -n "${_running_ids}" ]; then
IFS=' ' read -r -a _ids_array <<< "${_running_ids}"
docker stop "${_ids_array[@]}" 2>/dev/null || true
fi
print_step "Arrêt de docker-compose"
docker-compose down -v 2>/dev/null || true
print_step "Vérification qu'aucun conteneur ne tourne"
if docker ps --format "table {{.Names}}" | grep -q .; then
print_warning "Des conteneurs sont encore en cours d'exécution"
docker ps
else
print_success "Aucun conteneur en cours d'exécution"
fi
}
cleanup_containers() {
print_header "NETTOYAGE COMPLET"
print_step "Suppression de tous les conteneurs"
local _to_remove
_to_remove=$(docker ps -aq 2>/dev/null || true)
if [ -n "$_to_remove" ]; then
IFS=' ' read -r -a _to_remove_arr <<< "$_to_remove"
local _removed
_removed=$(docker rm -f "${_to_remove_arr[@]}" 2>/dev/null || true)
if [ -n "$_removed" ]; then
print_info "Conteneurs supprimés: $_removed"
else
print_info "Aucun conteneur à supprimer"
fi
else
print_info "Aucun conteneur à supprimer"
fi
print_step "Nettoyage des réseaux"
local removed_networks
removed_networks=$(docker network prune -f 2>/dev/null || true)
if [ -n "$removed_networks" ]; then
print_info "Réseaux supprimés: $removed_networks"
else
print_info "Aucun réseau à supprimer"
fi
}
create_network() {
print_header "CRÉATION DU RÉSEAU"
print_step "Création du réseau Docker: $NETWORK_NAME"
local network_id
network_id=$(docker network create "$NETWORK_NAME" 2>/dev/null || true)
if [ -n "$network_id" ]; then
print_success "Réseau créé: $network_id"
else
print_info "Réseau déjà existant ou erreur"
fi
}
start_tor() {
print_header "DÉMARRAGE DE TOR PROXY"
print_step "Démarrage de Tor Proxy"
local tor_ports
tor_ports=$(build_port_mapping "${TOR_PORTS[@]}")
local tor_container_id
tor_container_id=$(docker run -d \
--name tor-proxy \
--network "$NETWORK_NAME" \
--network-alias tor \
$tor_ports \
"$TOR_IMAGE")
print_success "Tor Proxy démarré: $tor_container_id"
wait_for_container "tor-proxy" 10
}
start_bitcoin() {
print_header "DÉMARRAGE DE BITCOIN CORE"
# Vérification du fichier de configuration
check_file_exists "$BITCOIN_CONF" "Configuration Bitcoin"
print_step "Démarrage de Bitcoin Core"
local bitcoin_ports
bitcoin_ports=$(build_port_mapping "${BITCOIN_PORTS[@]}")
local bitcoin_container_id
bitcoin_container_id=$(docker run -d \
--name bitcoin-signet \
--network "$NETWORK_NAME" \
--network-alias bitcoin \
$bitcoin_ports \
-v "$BITCOIN_VOLUME:/home/bitcoin/.bitcoin" \
-v "$BITCOIN_CONF:/home/bitcoin/bitcoin.conf" \
"$BITCOIN_IMAGE")
print_success "Bitcoin Core démarré: $bitcoin_container_id"
wait_for_container "bitcoin-signet" 15
}
start_blindbit() {
print_header "DÉMARRAGE DE BLINDBIT ORACLE"
# Vérification du fichier de configuration
check_file_exists "$BLINDBIT_CONF" "Configuration Blindbit"
print_step "Démarrage de Blindbit Oracle"
local blindbit_ports
blindbit_ports=$(build_port_mapping "${BLINDBIT_PORTS[@]}")
local blindbit_container_id
blindbit_container_id=$(docker run -d \
--name blindbit-oracle \
--network "$NETWORK_NAME" \
--network-alias blindbit \
$blindbit_ports \
-v "$BLINDBIT_VOLUME:/data" \
-v "$BLINDBIT_CONF:/data/blindbit.toml" \
-v "$BITCOIN_VOLUME:/home/bitcoin/.bitcoin" \
"$BLINDBIT_IMAGE")
print_success "Blindbit Oracle démarré: $blindbit_container_id"
wait_for_container "blindbit-oracle" 15
}
build_relay_image() {
print_header "CONSTRUCTION DE L'IMAGE SDK_RELAY"
print_step "Construction de l'image sdk_relay"
print_info "Cette étape peut prendre plusieurs minutes..."
if docker build -f sdk_relay/Dockerfile -t "$RELAY_IMAGE" ..; then
print_success "Image sdk_relay construite avec succès"
else
print_error "Échec de la construction de l'image sdk_relay"
exit 1
fi
}
start_relay() {
local relay_number=$1
local relay_name="sdk_relay_$relay_number"
local relay_conf_var="RELAY_${relay_number}_CONF"
local relay_conf="${!relay_conf_var}"
local relay_volume_var="RELAY_${relay_number}_VOLUME"
local relay_volume="${!relay_volume_var}"
local relay_ports_var="RELAY_${relay_number}_PORTS[@]"
local relay_ports=("${!relay_ports_var}")
print_header "DÉMARRAGE DE RELAY $relay_number"
# Vérification du fichier de configuration
check_file_exists "$relay_conf" "Configuration Relay $relay_number"
# Vérification du fichier de configuration externe
check_file_exists "$EXTERNAL_NODES_CONF" "Configuration des nœuds externes"
print_step "Démarrage de $relay_name"
local ports_mapping
ports_mapping=$(build_port_mapping "${relay_ports[@]}")
local env_vars
env_vars=$(build_env_vars)
local relay_container_id
relay_container_id=$(docker run -d \
--name "$relay_name" \
--network "$NETWORK_NAME" \
--network-alias "$relay_name" \
$ports_mapping \
-v "$BITCOIN_VOLUME:/home/bitcoin/.bitcoin" \
-v "$BITCOIN_CONF:/home/bitcoin/bitcoin.conf" \
-v "$relay_volume:/home/bitcoin/.4nk" \
-v "$relay_conf:/home/bitcoin/.conf.docker" \
-v "$PROJECT_DIR/sdk_relay/external_nodes.conf:/home/bitcoin/.4nk/external_nodes.conf" \
$env_vars \
"$RELAY_IMAGE" \
/bin/sh -c "cp /home/bitcoin/.conf.docker /home/bitcoin/.conf && cp /home/bitcoin/.bitcoin/signet/.cookie /home/bitcoin/.4nk/bitcoin.cookie && chmod 600 /home/bitcoin/.4nk/bitcoin.cookie && /usr/local/bin/sdk_relay --config .conf")
print_success "$relay_name démarré: $relay_container_id"
wait_for_container "$relay_name" 20
}
start_all_relays() {
print_header "DÉMARRAGE DE TOUS LES RELAYS"
start_relay 1
start_relay 2
start_relay 3
}
verify_final_status() {
print_header "VÉRIFICATION FINALE"
print_step "État de tous les services"
docker ps
print_step "Résumé des services actifs"
echo -e "${GREEN}Services en cours d'exécution:${NC}"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
print_step "Vérification des ports"
local expected_services=("tor-proxy" "bitcoin-signet" "blindbit-oracle" "sdk_relay_1" "sdk_relay_2" "sdk_relay_3")
local running_services=0
for service in "${expected_services[@]}"; do
if docker ps --format "table {{.Names}}" | grep -q "^$service$"; then
print_success "$service: ✅ En cours d'exécution"
((running_services++))
else
print_error "$service: ❌ Non démarré"
fi
done
print_info "Services actifs: $running_services/${#expected_services[@]}"
if [ $running_services -eq ${#expected_services[@]} ]; then
print_success "Tous les services sont opérationnels !"
else
print_warning "Certains services ne sont pas démarrés"
exit 1
fi
}
show_usage() {
echo -e "${BLUE}Usage: $0 [OPTIONS]${NC}"
echo ""
echo -e "${CYAN}Options:${NC}"
echo -e " ${GREEN}-h, --help${NC} Afficher cette aide"
echo -e " ${GREEN}-s, --stop${NC} Arrêter tous les services"
echo -e " ${GREEN}-c, --clean${NC} Nettoyer les conteneurs"
echo -e " ${GREEN}-n, --network${NC} Créer le réseau"
echo -e " ${GREEN}-t, --tor${NC} Démarrer Tor"
echo -e " ${GREEN}-b, --bitcoin${NC} Démarrer Bitcoin"
echo -e " ${GREEN}-l, --blindbit${NC} Démarrer Blindbit"
echo -e " ${GREEN}-r, --relays${NC} Démarrer les relais"
echo -e " ${GREEN}-v, --verify${NC} Vérifier le statut"
echo ""
echo -e "${CYAN}Exemples:${NC}"
echo -e " ${GREEN}$0${NC} Redémarrage complet"
echo -e " ${GREEN}$0 -s${NC} Arrêter tous les services"
echo -e " ${GREEN}$0 -r${NC} Démarrer uniquement les relais"
echo ""
}
# =============================================================================
# FONCTION PRINCIPALE
# =============================================================================
main() {
print_header "SCRIPT DE REDÉMARRAGE COMPLET $PROJECT_NAME"
print_info "Répertoire de travail: $PROJECT_DIR"
print_info "Date: $(date)"
# Traitement des arguments
if [ $# -eq 0 ]; then
# Redémarrage complet par défaut
stop_all_services
cleanup_containers
create_network
start_tor
start_bitcoin
start_blindbit
build_relay_image
start_all_relays
verify_final_status
else
# Traitement des options
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_usage
exit 0
;;
-s|--stop)
stop_all_services
;;
-c|--clean)
cleanup_containers
;;
-n|--network)
create_network
;;
-t|--tor)
start_tor
;;
-b|--bitcoin)
start_bitcoin
;;
-l|--blindbit)
start_blindbit
;;
-r|--relays)
build_relay_image
start_all_relays
;;
-v|--verify)
verify_final_status
;;
*)
print_error "Option inconnue: $1"
show_usage
exit 1
;;
esac
shift
done
fi
print_header "REDÉMARRAGE TERMINÉ"
print_success "L'infrastructure $PROJECT_NAME est maintenant opérationnelle !"
print_info "Services actifs: $(docker ps --format "table {{.Names}}" | wc -l)"
print_info "Ports exposés: $(docker ps --format "table {{.Ports}}" | grep -o '[0-9]*->[0-9]*' | wc -l)"
}
# =============================================================================
# EXÉCUTION
# =============================================================================
# Vérification de Docker
if ! command -v docker &> /dev/null; then
print_error "Docker n'est pas installé ou n'est pas dans le PATH"
exit 1
fi
# Vérification que Docker daemon est en cours d'exécution
if ! docker info &> /dev/null; then
print_error "Docker daemon n'est pas en cours d'exécution"
exit 1
fi
# Exécution du script principal
main "$@"

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/home/debian/code/4NK_dev/4NK_node"
TOR_CONF="$BASE_DIR/conf/tor.conf"
LINE2=""
if [[ -f "$TOR_CONF" ]]; then
LINE2=$(awk 'NR==2{print $0}' "$TOR_CONF" 2>/dev/null)
fi
if [[ "$LINE2" == "TorEnabled true" ]]; then
echo "No change detected in tor.conf line 2 (TorEnabled true)."
exit 0
else
echo "Change detected in tor.conf line 2: '$LINE2'"
echo "Running orchestration to apply changes..."
bash "$BASE_DIR/scripts/orchestrate_start.sh"
fi