Linux Debian/Ubuntu para Homelab: Guía Completa 2025

Introducción: Linux es el sistema operativo del homelab

Si vas en serio con homelab, Docker, Proxmox, Home Assistant, n8n o cualquier servidor self-hosted, tarde o temprano necesitas dominar Linux. El 90% de las guías técnicas asumen que sabes usar terminal, y sin ese conocimiento estás bloqueado.

Esta guía te lleva de cero a operativo en Debian/Ubuntu: instalación rápida, terminal esencial, gestión de servicios, redes, SSH, troubleshooting y automatización. Todo lo que necesitas para seguir cualquier tutorial avanzado sin perderte.

💡 Por qué esta guía se enfoca en Debian/Ubuntu:

  • Debian: Súper estable, base de Proxmox, usado en servidores de producción
  • Ubuntu Server: LTS con 5 años de soporte, mayor comunidad, más fácil para empezar
  • 70%+ de homelabs usan Debian o Ubuntu
  • apt (gestor de paquetes) es universal en ambos
  • Documentación masiva: Cualquier problema ya está resuelto en Stack Overflow

Olvidamos: RedHat/CentOS (dnf), Arch (pacman), openSUSE (zypper). Son excelentes, pero alargaríamos esta guía a 15,000 palabras.

Instalación rápida: Ubuntu Server 24.04 LTS

Hardware mínimo: 2GB RAM, 25GB disco, CPU 64-bit. Funciona en Raspberry Pi 4, VM Proxmox, VPS, servidor físico.

Pasos esenciales

  1. Descargar ISO: ubuntu.com/download/server (Ubuntu Server 24.04 LTS)
  2. Crear USB booteable: Rufus (Windows), Balena Etcher (multi-plataforma), o dd (Linux)
  3. Bootear desde USB → Installer automático aparece
  4. Configuración clave durante instalación:
    • Language: English (recomendado, mejor documentación) o Español
    • Network: DHCP automático (o configurar IP estática si prefieres)
    • Storage: Use entire disk (simple) o Custom si quieres LVM/RAID
    • Profile: Nombre, usuario, contraseña fuerte, hostname (homelab, servidor, etc.)
    • SSH:Install OpenSSH server (CRÍTICO, permite acceso remoto)
    • Snaps: Opcional (Docker, Nextcloud, etc. – puedes instalar después manualmente)
  5. Reboot → Quitar USB → Login con usuario/password

Primera conexión SSH desde otro PC:

# Desde Windows (PowerShell), Mac o Linux:
ssh usuario@192.168.1.100

# Aceptar fingerprint (primera vez): yes
# Ingresar password
# ¡Ya estás dentro! 🎉
⚡ Si instalas en VM Proxmox o VirtualBox:

Sigue los pasos normales del instalador. Para SSH necesitarás la IP de la VM (ip a dentro de la VM para verla).

Terminal básico: Comandos de supervivencia

Navegación del sistema de archivos

# Ver directorio actual (Print Working Directory)
pwd

# Listar archivos
ls                    # Básico
ls -l                 # Lista detallada (permisos, tamaño, fecha)
ls -lh                # Tamaños legibles (KB, MB, GB)
ls -la                # Incluir archivos ocultos (empiezan con .)
ls -lt                # Ordenar por fecha modificación (más reciente primero)

# Cambiar directorio
cd /home/usuario      # Ir a directorio específico
cd ..                 # Subir un nivel
cd ~                  # Ir a tu home (/home/usuario)
cd -                  # Volver al directorio anterior

# Crear directorio
mkdir proyectos
mkdir -p docker/stacks/media    # Crear directorios padres automáticamente

# Copiar archivos/directorios
cp archivo.txt backup.txt
cp -r directorio/ backup_directorio/    # -r = recursivo (para directorios)

# Mover/renombrar
mv archivo_viejo.txt archivo_nuevo.txt
mv archivo.txt /home/usuario/documentos/

# Eliminar (CUIDADO: no hay papelera de reciclaje)
rm archivo.txt
rm -r directorio/     # Eliminar directorio y contenido
rm -rf directorio/    # Forzar eliminación sin confirmar (PELIGROSO)

