Implementación de AWS EC2#

Guía completa para implementar Construbot en instancias EC2 de Amazon Web Services.

Descripción general#

Esta guía cubre la implementación de Construbot en AWS EC2 utilizando Docker Compose. Esta configuración es adecuada para implementaciones pequeñas y medianas (hasta varios miles de usuarios).

Qué construirás:

  • Instancia EC2 que ejecuta Ubuntu 22.04

  • Docker Compose orquestando todos los servicios

  • Base de datos RDS PostgreSQL (recomendada) o autohospedada

  • ElastiCache Redis (opcional) o autohospedado

  • S3 para almacenamiento de archivos multimedia

  • Ruta 53 para DNS (opcional)

  • Certificado SSL de Let’s Encrypt

Costo estimado: $20-80/mes dependiendo del tamaño de las instancias

Requisitos previos#

Configuración de la cuenta de AWS#

 AWS account with billing enabled
✓ AWS CLI installed and configured
✓ SSH key pair for EC2 access
✓ Domain name (for HTTPS)

Instalar AWS CLI:

# macOS
brew install awscli

# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Configure
aws configure

Requisitos locales#

 SSH client
✓ Git
✓ Basic Linux administration knowledge

Paso 1: iniciar la instancia EC2#

Selección de instancia#

Especificaciones recomendadas:

  • Tipo de instancia: t3.small (2 vCPU, 2 GB de RAM) mínimo, t3.medium (2 vCPU, 4 GB de RAM) recomendado

  • SO: Servidor Ubuntu 22.04 LTS

  • Almacenamiento: 30 GB gp3 SSD mínimo

  • Región: Elija la más cercana a sus usuarios

A través de la consola de AWS:

  1. Navegue al Panel de EC2

  2. Haga clic en «Iniciar instancia»

  3. Elija «Ubuntu Server 22.04 LTS (HVM), tipo de volumen SSD»

  4. Seleccione el tipo de instancia (t3.small o mayor)

  5. Configurar el almacenamiento (30 GB mínimo)

  6. Agregar etiquetas: Nombre=construbot-producción

  7. Configurar el grupo de seguridad (ver más abajo)

  8. Revisión y lanzamiento

A través de AWS CLI:

aws ec2 run-instances \\
  --image-id ami-0557a15b87f6559cf \\ # Ubuntu 22.04 (us-east-1)
  --instance-type t3.small \\
  --key-name your-key-pair \\
  --security-group-ids sg-xxxxx \\
  --subnet-id subnet-xxxxx \\
  --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \\
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=construbot-production}]'

Configuración del grupo de seguridad#

Reglas requeridas:

Type        Protocol    Port Range    Source          Description
SSH         TCP         22            Your IP         SSH access
HTTP        TCP         80            0.0.0.0/0       HTTP traffic
HTTPS       TCP         443           0.0.0.0/0       HTTPS traffic

A través de la consola de AWS:

  1. Panel EC2 → Grupos de seguridad → Crear grupo de seguridad

  2. Agregue reglas de entrada como se indica arriba

  3. Nombre: construbot-sg

A través de AWS CLI:

# Create security group
aws ec2 create-security-group \\
  --group-name construbot-sg \\
  --description "Construbot security group"

# Add rules
aws ec2 authorize-security-group-ingress \\
  --group-name construbot-sg \\
  --protocol tcp --port 22 --cidr your-ip/32

aws ec2 authorize-security-group-ingress \\
  --group-name construbot-sg \\
  --protocol tcp --port 80 --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \\
  --group-name construbot-sg \\
  --protocol tcp --port 443 --cidr 0.0.0.0/0

IP elástica#

Asignar IP estática:

# Allocate Elastic IP
aws ec2 allocate-address

# Associate with instance
aws ec2 associate-address \\
  --instance-id i-xxxxx \\
  --allocation-id eipalloc-xxxxx

Advertencia

Cargos de IP elástica: Se le cobra cuando se asigna la IP pero se detiene la instancia. Libere las IP elásticas no utilizadas para evitar cargos.

Paso 2: conectarse a la instancia#

Conexión SSH#

# Get instance public IP
aws ec2 describe-instances \\
  --instance-ids i-xxxxx \\
  --query 'Reservations[0].Instances[0].PublicIpAddress'

# Connect via SSH
ssh -i ~/.ssh/your-key.pem ubuntu@<public-ip>

Conexión por primera vez:

Verás un mensaje sobre la autenticidad del host. Escriba para continuar.

Paso 3: configuración del servidor#

Actualizaciones del sistema#

# Update package list
sudo apt update

# Upgrade packages
sudo apt upgrade -y

# Install basic tools
sudo apt install -y git curl wget vim

Instalar ventana acoplable#

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

