Saltar al contenido principal

EC2 Infrastructure

Las instancias AWS EC2 (Elastic Compute Cloud) son los servidores donde corren todos los microservicios de SwapBits en producción. Este documento explica la arquitectura, configuración y mejores prácticas.


Arquitectura EC2

Arquitectura EC2 de SwapBits
Click para ampliar (zoom y pan interactivo)

1. Tipos de Instancias

Production Environment

Configuración Real de Producción

SwapBits usa 1 instancia EC2 t3.large para todos los servicios principales y monitores.

const ProductionInstance = {
// Servidor Principal (1 instancia)
mainServer: {
type: 't3.large',
vcpu: 2,
memory: '8 GB',
network: 'Up to 5 Gbps',
storage: '100 GB gp3 SSD',

// Microservicios principales
services: [
'auth-service',
'user-service',
'wallet-service',
'bank-service',
'exchange-service',
'kyc-service',
'ws-service',
'webhook-service'
],

// Blockchain Monitors (en la misma instancia)
monitors: [
'solana-monitor',
'ethereum-monitor',
'bsc-monitor',
'tron-monitor',
'bitcoin-monitor'
],

location: 'AWS EC2 (eu-north-1)'
}
};

Admin Panel Local

El Admin Panel NO corre en EC2. Está desplegado localmente en 5 Raspberry Pi en red local.

  • Admin Backend: NestJS
  • Admin Frontend: React + Nginx
  • Deployment: Local network
  • Access: VPN o red privada

2. Setup Inicial de EC2

Launch Instance

# 1. Crear Security Group
aws ec2 create-security-group \
--group-name swapbits-app-sg \
--description "Security group for SwapBits application servers" \
--vpc-id vpc-XXXXXX

# 2. Agregar reglas
# HTTPS desde ALB
aws ec2 authorize-security-group-ingress \
--group-id sg-XXXXXX \
--protocol tcp \
--port 443 \
--source-group sg-ALB-XXXXXX

# HTTP desde ALB
aws ec2 authorize-security-group-ingress \
--group-id sg-XXXXXX \
--protocol tcp \
--port 80 \
--source-group sg-ALB-XXXXXX

# SSH desde IP específica (admin)
aws ec2 authorize-security-group-ingress \
--group-id sg-XXXXXX \
--protocol tcp \
--port 22 \
--cidr YOUR_IP/32

# 3. Launch instance
aws ec2 run-instances \
--image-id ami-XXXXXX \
--instance-type t3.large \
--key-name swapbits-prod-key \
--security-group-ids sg-XXXXXX \
--subnet-id subnet-XXXXXX \
--iam-instance-profile Name=SwapBitsEC2Role \
--user-data file://user-data.sh \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=swapbits-prod-1},{Key=Environment,Value=production}]'

User Data Script (Initial Setup)

#!/bin/bash
# user-data.sh - Ejecutado al crear la instancia

set -e

# Update system
apt-get update
apt-get upgrade -y

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# Install Docker Compose
curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# Install AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install
rm -rf aws awscliv2.zip

# Install monitoring tools
apt-get install -y htop iotop nethogs

# Configure Docker logging
cat > /etc/docker/daemon.json <<EOF
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF

systemctl restart docker

# Create app directory
mkdir -p /opt/swapbits
cd /opt/swapbits

# Pull code from GitHub (usando deploy key)
git clone git@github.com:DenisGomezCrack/swapbits-aws.git .

# Create .env from Secrets Manager
aws secretsmanager get-secret-value \
--secret-id production/swapbits/env-vars \
--query SecretString \
--output text > .env

# Start services
docker-compose up -d

echo "[SUCCESS] SwapBits EC2 instance ready!"

3. Configuración de Red (VPC)

VPC Architecture

const VPCConfig = {
vpc: {
cidr: '10.0.0.0/16',
enableDnsHostnames: true,
enableDnsSupport: true,
},

subnets: {
// Public subnets (para ALB, NAT Gateway)
publicA: {
cidr: '10.0.1.0/24',
availabilityZone: 'us-east-1a',
mapPublicIp: true,
},
publicB: {
cidr: '10.0.2.0/24',
availabilityZone: 'us-east-1b',
mapPublicIp: true,
},

// Private subnets (para EC2 instances)
privateA: {
cidr: '10.0.10.0/24',
availabilityZone: 'us-east-1a',
mapPublicIp: false,
},
privateB: {
cidr: '10.0.11.0/24',
availabilityZone: 'us-east-1b',
mapPublicIp: false,
},
},

routing: {
publicRoute: {
destination: '0.0.0.0/0',
target: 'Internet Gateway',
},
privateRoute: {
destination: '0.0.0.0/0',
target: 'NAT Gateway',
},
},
};

