32blogby StudioMitsu

Guía práctica de chmod y chown: resuelve errores de permisos

Domina chmod y chown para controlar permisos y propiedad de archivos en Linux. Cubre modo octal y simbólico, cambios recursivos, setuid/setgid, sticky bit, umask y patrones del mundo real.

16 min read
Contenido

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:

  1. Propietario (Owner) — el usuario dueño del archivo
  2. Grupo (Group) — el grupo asociado al archivo
  3. Permisos (Permissions) — qué puede hacer cada categoría (propietario, grupo, otros)

Ejecuta ls -l y verás los tres:

bash
ls -l deploy.sh
# -rwxr-xr-- 1 furuya developers 2048 Mar 23 10:00 deploy.sh

Desglose de -rwxr-xr--:

PosiciónCaracteresSignificado
1-Tipo de archivo (- = archivo, d = directorio, l = enlace simbólico)
2-4rwxPermisos del propietario (lectura, escritura, ejecución)
5-7r-xPermisos del grupo (lectura, ejecución)
8-10r--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
bash: ./deploy.sh: Permission denied

Generalmente es por una de tres razones:

  1. El bit de ejecución no está activado (chmod +x deploy.sh)
  2. No eres el propietario y grupo/otros no tienen los permisos necesarios
  3. Un directorio padre bloquea el recorrido (falta x en 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.

OctalBinarioPermisosSignificado
7111rwxAcceso completo
6110rw-Lectura + escritura
5101r-xLectura + ejecución
4100r--Solo lectura
0000---Sin acceso
bash
# 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)
bash
# 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

bash
# 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

bash
# 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

bash
# 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:

bash
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

bash
# 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

bash
# 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í:

bash
# 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:

bash
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.

bash
# 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:

bash
# 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.

bash
# 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:

bash
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.

bash
# 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

BitPrefijo octalSimbólicoEn archivosEn directorios
setuid4u+sSe ejecuta como el propietario(sin efecto)
setgid2g+sSe ejecuta como el grupoArchivos nuevos heredan el grupo
sticky1+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:

bash
# 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.

bash
# 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:

Defectoumask 022Resultado
Archivos666 (rw-rw-rw-)022644 (rw-r--r--)
Directorios777 (rwxrwxrwx)022755 (rwxr-xr-x)

Valores de umask comunes:

umaskArchivosDirectoriosCaso de uso
022644755Defecto en la mayoría de sistemas
002664775Desarrollo compartido en grupo
077600700Máxima privacidad
027640750Seguridad equilibrada
bash
# 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:

bash
# 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)

bash
# 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:

bash
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

bash
# 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

bash
# 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

bash
#!/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

bash
# 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, directorios 2755, archivos 644
  • Claves SSH: chmod 600 privada, 644 pública, 700 directorio
  • Directorios compartidos: chown :group, chmod 2775 para escritura de grupo con setgid
  • Scripts: chmod +x para 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.