# Add ubuntu user to docker group
sudo usermod -aG docker ubuntu

# Install Docker Compose
sudo apt install -y docker-compose-plugin

# Verify installation
docker --version
docker compose version

# Log out and back in for group changes to take effect
exit

Configurar cortafuegos#

# Enable UFW
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP
sudo ufw allow 443/tcp   # HTTPS
sudo ufw --force enable

# Check status
sudo ufw status

Paso 4: implementar la aplicación#

Repositorio de clones#

# Create application directory
sudo mkdir -p /opt/construbot
sudo chown ubuntu:ubuntu /opt/construbot

# Clone repository
cd /opt/construbot
git clone https://github.com/javier-llamas/construbot.git .

Configurar el entorno#

# Copy environment template
cp .env.example .env

# Edit environment file
nano .env

Producción mínima .env:

# Django
DJANGO_SETTINGS_MODULE=construbot.config.settings.production
DJANGO_DEBUG=False
DJANGO_SECRET_KEY=<generate-with-openssl-rand-base64-50>
DJANGO_ALLOWED_HOSTS=your-domain.com,www.your-domain.com

# Database (self-hosted)
DATABASE_URL=postgresql://construbot:strong-password@postgres:5432/construbot

# Redis
REDIS_URL=redis://redis:6379/0

# Email (example with Mailgun)
DJANGO_EMAIL_BACKEND=anymail.backends.mailgun.EmailBackend
MAILGUN_API_KEY=your-api-key
MAILGUN_SENDER_DOMAIN=mg.your-domain.com
DEFAULT_FROM_EMAIL=noreply@your-domain.com

# Static/Media
USE_S3=True
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_STORAGE_BUCKET_NAME=construbot-media
AWS_S3_REGION_NAME=us-east-1

# Security
DJANGO_SECURE_SSL_REDIRECT=True
DJANGO_SECURE_HSTS_SECONDS=31536000

# Monitoring
SENTRY_DSN=your-sentry-dsn

Construir y comenzar#

# Build production images
docker compose build

# Start services
docker compose up -d

# Check status
docker compose ps

Inicializar base de datos#

# Run migrations
docker compose run --rm django python manage.py migrate

# Create superuser
docker compose run --rm django python manage.py createsuperuser

# Collect static files
docker compose run --rm django python manage.py collectstatic --no-input

Paso 5: configurar el dominio y SSL#

Configuración de DNS#

Usando la Ruta 53:

# Create hosted zone (if not exists)
aws route53 create-hosted-zone --name your-domain.com --caller-reference $(date +%s)

# Get hosted zone ID
aws route53 list-hosted-zones

# Create A record
aws route53 change-resource-record-sets \\
  --hosted-zone-id Z1234567890ABC \\
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "your-domain.com",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [{"Value": "your-elastic-ip"}]
      }
    }]
  }'

Usando otros proveedores de DNS:

Agregue un registro que apunte a su IP elástica:

Type: A
Name: @
Value: <your-elastic-ip>
TTL: 3600

Certificado SSL (Vamos a cifrar)#

# Install certbot
sudo apt install -y certbot python3-certbot-nginx

# Stop nginx in Docker (if running)
docker compose stop nginx

# Obtain certificate
sudo certbot certonly --standalone -d your-domain.com -d www.your-domain.com

# Certificates saved to:
# /etc/letsencrypt/live/your-domain.com/fullchain.pem
# /etc/letsencrypt/live/your-domain.com/privkey.pem

# Set up auto-renewal
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

Actualice docker-compose.yml para montar certificados:

nginx:
  volumes:
    - /etc/letsencrypt:/etc/letsencrypt:ro

Reiniciar nginx:

docker compose up -d nginx

Paso 6: configurar los servicios de AWS#

ElastiCache Redis (opcional)#

aws elasticache create-cache-cluster \\
  --cache-cluster-id construbot-redis \\
  --engine redis \\
  --cache-node-type cache.t3.micro \\
  --num-cache-nodes 1 \\
  --security-group-ids sg-xxxxx

Actualizar .env:

REDIS_URL=redis://construbot-redis.abc123.cache.amazonaws.com:6379/0

S3 para archivos multimedia#

# Create S3 bucket
aws s3 mb s3://construbot-media-your-domain

# Block public access (use signed URLs)
aws s3api put-public-access-block \\
  --bucket construbot-media-your-domain \\
  --public-access-block-configuration \\
    "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

# Create IAM user for S3 access
aws iam create-user --user-name construbot-s3-user

# Attach S3 policy
aws iam put-user-policy \\
  --user-name construbot-s3-user \\
  --policy-name S3Access \\
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": ["s3:*"],
      "Resource": ["arn:aws:s3:::construbot-media-your-domain/*"]
    }]
  }'

