useradd vs adduser: Diferencias Técnicas, Casos de Uso y Cuándo Usar Cada Uno
`useradd` es una utilidad binaria de bajo nivel disponible en prácticamente todas las distribuciones Linux que crea cuentas de usuario escribiendo directamente en `/etc/passwd`, `/etc/shadow` y `/etc/group`. `adduser` es un script contenedor de nivel superior — típicamente escrito en Perl en sistemas basados en Debian — que llama a `useradd` internamente mientras automatiza la creación del directorio home, la población de archivos skeleton, la solicitud de contraseña y la recopilación de campos GECOS. La diferencia práctica no es solo ergonómica: elegir la herramienta incorrecta en un pipeline de aprovisionamiento automatizado o en un sistema que no sea Debian puede producir silenciosamente cuentas de usuario incompletas.
Ambos comandos en última instancia registran un usuario en la base de datos de autenticación del sistema, pero su comportamiento diverge significativamente en valores predeterminados, interactividad, portabilidad y capacidad de scripting. Esta guía cubre cada distinción técnica que un administrador necesita para tomar una decisión informada.
Lo que useradd realmente hace internamente
`useradd` es parte del paquete shadow-utils (a veces llamado `passwd` en distribuciones más antiguas). Cuando se invoca, realiza una serie de operaciones atómicas:
- Lee `/etc/login.defs` para determinar los rangos de UID predeterminados, las políticas de envejecimiento de contraseñas y si se debe crear un directorio home por defecto.
- Lee `/etc/default/useradd` para el shell predeterminado, la ruta del directorio skeleton y el comportamiento de grupos.
- Escribe una nueva entrada en `/etc/passwd` y `/etc/shadow`.
- Opcionalmente crea un directorio home y copia archivos desde `/etc/skel` si se pasa explícitamente `-m`.
- Opcionalmente crea un grupo privado que coincide con el nombre de usuario si `USERGROUPS_ENAB` está configurado como `yes` en `/etc/login.defs`.
Un punto crítico que muchas guías omiten: en las distribuciones basadas en Red Hat (RHEL, CentOS, Rocky Linux, AlmaLinux), `useradd` crea el directorio home por defecto porque `/etc/login.defs` establece `CREATE_HOME yes`. En Debian y Ubuntu, no lo hace — el indicador `-m` es obligatorio a menos que modifique `/etc/default/useradd`. Esta asimetría de comportamiento es una fuente frecuente de confusión cuando los administradores migran entre familias de distribuciones.
Indicadores clave y su comportamiento
| Indicador | Propósito | Notas |
|---|---|---|
| —— | ——— | ——- |
| `-m` | Crear directorio home | Requerido en Debian/Ubuntu sin cambio de configuración |
| `-d /path` | Establecer ruta de directorio home personalizada | No crea el directorio a menos que también se use `-m` |
| `-s /bin/bash` | Establecer shell de inicio de sesión | Por defecto es `/bin/sh` o el valor en `/etc/default/useradd` |
| `-u UID` | Asignar UID específico | Debe ser único; use `-o` para permitir duplicados |
| `-g GID` | Establecer grupo primario | El grupo debe existir previamente |
| `-G group1,group2` | Agregar grupos suplementarios | Separados por comas, sin espacios |
| `-e YYYY-MM-DD` | Fecha de expiración de la cuenta | Escrito en el campo 8 de `/etc/shadow` |
| `-f days` | Período de inactividad de contraseña | Días después de la expiración antes de que la cuenta sea bloqueada |
| `-r` | Crear cuenta de sistema | UID por debajo de `SYS_UID_MAX` en `/etc/login.defs`, sin directorio home por defecto |
| `-M` | No crear explícitamente el directorio home | Anula los valores predeterminados de la distribución |
| `-N` | No crear un grupo privado de usuario | El grupo primario del usuario se convierte en el grupo predeterminado |
| `-k /path` | Especificar directorio skeleton alternativo | Anula `/etc/skel` |
Ejemplo práctico de useradd con opciones completas
“`bash
useradd
-m
-d /srv/appuser
-s /bin/bash
-u 1500
-g developers
-G sudo,docker
-e 2025-12-31
-c "Application Service Account"
appuser
passwd appuser
“`
No se establece ninguna contraseña hasta que se llama a `passwd`. Hasta entonces, la cuenta existe pero está bloqueada — la entrada shadow contiene `!` como hash de contraseña, impidiendo el inicio de sesión mediante autenticación por contraseña. Sin embargo, el inicio de sesión basado en clave SSH no se ve afectado por este estado.
Lo que adduser realmente hace internamente
En Debian y Ubuntu, `adduser` es un script Perl ubicado en `/usr/sbin/adduser`. Lee su propia configuración desde `/etc/adduser.conf` — un archivo separado de `/etc/login.defs` — y luego llama a `useradd` con los indicadores apropiados basados en esa configuración más la entrada del usuario.
El script realiza pasos adicionales que `useradd` solo no hace:
- Solicita interactivamente una contraseña y la confirma con una segunda entrada.
- Recopila campos GECOS (nombre completo, número de habitación, teléfono del trabajo, teléfono del hogar, otros) mediante indicaciones guiadas.
- Copia archivos skeleton desde `/etc/skel` automáticamente sin requerir `-m`.
- Establece la propiedad y los permisos correctos en el directorio home.
- Opcionalmente agrega el usuario a grupos suplementarios definidos en `/etc/adduser.conf`.
En los sistemas basados en Red Hat, `adduser` es típicamente un enlace simbólico a `useradd`, lo que significa que se comporta de manera idéntica al binario de bajo nivel — no hay un contenedor interactivo. Este es el problema de portabilidad más importante al escribir scripts entre distribuciones.
Archivo de configuración de adduser: /etc/adduser.conf
Directivas clave en `/etc/adduser.conf` que afectan el comportamiento:
“`
DSHELL=/bin/bash # Default shell
DHOME=/home # Parent directory for home directories
GROUPHOMES=no # Whether to create group-named subdirectories
LETTERHOMES=no # Whether to use first-letter subdirectories
USERGROUPS=yes # Create a group with the same name as the user
USERS_GID=100 # Default GID if USERGROUPS=no
DIR_MODE=0755 # Permissions on new home directories
SETGID_HOME=no
QUOTAUSER=""
SKEL=/etc/skel
SKEL_IGNORE_REGEX="dpkg-(old|new|dist|tmp)"
“`
Modificar este archivo le permite estandarizar la creación de usuarios en una flota de servidores Debian/Ubuntu sin pasar indicadores cada vez.
Ejemplo práctico de adduser
“`bash
adduser customuser
“`
La sesión interactiva se ve así:
“`
Adding user 'customuser' …
Adding new group 'customuser' (1001) …
Adding new user 'customuser' (1001) with group 'customuser' …
Creating home directory '/home/customuser' …
Copying files from '/etc/skel' …
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for customuser
Enter the new value, or press ENTER for the default
Full Name []: Jane Smith
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] Y
“`
Para agregar un usuario existente a un grupo de forma no interactiva con `adduser`:
“`bash
adduser customuser sudo
“`
Esta es una característica notable: `adduser` funciona también como herramienta de gestión de membresía de grupos, lo cual `useradd` no replica en un solo comando.
Comparación lado a lado
| Característica | `useradd` | `adduser` |
|---|---|---|
| — | — | — |
| Tipo | Binario (programa en C) | Script (Perl en Debian, enlace simbólico en RHEL) |
| Interactividad | No interactivo; todas las opciones mediante indicadores | Indicaciones interactivas por defecto |
| Directorio home | No se crea a menos que se pase `-m` (Debian) | Se crea automáticamente |
| Configuración de contraseña | Requiere un comando `passwd` separado | Se solicita durante la creación |
| Campos GECOS | Se establecen mediante el indicador `-c` como una sola cadena | Se recopilan campo por campo de forma interactiva |
| Archivos skeleton | Se copian solo con el indicador `-m` | Siempre se copian |
| Archivo de configuración | `/etc/login.defs`, `/etc/default/useradd` | `/etc/adduser.conf` |
| Disponibilidad entre distribuciones | Todas las distribuciones Linux | Solo Debian/Ubuntu (como script contenedor) |
| Idoneidad para scripting | Excelente — completamente no interactivo | Deficiente — requiere los indicadores `–disabled-password` y `–gecos` para evitar indicaciones |
| Cuentas de sistema | Compatible mediante el indicador `-r` | Compatible mediante el indicador `–system` |
| Gestión de grupos | Solo en el momento de la creación | Puede agregar usuario a un grupo existente después de la creación |
| Granularidad | Control total sobre cada parámetro | Valores predeterminados con opinión, menos granular |
Cuándo usar useradd
Automatización e Infraestructura como Código
`useradd` es la opción correcta en cualquier contexto no interactivo: playbooks de Ansible, provisionadores de Terraform, instrucciones `RUN` de Docker, scripts de cloud-init y pipelines de CI/CD. Produce resultados deterministas sin dependencia de stdin.
“`bash
Ansible task equivalent
useradd -m -s /bin/bash -G sudo -c "Deploy User" deployuser
echo "deployuser:$(openssl passwd -6 'securepassword')" | chpasswd
“`
Portabilidad entre distribuciones
Cualquier script de shell destinado a ejecutarse tanto en sistemas basados en Debian como en RHEL debe usar `useradd`. Depender del comportamiento de `adduser` producirá fallos silenciosos o comportamiento inesperado en CentOS, Fedora, Rocky Linux o Alpine Linux.
Cuentas de sistema y servicio
Crear cuentas de servicio bloqueadas sin inicio de sesión para demonios es una especialidad de `useradd`:
“`bash
useradd -r -s /usr/sbin/nologin -d /var/lib/myservice -m myservice
“`
El indicador `-r` asigna un UID por debajo del umbral de cuentas de sistema, señala a los administradores que esta no es una cuenta de usuario humano, y es el patrón estándar para la implementación de aplicaciones en entornos de Hosting VPS donde el aislamiento de servicios es crítico.
Control preciso de UID/GID
En entornos NFS, orquestación de contenedores, o al sincronizar bases de datos de usuarios entre múltiples servidores, los UID y GID consistentes son obligatorios. `useradd -u 1500 -g 1500` garantiza esto; `adduser` no ofrece el mismo control determinista sin una configuración significativa.
Cuándo usar adduser
Configuración interactiva del servidor
Al aprovisionar manualmente un nuevo Servidor Dedicado y agregar las primeras cuentas de usuario humanas, `adduser` reduce el riesgo de una configuración incompleta. Las indicaciones guiadas hacen que sea casi imposible olvidar el paso de la contraseña.
Entornos Debian/Ubuntu con valores predeterminados estándar
Si toda su infraestructura ejecuta Debian o Ubuntu y está creando usuarios estándar con directorio home, `adduser` produce resultados correctos más rápido con menos indicadores que recordar.
Gestión de grupos posterior a la creación
La sintaxis `adduser username groupname` para agregar un usuario existente a un grupo existente es más limpia que `usermod -aG groupname username`, aunque ambas son válidas.
Incorporación de administradores junior
La naturaleza interactiva de `adduser` lo convierte en una mejor herramienta de enseñanza. Muestra los campos que importan (contraseña, nombre completo) y oculta la complejidad de los rangos de UID y los directorios skeleton hasta que el administrador esté listo para aprenderlos.
Casos límite críticos y trampas
La trampa del directorio home faltante
En Debian/Ubuntu, ejecutar `useradd username` sin `-m` crea el usuario pero no el directorio home. El usuario puede iniciar sesión (una vez que se establece una contraseña), pero `$HOME` no existirá, causando fallos en cualquier aplicación que escriba en el directorio home en el primer inicio de sesión — incluyendo `.bash_history`, `.ssh/authorized_keys` y muchos directorios de configuración de aplicaciones.
“`bash
Verify home directory existence after creation
ls -la /home/newuser || echo "Home directory missing — run: mkhomedir_helper newuser"
“`
Bloqueo del archivo shadow
Ambos comandos bloquean `/etc/shadow` durante las escrituras. En scripts de aprovisionamiento de alta concurrencia que crean docenas de usuarios simultáneamente, esto causa condiciones de carrera. Use una cola o ejecución secuencial al crear usuarios en masa.
Colisión de UID en entornos contenerizados
Al implementar aplicaciones en VPS con cPanel u otros entornos de panel de control, el propio panel gestiona la asignación de UID. Ejecutar `useradd` manualmente con un UID codificado puede colisionar con los UID asignados por el panel, causando errores de permisos en múltiples cuentas. Siempre verifique `getent passwd | awk -F: '{print $3}' | sort -n` antes de especificar un UID manualmente.
adduser –disabled-password para scripting
Si debe usar `adduser` en un script (por ejemplo, para aprovechar sus valores predeterminados de `/etc/adduser.conf`), suprima las indicaciones interactivas:
“`bash
adduser –disabled-password –gecos "Automated User,,," scriptuser
echo "scriptuser:$(openssl passwd -6 'password')" | chpasswd
“`
El indicador `–gecos` acepta una cadena separada por comas que coincide con los campos GECOS, eliminando todas las indicaciones interactivas.
Integración con PAM y NSS
Ni `useradd` ni `adduser` configuran módulos PAM ni entradas NSS (Name Service Switch) para LDAP, Active Directory u otros sistemas de autenticación centralizada. En servidores integrados con `sssd` o `winbind`, la creación de usuarios locales con cualquiera de los comandos crea cuentas que pueden entrar en conflicto con las cuentas del servicio de directorio o ser reemplazadas por ellas. Verifique `/etc/nsswitch.conf` antes de crear usuarios locales en sistemas unidos a un dominio.
Personalización de archivos skeleton
Ambos comandos copian desde `/etc/skel` por defecto. Para equipos que gestionan entornos de Hosting Web Compartido donde cada usuario necesita un `.bashrc`, `.vimrc` o configuración SSH preconfigurada, poblar `/etc/skel` antes de ejecutar cualquiera de los comandos es el enfoque correcto — no modificar archivos después de la creación de la cuenta.
Verificación de la creación de usuarios
Independientemente del comando que use, verifique el resultado:
“`bash
Check passwd entry
getent passwd newuser
Check shadow entry (requires root)
getent shadow newuser
Check group memberships
groups newuser
id newuser
Verify home directory and permissions
ls -la /home/newuser
Test login shell
su -s /bin/bash – newuser -c "echo login successful"
“`
Modificación y eliminación de usuarios
`useradd` y `adduser` solo crean cuentas. La gestión posterior a la creación utiliza diferentes comandos:
- `usermod` — Modificar atributos de usuario existentes (shell, grupos, directorio home, expiración).
- `userdel` / `deluser` — Eliminar cuentas. `deluser –remove-home username` en Debian también elimina el directorio home y el spool de correo.
- `passwd` — Establecer o cambiar contraseñas, bloquear/desbloquear cuentas.
- `chage` — Gestionar políticas de envejecimiento y expiración de contraseñas.
“`bash
Lock an account without deleting it
usermod -L username
Unlock
usermod -U username
Force password change on next login
chage -d 0 username
“`
Matriz de decisión práctica
Use esta lista de verificación para seleccionar el comando correcto:
- ¿El script se ejecuta en un sistema que no es Debian o necesita ser portable? Use `useradd`.
- ¿Es un entorno automatizado y no interactivo (CI/CD, Ansible, Docker)? Use `useradd`.
- ¿Necesita un UID/GID específico para consistencia en NFS o contenedores? Use `useradd -u -g`.
- ¿Está creando una cuenta de sistema/servicio sin shell de inicio de sesión? Use `useradd -r -s /usr/sbin/nologin`.
- ¿Está en Debian/Ubuntu, creando una cuenta de usuario humano estándar de forma interactiva? Use `adduser`.
- ¿Desea agregar un usuario existente a un grupo con un comando limpio de una línea? Use `adduser username groupname`.
- ¿Está escribiendo documentación o capacitando a personal junior en Debian? Use `adduser`.
- ¿Necesita personalizar la ubicación del directorio home, la expiración o el shell de forma no interactiva a escala? Use `useradd` con indicadores explícitos.
La higiene adecuada de cuentas de usuario es fundamental para la seguridad del servidor. Ya sea que esté gestionando un solo VPS o una flota de Servidores Dedicados, comprender exactamente qué escribe cada comando en el disco — y qué deja sin configurar — previene la clase de escaladas de privilegios y fallos de autenticación que se derivan de un aprovisionamiento de cuentas incompleto.
Preguntas frecuentes
¿useradd crea un directorio home por defecto?
Depende de la distribución. En sistemas basados en Red Hat (RHEL, CentOS, Rocky Linux), `CREATE_HOME yes` en `/etc/login.defs` hace que `useradd` cree el directorio home automáticamente. En Debian y Ubuntu, no se crea ningún directorio home a menos que pase explícitamente el indicador `-m`.
¿Está disponible adduser en CentOS o Rocky Linux?
En las distribuciones basadas en RHEL, `adduser` es un enlace simbólico a `useradd`, no el contenedor interactivo de Perl que se encuentra en Debian/Ubuntu. Ejecutar `adduser username` en CentOS se comporta de manera idéntica a `useradd username` — sin indicaciones, sin directorio home automático con los valores predeterminados al estilo Debian.
¿Cómo uso adduser de forma no interactiva en un script?
Pase `–disabled-password` para omitir la solicitud de contraseña y `–gecos ""` para omitir las indicaciones de campos GECOS: `adduser –disabled-password –gecos "" username`. Establezca la contraseña después con `echo "username:password" | chpasswd` o canalizando un hash `openssl passwd -6`.
¿Cuál es la diferencia entre /etc/login.defs y /etc/adduser.conf?
`/etc/login.defs` es el archivo de configuración de todo el sistema leído por `useradd`, `userdel` y `usermod` — controla los rangos de UID/GID, los valores predeterminados de envejecimiento de contraseñas y el comportamiento de creación del directorio home. `/etc/adduser.conf` es leído exclusivamente por los scripts Perl `adduser` y `deluser` en sistemas basados en Debian y controla valores predeterminados de nivel superior como el shell predeterminado, la ruta del directorio home padre y el directorio skeleton.
¿Puedo mezclar useradd y adduser de forma segura en el mismo servidor Debian?
Sí. Ambos en última instancia escriben en los mismos archivos `/etc/passwd`, `/etc/shadow` y `/etc/group`. Las cuentas creadas con cualquiera de los comandos son indistinguibles a nivel del sistema. La única preocupación práctica es la consistencia: si su equipo usa `adduser` de forma interactiva y un script de automatización usa `useradd` sin `-m`, puede terminar con algunos usuarios sin directorios home. Estandarice un enfoque por entorno y documéntelo.
