Todo se puede hacer en tu máquina local (tu "servidor de pruebas"). Lo que toque producción lo simulamos aquí. No mires solutions.md hasta entregar.
Preparación:
cd ~/dev/ticketflow && source .venv/bin/activateEjercicio 1 — Anatomía de tus procesos
- Arranca Gunicorn:
gunicorn config.wsgi --bind 127.0.0.1:8000 --workers 2en un terminal. - En otro:
ps -o pid,ppid,rss,cmd -C gunicorn. Identifica el proceso padre (arbiter) y los 2 workers. ¿Cómo lo distingues por el comando? kill -TERM <pid_de_un_worker>: ¿qué pasa en el terminal de Gunicorn? ¿El servicio sigue respondiendo acurl? (pista: el arbiter lo reemplaza).kill -9 <pid_de_un_worker>y repite: ¿qué diferencia observas en los logs?
Ejercicio 2 — Puertos y carga
ss -tlnp | grep -E '8000|5432|6379': ¿qué procesos escuchan en cada puerto?- Genera carga y observa:
top(ohtop) mientras corresfor i in $(seq 200); do curl -s -o /dev/null http://127.0.0.1:8000/api/health/ & done. ¿Cuánta CPU consumen los workers? ¿Y el procesocurl? uptimetras la prueba: ¿cómo interpretas los tres números en TU máquina (busca cuántos núcleos tiene connproc)?
Ejercicio 3 — El pipeline de logs
- Genera un log de prueba con 100 líneas (o usa el error.log de Gunicorn).
- Ejecuta y explica cada eslabón:
cat access.log | awk '{print $9}' | sort | uniq -c | sort -rn(¿qué es $9 en un log de acceso de Nginx/Gunicorn? ¿qué pregunta responde?)
- Escribe un pipeline que muestre el top 5 de rutas más lentas (las que tarden más). Pista: si tu log tiene la duración, usa
sort -kyhead; si no, añade la duración al formato de log primero.
Ejercicio 4 — Permisos de verdad
- Crea un usuario sin shell:
sudo useradd -r -s /usr/sbin/nologin app_test. - Crea un fichero con un secreto simulado y dale 644:
echo "SECRET=x" > /tmp/secreto.env && chmod 644 /tmp/secreto.env. Consudo -u app_test cat /tmp/secreto.env, ¿puede leerlo? ¿Por qué? - Cambia a
chmod 640y pon grupo del usuario de la app: ¿quién puede leerlo ahora? ¿Y con 600? - Escribe la regla que aplicarás a tu
.envreal (y ejecútala en tu proyecto:chmod 600.env).
Ejercicio 5 — El.env bien hecho
- En tu proyecto, crea
env.examplecon todos los nombres que usasettings.py(sin valores reales). - Verifica que tu
.envreal está ignorado por Git:git check-ignore -v.env(si no lo está, corrígelo YA y confirma congit statusque no aparece). - Busca secretos filtrados en tu historial:
git log -p | grep -iE "secret|password|key" | head. Si aparece algo, anótalo para rotarlo (la lección de seguridad lo sistematiza).
Ejercicio 6 — SSH local (laboratorio)
- Genera (si no tienes) tu clave ed25519 y pruébala contra localhost:
ssh-copy-id tu_usuario@localhosty luegossh tu_usuario@localhost "hostname". ¿Entró sin contraseña? - Crea
~/.ssh/configcon un hostlocaltestapuntando a localhost y repite el comando conssh localtest hostname. - Túnel simulado:
ssh -L 5433:localhost:5432 tu_usuario@localhosten un terminal; en otro, comprueba el puerto:ss -tlnp | grep 5433. ¿Quién está escuchando? ¿Qué te permitiría esto con una BD real remota?
Ejercicio 7 — Tu primer script de operación
- Escribe
healthcheck.sh(el de la lección) y hazlo ejecutable (chmod +x). Prueba con Gunicorn caído y levantado. - Añade la comprobación del broker: si Redis no responde (
redis-cli ping), el script avisa pero no falla (exit 0 con aviso); si la API no responde, sí falla. Justifica la diferencia de severidad. - Programa que se ejecute cada minuto en segundo plano con
watch -n 60./healthcheck.shdurante un rato. ¿Cómo lo harías "de verdad" en producción? (pista: systemd timer o cron — anótalo, lo formalizamos en la Lección 31).
Entrega
Pega outputs recortados y tu healthcheck.sh en el chat. Cierra la 05 y pasamos a la Lección 06 — Git profesional: del commit diario al flujo de equipo con ramas, rebase y conflictos.