# Create access keys
aws iam create-access-key --user-name construbot-s3-user

Actualizar .env:

USE_S3=True
AWS_ACCESS_KEY_ID=<access-key>
AWS_SECRET_ACCESS_KEY=<secret-key>
AWS_STORAGE_BUCKET_NAME=construbot-media-your-domain

Paso 7: automatizar el inicio#

Servicio Systemd#

Cree /etc/systemd/system/construbot.service:

[Unit]
Description=Construbot Docker Compose
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/construbot
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down

[Install]
WantedBy=multi-user.target

Habilitar servicio:

sudo systemctl enable construbot
sudo systemctl start construbot

La aplicación ahora se inicia automáticamente al arrancar.

Paso 8: Monitoreo y Mantenimiento#

Monitoreo de CloudWatch#

Habilitar monitoreo detallado:

aws ec2 monitor-instances --instance-ids i-xxxxx

Crear alarmas de CloudWatch:

# CPU alarm
aws cloudwatch put-metric-alarm \\
  --alarm-name construbot-high-cpu \\
  --alarm-description "Alert when CPU > 80%" \\
  --metric-name CPUUtilization \\
  --namespace AWS/EC2 \\
  --statistic Average \\
  --period 300 \\
  --evaluation-periods 2 \\
  --threshold 80 \\
  --comparison-operator GreaterThanThreshold \\
  --dimensions Name=InstanceId,Value=i-xxxxx

Copias de seguridad automatizadas#

Crear script de respaldo /opt/construbot/scripts/backup.sh:

#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BUCKET="s3://construbot-backups"

# Database backup (if using self-hosted)
docker compose exec -T postgres pg_dump -U construbot construbot | \\
  gzip > /tmp/db_backup_$DATE.sql.gz

# Upload to S3
aws s3 cp /tmp/db_backup_$DATE.sql.gz $BUCKET/database/

# Cleanup
rm /tmp/db_backup_$DATE.sql.gz

Programar con cron:

# crontab -e
0 2 * * * /opt/construbot/scripts/backup.sh

Gestión de registros#

Enviar registros a CloudWatch:

# Install CloudWatch agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i amazon-cloudwatch-agent.deb

# Configure agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard

Paso 9: Escalar#

Escalado vertical#

# Stop instance
aws ec2 stop-instances --instance-ids i-xxxxx

# Wait for stopped state
aws ec2 wait instance-stopped --instance-ids i-xxxxx

# Change instance type
aws ec2 modify-instance-attribute \\
  --instance-id i-xxxxx \\
  --instance-type "{\"Value\": \"t3.medium\"}"

# Start instance
aws ec2 start-instances --instance-ids i-xxxxx

Escala horizontal#

Para implementación de múltiples instancias:

  1. Utilice el equilibrador de carga de aplicaciones (ALB)

  2. Crear grupo de Auto Scaling

  3. Utilice RDS para la base de datos (obligatorio)

  4. Utilice ElastiCache para Redis (obligatorio)

  5. Utilice S3 para archivos multimedia (obligatorio)

Esto va más allá del alcance de un solo servidor: considere usar ECS o EKS para la orquestación de contenedores.

Solución de problemas#

Instancia no accesible#

# Check instance status
aws ec2 describe-instance-status --instance-ids i-xxxxx

# Check security group
aws ec2 describe-security-groups --group-ids sg-xxxxx

# Verify Elastic IP association
aws ec2 describe-addresses

La aplicación no se inicia#

# SSH into instance
ssh -i ~/.ssh/your-key.pem ubuntu@<elastic-ip>

# Check Docker logs
cd /opt/construbot
docker compose logs

# Check service status
docker compose ps

Sin espacio en disco#

# Check disk usage
df -h

# Clean Docker
docker system prune -a -f

# Resize volume (AWS Console or CLI)
aws ec2 modify-volume --volume-id vol-xxxxx --size 50

Optimización de costos#

Reducir costos#

  1. Utilice instancias reservadas: ahorre hasta un 75 % con un compromiso de 1 a 3 años

  2. Instancias del tamaño adecuado: supervise y ajuste según el uso real

  3. Utilice instancias puntuales: ahorre hasta un 90 % (para cargas de trabajo no críticas)

  4. Habilitar niveles inteligentes de S3: optimización automática de costos

  5. Configurar alertas de presupuesto - Supervisar el gasto

Costos mensuales estimados (us-east-1):

t3.small EC2 instance:      $15-20
30 GB gp3 storage:          $3
RDS db.t3.micro:            $15
50 GB S3 storage:           $1
Data transfer (100 GB):     $9
--------------------------------
Total:                      $43-48/month

Ver también#