# Ver contenido de archivo
cat archivo.txt       # Todo el archivo
less archivo.txt      # Ver con scroll (q para salir)
head archivo.txt      # Primeras 10 líneas
head -n 20 archivo.txt    # Primeras 20 líneas
tail archivo.txt      # Últimas 10 líneas
tail -f /var/log/syslog   # Ver archivo en tiempo real (logs)

Permisos: el concepto MÁS importante de Linux

Todo en Linux tiene permisos: archivos, directorios, scripts. Sin entender esto, te encontrarás con «Permission denied» constantemente.

Ver permisos:

ls -l archivo.sh

# Salida ejemplo:
# -rwxr-xr-x 1 usuario grupo 1234 Oct 10 15:30 archivo.sh
#  ↑↑↑↑↑↑↑↑↑
#  |||||||└─ Otros: r-x (leer, ejecutar)
#  ||||||└── Grupo: r-x (leer, ejecutar)
#  |||||└─── Usuario: rwx (leer, escribir, ejecutar)
#  ||||└──── Número de links
#  |||└───── Propietario (usuario)
#  ||└────── Grupo
#  |└─────── Tamaño (bytes)
#  └──────── - = archivo, d = directorio, l = link

Cambiar permisos con chmod:

# Método numérico (más común):
# r (read) = 4, w (write) = 2, x (execute) = 1
# Usuario - Grupo - Otros

chmod 755 script.sh
# 7 (usuario: rwx = 4+2+1)
# 5 (grupo: r-x = 4+0+1)
# 5 (otros: r-x = 4+0+1)
# Resultado: Usuario puede todo, grupo y otros solo leer/ejecutar

chmod 644 archivo.txt
# Usuario: rw- (6 = 4+2)
# Grupo: r-- (4)
# Otros: r-- (4)
# Archivo de texto normal: solo owner puede modificar

chmod 600 ~/.ssh/id_rsa
# Solo usuario puede leer/escribir (SSH keys privadas DEBEN ser 600)

# Hacer script ejecutable (método rápido):
chmod +x script.sh

# Recursivo (aplicar a todo dentro de directorio):
chmod -R 755 /var/www/html/

Cambiar propietario con chown:

# Cambiar owner
sudo chown usuario archivo.txt

# Cambiar owner y grupo
sudo chown usuario:grupo archivo.txt

# Recursivo
sudo chown -R usuario:grupo /var/www/html/

# Caso común: Docker volúmenes con permisos incorrectos
sudo chown -R 1000:1000 ~/docker/data/nextcloud/
🔑 Regla de oro de permisos:

  • Archivos normales: 644 (rw-r–r–)
  • Scripts ejecutables: 755 (rwxr-xr-x)
  • Directorios: 755 (rwxr-xr-x)
  • SSH keys privadas: 600 (rw——-)
  • Archivos de configuración sensibles: 600

Editar archivos: nano (el más fácil)

# Abrir/crear archivo
nano archivo.txt

# Atajos esenciales (aparecen abajo, ^ = Ctrl):
# Ctrl+O → Guardar (Write Out)
# Enter  → Confirmar nombre archivo
# Ctrl+X → Salir
# Ctrl+K → Cortar línea
# Ctrl+U → Pegar
# Ctrl+W → Buscar
# Ctrl+\ → Buscar y reemplazar

# Editar archivo de sistema (requiere sudo):
sudo nano /etc/hosts

Alternativa: vim (más potente pero curva de aprendizaje):

# Abrir archivo
vim archivo.txt

# Modos:
# - Modo Normal (default): navegación
# - Modo Insert: presionar 'i' para empezar a escribir
# - Modo Command: presionar Esc + ':'

# Comandos básicos:
i          # Entrar modo Insert
Esc        # Volver a modo Normal
:w         # Guardar (write)
:q         # Salir (quit)
:wq        # Guardar y salir
:q!        # Salir sin guardar (forzar)

# Si te quedas atascado en vim: Esc + :q!

Gestión de procesos

# Ver procesos en tiempo real (mejor que top)
htop    # Si no está instalado: sudo apt install htop

# Dentro de htop:
# F3 = Buscar proceso
# F9 = Matar proceso
# F10 = Salir

