Saltar a contenido

Descripción general de la arquitectura

KanjiIQ sigue una arquitectura de pod multi-contenedor desplegada en Kubernetes. El frontend y el backend se ejecutan como contenedores separados dentro del mismo pod, comunicándose a través de localhost.

Diagrama del sistema

graph TB
    subgraph Internet
        U[User Browser]
    end

    subgraph Hetzner["Hetzner k3s Cluster"]
        subgraph NS["Namespace: jlpt-kanji"]
            T[Traefik Ingress Controller]

            subgraph Pod["Application Pod (x2 replicas)"]
                FE[Flutter Web<br/>Nginx :80]
                BE[Dart Frog API<br/>:8080]
            end

            PG[(PostgreSQL 15<br/>PVC)]

            subgraph Middleware["Traefik Middlewares"]
                RL[Rate Limiting]
                SH[Security Headers]
            end
        end

        CM[cert-manager<br/>Let's Encrypt]
    end

    U -->|HTTPS| T
    T --> Middleware
    Middleware -->|kanjiiq.com| FE
    Middleware -->|api.kanjiiq.com| BE
    FE -->|/api/ proxy| BE
    BE --> PG
    CM -->|TLS Certificates| T

Arquitectura de dominios

Dominio Servicio Propósito
kanjiiq.com Frontend (Nginx) Aplicación Flutter Web
www.kanjiiq.com Frontend (Nginx) Redirección al dominio principal
api.kanjiiq.com Backend (Dart Frog) REST API
admin.kanjiiq.com Backend (Dart Frog) API del panel de administración
docs.kanjiiq.app Docs (Nginx) Este sitio de documentación

Diseño de pod multi-contenedor

La aplicación se ejecuta como un único Deployment de Kubernetes con 2 réplicas, cada una conteniendo dos contenedores:

# Simplified view of k8s/05-deployment.yaml
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: backend    # Dart Frog API on :8080
        - name: frontend   # Nginx serving Flutter Web on :80

¿Por qué un pod multi-contenedor?

  • El Nginx del frontend redirige las solicitudes /api/ a localhost:8080 (el backend), evitando problemas de cross-origin
  • Ambos contenedores escalan juntos — cada réplica es una unidad completa y autocontenida
  • Red simplificada: la comunicación frontend-backend permanece dentro del pod

Resumen de componentes

Frontend

  • Framework: Flutter Web con Material Design 3
  • Servidor: Nginx Alpine (non-root, UID 1000)
  • Gestión de estado: Provider
  • Enrutamiento: GoRouter
  • Soporte offline: Caché SQLite local con sincronización en segundo plano

Backend

  • Framework: Dart Frog 1.1.0
  • Autenticación: JWT (para endpoints de administración)
  • Seguridad: Pila de middleware multicapa (bloqueo de IP, detección de rutas, limitación de velocidad)
  • Traducción: OpenAI API para traducción dinámica de contenido

Base de datos

  • Motor: PostgreSQL 15
  • Almacenamiento: Kubernetes PersistentVolumeClaim (10Gi)
  • Esquema: Columnas JSONB para almacenamiento de contenido multilingüe
  • Claves primarias: UUID

Infraestructura

  • Clúster: k3s en servidor dedicado Hetzner
  • Ingress: Traefik con HTTPS automático
  • TLS: cert-manager con Let's Encrypt
  • CI/CD: Forgejo Actions (autoalojado)
  • Registro: Forgejo Container Registry

Capas de seguridad

KanjiIQ implementa defensa en profundidad con múltiples capas de seguridad:

graph LR
    R[Request] --> L1[Traefik<br/>Rate Limiting]
    L1 --> L2[Traefik<br/>Security Headers]
    L2 --> L3[App: IP<br/>Blocklist Check]
    L3 --> L4[App: Malicious<br/>Path Detection]
    L4 --> L5[App: SQL Injection<br/>Detection]
    L5 --> L6[App: Regional<br/>Analytics]
    L6 --> H[Request Handler]
  1. Nivel de infraestructura (Traefik): Limitación de velocidad (100 req/min público, 50 req/min admin) y cabeceras de seguridad (HSTS, X-Frame-Options, CSP)
  2. Nivel de aplicación (middleware Dart Frog): Lista de bloqueo de IP, detección de rutas maliciosas (.env, .php, archivos de configuración), patrones de inyección SQL, prevención de path traversal
  3. Nivel de analítica: Seguimiento regional de solicitudes con bloqueo automático después de 3 solicitudes sospechosas en 24 horas

Consulta Arquitectura del backend para más detalles sobre la pila de middleware.