Security Groups

const SecurityGroups = {
// ALB Security Group
albSG: {
inbound: [
{ port: 443, source: '0.0.0.0/0', protocol: 'tcp' }, // HTTPS from Internet
{ port: 80, source: '0.0.0.0/0', protocol: 'tcp' }, // HTTP from Internet (redirect to HTTPS)
],
outbound: [
{ port: 'all', destination: '10.0.0.0/16' }, // To VPC
],
},

// EC2 Application Servers
appSG: {
inbound: [
{ port: 3000, source: 'albSG', protocol: 'tcp' }, // From ALB
{ port: 22, source: 'adminIP', protocol: 'tcp' }, // SSH from admin
],
outbound: [
{ port: 443, destination: '0.0.0.0/0', protocol: 'tcp' }, // HTTPS to Internet
{ port: 27017, destination: 'mongoSG', protocol: 'tcp' }, // MongoDB
{ port: 6379, destination: 'redisSG', protocol: 'tcp' }, // Redis
],
},

// MongoDB/DocumentDB
mongoSG: {
inbound: [
{ port: 27017, source: 'appSG', protocol: 'tcp' },
],
},

// Redis/ElastiCache
redisSG: {
inbound: [
{ port: 6379, source: 'appSG', protocol: 'tcp' },
],
},
};

4. IAM Role para EC2