# Ver todos los procesos
ps aux

# Buscar proceso específico
ps aux | grep nginx

# Matar proceso por PID
kill 1234        # SIGTERM (graceful)
kill -9 1234     # SIGKILL (forzar, usar solo si SIGTERM falla)

# Matar por nombre
pkill nginx
killall nginx

# Ver uso de CPU/RAM de proceso
top -p 1234

Espacio en disco

# Ver espacio en discos montados
df -h

# Ver tamaño de directorios
du -sh /var/log/
du -sh /home/usuario/*

# Top 10 directorios más grandes
du -sh /* | sort -rh | head -10

# Ver inodos (si disk full pero df muestra espacio libre)
df -i

Gestión de paquetes con apt

apt es el gestor de paquetes de Debian/Ubuntu. Instala, actualiza y elimina software.

Comandos esenciales

# Actualizar lista de paquetes disponibles (SIEMPRE primero)
sudo apt update

# Actualizar todos los paquetes instalados
sudo apt upgrade

# Actualizar sistema completo (incluye cambios de dependencias)
sudo apt dist-upgrade

# Instalar paquete
sudo apt install nginx

# Instalar múltiples
sudo apt install docker.io docker-compose curl git htop

# Eliminar paquete
sudo apt remove nginx

# Eliminar paquete + archivos de configuración
sudo apt purge nginx

# Eliminar paquetes huérfanos (ya no necesarios)
sudo apt autoremove

# Buscar paquete
apt search docker

# Ver info de paquete
apt show docker.io

# Ver qué archivos instaló un paquete
dpkg -L nginx

# Ver qué paquete instaló un archivo
dpkg -S /usr/bin/nginx

Repositorios adicionales

A veces necesitas software que no está en repos oficiales.

# Ejemplo: Añadir repo de Docker oficial
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

# Ver repositorios activos
ls /etc/apt/sources.list.d/
cat /etc/apt/sources.list

Servicios con systemd

systemd gestiona servicios (daemons) en Linux moderno. Controla qué corre, cuándo arranca, logs, etc.

Comandos systemctl

# Ver estado de servicio
sudo systemctl status nginx

# Iniciar servicio
sudo systemctl start nginx

# Parar servicio
sudo systemctl stop nginx

# Reiniciar servicio
sudo systemctl restart nginx

# Recargar configuración sin reiniciar (si servicio lo soporta)
sudo systemctl reload nginx

# Habilitar arranque automático (boot)
sudo systemctl enable nginx

# Deshabilitar arranque automático
sudo systemctl disable nginx

# Ver si servicio está habilitado
systemctl is-enabled nginx

# Ver si servicio está corriendo
systemctl is-active nginx

# Listar todos los servicios
systemctl list-units --type=service

# Listar solo servicios corriendo
systemctl list-units --type=service --state=running

# Listar servicios fallidos
systemctl --failed

Logs de servicios (journalctl)

# Ver logs de servicio
sudo journalctl -u nginx

# Últimas 50 líneas
sudo journalctl -u nginx -n 50

# Logs en tiempo real (como tail -f)
sudo journalctl -u nginx -f

# Logs desde arranque actual
sudo journalctl -u nginx -b

# Logs desde fecha específica
sudo journalctl -u nginx --since "2025-10-10 14:00:00"

# Últimas 2 horas
sudo journalctl -u nginx --since "2 hours ago"

# Ver logs de todo el sistema
sudo journalctl

# Limpiar logs antiguos (liberar espacio)
sudo journalctl --vacuum-time=7d    # Mantener solo 7 días
sudo journalctl --vacuum-size=500M  # Mantener máximo 500MB

Crear servicio personalizado

Ejemplo: Script Python que corre como servicio

1. Crear script (/home/usuario/mi_app.py):

#!/usr/bin/env python3
import time
while True:
    print("App corriendo...")
    time.sleep(60)

2. Crear servicio (/etc/systemd/system/mi-app.service):

[Unit]
Description=Mi aplicación Python
After=network.target

[Service]
Type=simple
User=usuario
WorkingDirectory=/home/usuario
ExecStart=/usr/bin/python3 /home/usuario/mi_app.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

3. Activar servicio:

sudo systemctl daemon-reload
sudo systemctl enable mi-app
sudo systemctl start mi-app
sudo systemctl status mi-app

Redes: Configuración y diagnóstico

Ver configuración de red

# Ver interfaces y IPs (comando moderno)
ip a

# Ver solo IPs activas
ip -br a

# Ver tabla de routing
ip route

# Ver gateway por defecto
ip route show default

# Ver conexiones activas
ss -tulpn

# Alternativa antigua (deprecated pero aún funciona):
ifconfig
netstat -tulpn

Configurar IP estática

Ubuntu 20.04+ usa Netplan:

# Editar configuración
sudo nano /etc/netplan/00-installer-config.yaml

# Contenido ejemplo (IP estática):
network:
  version: 2
  ethernets:
    enp0s3:    # Nombre de tu interfaz (verificar con 'ip a')
      addresses:
        - 192.168.1.100/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
          - 1.1.1.1

# Aplicar cambios
sudo netplan apply

# Si hay error, ver qué falla:
sudo netplan --debug apply

Debian (sin Netplan, usa /etc/network/interfaces):

sudo nano /etc/network/interfaces

# Contenido:
auto enp0s3
iface enp0s3 inet static
  address 192.168.1.100
  netmask 255.255.255.0
  gateway 192.168.1.1
  dns-nameservers 8.8.8.8 1.1.1.1

# Reiniciar networking
sudo systemctl restart networking

Diagnóstico de red

# Test conectividad IP
ping 8.8.8.8

# Test DNS
ping google.com

# Ver ruta de paquetes
traceroute google.com

# Test puerto específico
telnet 192.168.1.1 80
# O mejor (si telnet no está instalado):
nc -zv 192.168.1.1 80

# Ver qué proceso usa puerto
sudo ss -tulpn | grep :80
sudo lsof -i :80

# Escanear puertos abiertos en servidor remoto (requiere nmap)
sudo apt install nmap
nmap 192.168.1.100

SSH: Acceso remoto seguro

Configuración básica servidor SSH

# Instalar (si no está)
sudo apt install openssh-server

# Verificar que corre
sudo systemctl status ssh

# Archivo de configuración principal
sudo nano /etc/ssh/sshd_config

# Cambios recomendados:
Port 22                    # Cambiar a otro (ej: 2222) para seguridad
PermitRootLogin no         # No permitir login como root
PasswordAuthentication yes # Después cambiar a 'no' cuando uses keys
PubkeyAuthentication yes   # Permitir login con SSH keys

# Reiniciar SSH después de cambios
sudo systemctl restart ssh

SSH Keys (autenticación sin contraseña)

1. Generar par de keys en tu PC local (no en servidor):

# En tu laptop/desktop (Windows/Mac/Linux)
ssh-keygen -t ed25519 -C "tu_email@example.com"

# Pregunta dónde guardar: Enter (default: ~/.ssh/id_ed25519)
# Passphrase (opcional pero recomendado): ingresar o dejar vacío

# Resultado:
# ~/.ssh/id_ed25519      ← Clave PRIVADA (NUNCA compartir)
# ~/.ssh/id_ed25519.pub  ← Clave PÚBLICA (esta sí se comparte)

2. Copiar clave pública al servidor:

# Método automático (más fácil):
ssh-copy-id usuario@192.168.1.100

# Método manual:
cat ~/.ssh/id_ed25519.pub | ssh usuario@192.168.1.100 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Desde Windows (PowerShell):
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh usuario@192.168.1.100 "cat >> ~/.ssh/authorized_keys"

3. Probar login sin contraseña:

ssh usuario@192.168.1.100
# Si configuraste passphrase en key, la pregunta. Sino, login directo.

4. Deshabilitar password login (máxima seguridad):

sudo nano /etc/ssh/sshd_config

# Cambiar:
PasswordAuthentication no

sudo systemctl restart ssh

Copiar archivos con SCP y rsync

# SCP (simple copy)
# Local → Remoto
scp archivo.txt usuario@192.168.1.100:/home/usuario/

# Remoto → Local
scp usuario@192.168.1.100:/home/usuario/archivo.txt .

# Directorio completo (recursivo)
scp -r directorio/ usuario@192.168.1.100:/home/usuario/

# rsync (mejor para archivos grandes, resume si falla)
# Local → Remoto
rsync -avz archivo.txt usuario@192.168.1.100:/home/usuario/

# Directorio con progress bar
rsync -avzP directorio/ usuario@192.168.1.100:/home/usuario/directorio/

# Flags:
# -a = archive (preserva permisos, timestamps)
# -v = verbose
# -z = compress
# -P = progress + partial (resume si falla)

Usuarios y grupos

# Crear usuario
sudo adduser nuevo_usuario
# Sigue wizard: password, nombre completo, etc.

# Crear usuario sin wizard (avanzado)
sudo useradd -m -s /bin/bash nuevo_usuario
sudo passwd nuevo_usuario

# Eliminar usuario
sudo deluser usuario
sudo deluser --remove-home usuario    # Eliminar también /home/usuario

# Añadir usuario a grupo
sudo usermod -aG docker usuario
# -aG = append to group (no sobrescribe otros grupos)

# Ver grupos de usuario
groups usuario

# Cambiar password
passwd              # Tu propio password
sudo passwd usuario # Password de otro usuario

# Cambiar a otro usuario
su - usuario
# Volver a tu usuario: exit

# Ejecutar comando como otro usuario
sudo -u usuario comando

# Permitir sudo sin password (CUIDADO, solo para users confiables)
sudo visudo
# Añadir al final:
usuario ALL=(ALL) NOPASSWD:ALL

Firewall con UFW

UFW (Uncomplicated Firewall) simplifica iptables. Esencial para servidores expuestos a internet.

# Instalar (viene preinstalado en Ubuntu)
sudo apt install ufw

# Ver estado
sudo ufw status

# Habilitar firewall (IMPORTANTE: permitir SSH primero o te bloqueas)
sudo ufw allow 22/tcp
sudo ufw enable

# Permitir servicios comunes
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw allow 8123/tcp    # Home Assistant
sudo ufw allow 9090/tcp    # Prometheus

# Permitir rango de puertos
sudo ufw allow 6000:6100/tcp

# Permitir desde IP específica
sudo ufw allow from 192.168.1.0/24

# Permitir SSH solo desde tu red local
sudo ufw allow from 192.168.1.0/24 to any port 22

# Denegar puerto
sudo ufw deny 23/tcp

# Ver reglas numeradas
sudo ufw status numbered

# Eliminar regla por número
sudo ufw delete 3

# Eliminar regla por descripción
sudo ufw delete allow 8080/tcp

# Resetear firewall (eliminar todas las reglas)
sudo ufw reset

# Deshabilitar firewall
sudo ufw disable
⚠️ CUIDADO al habilitar UFW en SSH remoto:

Si habilitas UFW sin permitir puerto SSH primero, te bloquearás y perderás acceso. SIEMPRE ejecutar sudo ufw allow 22/tcp ANTES de sudo ufw enable.

Cron: Tareas programadas

Cron ejecuta comandos automáticamente en horarios específicos. Ideal para backups, limpieza, actualizaciones.

Sintaxis cron

# Formato:
# ┌───────────── minuto (0-59)
# │ ┌───────────── hora (0-23)
# │ │ ┌───────────── día del mes (1-31)
# │ │ │ ┌───────────── mes (1-12)
# │ │ │ │ ┌───────────── día de la semana (0-7, 0 y 7 = domingo)
# │ │ │ │ │
# * * * * * comando_a_ejecutar

# Ejemplos:
30 2 * * *     # Cada día a las 02:30
0 */6 * * *    # Cada 6 horas
0 9 * * 1      # Cada lunes a las 09:00
0 0 1 * *      # Primer día de cada mes a medianoche
*/15 * * * *   # Cada 15 minutos

