chmod define qué acciones se pueden realizar sobre un archivo. chown define quién es el dueño. Juntos forman el modelo de permisos de Linux — la propiedad establece la identidad, los permisos establecen la capacidad.
En resumen: chmod 755 script.sh da acceso completo al propietario y lectura+ejecución al resto. chown deploy:www-data /var/www cambia el propietario y el grupo de un archivo. Añade -R para cambios recursivos. Usa umask para controlar los permisos por defecto de archivos nuevos.
Cómo funcionan realmente los permisos en Linux
Cada archivo y directorio en Linux tiene tres componentes de metadatos:
- Propietario (Owner) — el usuario dueño del archivo
- Grupo (Group) — el grupo asociado al archivo
- Permisos (Permissions) — qué puede hacer cada categoría (propietario, grupo, otros)
Ejecuta ls -l y verás los tres:
ls -l deploy.sh
# -rwxr-xr-- 1 furuya developers 2048 Mar 23 10:00 deploy.sh
Desglose de -rwxr-xr--:
| Posición | Caracteres | Significado |
|---|---|---|
| 1 | - | Tipo de archivo (- = archivo, d = directorio, l = enlace simbólico) |
| 2-4 | rwx | Permisos del propietario (lectura, escritura, ejecución) |
| 5-7 | r-x | Permisos del grupo (lectura, ejecución) |
| 8-10 | r-- | Permisos de otros (solo lectura) |
furuya es el propietario, developers es el grupo. Cualquiera en el grupo developers recibe los permisos de grupo. El resto obtiene los permisos de "otros".
Por qué ocurren los errores de permisos
El error de permisos más común que veo en servidores:
bash: ./deploy.sh: Permission denied
Generalmente es por una de tres razones:
- El bit de ejecución no está activado (
chmod +x deploy.sh) - No eres el propietario y grupo/otros no tienen los permisos necesarios
- Un directorio padre bloquea el recorrido (falta
xen algún directorio de la ruta)
En un servidor de staging de 32blog, pasé 20 minutos depurando por qué Nginx no podía servir archivos estáticos. Los archivos tenían permisos 644 (correcto), pero el directorio /var/www/32blog era 700 — el usuario www-data de Nginx no podía ni entrar al directorio. Lo cambié a 755 y todo funcionó.
chmod: permisos con números y símbolos
chmod tiene dos estilos de sintaxis. Usa el que te resulte más natural — hacen exactamente lo mismo.
Modo octal (numérico)
Cada permiso corresponde a un número: lectura = 4, escritura = 2, ejecución = 1. Suma por categoría.
| Octal | Binario | Permisos | Significado |
|---|---|---|---|
7 | 111 | rwx | Acceso completo |
6 | 110 | rw- | Lectura + escritura |
5 | 101 | r-x | Lectura + ejecución |
4 | 100 | r-- | Solo lectura |
0 | 000 | --- | Sin acceso |
# Propietario: rwx, Grupo: r-x, Otros: r-x
chmod 755 deploy.sh
# Propietario: rw-, Grupo: r--, Otros: r--
chmod 644 config.yaml
# Propietario: rwx, Grupo: ---, Otros: ---
chmod 700 ~/.ssh
# Propietario: rw-, Grupo: rw-, Otros: ---
chmod 660 shared-log.txt
Modo simbólico
En vez de números, usa letras. El formato es [quién][operador][permisos]:
- Quién:
u(usuario/propietario),g(grupo),o(otros),a(todos) - Operador:
+(añadir),-(quitar),=(establecer exactamente) - Permisos:
r(lectura),w(escritura),x(ejecución)
# Añadir permiso de ejecución para todos
chmod a+x deploy.sh
# Quitar permiso de escritura a grupo y otros
chmod go-w config.yaml
# Establecer permisos exactos para propietario, lectura+ejecución para el resto
chmod u=rwx,go=rx deploy.sh # Igual que chmod 755
# Añadir permiso de escritura solo al grupo
chmod g+w shared-project/
El modo simbólico destaca cuando quieres cambiar solo una cosa sin tocar el resto. chmod g+w file añade escritura al grupo sin afectar nada más. Con modo octal necesitarías conocer los permisos actuales primero.
Cambios recursivos con -R
# Establecer directorios en 755 y archivos en 644 — estándar para servidores web
chmod -R 755 /var/www/32blog/
# Pero esto hace los archivos ejecutables también. Mejor enfoque:
find /var/www/32blog -type d -exec chmod 755 {} +
find /var/www/32blog -type f -exec chmod 644 {} +
Patrones útiles de chmod
# Hacer un script ejecutable
chmod +x scripts/deploy.sh
# Proteger tus claves SSH (SSH se niega a usar claves con permisos relajados)
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 700 ~/.ssh
# Archivos de aplicación web
find /var/www/app -type d -exec chmod 755 {} +
find /var/www/app -type f -exec chmod 644 {} +
# Directorio compartido donde los miembros del grupo pueden escribir
chmod 775 /opt/shared-project/
# Eliminar todos los permisos de otros
chmod o= sensitive-data/
chown: cambiar el propietario de archivos
chown cambia quién es el dueño de un archivo y a qué grupo pertenece. A diferencia de chmod, normalmente necesitas sudo para ejecutar chown — no puedes ceder la propiedad de tus archivos a otro usuario sin privilegios de root.
Sintaxis básica
# Cambiar solo el propietario
sudo chown deploy deploy.sh
# Cambiar propietario y grupo
sudo chown deploy:www-data /var/www/32blog/
# Cambiar solo el grupo (dos puntos antes del nombre del grupo, sin propietario)
sudo chown :www-data /var/www/32blog/index.html
# Lo mismo pero usando chgrp
sudo chgrp www-data /var/www/32blog/index.html
La sintaxis usuario:grupo resuelve el caso más común en un solo comando. Cuando configuro un nuevo despliegue de 32blog, lo primero que ejecuto es:
sudo chown -R deploy:www-data /var/www/32blog
Esto da la propiedad al usuario deploy (para que los scripts de despliegue puedan escribir archivos) y acceso al grupo www-data (para que Nginx pueda leerlos).
Cambios recursivos de propiedad
# Cambiar propietario y grupo para todo un árbol de directorios
sudo chown -R deploy:www-data /var/www/32blog/
# Cambiar solo el grupo recursivamente
sudo chown -R :developers /opt/project/
# Modo verbose — ver qué se cambia
sudo chown -Rv deploy:www-data /var/www/32blog/
Copiar propiedad de otro archivo
# Hacer que target.conf coincida con la propiedad de reference.conf
sudo chown --reference=reference.conf target.conf
Muy útil cuando creas archivos de configuración que necesitan coincidir con los existentes.
Manejo de enlaces simbólicos
Por defecto, chown sigue los enlaces simbólicos y cambia el archivo destino. Usa -h para cambiar el enlace en sí:
# Cambia la propiedad del archivo destino del enlace
sudo chown deploy:www-data /var/www/current
# Cambia la propiedad del enlace simbólico en sí
sudo chown -h deploy:www-data /var/www/current
Permisos especiales: setuid, setgid y sticky bit
Más allá del rwx básico, Linux tiene tres bits de permisos especiales. Los vas a encontrar en producción y necesitas entenderlos para auditorías de seguridad.
setuid (Set User ID)
Cuando se activa en un ejecutable, se ejecuta como el propietario del archivo en vez del usuario que lo lanzó. El ejemplo clásico:
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 Mar 23 10:00 /usr/bin/passwd
Esa s en la posición de ejecución del propietario indica que setuid está activo. passwd se ejecuta como root aunque un usuario normal lo lance — porque necesita escribir en /etc/shadow. La página man de chmod documenta estos bits especiales en detalle.
# Activar el bit setuid
chmod u+s /usr/local/bin/my-tool
# O con octal (prefijo 4)
chmod 4755 /usr/local/bin/my-tool
# Desactivar setuid
chmod u-s /usr/local/bin/my-tool
setgid (Set Group ID)
En ejecutables, funciona como setuid pero para el grupo. Se usa más comúnmente en directorios — los archivos creados dentro heredan el grupo del directorio:
# Crear un directorio de proyecto compartido
sudo mkdir /opt/team-project
sudo chown :developers /opt/team-project
sudo chmod 2775 /opt/team-project
# Ahora cualquier archivo creado dentro obtiene el grupo "developers"
touch /opt/team-project/notes.txt
ls -l /opt/team-project/notes.txt
# -rw-rw-r-- 1 furuya developers 0 Mar 23 10:00 notes.txt
Sin setgid, el archivo obtendría el grupo primario del usuario que lo creó, rompiendo el acceso compartido.
# Verificar setgid en un directorio
ls -ld /opt/team-project
# drwxrwsr-x 2 root developers 4096 Mar 23 10:00 /opt/team-project
# ^ la 's' indica que setgid está activo
Sticky bit
Evita que los usuarios borren archivos que no les pertenecen, incluso si tienen permiso de escritura en el directorio. /tmp es el ejemplo clásico:
ls -ld /tmp
# drwxrwxrwt 15 root root 4096 Mar 23 10:00 /tmp
# ^ la 't' indica que el sticky bit está activo
Todos pueden escribir en /tmp, pero solo puedes borrar tus propios archivos.
# Activar sticky bit
chmod +t /opt/shared-uploads/
# O con octal (prefijo 1)
chmod 1777 /tmp
# Desactivar sticky bit
chmod -t /opt/shared-uploads/
Tabla de referencia rápida
| Bit | Prefijo octal | Simbólico | En archivos | En directorios |
|---|---|---|---|---|
| setuid | 4 | u+s | Se ejecuta como el propietario | (sin efecto) |
| setgid | 2 | g+s | Se ejecuta como el grupo | Archivos nuevos heredan el grupo |
| sticky | 1 | +t | (sin efecto) | Solo los dueños pueden borrar sus archivos |
Encontrar archivos con permisos especiales
Las auditorías de seguridad frecuentemente requieren localizar binarios con setuid/setgid:
# Encontrar todos los archivos setuid
find / -perm -4000 -type f 2>/dev/null
# Encontrar todos los archivos setgid
find / -perm -2000 -type f 2>/dev/null
# Encontrar ambos
find / -perm /6000 -type f 2>/dev/null
Ejecuto estos comandos en cada servidor que configuro para la infraestructura de 32blog. Binarios setuid inesperados son una señal de alerta.
umask: controlar los permisos por defecto
Cada vez que creas un archivo o directorio, el sistema aplica una umask — una máscara que resta permisos de los valores por defecto. El defecto es 666 para archivos y 777 para directorios.
# Ver tu umask actual
umask
# 0022
# Con salida simbólica
umask -S
# u=rwx,g=rx,o=rx
Cómo funciona el cálculo de umask
La umask resta permisos del valor por defecto:
| Defecto | umask 022 | Resultado | |
|---|---|---|---|
| Archivos | 666 (rw-rw-rw-) | 022 | 644 (rw-r--r--) |
| Directorios | 777 (rwxrwxrwx) | 022 | 755 (rwxr-xr-x) |
Valores de umask comunes:
| umask | Archivos | Directorios | Caso de uso |
|---|---|---|---|
022 | 644 | 755 | Defecto en la mayoría de sistemas |
002 | 664 | 775 | Desarrollo compartido en grupo |
077 | 600 | 700 | Máxima privacidad |
027 | 640 | 750 | Seguridad equilibrada |
# Establecer umask para la sesión actual
umask 027
# Probarlo
touch test-file
mkdir test-dir
ls -l test-file # -rw-r----- (640)
ls -ld test-dir # drwxr-x--- (750)
Hacer umask persistente
La umask se reinicia con cada nueva sesión de shell. Para hacerla permanente, añádela a tu perfil de shell:
# Para bash
echo "umask 027" >> ~/.bashrc
# Para zsh
echo "umask 027" >> ~/.zshrc
# A nivel de sistema (todos los usuarios)
echo "umask 027" >> /etc/profile
Para servicios del sistema, la umask del perfil de shell no aplica. Configúrala en el archivo de unidad systemd con UMask=027 en la sección [Service].
Patrones de permisos en la vida real
Estos son los patrones que realmente uso en servidores de producción y máquinas de desarrollo.
Configuración de servidor web (Nginx + usuario de despliegue)
# Crear el directorio raíz web
sudo mkdir -p /var/www/32blog
sudo chown -R deploy:www-data /var/www/32blog
# Establecer permisos
find /var/www/32blog -type d -exec chmod 2755 {} +
find /var/www/32blog -type f -exec chmod 644 {} +
# Directorios donde la app necesita escribir (subidas, caché)
chmod 2775 /var/www/32blog/.next/cache
El 2755 en directorios activa el bit setgid — los archivos creados por el proceso de despliegue heredarán automáticamente el grupo www-data, así Nginx siempre podrá leerlos.
Permisos de claves SSH
SSH es estricto con los permisos y se negará a usar claves con permisos demasiado abiertos:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 # Clave privada
chmod 644 ~/.ssh/id_ed25519.pub # Clave pública
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config
Si ves WARNING: UNPROTECTED PRIVATE KEY FILE!, esta es la razón.
Directorio de desarrollo compartido
# Crear espacio de proyecto compartido
sudo mkdir -p /opt/projects/32blog
sudo chown -R :developers /opt/projects/32blog
sudo chmod -R 2775 /opt/projects/32blog
# Asegurar que todos los miembros del equipo estén en el grupo
sudo usermod -aG developers furuya
sudo usermod -aG developers colleague
La combinación 2775 + setgid significa: todos en developers pueden leer y escribir, y los archivos nuevos automáticamente pertenecen al grupo developers.
Docker y permisos de contenedores
# Solucionar problemas comunes de permisos en volúmenes Docker
# Cuando el contenedor ejecuta como UID 1000 pero los archivos del host son de root
sudo chown -R 1000:1000 ./docker-volumes/
# Patrón en Dockerfile para usuario no-root
# RUN useradd -r -u 1000 appuser && \
# chown -R appuser:appuser /app
Script de corrección de permisos para un despliegue Next.js
#!/bin/bash
# fix-permissions.sh — Ejecutar después de desplegar 32blog
set -euo pipefail
WEBROOT="/var/www/32blog"
OWNER="deploy"
GROUP="www-data"
echo "Corrigiendo propiedad..."
sudo chown -R "${OWNER}:${GROUP}" "${WEBROOT}"
echo "Estableciendo permisos de directorios..."
find "${WEBROOT}" -type d -exec chmod 2755 {} +
echo "Estableciendo permisos de archivos..."
find "${WEBROOT}" -type f -exec chmod 644 {} +
echo "Haciendo scripts ejecutables..."
find "${WEBROOT}/scripts" -name "*.sh" -exec chmod 755 {} +
echo "Listo. Permisos corregidos para ${WEBROOT}"
Auditoría de permisos
# Encontrar archivos escribibles por todos (riesgo de seguridad)
find /var/www -perm -o=w -type f 2>/dev/null
# Encontrar archivos sin propietario (huérfanos — generalmente de usuarios eliminados)
find / -nouser -o -nogroup 2>/dev/null
# Encontrar archivos modificados en las últimas 24 horas (respuesta a incidentes)
find /var/www -mtime -1 -type f -ls
# Listar binarios setuid/setgid
find / -perm /6000 -type f -ls 2>/dev/null
FAQ
¿Qué hace exactamente chmod 777, y por qué debo evitarlo?
chmod 777 otorga a todos los usuarios del sistema acceso completo de lectura, escritura y ejecución. Básicamente anula el modelo de permisos de Linux. En un servidor web, cualquier proceso comprometido podría modificar tu código. El único uso legítimo es /tmp (protegido por el sticky bit). En vez de 777, identifica qué usuario o grupo necesita acceso y configura los permisos específicamente — chmod 775 con la propiedad de grupo adecuada resuelve la mayoría de los problemas de "permission denied".
¿Cuál es la diferencia entre chmod y chown?
chmod controla qué se puede hacer (leer, escribir, ejecutar). chown controla quién es el dueño (usuario y grupo). Funcionan juntos: primero estableces la propiedad con chown para definir la identidad, luego los permisos con chmod para definir las capacidades. Puedes usar chmod siendo el propietario del archivo, pero chown generalmente requiere root.
¿Cómo soluciono "Permission denied" al ejecutar un script?
Primero verifica si el bit de ejecución está activado: ls -l script.sh. Si ves -rw-r--r-- (sin x), añádelo con chmod +x script.sh. Si el script sigue fallando, revisa los directorios padre — necesitas permiso de ejecución en cada directorio de la ruta desde / hasta el script.
¿Debo usar modo octal (755) o simbólico (u=rwx,go=rx)?
Ambos producen resultados idénticos. El octal es más rápido de escribir y más común en documentación. El simbólico es más legible y más seguro para cambios selectivos — chmod g+w file añade escritura al grupo sin tocar nada más. La mayoría de administradores de sistemas usan octal para establecer permisos completos y simbólico para ajustar bits individuales.
¿Cómo verifico los permisos actuales de un archivo?
ls -l file muestra permisos en formato simbólico. Para verlos en octal, usa stat -c "%a %n" file en Linux o stat -f "%Lp %N" file en macOS. Para ACLs (listas de control de acceso más allá de los permisos básicos), usa getfacl file.
¿Qué significa la 's' en la salida de permisos?
Indica setuid (en la posición del propietario) o setgid (en la posición del grupo). rwsr-xr-x significa que el archivo se ejecuta como el propietario sin importar quién lo ejecute — usado por comandos del sistema como passwd que necesitan acceso root. En directorios, setgid (rws en la posición del grupo) hace que los archivos nuevos hereden el grupo del directorio.
¿Por qué SSH se queja de los permisos de mis claves?
SSH impone permisos estrictos por seguridad. Las claves privadas deben ser 600 (solo lectura/escritura del propietario), el directorio .ssh debe ser 700, y authorized_keys debe ser 600. Si cualquiera de estos es demasiado permisivo, SSH se niega a usarlos. Ejecuta chmod 600 ~/.ssh/id_* y chmod 700 ~/.ssh para solucionarlo.
¿Cuándo debo usar ACLs en vez de chmod?
Cuando necesitas más de tres categorías de permisos (propietario, grupo, otros). Los permisos estándar solo pueden asignar un grupo a un archivo. Las ACLs (setfacl/getfacl) te permiten establecer permisos diferentes para múltiples usuarios y grupos específicos. Caso común: un archivo necesita acceso de lectura para el grupo A y lectura/escritura para el grupo B. Los permisos estándar no pueden hacer esto — las ACLs sí. Red Hat tiene una buena introducción a las ACLs en Linux si quieres profundizar.
Conclusión
Los permisos en Linux se reducen a dos preguntas: "¿de quién es esto?" (chown) y "¿qué pueden hacer?" (chmod). Los patrones que vas a usar el 90% del tiempo:
- Servidores web:
chown deploy:www-data, directorios2755, archivos644 - Claves SSH:
chmod 600privada,644pública,700directorio - Directorios compartidos:
chown :group,chmod 2775para escritura de grupo con setgid - Scripts:
chmod +xpara hacerlos ejecutables
Empieza con el principio de mínimo privilegio — otorga los permisos mínimos necesarios. Cuando algo falle, ls -l y stat son tus herramientas de diagnóstico. Y si necesitas buscar problemas de permisos en todo tu sistema de archivos, find con -perm puede rastrearlos.