Claude para sysadmins: tareas diarias en servidores
Vea seis tareas donde Claude ayuda: leer logs de unidades fallidas, redactar unidades systemd y revisar archivos nginx y Compose, sin pegar secretos.
Claude para administradores de sistemas: primero el asesoramiento, después la ejecución
Claude funciona mejor como revisor para tareas de administración de sistemas. Pegue un fragmento de registro, un archivo de configuración, un comando que no reconozca o un mensaje de error, y obtendrá una explicación que puede comprobar antes de cambiar nada en el servidor. Una respuesta incorrecta no tiene consecuencias hasta que la ejecuta. Por eso, mantener el modelo en el lado del asesoramiento es la base de seguridad.
Cada semana aparecen seis tareas en un Linux VPS (servidor privado virtual) alquilado. A continuación se muestra un patrón de prompt que funciona para cada una, el comando que permite comprobar la respuesta y el modo de fallo que debe esperar. Ninguna requiere que el modelo tenga acceso al servidor.
El orden importa en un servidor de producción: lea la explicación, ejecute la comprobación usted mismo y después decida. La autonomía es adecuada en una VM de pruebas. En el servidor que presta servicio a sus clientes, la revisión es preferible, porque el modelo no puede ver el estado sobre el que está haciendo suposiciones.
Lo que nunca debe pegar
Todo lo incluido en el mensaje sale de su servidor. Hay cuatro categorías que deben permanecer en el equipo:
- Claves privadas:
~/.ssh/id_ed25519,/etc/ssh/ssh_host_*_keyy cualquier clave TLS (seguridad de la capa de transporte) situada bajo/etc/letsencrypt/live/. - Archivos de credenciales:
.env,~/.aws/credentials,/root/.docker/config.jsony las contraseñas de bases de datos incluidas en cualquier archivo o línea de registro. - Datos de cuentas:
/etc/shadowy/etc/gshadow. Ninguna pregunta de administración de sistemas necesita un hash de contraseña para responderla. - Cualquier dato perteneciente a sus usuarios: direcciones de correo electrónico, filas de pedidos, registros de solicitudes que contengan cookies de sesión o PII (información de identificación personal).
Las claves públicas se pueden pegar. Las claves privadas no. Además, ambos archivos pueden parecerse a simple vista, así que lea la primera línea antes de copiarla: un archivo cuya primera línea contenga BEGIN OPENSSH PRIVATE KEY nunca debe incluirse en un mensaje. Distinguir correctamente el material de sus claves SSH merece diez minutos por sí solo.
Redacte la información antes de pegarla, en lugar de confiar en que detectará un token entre 200 líneas:
sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'Hay una particularidad relacionada con Docker. docker compose config interpola los valores de .env en la salida que muestra, por lo que esa salida es un secreto aunque el archivo del disco no lo fuera. Use docker compose config -q, que valida la configuración y no muestra ninguna salida. Para consultar la política general sobre lo que un agente puede ver, mantener los secretos fuera de los agentes de IA explica la parte relacionada con el entorno.
Trabajo 1: ¿por qué falló este servicio?
Empiece con los dos comandos que contienen la respuesta:
systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-isoPegue ambos comandos junto con el contexto que el modelo no puede deducir: la distribución y la versión, qué cambió por última vez, si alguna vez funcionó y hace cuánto dejó de funcionar. Pida primero el mecanismo.
Ubuntu 24.04.myapp.servicefuncionaba hasta que edité la unidad hace una hora. Aquí estánsystemctl statusy las últimas 100 líneas del journal. ¿Qué línea es el primer error real y qué significa? Todavía no quiero una solución.
«Todavía no quiero una solución» cumple una función importante en esa solicitud. Los registros ocultan el primer fallo entre los reintentos que este provoca, por lo que un modelo al que se le pide una solución explicará la última línea que encuentre. La línea importante suele estar veinte líneas antes del ruido.
El resultado puede ser una línea como Main PID: 1841 (code=exited, status=203/EXEC). El estado de salida 203/EXEC significa que el kernel no pudo ejecutar el archivo indicado en ExecStart: la ruta no existe, o el archivo existe pero no tiene permisos de ejecución. Una línea #! que indique un intérprete no instalado produce el mismo estado. Todo esto se puede comprobar con ls -l y head -1.
Modo de fallo: una causa inventada. Si pega muy poco contenido, el modelo completa la información que falta con algo genérico, como «el puerto ya está en uso». La solución es hacer una pregunta de seguimiento: «¿Qué línea de lo que te proporcioné respalda eso?». Una causa que nadie puede señalar en el texto es una suposición.
Redactar una unidad de systemd o una entrada de cron
Incluya los datos que necesita el archivo de unidad: el comando exacto, el usuario con el que se ejecuta, el directorio de trabajo, si debe esperar a la red y qué debe ocurrir cuando termine con un código distinto de cero. Después, compruebe el resultado antes de habilitar nada.
sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pagersystemd-analyze verify analiza el archivo del mismo modo que systemd, por lo que detecta errores que pueden pasar inadvertidos. Una directiva mal escrita muestra /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.. Si falta un binario, muestra Command /usr/local/bin/myapp is not executable: No such file or directory. Ambos errores permanecen ocultos durante daemon-reload. Por eso una unidad puede cargarse correctamente y fallar en el momento de ejecutarse.
Hay dos errores de redacción que se repiten. El primero es After=network.target. Esto sólo indica que la pila de red está configurada, no que ya exista una dirección. Un servicio que se enlaza a una IP concreta falla durante el arranque con bind: Cannot assign requested address. La solución es Wants=network-online.target junto con After=network-online.target. El segundo es Type=simple para un programa que se convierte en daemon: systemd considera que el primer proceso es el servicio, el proceso padre termina de inmediato y la unidad se marca como inactiva mientras el proceso real sigue ejecutándose sin gestión.
Para una planificación, compruébela en lugar de interpretarla:
systemd-analyze calendar 'Mon *-*-* 04:00:00'Esto muestra la forma normalizada y la próxima hora en la que se ejecutará la expresión. Así se resuelve cualquier duda sobre su significado. Si está eligiendo entre un timer y un crontab, servicios y timers de systemd en un VPS explica las diferencias.
Cron tiene una particularidad que ningún modelo le advertirá si no se lo pide. Cron ejecuta los trabajos con un entorno mínimo, por lo que PATH es aproximadamente /usr/bin:/bin y nunca se lee el perfil del shell. Un trabajo que funciona al pegarlo en el terminal falla con cron y muestra /bin/sh: 1: docker: not found, porque ese binario está en /usr/local/bin. Use rutas absolutas en los crontabs.
Trabajo 3: revisar un archivo de nginx o Compose antes de ponerlo en producción
Este trabajo ofrece el mejor rendimiento. Pegue el archivo, indique qué debería hacer y pida una explicación línea por línea de lo que hace realmente.
Este vhost debe servirexample.commediante HTTPS y enviar/apia un servicio local en el puerto 8080. Léalo de nuevo y señale cualquier elemento que no coincida con esa descripción.
A continuación, ejecute la herramienta que conoce la sintaxis:
sudo nginx -t
docker compose config -qnginx -t muestra nginx: configuration file /etc/nginx/nginx.conf test is successful o indica el archivo y la línea, como en nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12. docker compose config -q no muestra nada cuando el archivo se analiza correctamente, y muestra algo directo como yaml: line 7: did not find expected key cuando la indentación es incorrecta.
Ninguna de las dos herramientas comprueba la intención. Una configuración que supera nginx -t todavía puede enviar las peticiones al puerto incorrecto o escuchar en 0.0.0.0 cuando pretendía hacerlo en 127.0.0.1. Esa diferencia es donde el modelo resulta útil, pero también donde falla: si le pide corregir una directiva, a menudo devuelve el archivo completo reescrito y elimina silenciosamente dos de sus directivas. Pida las líneas modificadas y el motivo de cada cambio. Después, edite el archivo manualmente.
Confirme qué ha expuesto realmente:
sudo ss -tulpnSin sudo puede ver los sockets en escucha, pero no los procesos que los poseen. Si esa salida le sorprende, qué son los puertos y cómo los enlaza Linux es una explicación más breve.
Tarea 4: explique un comando desconocido antes de ejecutarlo
Pegue el comando y haga cuatro preguntas sobre él: qué hace cada opción, qué escribe, qué elimina y qué ocurre si lo ejecuto dos veces. La última pregunta detecta más daños que las demás.
Considere find /var/log -name '*.gz' -mtime +7 -delete. Una buena respuesta le indica que -mtime +7 cuenta períodos completos de 24 horas y descarta la fracción, por lo que coincide con archivos que tienen al menos ocho días, no siete. También le indica que find evalúa su expresión de izquierda a derecha, por lo que colocar -delete delante de -name elimina todo lo que haya bajo la ruta inicial. El segundo punto aparece como advertencia en la página de manual de find y ha costado a algunas personas su /var/log.
Considere también rsync -a --delete /srv/app/ /backup/app/. La barra final de la ruta de origen significa «el contenido de este directorio». Si la quita, obtiene /backup/app/app/. Si añade --delete, se elimina todo lo que falte en el destino respecto al origen. Esto es correcto para un espejo y desastroso si la ruta de origen es incorrecta.
Verifíquelo con la herramienta, no con el modelo:
rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7Ejecute find sin -delete para obtener una lista en lugar de perder datos.
Modo de fallo: alucinación de opciones. El modelo es fiable con herramientas que tienen treinta años de documentación y mucho menos fiable con las interfaces de línea de comandos de los proveedores y los subcomandos recientes. En esos casos, produce una opción que parece correcta pero no existe. --help lo confirma en un segundo. Las comillas son otro punto débil. Por eso, cuando un comando contiene una expresión $(...), lea cómo se expande la sustitución de comandos antes de ejecutar el comando en lugar de confiar en la explicación.
Trabajo 5: convierta el historial del shell en un procedimiento operativo
Acaba de dedicar dos horas a conseguir que algo funcionara. Ese conocimiento está en el desplazamiento de la terminal y desaparecerá el mes que viene.
history 200 > /tmp/session.txtLea ese archivo y elimine todas las líneas que contengan una contraseña, un token o un identificador de cliente antes de compartirlo. El historial del shell es uno de los lugares más fiables para encontrar un secreto en un sistema Linux, porque todo el mundo escribe alguno en línea al menos una vez. Establezca HISTCONTROL=ignorespace en ~/.bashrc y los comandos escritos con un espacio inicial no se guardarán en el historial.
El prompt que produce un procedimiento operativo útil solicita comprobaciones, no sólo pasos:
Esta es una sesión de shell que convirtió un sistema Debian 13 recién instalado en una instalación funcional de Postgres. Documenta el proceso como un procedimiento operativo numerado. Incluye un comando por paso. Después de cada paso, indica el comando que demuestra que funcionó y describe cómo debería ser una salida correcta. Marca los pasos que dependieron de mi host concreto.
Modo de fallo: una historia ordenada. En su sesión hubo un paso que hizo mal dos veces antes de corregirlo, y ese es el paso que el modelo suaviza porque la transcripción parece más limpia sin él. Compare el procedimiento operativo con el historial y vuelva a incluir la corrección. También inventa comandos de verificación plausibles, así que ejecute todas las comprobaciones que escriba antes de guardar el archivo. Si el procedimiento operativo cubre el primer arranque, compárelo con los primeros diez minutos en un VPS nuevo para no documentar una versión peor de un problema ya resuelto.
Trabajo 6: convertir un mensaje de error en una solución
Pegue la cadena exacta, el comando que la produjo y el único cambio realizado antes de que apareciera. Solicite una lista ordenada de causas con un comando de comprobación para cada una. Esto obliga a que la respuesta se pueda probar.
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). Ordena las causas probables y dame un comando por causa que la confirme o la descarte.
En este error, el mecanismo no es ambiguo: otro proceso ya ocupa el puerto 80 y sudo ss -tulpn | grep ':80 ' identifica cuál es. A menudo se trata de un segundo proceso maestro de nginx que quedó activo tras una recarga fallida, o de Apache, que se instaló como dependencia y se inició mediante su propio paquete.
Modo de fallo: una solución que funciona ocultando la causa. chmod 777, --privileged, deshabilitar SELinux y ejecutar el servicio como root hacen que el error desaparezca. Rechace cualquier solución que amplíe los permisos hasta que el modelo haya explicado por qué falló el permiso limitado. Esa explicación es la respuesta real. Una solución alternativa sólo silencia el error.
Lo que suele hacer mal
- No puede ver su servidor. Cada respuesta depende de lo que haya pegado, y no le indicará que el fragmento era demasiado corto.
- Pierde precisión con las versiones. Los nombres de los paquetes y las opciones predeterminadas cambian entre distribuciones y versiones, y el modelo hace una media de todas ellas.
- Se expresa con fluidez cuando se equivoca. Un mecanismo inventado se lee exactamente como uno correcto. Por eso, cada causa anterior incluye un comando para comprobarla.
- Pierde el hilo en sesiones largas. Los datos del inicio de una conversación de dos horas dejan de influir en las respuestas del final.
Este último punto es más un problema operativo que del modelo. La solución práctica es gestionar el contexto en una sesión larga de Claude Code: sesiones más cortas y una tarea por sesión.
Instalar el agente en el propio servidor
Todo lo anterior consiste en copiar y pegar, por lo que el modelo nunca interactúa con su máquina. Cuando se ejecuta en el servidor, lee archivos y ejecuta comandos. La naturaleza del riesgo cambia: un comando incorrecto puede dejar un servicio fuera de línea. Asígnele un usuario sin privilegios en lugar de root, manténgalo fuera del servidor de producción mientras conoce su comportamiento y cree primero una instantánea. Ejecutar Claude Code de forma segura en un VPS explica el aislamiento y el modelo de permisos. Ejecutar Claude Code dentro de tmux resuelve la otra mitad, porque una sesión SSH (secure shell) interrumpida termina un agente en primer plano mientras todavía está trabajando. Cree la cuenta como lo haría con cualquier cuenta de servicio. usuarios con privilegios mínimos en un VPS describe este proceso.
FAQ
¿Claude puede leer directamente los registros de mi servidor?
No por sí solo. La interfaz de chat sólo ve el texto que pega en ella. Claude Code, ejecutado en el servidor como herramienta de línea de comandos, puede leer archivos y ejecutar comandos con los permisos del usuario que lo inició. Esto implica una decisión de confianza más importante. Para una consulta de soporte habitual, pegar un fragmento de 100 líneas con los datos sensibles ocultos es más rápido y seguro que conceder acceso de shell a un agente.
¿Qué no debo pegar nunca de un servidor?
Claves privadas, archivos `.env y otros almacenes de credenciales, /etc/shadow, y cualquier dato perteneciente a sus usuarios. Oculte los tokens de los fragmentos de registros antes de incluirlos en el prompt. Hay un caso menos evidente: la salida de docker compose config incluye interpolados sus valores de .env, por lo que debe usar docker compose config -q`, que valida el archivo y no muestra ninguna salida.
¿Es seguro permitir que Claude ejecute comandos en un VPS de producción?
Trátelo como a un administrador nuevo que no conoce el entorno: puede leer, pero escribir requiere revisión. En producción, pida la explicación y ejecute el comando usted mismo. Si quiere que un agente ejecute comandos, asígnele una cuenta sin privilegios dedicada y sin acceso general mediante sudo. Empiece en un sistema de staging, donde un error obligue a reconstruirlo en lugar de provocar una interrupción del servicio.
¿Por qué Claude sugiere un indicador que no existe?
Porque predice texto plausible, y un indicador plausible tiene el mismo aspecto que uno real. Ocurre sobre todo con las CLI de los proveedores y los subcomandos más recientes, cuya documentación disponible para el modelo es escasa o ha cambiado desde entonces. `--help y man` son la referencia definitiva. Cualquier comando que elimine o sobrescriba datos debe probarse primero con una ejecución en seco.
¿Cómo compruebo una unidad de systemd antes de habilitarla?
Ejecute `sudo systemd-analyze verify /etc/systemd/system/myapp.service. Analiza el archivo con el propio analizador de systemd, informa de las directivas desconocidas junto con sus números de línea y señala si falta un binario ExecStart o no es ejecutable. Después ejecute daemon-reload, start y lea systemctl status antes de enable` la unidad, porque una unidad que se carga correctamente todavía puede fallar en su primera ejecución.