Gestionar crontab

# Editar crontab de tu usuario
crontab -e
# Primera vez pregunta editor: elige nano (opción 1)

# Ver crontab actual
crontab -l

# Eliminar crontab completo
crontab -r

# Editar crontab de otro usuario (como root)
sudo crontab -u usuario -e

Ejemplos prácticos

# Backup diario de directorio a las 3am
0 3 * * * tar -czf /backups/home-$(date +\%Y\%m\%d).tar.gz /home/usuario/

# Limpiar logs antiguos cada domingo a medianoche
0 0 * * 0 find /var/log/ -name "*.log" -mtime +30 -delete

# Actualizar sistema cada lunes a las 4am
0 4 * * 1 apt update && apt upgrade -y

# Reiniciar servicio cada día a las 5am
0 5 * * * systemctl restart mi-servicio

# Ejecutar script Python cada hora
0 * * * * /usr/bin/python3 /home/usuario/script.py

# Logs de cron (para debugging):
# Añadir redirección al final de comando:
0 3 * * * /home/usuario/backup.sh >> /var/log/mi-backup.log 2>&1
💡 Tips cron:

  • Usa rutas absolutas (/usr/bin/python3 no python3)
  • Cron usa PATH limitado, especifica paths completos
  • Redirige output a log para debugging: comando >> /var/log/cron.log 2>&1
  • Test tu comando manualmente antes de añadir a cron
  • Para tareas complejas, crea script y llámalo desde cron

