Header always set X-Content-Type-Options "nosniff" Header always set X-Frame-Options "SAMEORIGIN" Header always set Referrer-Policy "strict-origin-when-cross-origin"
HSTS (solo si vais a usar HTTPS siempre; en lab puede dar guerra si cambiáis):
Header always set Strict-Transport-Security "max-age=86400"
7) Logs y troubleshooting (lo que siempre salva vidas)
Apache no escucha en 443: revisa que ssl esté activo y que el sitio https-lab.conf esté habilitado. sudo a2query -m ssl sudo a2query -s https-lab sudo apache2ctl -S
Certificado no coincide (CN mal): recrea el cert con CN correcto.
Permisos: que Apache pueda leer el .crt y .key (en /etc/apache2/ssl suele ir bien con root y lectura adecuada; si te pasas bloqueando, falla).
El objetivo de esta práctica es diseñar, instalar, configurar y documentar una pequeña infraestructura virtual compuesta por varias máquinas Ubuntu Server conectadas en red local.
Cada máquina deberá tener una función concreta dentro del sistema y deberá relacionarse con las demás. El alumno tendrá que demostrar conocimientos de instalación de sistemas operativos, virtualización, configuración de red, instalación de servicios, administración del sistema, seguridad, automatización y documentación técnica.
Requisitos del proyecto
Debes crear al menos 3 máquinas virtuales Ubuntu Server con IP fija:
un servidor web
un servidor de base de datos
un servidor de administración o mantenimiento
Debes realizar, como mínimo, las siguientes tareas
instalar Ubuntu Server en las máquinas virtuales
configurar la red local y las IP fijas
instalar y configurar Apache en el servidor web
instalar y configurar MySQL o MariaDB en el servidor de base de datos
comprobar la comunicación entre el servidor web y el de base de datos
administrar servicios con systemctl
consultar registros con journalctl
aplicar reglas básicas de seguridad con ufw
crear scripts Bash de mantenimiento
automatizar tareas con cron
documentar todo el proceso en un README técnico
La entrega deberá incluir
README.md principal
capturas o evidencias organizadas por apartados
scripts utilizados
archivos de configuración relevantes
comprobaciones finales de funcionamiento
Importante
No se valorará únicamente que “funcione”, sino que el trabajo esté bien explicado, justificado y documentado. Cada apartado debe mostrar comandos, explicación de su uso, resultado obtenido y evidencias del funcionamiento.
Objetivos didácticos
Con este proyecto el alumno deberá demostrar que sabe:
Crear y configurar máquinas virtuales
Instalar Ubuntu Server
Asignar IP fija a cada máquina
Configurar red local entre máquinas
Instalar y administrar servicios como:
Apache o Nginx
MySQL o MariaDB
Gestionar servicios con systemctl
Consultar registros con journalctl
Configurar reglas básicas de seguridad con ufw
Crear scripts Bash para tareas de mantenimiento
Programar tareas automáticas con cron
Verificar conectividad y dependencias entre sistemas
Para que el proyecto tenga sentido, conviene que las máquinas tengan relación entre sí.
Máquina 1: servidor web
Nombre: web01
IP fija: 192.168.1.10
Servicios:
Apache2
Página web de prueba
Función:
Servir una web que muestre información del sistema
Conectarse a la base de datos remota para validar que existe comunicación
Máquina 2: servidor de base de datos
Nombre: db01
IP fija: 192.168.1.20
Servicios:
MySQL Server o MariaDB
Función:
Alojar una base de datos
Permitir conexión desde web01
Tener usuarios y permisos configurados
Máquina 3: servidor de administración / monitorización básica
Nombre: admin01
IP fija: 192.168.1.30
Servicios y funciones:
Acceso por SSH a las otras máquinas
Scripts de mantenimiento
Tareas programadas por cron
Recolección de información del sistema
Función:
Ejecutar scripts
Hacer comprobaciones de red
Centralizar tareas administrativas básicas
Relación de dependencia entre máquinas
web01 depende de db01 porque debe conectarse a la base de datos remota
admin01 depende de web01 y db01 porque debe administrarlas o comprobar su estado
todas deben estar en la misma red local virtual y responder entre sí
graph TD
A[Entorno de virtualización] --> B[Red local virtual 192.168.50.0/24]
B --> C[web01<br>192.168.50.10<br>Ubuntu Server<br>Apache]
B --> D[db01<br>192.168.50.20<br>Ubuntu Server<br>MySQL / MariaDB]
B --> E[admin01<br>192.168.50.30<br>Ubuntu Server<br>SSH / Scripts / Cron]
C -->|Consulta remota| D
E -->|Administración y comprobación| C
E -->|Administración y comprobación| D
C --> F[Servicio web activo]
D --> G[Base de datos activa]
E --> H[Scripts de mantenimiento]
E --> I[Tareas automáticas con cron]
E --> J[Comprobación de logs y servicios]
C --> K[UFW]
D --> K
E --> K
F --> L[Documentación README]
G --> L
H --> L
I --> L
J --> L
K --> L
Requisitos mínimos del proyecto
El alumno deberá cumplir, como mínimo, lo siguiente:
Virtualización
Crear 3 máquinas virtuales
Asignar recursos coherentes
Instalar Ubuntu Server en todas
Red
Configurar una red local virtual
Asignar IP fija a cada máquina
Verificar conectividad con ping
Servicios
Instalar Apache en web01
Instalar MySQL o MariaDB en db01
Comprobar que el servicio web funciona desde navegador o con curl
Comprobar que la base de datos acepta conexiones
Administración
Usar comandos de terminal durante todo el proyecto
Gestionar servicios con systemctl
Consultar logs con journalctl
Seguridad
Activar y configurar ufw
Permitir solo los puertos necesarios
Explicar qué puertos se abren y por qué
Automatización
Crear al menos 2 scripts Bash
Programar al menos 2 tareas con cron
Fases del proyecto
flowchart TD
A[Planificación] --> B[Virtualización]
B --> C[Instalación de sistemas]
C --> D[Configuración de red]
D --> E[Conectividad]
E --> F[Servidor web]
E --> G[Servidor de base de datos]
F --> H[Comunicación entre servicios]
G --> H
H --> I[Administración de servicios]
I --> J[Revisión de logs]
J --> K[Seguridad con UFW]
K --> L[Scripts de mantenimiento]
L --> M[Tareas automáticas con cron]
M --> N[Pruebas finales]
N --> O[Documentación README y evidencias]
Fase 1. Creación de la infraestructura virtual
Tareas
Instalar el software de virtualización
VirtualBox, VMware o similar
Crear 3 máquinas virtuales
Asignar nombre a cada una
Instalar Ubuntu Server en cada una
Evidencias obligatorias
Captura del software de virtualización mostrando las 3 máquinas
Captura del proceso de instalación o del sistema ya instalado
Tabla con nombre, RAM, disco y función de cada VM
Qué debe explicar en el README
Qué programa de virtualización ha utilizado
Qué recursos ha asignado a cada VM
Por qué ha organizado así la infraestructura
Fase 2. Configuración de red
Tareas
Configurar red local entre las máquinas
Asignar IP fija a cada sistema
Comprobar conectividad
Ejemplo de tabla de red
Máquina
IP
Máscara
Puerta de enlace
Función
web01
192.168.50.10
255.255.255.0
192.168.50.1 o vacía si no aplica
Web
db01
192.168.50.20
255.255.255.0
192.168.50.1 o vacía si no aplica
BD
admin01
192.168.50.30
255.255.255.0
192.168.50.1 o vacía si no aplica
Administración
Comprobaciones que deben hacer
ip a
hostnamectl
ping entre máquinas
Evidencias obligatorias
Archivo de configuración de red o capturas del mismo
Resultado de ip a
Resultado de pings exitosos entre las máquinas
Qué debe explicar en el README
Cómo ha configurado la IP fija
Qué problemas encontró
Cómo comprobó que la red funciona
Fase 3. Instalación y configuración del servidor web
Tareas
En web01:
Instalar Apache2
Arrancar y habilitar el servicio
Crear una página de prueba
Comprobar acceso desde la propia máquina y desde otra
Qué riesgos existirían si se abrieran más puertos de la cuenta
Fase 8. Scripts de mantenimiento
Tareas
Crear al menos dos scripts Bash.
Script 1: comprobación del sistema
Debe mostrar:
hostname
IP
uso de disco
uso de memoria
fecha
estado de un servicio
Script 2: copia de logs o informe de mantenimiento
Debe:
crear una carpeta de copias o informes
guardar fecha y hora
copiar un log o generar un resumen del sistema a un archivo
Ejemplo de ideas
check_web.sh
backup_logs.sh
estado_sistema.sh
Evidencias obligatorias
Código de los scripts
Captura de ejecución
Explicación línea por línea o por bloques
Qué debe explicar en el README
Para qué sirve cada script
Cómo se ejecuta
Qué permisos necesita
Qué salida genera
Fase 9. Automatización con cron
Tareas
Programar al menos dos tareas automáticas:
una para ejecutar un script de mantenimiento
otra para generar un informe o copia
Comandos esperados
crontab -e crontab -l
Evidencias obligatorias
Captura de crontab -l
Captura o prueba del archivo generado por cron
Explicación del formato del cron
Qué debe explicar en el README
Qué tarea automatizó
Cada cuánto se ejecuta
Cómo verificó que realmente se ejecutó
Plantilla de README
Puedes darles esta estructura para obligarles a documentar bien.
# Proyecto: infraestructura virtualizada con Ubuntu Server
## 1. Datos del alumno
- Nombre:
- Curso:
- Módulo:
- Fecha:
## 2. Introducción
Explica brevemente en qué consiste el proyecto y cuáles son sus objetivos.
## 3. Diseño de la infraestructura
### 3.1 Máquinas virtuales creadas
| Máquina | Función | IP | Sistema operativo |
|---|---|---|---|
### 3.2 Relación entre máquinas
Explica cómo se comunican y de qué depende cada una.
## 4. Instalación de Ubuntu Server
Describe el proceso de creación e instalación de cada máquina virtual.
### Evidencias
- Capturas
- Configuración asignada
- Observaciones
## 5. Configuración de red
Explica cómo configuraste la IP fija en cada máquina.
### Comandos utilizados
~~~bash
ip a
ping
Estructura de entrega recomendada
Puedes utilizar esta estructura para la documentación:
Explica la instalación del servidor de base de datos en db01.
Comandos utilizados
sudo apt install mysql-server -y
Verificación
Explica cómo comprobaste que funciona.
Comunicación entre servicios
Explica cómo el servidor web accede al servidor de base de datos.
Pruebas realizadas
ping
conexión remota
consulta SQL
Gestión de servicios con systemctl
Explica qué comandos usaste para iniciar, parar, reiniciar y habilitar servicios.
Consulta de logs con journalctl
Indica qué logs revisaste y qué información encontraste.
Seguridad con UFW
Explica qué reglas configuraste y por qué.
Scripts de mantenimiento
Script 1
Nombre:
Función:
Código:
Resultado:
Script 2
Nombre:
Función:
Código:
Resultado:
Tareas programadas con cron
Explica qué tareas automatizaste y cómo las comprobaste.
Comprobaciones finales
Incluye evidencias de:
IP fija
conectividad entre máquinas
Apache funcionando
MySQL funcionando
firewall activo
scripts funcionando
cron funcionando
Problemas encontrados y soluciones
Describe los errores o dificultades y cómo los resolviste.
Cómo verificar que realmente ha hecho el trabajo
Esto es clave. Hay que pedir pruebas que huelan a trabajo real y no a “copié cuatro cosas de internet y recé”. Para demostrar que es una implementación real, puedes ir incluyendo en la documentación (Donde toque) el resultado de algunso comandos.
El objetivo es instalar un servidor GitLab Self-Managed sobre una máquina con Ubuntu Server.
Este servidor permitirá:
Guardar proyectos de programación.
Centralizar scripts personales.
Mantener archivos de configuración.
Trabajar desde diferentes ordenadores.
Controlar las versiones de los archivos.
Recuperar versiones anteriores.
Desplegar proyectos en otros servidores.
Automatizar despliegues mediante GitLab CI/CD.
Mantener copias de seguridad de todos los repositorios.
Aunque muchas veces se utiliza la expresión “instalar un GitHub”, realmente instalaremos GitLab, que ofrece un servicio similar a GitHub, pero alojado en nuestro propio servidor.
La arquitectura inicial será:
Ordenador personal
│
│ Git mediante SSH o HTTPS
▼
https://gitlab.tudominio.es
│
▼
Router de Internet
│
│ Puertos 80, 443 y 2222
▼
Ubuntu Server
│
▼
Docker Compose
│
▼
GitLab Community Edition
Fase 0. Planificación y requisitos
0.1. Requisitos recomendados
Para una instalación personal se recomienda:
Ubuntu Server 22.04 LTS o 24.04 LTS.
Procesador de 64 bits.
4 núcleos de CPU recomendados.
8 GB de RAM recomendados.
50 GB de almacenamiento como mínimo.
Dirección IP local fija.
Dominio propio.
Acceso a la configuración del router.
Conexión a Internet sin CG-NAT, o con posibilidad de abrir puertos.
Usuario de Ubuntu con permisos sudo.
GitLab consume bastantes más recursos que un servidor Git básico. Con 4 GB de RAM puede funcionar para pruebas, pero para un uso continuado es preferible disponer de 8 GB o más.
0.2. Datos utilizados en los ejemplos
Durante la documentación utilizaremos estos datos:
Dominio: gitlab.tudominio.es
IP local del servidor: 192.168.1.50
Puerto web HTTP: 80
Puerto web HTTPS: 443
Puerto SSH de GitLab: 2222
Directorio de instalación: /srv/gitlab
El puerto SSH externo será el 2222 porque el puerto 22 normalmente ya está siendo utilizado por el servicio SSH de Ubuntu Server.
0.3. Comprobar la versión de Ubuntu
lsb_release -a
También podemos utilizar:
cat /etc/os-release
0.4. Comprobar procesador, memoria y almacenamiento
Procesador:
lscpu
Memoria:
free -h
Espacio en disco:
df -h
0.5. Actualizar Ubuntu Server
sudo apt update
sudo apt upgrade -y
Reiniciamos si se ha actualizado el kernel:
sudo reboot
Fase 1. Configuración de red y dominio
1.1. Asignar una IP fija al servidor
El servidor debe mantener siempre la misma dirección IP dentro de la red local.
Tenemos dos posibilidades:
Crear una reserva DHCP en el router.
Configurar una IP estática en Ubuntu Server.
La opción más sencilla suele ser crear una reserva DHCP en el router asociando la dirección MAC del servidor con una IP, por ejemplo:
192.168.1.50
Para consultar la dirección IP actual:
ip address
Versión abreviada:
ip -br address
Para conocer la puerta de enlace:
ip route
1.2. Comprobar la IP pública
Desde el servidor podemos ejecutar:
curl https://ifconfig.me
También podemos consultar la IP pública desde el panel del router.
1.3. Crear el registro DNS
En el proveedor del dominio debemos crear un registro de tipo A.
Ejemplo:
Tipo: A
Nombre: gitlab
Destino: IP_PUBLICA
TTL: Automático
El resultado será:
gitlab.tudominio.es → IP pública del router
Si la conexión utiliza una IP pública dinámica, será necesario configurar un servicio de DNS dinámico o actualizar automáticamente el registro DNS.
El dominio debe resolver públicamente hacia el servidor para que GitLab pueda solicitar automáticamente el certificado HTTPS de Let’s Encrypt.
1.4. Comprobar la resolución DNS
Desde otro ordenador:
nslookup gitlab.tudominio.es
En Linux o macOS también podemos utilizar:
dig gitlab.tudominio.es
El resultado debe mostrar nuestra IP pública.
1.5. Configurar la redirección de puertos
En el router debemos crear estas reglas NAT o Port Forwarding:
Puerto externo
IP interna
Puerto interno
Protocolo
80
192.168.1.50
80
TCP
443
192.168.1.50
443
TCP
2222
192.168.1.50
2222
TCP
Los puertos 80 y 443 deben ser accesibles desde Internet para la validación y renovación automática del certificado de Let’s Encrypt.
1.6. Comprobar si existe CG-NAT
Compara:
La IP pública mostrada por el router.
La IP obtenida con curl https://ifconfig.me.
Si son diferentes, es posible que la conexión esté detrás de CG-NAT.
En ese caso, las redirecciones de puertos no funcionarán directamente. Las alternativas serían:
Solicitar una IP pública al proveedor.
Utilizar una VPN como WireGuard o Tailscale.
Utilizar un túnel inverso.
Alojar GitLab en un VPS.
Fase 2. Instalación de Docker y Docker Compose
2.1. Eliminar paquetes incompatibles
Antes de instalar Docker desde su repositorio oficial eliminamos posibles versiones anteriores:
No ocurre nada si algunos de estos paquetes no estaban instalados.
Docker recomienda utilizar su repositorio oficial de APT e instalar el complemento moderno docker compose, en lugar del antiguo ejecutable independiente docker-compose.
La imagen oficial de GitLab utiliza precisamente /etc/gitlab, /var/log/gitlab y /var/opt/gitlab para conservar la configuración, los registros y los datos.
Fase 4. Instalación de GitLab con Docker Compose
4.1. Elegir una versión
GitLab ofrece:
GitLab Community Edition: gitlab/gitlab-ce
GitLab Enterprise Edition: gitlab/gitlab-ee
Para este proyecto personal utilizaremos Community Edition.
Para una primera prueba se puede utilizar:
gitlab/gitlab-ce:latest
Sin embargo, cuando el servidor esté funcionando conviene fijar una versión concreta:
gitlab/gitlab-ce:19.x.x-ce.0
GitLab recomienda fijar una versión específica en entornos estables y utilizar latest principalmente para pruebas.
Puerto 80 del servidor → puerto 80 de GitLab
Puerto 443 del servidor → puerto 443 de GitLab
Puerto 2222 del servidor → puerto 22 del contenedor
El valor:
gitlab_rails['gitlab_shell_ssh_port'] = 2222
indica a GitLab que debe mostrar el puerto 2222 en las direcciones de clonación SSH. La documentación oficial contempla configurar un puerto SSH externo diferente cuando el puerto 22 del servidor está ocupado.
4.4. Validar el archivo
cd /srv/gitlab
docker compose config
Si no aparecen errores, la sintaxis es correcta.
4.5. Descargar la imagen
docker compose pull
4.6. Iniciar GitLab
docker compose up -d
4.7. Consultar el estado
docker compose ps
4.8. Consultar los registros
docker compose logs -f gitlab
Para dejar de visualizar los registros:
Ctrl + C
La primera inicialización es más lenta que los siguientes arranques porque GitLab debe configurar PostgreSQL, Redis, NGINX, Gitaly y el resto de sus componentes internos.
El archivo con la contraseña inicial se elimina automáticamente después del primer reinicio transcurridas aproximadamente 24 horas, por lo que conviene obtenerla y cambiarla cuanto antes.
5.2. Entrar en GitLab
Revisa la configuración persistente
Como /srv/gitlab/config es persistente, puede conservarse la dirección anterior.
Guardamos los códigos de recuperación en un lugar seguro.
Fase 6. Configuración de Git y claves SSH
GitLab permite trabajar mediante HTTPS o SSH. Para trabajar habitualmente desde varios equipos utilizaremos SSH, que GitLab recomienda como método de autenticación para clonar repositorios.
Title: Servidor web
Key: contenido de id_ed25519.pub
Para un despliegue que solamente descarga archivos, no activamos permisos de escritura.
Las Deploy Keys están pensadas precisamente para permitir que servidores externos accedan a repositorios sin asociar el acceso a la clave personal de un usuario.
11.4. Configurar SSH en el servidor destino
nano ~/.ssh/config
Contenido:
Host gitlab-personal
HostName gitlab.tudominio.es
User git
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Las claves privadas utilizadas por CI/CD no deben ser las claves personales del usuario. GitLab recomienda utilizar claves específicas para la automatización y almacenarlas de forma protegida.
La instalación y configuración completa de Runner debe realizarse como una fase independiente después de dominar:
Repositorios.
Clonado.
Commits.
Push y pull.
Claves SSH.
Deploy Keys.
Despliegue manual.
Fase 14. Copias de seguridad
Un repositorio Git distribuido ya proporciona copias parciales en los equipos donde se ha clonado, pero eso no sustituye una copia completa de GitLab.
La copia de GitLab debe incluir:
Base de datos.
Repositorios.
Archivos subidos.
Configuración.
Secretos.
Certificados.
Archivo compose.yaml.
Archivo .env.
GitLab advierte de que debe conservarse también gitlab-secrets.json, porque contiene secretos necesarios para descifrar determinados datos durante una recuperación.
GitLab recomienda crear una copia antes de actualizar. Para saltos grandes también puede exigir versiones intermedias obligatorias, por lo que no debe pasarse directamente de una versión muy antigua a la última sin revisar la ruta de actualización.