1. Introducción
El objetivo de este laboratorio es disponer de un entorno local donde practicar conceptos y servicios de las principales plataformas cloud sin depender directamente de infraestructura real ni generar costes durante las pruebas.
El laboratorio utiliza:
- Proxmox VE como plataforma de virtualización.
- Ubuntu Server como sistema operativo de la máquina virtual.
- Docker Engine y Docker Compose para ejecutar servicios.
- Floci AWS para emular servicios de Amazon Web Services.
- Floci Azure para emular servicios de Microsoft Azure.
- Floci GCP para emular servicios de Google Cloud Platform.
- Floci UI como interfaz web multicloud.
- AWS CLI para interactuar con el entorno AWS emulado.
Arquitectura final:
Proxmox VE
└── VM cloud-lab
├── Ubuntu Server
├── Docker Engine
├── Docker Compose
├── Floci AWS
│ ├── Interno TCP 4566
│ └── Publicado TCP 14566
├── Floci Azure
│ ├── Interno TCP 4577
│ ├── Interno TCP 5672
│ ├── Interno TCP 5673
│ ├── Interno TCP 9093
│ ├── Publicado TCP 14577
│ ├── Publicado TCP 15672
│ ├── Publicado TCP 15673
│ └── Publicado TCP 19093
├── Floci GCP
│ ├── Interno TCP 4588
│ └── Publicado TCP 14588
├── Floci API
│ ├── Interno TCP 4501
│ └── Publicado TCP 14501
└── Floci UI
├── Interno TCP 4500
└── Publicado TCP 14500
Todos los componentes quedan accesibles desde otros dispositivos de la red local usando la IP reservada de la VM y los puertos publicados que defina cada instalación.
Antes de empezar: valores que debes cambiar
Por seguridad, los datos propios del entorno se han dejado anonimizados. Antes de ejecutar los comandos hay que sustituir estos valores por los reales de la instalación.
| Valor en el manual | Qué debes poner |
|---|---|
<VMID> | ID libre de la VM en Proxmox, obtenido con pvesh get /cluster/nextid |
<usuario> | Usuario local creado durante la instalación de Ubuntu Server |
<IP_VM> | IP reservada para la VM en la LAN |
local-lvm | Storage de Proxmox donde se creará el disco de la VM |
local:iso/ubuntu-server-amd64.iso | Ruta exacta de la ISO subida a Proxmox |
vmbr0 | Bridge de red que usará la VM |
enp6s18 | Nombre de la interfaz de red dentro de Ubuntu, si en tu caso aparece diferente |
2. Recursos de la máquina virtual
Recursos utilizados en el laboratorio:
| Recurso | Configuración |
|---|---|
| CPU | 4 vCPU |
| RAM | 10 GB |
| Disco | 100 GB |
| Sistema | Ubuntu Server LTS |
| BIOS | OVMF / UEFI |
| Máquina | q35 |
| Controlador | VirtIO SCSI |
| Red | VirtIO |
| QEMU Guest Agent | Sí |
Para un laboratorio básico se podría usar menos memoria, pero 10 GB dan margen para varios runtimes, contenedores auxiliares, bases de datos, Functions/Lambda y una fase posterior con Kubernetes.
3. Comprobaciones previas en Proxmox
Comprobar almacenamientos:
pvesm status
Verificar que la ISO de Ubuntu esté disponible:
pvesm list local --content iso | grep ubuntu
Ejemplo anonimizado:
local:iso/ubuntu-server-amd64.iso
Comprobar el bridge de red:
ip link show vmbr0
Debe aparecer en estado:
UP
Obtener un VM ID disponible:
pvesh get /cluster/nextid
En el resto del manual se usa <VMID> como identificador genérico.
4. Crear la VM desde la consola de Proxmox
La VM se puede crear completamente por CLI:
qm create <VMID> \
--name cloud-lab \
--description "Laboratorio multicloud - Floci AWS Azure GCP" \
--ostype l26 \
--machine q35 \
--bios ovmf \
--cpu host \
--sockets 1 \
--cores 4 \
--memory 10240 \
--balloon 0 \
--scsihw virtio-scsi-single \
--scsi0 local-lvm:100,discard=on,iothread=1,ssd=1 \
--efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=1 \
--ide2 local:iso/ubuntu-server-amd64.iso,media=cdrom \
--net0 virtio,bridge=vmbr0,firewall=1 \
--agent enabled=1 \
--onboot 1 \
--boot 'order=ide2;scsi0'
Comprobar la configuración:
qm config <VMID>
Arrancar la VM:
qm start <VMID>
Comprobar el estado:
qm status <VMID>
Resultado esperado:
status: running
5. Instalación de Ubuntu Server
Durante el instalador se usa Ubuntu Server.
Configuración recomendada:
- Hostname:
cloud-lab - Usuario:
<usuario> - Disco: utilizar todo el disco
- Red: DHCP inicialmente
- OpenSSH Server: instalar
No es necesaria ninguna interfaz gráfica.
Cuando termine la instalación, apagar la VM y retirar la ISO desde Proxmox:
qm set <VMID> --delete ide2
qm set <VMID> --boot order=scsi0
Después se puede arrancar normalmente:
qm start <VMID>
6. Conexión mediante SSH
Consultar la IP asignada por DHCP dentro de la VM:
ip addr
La interfaz VirtIO puede aparecer como enp6s18 u otro nombre similar.
Desde otro equipo:
ssh <usuario>@<IP_VM>
<IP_VM> debe sustituirse por la IP reservada de la máquina virtual en la red local.
7. Actualizar Ubuntu
Actualizar repositorios:
sudo apt update
Actualizar paquetes:
sudo apt upgrade -y
8. Instalar QEMU Guest Agent
Instalar:
sudo apt install qemu-guest-agent -y
Comprobar:
systemctl status qemu-guest-agent --no-pager
Resultado esperado:
Active: active (running)
Esto mejora la integración entre Proxmox y la máquina virtual.
9. Configuración de red
Inicialmente Ubuntu utiliza DHCP.
Ejemplo de Netplan:
network:
version: 2
ethernets:
enp6s18:
dhcp4: true
En lugar de configurar una IP estática dentro de Ubuntu, se recomienda usar una reserva DHCP en el router:
MAC de la VM
└── Reserva DHCP
└── IP estable para la VM
Ventajas:
- Ubuntu sigue recibiendo gateway y DNS automáticamente.
- Se evita mantener configuración manual de red dentro de la VM.
- La dirección de la VM permanece estable.
Antes de modificar Netplan conviene crear una copia:
sudo cp /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak
En este laboratorio se mantiene:
dhcp4: true
10. Verificar hostname
Comprobar:
hostnamectl
El hostname utilizado es:
cloud-lab
Si hace falta modificarlo:
sudo hostnamectl set-hostname cloud-lab
También debe comprobarse:
cat /etc/hosts
La entrada correspondiente debe ser similar a:
127.0.1.1 cloud-lab
Si fuera necesario corregirla:
sudo sed -i 's/hostname-antiguo/cloud-lab/' /etc/hosts
11. Reinicio y validación
Reiniciar:
sudo reboot
Volver a acceder por SSH y comprobar:
hostnamectl
systemctl is-active qemu-guest-agent
Resultado esperado:
active
12. Instalación de Docker Engine
Se utiliza el repositorio oficial de Docker.
Instalar dependencias:
sudo apt update
sudo apt install ca-certificates curl -y
Crear el directorio de claves:
sudo install -m 0755 -d /etc/apt/keyrings
Descargar la clave:
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
Dar permisos de lectura:
sudo chmod a+r /etc/apt/keyrings/docker.asc
Crear el repositorio:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Actualizar:
sudo apt update
Instalar Docker:
sudo apt install \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin \
-y
13. Comprobar Docker
Estado:
systemctl is-active docker
Resultado esperado:
active
Versión de Docker:
docker --version
Docker Compose:
docker compose version
14. Ejecutar Docker sin sudo
Añadir el usuario al grupo Docker:
sudo usermod -aG docker $USER
Actualizar la sesión:
newgrp docker
Comprobar:
groups
Debe aparecer el grupo:
docker
El grupo docker proporciona privilegios elevados sobre el sistema. Solo deben pertenecer a él usuarios de confianza.
15. Prueba de Docker
Ejecutar:
docker run --rm hello-world
Resultado esperado:
Hello from Docker!
This message shows that your installation appears to be working correctly.
16. Crear estructura del laboratorio
Crear directorios:
mkdir -p ~/floci/aws
mkdir -p ~/floci/azure
mkdir -p ~/floci/gcp
Crear una red Docker compartida:
docker network create floci_shared
Comprobar:
docker network ls | grep floci_shared
Esta red permitirá conectar:
Floci UI
└── Floci API
└── floci_shared
├── AWS
├── Azure
└── GCP
17. Floci AWS
Entrar en el directorio:
cd ~/floci/aws
Crear compose.yaml:
services:
floci:
image: floci/floci:latest
container_name: floci-aws
restart: unless-stopped
ports:
- "14566:4566"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
environment:
FLOCI_STORAGE_MODE: hybrid
FLOCI_STORAGE_PERSISTENT_PATH: /app/data
networks:
- default
- floci_shared
networks:
floci_shared:
external: true
Validar:
docker compose config
Arrancar:
docker compose up -d
Comprobar:
docker ps --filter name=floci-aws
Debe aparecer en estado:
healthy
18. Comprobar Floci AWS
Endpoint de salud:
curl http://localhost:14566/_floci/health
La respuesta debe contener servicios en estado running.
Servicios habituales disponibles:
- S3
- EC2
- Lambda
- IAM
- DynamoDB
- SQS
- SNS
- RDS
- ECS
- EKS
- CloudFormation
- Route53
- CloudFront
- API Gateway
- Secrets Manager
- KMS
19. Instalar AWS CLI
Instalar unzip:
sudo apt install unzip -y
Descargar:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \
-o awscliv2.zip
Descomprimir:
unzip awscliv2.zip
Instalar:
sudo ./aws/install
Comprobar:
aws --version
20. Perfil AWS exclusivo para Floci
Es importante no utilizar credenciales reales de AWS.
Crear un perfil exclusivo:
aws configure --profile floci
Usar valores de prueba:
AWS Access Key ID: test
AWS Secret Access Key: test
Default region: us-east-1
Output: json
Comprobar:
aws configure list --profile floci
21. Primera prueba AWS
Listar buckets:
aws \
--endpoint-url=http://localhost:14566 \
s3api list-buckets \
--profile floci
Inicialmente debe devolver:
{
"Buckets": []
}
Crear un bucket:
aws \
--endpoint-url=http://localhost:14566 \
s3 mb s3://laboratorio-floci-demo \
--profile floci
Resultado esperado:
make_bucket: laboratorio-floci-demo
Esto confirma que AWS CLI está interactuando con Floci.
22. Floci Azure
Entrar:
cd ~/floci/azure
Crear compose.yaml:
services:
floci-az:
image: floci/floci-az:latest
container_name: floci-azure
restart: unless-stopped
ports:
- "14577:4577"
- "15672:5672"
- "15673:5673"
- "19093:9093"
volumes:
- ./data:/app/data
- /var/run/docker.sock:/var/run/docker.sock
networks:
- default
- floci_shared
networks:
floci_shared:
external: true
Validar:
docker compose config
Arrancar:
docker compose up -d
Comprobar:
docker ps --filter name=floci-azure
Debe aparecer en estado:
healthy
23. Validar Azure
Ejecutar:
curl http://localhost:14577/health
Respuesta esperada:
{
"edition": "floci-az-always-free",
"status": "UP"
}
24. Floci GCP
Entrar:
cd ~/floci/gcp
Crear compose.yaml:
services:
floci-gcp:
image: floci/floci-gcp:latest
container_name: floci-gcp
restart: unless-stopped
ports:
- "14588:4588"
volumes:
- ./data:/app/data
- /var/run/docker.sock:/var/run/docker.sock
networks:
- default
- floci_shared
networks:
floci_shared:
external: true
Validar:
docker compose config
Arrancar:
docker compose up -d
25. Validar GCP
Comprobar el contenedor:
docker ps --filter name=floci-gcp
Debe mostrar:
healthy
Consultar salud:
curl http://localhost:14588/health
Servicios habituales disponibles:
- BigQuery
- Pub/Sub
- GKE
- IAM
- Firestore
- Cloud Functions
- Cloud SQL
- Cloud Storage
- Cloud Run
- Secret Manager
- KMS
- Cloud Tasks
- Firebase Auth
26. Comprobar los tres runtimes
Ejecutar:
docker ps
Debe aparecer aproximadamente:
floci-aws healthy
floci-azure healthy
floci-gcp healthy
Puertos publicados hacia la LAN:
| Proveedor | Puerto interno | Puerto publicado |
|---|---|---|
| AWS | 4566 | 14566 |
| Azure API | 4577 | 14577 |
| Azure AMQP | 5672 | 15672 |
| Azure AMQP TLS | 5673 | 15673 |
| Azure Event Hub/Kafka | 9093 | 19093 |
| GCP | 4588 | 14588 |
27. Acceso desde otros equipos de la LAN
Docker publica los puertos sobre 0.0.0.0, por lo que los runtimes pueden consultarse desde otros dispositivos de la misma red.
Ejemplos desde otro equipo de la LAN:
http://<IP_VM>:14566
http://<IP_VM>:14577
http://<IP_VM>:14588
Desde Windows:
curl.exe http://<IP_VM>:14566/_floci/health
Una respuesta HTTP 200 confirma el acceso desde la LAN.
No se recomienda publicar estos puertos directamente a Internet.
28. Instalar Floci UI
Clonar la interfaz oficial:
cd ~/floci
git clone https://github.com/floci-io/floci-ui.git ui
Entrar:
cd ui
Comprobar:
git status
29. Por qué no usar directamente el Compose oficial
El docker-compose.yml oficial puede levantar también runtimes propios para AWS, Azure y GCP.
En este laboratorio esos runtimes ya existen y sus puertos publicados están personalizados, así que se crea un Compose específico solo para:
- Floci UI
- Floci API
Ambos se conectan a los runtimes existentes mediante la red floci_shared.
30. Compose personalizado para Floci UI
Crear compose.external.yaml:
services:
floci-ui:
build:
context: ./packages/frontend
dockerfile: Dockerfile.dev
container_name: floci-ui
volumes:
- ./packages/frontend/src:/app/src
- ./packages/frontend/index.html:/app/index.html
- ./packages/frontend/vite.config.ts:/app/vite.config.ts
- ./packages/frontend/tsconfig.json:/app/tsconfig.json
- ./packages/frontend/tsconfig.node.json:/app/tsconfig.node.json
ports:
- "14500:4500"
environment:
API_TARGET: http://floci-api:4501
VITE_USE_POLLING: "true"
depends_on:
- floci-api
networks:
- floci_shared
floci-api:
build:
context: ./packages/api
dockerfile: Dockerfile.dev
container_name: floci-api
volumes:
- ./packages/api/src:/app/src
ports:
- "14501:4501"
environment:
FLOCI_ENDPOINT: http://floci-aws:4566
FLOCI_AZURE_ENDPOINT: http://floci-azure:4577
FLOCI_GCP_ENDPOINT: http://floci-gcp:4588
FLOCI_GCP_PROJECT: floci-local
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
PORT: "4501"
networks:
- floci_shared
networks:
floci_shared:
external: true
31. Validar Floci UI
Antes de ejecutar:
docker compose -f compose.external.yaml config
Esto ayuda a detectar:
- errores YAML;
- indentación incorrecta;
- variables mal declaradas;
- rutas inválidas.
32. Construir la interfaz
Ejecutar:
docker compose -f compose.external.yaml build
Resultado esperado:
Image ui-floci-api Built
Image ui-floci-ui Built
33. Arrancar Floci UI
Ejecutar:
docker compose -f compose.external.yaml up -d
Comprobar:
docker ps --filter name=floci-
La arquitectura queda:
floci-ui LAN 14500 -> interno 4500
floci-api LAN 14501 -> interno 4501
floci-aws LAN 14566 -> interno 4566
floci-azure LAN 14577 -> interno 4577
floci-gcp LAN 14588 -> interno 4588
34. Acceder a Floci UI
Desde otro equipo:
http://<IP_VM>:14500
La interfaz permite cambiar entre:
- AWS
- Microsoft Azure
- Google Cloud
y consultar diferentes servicios y recursos.
35. Comprobar el proxy multicloud
La API de la interfaz permite validar cada proveedor.
AWS:
curl -s http://localhost:14500/api/clouds/aws/status
Azure:
curl -s http://localhost:14500/api/clouds/azure/status
GCP:
curl -s http://localhost:14500/api/clouds/gcp/status
Respuesta correcta:
{
"adapterRegistered": true,
"runtime": "reachable",
"error": null
}
En el laboratorio se confirmó este estado en los tres proveedores.
36. Incidencia conocida de Floci UI
Durante las pruebas puede aparecer una discrepancia visual en la barra superior de Floci UI.
La interfaz puede mostrar:
No conectado
mientras que la API devuelve:
{
"runtime": "reachable",
"error": null
}
Si además se cumple lo siguiente:
- los recursos pueden consultarse;
- AWS CLI funciona;
- cada endpoint runtime responde;
- los tres contenedores están
healthy; - el proxy de Floci UI accede correctamente a ellos;
entonces se considera una incidencia visual de la interfaz, no un problema de red ni de los runtimes.
No se recomienda modificar el código fuente de Floci UI solo para corregir ese indicador mientras el backend siga devolviendo reachable.
37. Estado final del laboratorio
Al terminar esta fase:
- Ubuntu Server OK
- SSH OK
- QEMU Guest Agent OK
- Reserva DHCP OK
- Docker Engine OK
- Docker Compose OK
- Floci AWS OK
- Floci Azure OK
- Floci GCP OK
- AWS CLI OK
- S3 de prueba OK
- Red Docker multicloud OK
- Floci API OK
- Floci UI OK
- Acceso desde LAN OK
38. Próximas fases del laboratorio
A partir de aquí la infraestructura base permite comenzar con ejercicios reales.
AWS:
- S3
- IAM
- EC2
- VPC
- Subnets
- Security Groups
- Lambda
- DynamoDB
- RDS
- SQS
- SNS
- ECS
- EKS
- CloudFormation
Azure:
- Resource Groups
- Virtual Networks
- Virtual Machines
- Blob Storage
- Azure Functions
- Cosmos DB
- Azure SQL
- Key Vault
- AKS
- Service Bus
- Event Hubs
Google Cloud:
- Cloud Storage
- Compute
- VPC
- IAM
- Cloud Functions
- Cloud Run
- Firestore
- BigQuery
- Pub/Sub
- Cloud SQL
- GKE
Herramientas para fases posteriores:
- Azure CLI
- Google Cloud CLI
- Terraform
- OpenTofu
- kubectl
- Ansible
- CI/CD
39. Seguridad del laboratorio
Al ser un entorno de aprendizaje es importante mantener varias precauciones:
- No utilizar credenciales reales de AWS dentro de Floci.
- No reutilizar contraseñas personales.
- No publicar los puertos del laboratorio directamente a Internet.
- Mantenerlo accesible únicamente desde la LAN o mediante una VPN.
- No publicar IP internas reales, MAC, usuarios o contraseñas.
- No mostrar tokens ni archivos
~/.aws/credentials. - Recordar que pertenecer al grupo
dockerconcede privilegios elevados. - Realizar snapshots antes de experimentos importantes.
40. Prompt para pedir ayuda a una IA
El siguiente prompt sirve para pedirle a una IA que acompañe el montaje del laboratorio desde cero. Antes de usarlo, rellena los valores entre corchetes con los datos de tu entorno.
Actúa como un administrador de sistemas senior. Quiero que me guíes paso a paso para montar un laboratorio multicloud local en una VM de Proxmox VE usando Ubuntu Server, Docker, Docker Compose, Floci AWS, Floci Azure, Floci GCP, Floci UI y AWS CLI.
Objetivo:
- Crear una VM llamada cloud-lab.
- Instalar Ubuntu Server sin entorno gráfico.
- Instalar QEMU Guest Agent.
- Dejar la VM con DHCP y una reserva en el router.
- Instalar Docker Engine y Docker Compose.
- Crear una red Docker compartida llamada floci_shared.
- Levantar Floci AWS, Floci Azure y Floci GCP como runtimes locales.
- Levantar Floci UI y Floci API conectados a esos runtimes.
- Configurar AWS CLI con un perfil exclusivo llamado floci usando credenciales ficticias.
- Validar cada fase con comandos concretos.
Datos de mi entorno:
- ID de VM en Proxmox: [ESCRIBE_AQUI_EL_VMID]
- Nombre de la VM: cloud-lab
- Usuario Linux: [ESCRIBE_AQUI_EL_USUARIO]
- IP reservada de la VM: [ESCRIBE_AQUI_LA_IP_VM]
- Bridge de red Proxmox: [ESCRIBE_AQUI_EL_BRIDGE, por ejemplo vmbr0]
- Storage para disco: [ESCRIBE_AQUI_EL_STORAGE, por ejemplo local-lvm]
- Storage de ISO: [ESCRIBE_AQUI_EL_STORAGE_ISO, por ejemplo local]
- Nombre exacto de la ISO: [ESCRIBE_AQUI_EL_NOMBRE_DE_LA_ISO]
- Interfaz de red dentro de Ubuntu, si ya la conozco: [ESCRIBE_AQUI_LA_INTERFAZ, por ejemplo enp6s18]
Usa estos puertos de ejemplo para publicar los servicios en la LAN:
- Floci AWS: 14566 hacia el puerto interno 4566.
- Floci Azure API: 14577 hacia el puerto interno 4577.
- Floci Azure AMQP: 15672 hacia el puerto interno 5672.
- Floci Azure AMQP TLS: 15673 hacia el puerto interno 5673.
- Floci Azure Event Hub/Kafka: 19093 hacia el puerto interno 9093.
- Floci GCP: 14588 hacia el puerto interno 4588.
- Floci API: 14501 hacia el puerto interno 4501.
- Floci UI: 14500 hacia el puerto interno 4500.
- Si alguno está ocupado, proponme otro puerto libre y actualiza todos los comandos relacionados.
Condiciones de seguridad:
- No debo usar credenciales reales de AWS, Azure ni Google Cloud.
- No debo exponer puertos directamente a Internet.
- Los servicios solo deben quedar accesibles desde la LAN o por VPN.
- No debo publicar IPs reales, MAC, UUID, Machine ID, Boot ID, usuarios reales, contraseñas ni tokens.
- Si preparo documentación pública, ayúdame a sustituir los datos sensibles por valores ficticios o placeholders.
Forma de respuesta que necesito:
- Divide el trabajo por fases.
- En cada fase dame comandos listos para copiar y pegar.
- Después de cada bloque de comandos añade cómo comprobar si salió bien.
- Si un comando usa un placeholder, explícame qué valor debo poner ahí.
- Incluye los docker compose completos para AWS, Azure, GCP, Floci UI y Floci API.
- Incluye pruebas con curl, docker ps y AWS CLI.
- Añade una sección de problemas conocidos. En concreto, explica que Floci UI puede mostrar un estado visual incorrecto en la barra superior, pero que si la API devuelve runtime reachable, los contenedores están healthy y los recursos se consultan, el laboratorio funciona correctamente.