Scripts Bash básicos

Bash scripts automatizan secuencias de comandos. Esencial para backups, deployments, mantenimiento.

Estructura básica

#!/bin/bash
# Shebang: indica que es script bash

# Variables
NOMBRE="Mundo"
FECHA=$(date +%Y-%m-%d)

# Echo (imprimir)
echo "Hola $NOMBRE"
echo "Hoy es $FECHA"

# Condicionales
if [ -f "/etc/hosts" ]; then
    echo "Archivo existe"
else
    echo "Archivo no existe"
fi

# Loop archivos
for archivo in /var/log/*.log; do
    echo "Procesando $archivo"
done

# Loop numérico
for i in {1..5}; do
    echo "Iteración $i"
done

# While loop
CONTADOR=1
while [ $CONTADOR -le 5 ]; do
    echo "Contador: $CONTADOR"
    CONTADOR=$((CONTADOR + 1))
done

# Funciones
mi_funcion() {
    echo "Argumentos recibidos: $1 $2"
}

mi_funcion "arg1" "arg2"

Ejemplo práctico: Script backup

#!/bin/bash

# Script de backup con rotación de archivos antiguos

BACKUP_DIR="/backups"
SOURCE_DIR="/home/usuario/datos"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_$DATE.tar.gz"

# Crear directorio de backups si no existe
mkdir -p "$BACKUP_DIR"

# Verificar que source existe
if [ ! -d "$SOURCE_DIR" ]; then
    echo "ERROR: Directorio $SOURCE_DIR no existe"
    exit 1
fi

# Crear backup
echo "Iniciando backup de $SOURCE_DIR..."
tar -czf "$BACKUP_FILE" "$SOURCE_DIR"

if [ $? -eq 0 ]; then
    echo "✅ Backup completado: $BACKUP_FILE"
else
    echo "❌ Error en backup"
    exit 1
fi

# Eliminar backups antiguos (mantener últimos 7)
echo "Limpiando backups antiguos..."
cd "$BACKUP_DIR"
ls -t backup_*.tar.gz | tail -n +8 | xargs -r rm

echo "Backups actuales:"
ls -lh backup_*.tar.gz

echo "✅ Proceso completado"

Hacer ejecutable y usar:

chmod +x backup.sh
./backup.sh

# Añadir a cron (diario a las 3am):
# crontab -e
# 0 3 * * * /home/usuario/backup.sh >> /var/log/backup.log 2>&1

Troubleshooting: Problemas comunes

Problema 1: Sistema no arranca / Kernel panic

Síntomas: Pantalla negra, error «Kernel panic», bootloop.

Causas:

  • Actualización de kernel fallida
  • Disco lleno durante update
  • Archivo /boot corrupto
  • fstab con error (disco no montado)

Soluciones:

  1. Bootear kernel anterior:
    • Reiniciar → En GRUB presionar Shift (o Esc en algunas BIOS)
    • Advanced options → Elegir kernel anterior
    • Una vez dentro: sudo apt remove linux-image-VERSION-PROBLEMATICA
  2. Modo recovery:
    • GRUB → Recovery mode
    • Drop to root shell prompt
    • Montar filesystem: mount -o remount,rw /
    • Reparar: apt --fix-broken install
  3. Verificar fstab:
    • Recovery shell: nano /etc/fstab
    • Comentar (#) líneas de discos que no existen
    • Reboot

Problema 2: Sin red / No ping

Diagnóstico paso a paso:

# 1. Ver si interfaz está UP
ip a
# Buscar: estado UP, inet (IP asignada)

# Si interfaz está DOWN:
sudo ip link set enp0s3 up

# 2. Test gateway
ip route show default
# Copiar IP del gateway (ej: 192.168.1.1)
ping 192.168.1.1

# Si no responde: problema en red local (cable, switch, DHCP)

# 3. Test DNS
ping 8.8.8.8
# Si funciona: problema de DNS
# Solución temporal:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

# 4. Test internet
ping google.com
# Si falla pero 8.8.8.8 funciona: DNS incorrecto

# 5. Reiniciar networking
sudo systemctl restart networking      # Debian
sudo systemctl restart NetworkManager  # Ubuntu Desktop
sudo netplan apply                     # Ubuntu Server

# 6. Verificar firewall
sudo ufw status
# Si está bloqueando, deshabilitar temporalmente:
sudo ufw disable

Problema 3: Disco lleno

Síntomas: Errores «No space left on device», servicios fallan, sistema lento.

Diagnóstico y limpieza:

# 1. Ver uso de disco
df -h
# Identificar partición llena (/, /home, /var)

# 2. Buscar qué consume espacio
sudo du -sh /* | sort -rh | head -10
sudo du -sh /var/* | sort -rh | head -10

# 3. Limpiezas comunes:

# Logs antiguos
sudo journalctl --vacuum-time=7d
sudo find /var/log/ -name "*.log" -mtime +30 -delete

# Paquetes apt cache
sudo apt clean
sudo apt autoremove

# Kernels antiguos
dpkg -l | grep linux-image
sudo apt remove linux-image-VERSION-ANTIGUA

# Archivos temporales
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*

# Docker (si usas)
docker system prune -a --volumes

# Snapshots (si usas Timeshift, etc.)
# Eliminar snapshots antiguos manualmente

# 4. Verificar inodos (a veces disco "lleno" pero df muestra espacio)
df -i
# Si uso de inodos al 100%: muchos archivos pequeños
sudo find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
# Eliminar directorios con millones de archivos pequeños

Problema 4: Servicio no arranca

Diagnóstico sistemático:

# 1. Ver estado y error
sudo systemctl status nginx

# 2. Ver logs detallados
sudo journalctl -u nginx -n 100 --no-pager

# 3. Verificar configuración (si aplica)
sudo nginx -t    # Test config nginx
# Para otros servicios: ver su documentación

# 4. Verificar permisos de archivos
ls -l /var/log/nginx/
# Si owner incorrecto:
sudo chown -R www-data:www-data /var/log/nginx/

# 5. Verificar puerto no esté en uso
sudo ss -tulpn | grep :80
# Si otro proceso lo usa, matar o cambiar puerto

# 6. Verificar dependencias
# Algunos servicios requieren otros (ej: app → database)
sudo systemctl status postgresql

# 7. Restart forzado
sudo systemctl restart nginx
sudo systemctl daemon-reload  # Si cambiaste .service

# 8. Si nada funciona: reinstalar
sudo apt purge nginx
sudo apt install nginx

Problema 5: Permission denied constante

Causas:

  • Usuario no es owner del archivo/directorio
  • Permisos incorrectos
  • Usuario no está en grupo necesario (ej: docker)
  • SELinux/AppArmor bloqueando (avanzado)

Soluciones:

# Ver permisos y owner
ls -la archivo

# Cambiar owner
sudo chown usuario:usuario archivo
sudo chown -R usuario:usuario directorio/

# Cambiar permisos
chmod 644 archivo      # Usuario: rw, otros: r
chmod 755 directorio/  # Usuario: rwx, otros: rx

# Añadir usuario a grupo (ej: docker)
sudo usermod -aG docker $USER
# IMPORTANTE: logout y login para aplicar cambio de grupo

# Verificar grupos actuales
groups

# Si problema persiste: verificar AppArmor
sudo aa-status
# Deshabilitar perfil problemático (temporal):
sudo aa-complain /usr/bin/programa

Problema 6: SSH no conecta

Diagnóstico:

# 1. Verificar que SSH server corre
sudo systemctl status ssh

# Si no corre:
sudo systemctl start ssh

# 2. Verificar puerto
sudo ss -tulpn | grep :22

# 3. Test desde el propio servidor (localhost)
ssh localhost
# Si funciona: problema de red/firewall
# Si no funciona: problema de SSH config

# 4. Ver logs SSH
sudo journalctl -u ssh -f
# En otra terminal, intenta conectar y observa logs

# 5. Verificar firewall
sudo ufw status
sudo ufw allow 22/tcp

# 6. Test desde cliente con verbose
ssh -vvv usuario@IP
# Muestra debug completo, ver dónde falla

# 7. Verificar sshd_config
sudo nano /etc/ssh/sshd_config
# Verificar:
# Port 22
# PermitRootLogin no
# PubkeyAuthentication yes
# PasswordAuthentication yes

sudo systemctl restart ssh

# 8. Permisos SSH keys (si usas)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys

Mejores prácticas

Seguridad

  • Actualizar regularmente: sudo apt update && sudo apt upgrade semanal
  • Firewall activo: UFW configurado, solo puertos necesarios abiertos
  • SSH con keys: Deshabilitar password authentication
  • fail2ban: Banear IPs con intentos de login fallidos (instalar: sudo apt install fail2ban)
  • No correr servicios como root: Usar usuarios dedicados
  • Permisos mínimos: 644 para archivos, 755 para directorios y scripts
  • Backups automáticos: Cron + script, offsite si es producción

Mantenimiento

  • Monitorizar espacio en disco: Alertas cuando >80%
  • Limpiar logs antiguos: journalctl vacuum, logrotate
  • Eliminar paquetes huérfanos: sudo apt autoremove mensual
  • Verificar servicios críticos: systemctl --failed diario
  • Actualizar Docker images: docker compose pull && docker compose up -d
  • Test de backups: Restaurar periódicamente para verificar que funcionan

Documentación

  • Documentar cambios importantes: Archivo CHANGELOG.md o notas en wiki
  • Comentar scripts: Qué hace, por qué, cuándo se ejecuta
  • Inventario de servicios: Qué corre dónde, puertos, dependencias
  • Passwords en gestor: Vaultwarden, Bitwarden, 1Password (no en scripts plain text)

Recursos y siguiente nivel

Documentación oficial:

Comunidad:

Siguientes pasos:

  1. Práctica constante: Usa Linux como daily driver (WSL2, VM, o bare metal)
  2. Proyectos homelab: Aplica lo aprendido (Docker, Proxmox, Home Assistant)
  3. Scripting avanzado: Automatiza todo (backups, deployments, monitoring)
  4. Networking profundo: iptables, VLANs, VPN (WireGuard, OpenVPN)
  5. Contenedores: Docker mastery, Kubernetes (k3s para homelab)
  6. Infraestructura como código: Ansible, Terraform
  7. Monitorización avanzada: Prometheus, Grafana, Loki

Conclusión

Linux no es difícil, es diferente. Con esta guía dominas lo esencial para:

  • ✅ Instalar y configurar Ubuntu Server/Debian
  • ✅ Navegar terminal sin perderte
  • ✅ Gestionar permisos (el concepto MÁS importante)
  • ✅ Instalar software con apt
  • ✅ Gestionar servicios con systemd
  • ✅ Configurar redes y SSH
  • ✅ Automatizar con cron y bash scripts
  • ✅ Solucionar los 6 problemas más comunes
💪 Ahora puedes seguir CUALQUIER guía técnica:

Docker Compose, Proxmox, Home Assistant, n8n, todo asume estos conocimientos. Ya no te frenan comandos desconocidos. Practica, rompe cosas (en VMs), aprende, repite. En 2 semanas de uso diario dominarás Linux.

¡Bienvenido al mundo Linux! 🐧🚀

Por ziru

El Diario IA
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.