Instance Profile

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": [
"arn:aws:secretsmanager:us-east-1:ACCOUNT_ID:secret:production/swapbits/*"
]
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": "arn:aws:kms:us-east-1:ACCOUNT_ID:key/*"
},
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws:lambda:us-east-1:ACCOUNT_ID:function:CreateWallet*",
"arn:aws:lambda:us-east-1:ACCOUNT_ID:function:SendHotWallet*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::swapbits-backups/*",
"arn:aws:s3:::swapbits-uploads/*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:ACCOUNT_ID:log-group:/aws/ec2/swapbits/*"
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricData"
],
"Resource": "*"
}
]
}

5. Deployment en EC2

Estructura de Directorios Real

📁 Estructura de Directorios Real

~/swapbits/ — organización del proyecto
~/swapbits/
├── docs/ # Documentación Docusaurus
│ ├── build/ # Build de producción
│ ├── docs/
│ ├── src/
│ ├── package.json
│ └── docusaurus.config.ts

├── services/ # Microservicios
│ ├── auth-service/
│ │ ├── docker-compose.yml
│ │ ├── Dockerfile
│ │ └── src/
│ ├── user-service/
│ ├── wallet-service/
│ ├── bank-service/
│ ├── exchange-service/
│ ├── kyc-service/
│ ├── ws-service/
│ └── webhook-service/

├── monitors/ # Blockchain monitors
│ ├── bsc/
│ │ ├── docker-compose.yml
│ │ └── src/
│ ├── solana/
│ ├── ethereum/
│ ├── tron/
│ └── bitcoin/

└── swapbits-packages/ # Paquetes compartidos
├── analytics/
├── chat/
├── redis/
├── schemas/
└── ...

Ubicaciones Importantes

  • Código fuente: ~/swapbits/
  • Documentación web: /var/www/docs.swapbits.site/
  • Nginx config: /etc/nginx/sites-enabled/swapbits

Proceso de Deployment Manual

No hay Script Automatizado

El deployment se hace manualmente servicio por servicio, no hay script deploy.sh.

1. Actualizar Código

# SSH a la instancia EC2
ssh user@ec2-instance

# Ir al directorio del proyecto
cd ~/swapbits

# Pull cambios desde Git
git pull origin main

2. Deployar Microservicios

Cada servicio se deploya individualmente con Docker Compose:

#### 2. Deployar Microservicios

Cada servicio se deploya individualmente con Docker Compose:

```bash
# Auth Service
cd ~/swapbits
docker compose -f ./services/auth-service/docker-compose.yml up -d --build --no-deps --remove-orphans auth-service

# User Service
docker compose -f ./services/user-service/docker-compose.yml up -d --build --no-deps --remove-orphans user-service

# Wallet Service
docker compose -f ./services/wallet-service/docker-compose.yml up -d --build --no-deps --remove-orphans wallet-service
docker logs -f wallet-service

# Bank Service
sudo docker compose -f ./services/bank-service/docker-compose.yml build bank-service
sudo docker compose -f ./services/bank-service/docker-compose.yml up -d --remove-orphans

# Exchange Service
docker compose -f ./services/exchange-service/docker-compose.yml up -d --build --no-deps --remove-orphans exchange-service
docker logs -f exchange-service

# KYC Service
docker compose -f ./services/kyc-service/docker-compose.yml up -d --build --no-deps --remove-orphans kyc-service
docker logs -f kyc-service

# WebSocket Service
docker compose -f ./services/ws-service/docker-compose.yml up -d --build --no-deps --remove-orphans ws-service
docker logs -f ws-service

# Webhook Service
docker compose -f ./services/webhook-service/docker-compose.yml up -d --build --no-deps --remove-orphans webhook-service

3. Deployar Monitors

Los monitors se deplayan de forma similar pero con un proceso ligeramente diferente:

cd ~/swapbits/monitors/bsc

# Bajar el servicio actual
docker-compose down

# Rebuild sin cache
docker-compose build --no-cache

# Levantar en background
docker-compose up -d

# Ver logs en tiempo real
docker logs -f bsc-miniwallet-monitor

Patrón de Deployment

Proceso común:

  1. cd ~/swapbits (volver al root del proyecto)
  2. git pull (actualizar código)
  3. Ir 2 carpetas arriba del servicio modificado
  4. Ejecutar comando docker compose específico
  5. Ver logs con docker logs -f <service-name>

4. Deployar Documentación (Docusaurus)

# Build de la documentación
cd ~/swapbits/docs
npm run build

# Mover build a directorio de Nginx
sudo mv ./build/* /var/www/docs.swapbits.site/

# Verificar y recargar Nginx
sudo nano /etc/nginx/sites-enabled/swapbits
sudo nginx -t && sudo systemctl reload nginx

6. Monitoreo y Logs

Ver Logs de Servicios

# Ver logs en tiempo real
docker logs -f auth-service
docker logs -f wallet-service
docker logs -f ws-service

# Ver últimas 100 líneas
docker logs --tail 100 bank-service

# Ver logs de monitor BSC
docker logs -f bsc-miniwallet-monitor

Verificar Estado de Contenedores

# Listar todos los contenedores corriendo
docker ps

# Ver recursos usados
docker stats

# Inspeccionar un servicio específico
docker inspect ws-service

Reiniciar Servicios

# Reiniciar un servicio específico
docker restart auth-service

# Reiniciar todos los servicios
docker restart $(docker ps -q)

7. Security Best Practices

Seguridad en EC2

  • [✓] IAM Roles: EC2 usa IAM roles, NO access keys hardcodeadas
  • [✓] Secrets Manager: Todos los secrets se cargan desde AWS Secrets Manager
  • [✓] Security Groups: Solo puertos necesarios abiertos
  • [✓] Private Subnets: Servicios en subnet privada (no IP pública directa)
  • [✓] SSH Keys: Acceso SSH solo con key pair, sin passwords
  • [✓] Updates: Mantener sistema operativo y Docker actualizados

Firewall (Security Groups)

# Puertos abiertos típicos:
22 - SSH (solo desde IPs específicas)
80 - HTTP (redirect a HTTPS)
443 - HTTPS (público)
3000 - Servicios internos (solo dentro de VPC)
6379 - Redis (solo dentro de VPC)
27017 - MongoDB (solo dentro de VPC)

8. Troubleshooting

Servicio no Arranca

# Ver logs del servicio
docker logs auth-service

# Ver si el contenedor está corriendo
docker ps -a | grep auth-service

# Ver uso de recursos
docker stats auth-service

# Inspeccionar configuración
docker inspect auth-service

Problemas de Memoria

# Ver uso de memoria del sistema
free -h

# Ver procesos que más consumen
top

# Limpiar containers parados
docker container prune

# Limpiar imágenes sin usar
docker image prune

Problemas de Disco

# Ver espacio en disco
df -h

# Ver logs grandes
du -sh /var/lib/docker/containers/*

# Limpiar logs de Docker
truncate -s 0 /var/lib/docker/containers/*/*-json.log

Resumen

EC2 Infrastructure - SwapBits

Configuración Actual:

  • 1 instancia EC2 t3.large en eu-north-1
  • Docker Compose para orquestación de servicios
  • IAM Roles para acceso a AWS services
  • 8 microservicios + 5 monitors en la misma instancia
  • Documentación servida desde Nginx
  • Admin Panel desplegado localmente en 5 Raspberry Pi

Deployment:

  • Manual servicio por servicio
  • git pulldocker compose up -d --build
  • Logs con docker logs -f <service>
  • Docs: build → /var/www/docs.swapbits.site/

NO se usa:

  • Auto Scaling Groups
  • Load Balancers (ALB/NLB)
  • Scripts automatizados de deployment
  • AMI backups automáticos
  • Health check scripts

Última actualización: Octubre 2025