Son las 11 de la noche. Llevas media hora debugueando con la IA un 500 en un endpoint que nunca te había fallado: le pegas el log, te sugiere un comando, lo corres, le pegas el resultado. Una y otra y otra vez — hasta que en uno de esos tantos copy-paste te manda a probar algo dentro del contenedor y, sin que tenga nada que ver con el 500 original, ahí aparece, como quien no quiere la cosa:
$ docker exec myapp-app-1 touch /app/uploads/test.txt
touch: cannot touch '/app/uploads/test.txt': Permission deniedBuscas el error, encuentras un issue de GitHub con 200 comentarios. La solución más votada, tres palabras:
chmod 777 -R ./uploadsFunciona. El contenedor arranca. Tú sigues con tu vida. Y así, sin querer, acabas de practicar la disciplina más antigua del gremio: el cargo cult programming — copiar el ritual sin entender el dios al que le rezas.
El problema es que chmod 777 es el try { ... } catch (e) {} de los permisos: silencia el error, no lo arregla. Y aquí ni siquiera es tu propio usuario el que tenía el problema — es el UID con el que corre el proceso dentro del contenedor, uno que probablemente no conoces ni vas a conocer si sigues tirando 777 a todo lo que se queja.
Hoy vamos a entender qué demonios significan esas letritas rwx, de dónde salen los números mágicos, y por qué 777 te va a doler en algún momento de tu carrera.
Todo lo que hay aquí aplica igual en Linux, macOS y WSL. Son permisos POSIX, el estándar de toda la familia Unix. Si estás en Windows nativo, esto no aplica: NTFS usa ACLs, que son otro animal (más potente y muchísimo más aburrido).
1. El origen: Unix nació multiusuario
Contexto rápido, porque explica todo lo demás.
Unix se diseñó en 1969 para máquinas que costaban una fortuna y que compartían decenas de personas a la vez. Un solo ordenador, muchos usuarios conectados por terminales tontas, todos escribiendo en el mismo disco.
Con ese escenario, hay una pregunta que el sistema operativo tiene que responder unas cien mil veces por segundo:
¿Esta persona puede tocar este archivo?
Los permisos son la respuesta a esa pregunta. Y como en 1969 cada byte de RAM se pagaba con sangre, la respuesta tenía que ocupar lo mínimo posible. Spoiler: acabaron cabiendo en 9 bits. Poco más de un byte para toda la seguridad del sistema de archivos. Eso es ingeniería.
Tu portátil no lo comparte nadie, pero el modelo sigue ahí. Y sigue siendo el que te salva el culo cuando tu servidor web se conecta a internet, donde por definición hay "otros usuarios": todo el planeta.
2. Diseccionando ls -lha línea por línea
Empecemos por donde empiezan todos: mirando la matrix.
ls -lhaTraducción del comando, que también hay gente que lleva años escribiéndolo sin saber qué pide:
-l→ long format, la vista detallada (sin esto solo ves nombres).-h→ human readable, tamaños en4.0Ken lugar de4096.-a→ all, incluye los archivos ocultos (los que empiezan por punto, como.env).
Y esto es lo que escupe:
drwxr-xr-x 5 jose developers 160B Aug 2 10:12 proyecto/
-rw-r--r-- 1 jose developers 1.2K Aug 2 10:14 README.md
-rwxr-xr-x 1 jose developers 840B Aug 2 10:15 deploy.sh
-rw------- 1 jose developers 3.1K Aug 2 10:16 .envVamos columna por columna:
Columna | Ejemplo | Qué es |
|---|---|---|
1 |
| Tipo + permisos ← el protagonista de hoy |
2 |
| Número de hard links que apuntan al archivo |
3 |
| Dueño (owner / user) |
4 |
| Grupo |
5 |
| Tamaño |
6 |
| Última modificación |
7 |
| Nombre |
Nos quedamos con la columna 1, que son diez caracteres y no uno solo, aunque parezca un churro.

En Unix todo es un archivo: tu ratón, tu tarjeta de red, el generador de números aleatorios. Esa frase que suena a camiseta de conferencia es literalmente cierta, y esta columna es la prueba.
El primer carácter, eso sí, no es un permiso: es la etiqueta que dice si es archivo (-) o directorio (d) — también hay enlaces, dispositivos, sockets y pipes, pero para chmod del día a día solo te importan esos dos.
Los otros nueve caracteres sí son los permisos. Y aquí viene la única idea que necesitas de verdad.
3. La idea central: tres grupos de tres
Esos 9 caracteres son en realidad tres bloques de tres:
- rwx r-x r--
│ │ │ │
│ │ │ └── OTHERS (otros): todo el resto del mundo
│ │ └─────── GROUP (grupo): los del grupo del archivo
│ └──────────── USER (dueño): quien es propietario
└──────────────── tipo (archivo, directorio...)La analogía de casa, que funciona sospechosamente bien:
- User (
u) — tú, en tu cuarto. Es tuyo, tú mandas. - Group (
g) — tu familia / tus roomies. Pueden entrar al cuarto, con matices. - Others (
o) — la visita. El técnico del gas. El repartidor. Internet entero.
El sistema evalúa en ese orden y se queda con el primero que aplique. Ojo con esto porque es contraintuitivo:
Si tú eres el dueño del archivo, Linux aplica solo los permisos de user y ni siquiera mira los de group u others. Por eso chmod 077 archivo.txt (----rwxrwx) es la mejor forma de dejarte a ti mismo fuera de tu propio archivo mientras el resto del mundo hace fiesta dentro. Sí, es tan absurdo como suena. Sí, alguien lo ha hecho en producción.
4. r, w, x: las tres letras
Cada bloque tiene los mismos tres huecos, siempre en el mismo orden. Si el permiso está, aparece la letra; si no, aparece un guion -.
Letra | Nombre | En un archivo | En un directorio |
|---|---|---|---|
| read | Puedes leer el contenido | Puedes listar qué hay dentro ( |
| write | Puedes modificarlo | Puedes crear, borrar y renombrar cosas dentro |
| execute | Puedes ejecutarlo como programa | Puedes atravesarlo ( |
La columna de la derecha es donde se cae absolutamente todo el mundo la primera vez. Vamos con ella, porque es donde está el 90% de los bugs de permisos reales.
La x en directorios no es "ejecutar", es "atravesar"
Un directorio no es una caja con archivos dentro. Es una tabla: una lista de pares nombre → inodo (el identificador real del archivo en el disco).
Con eso en mente:
rsinx→ puedes ver los nombres, pero no puedes hacer nada con ellos.lste devuelve la lista yls -lte devuelve una fila de errores. Es como tener el índice de un libro sin las páginas.xsinr→ no puedes listar, pero sí puedes entrar y abrir un archivo si sabes su nombre exacto. Esto es una técnica real: se usa para directorios "semiprivados" donde no quieres que nadie fisgue el contenido.
Regla práctica: para que alguien pueda llegar a /var/www/html/index.html, necesita permiso de x en todos los directorios del camino: /, /var, /var/www y /var/www/html. Un solo eslabón sin x y el archivo es inalcanzable, aunque tenga rwxrwxrwx. Cuando algo "no se ve" y juras que los permisos están bien, revisa el camino completo, no solo el destino.
El borrado no depende del archivo, depende de la carpeta
Esta es la que rompe cerebros:
-r--r--r-- 1 root root 0B Aug 2 archivo-sagrado.txtEse archivo es de root y es de solo lectura para todos. Nadie puede modificarlo.
Pero cualquiera con w en la carpeta que lo contiene puede borrarlo. ¿Por qué? Porque borrar no es tocar el archivo: es quitar una fila de la tabla del directorio. Estás editando la carpeta, no el archivo. El permiso que se comprueba es el de la carpeta.
Es exactamente igual que arrancar una página del índice de un libro: no has tocado el capítulo, has tocado el índice.
De aquí nace el sticky bit, esa t rara que ves en /tmp (drwxrwxrwt). En /tmp todo el mundo puede escribir, así que sin protección cualquiera podría borrar los archivos temporales de los demás — un DoS de andar por casa. El sticky bit dice: "aquí puedes crear lo tuyo, pero solo puedes borrar lo que es tuyo". Lo vemos en la sección de bonus.
5. Y ahora sí: de dónde salen los números
Volvamos al chmod 777 del principio. ¿Por qué siete?
Fíjate en el bloque de permisos con ojos de máquina. Cada permiso solo puede estar encendido o apagado. Tres interruptores por bloque. ¿Cómo representa un ordenador tres interruptores? Con tres bits:
r w x
1 1 1 → binario 111 → decimal 7
r - x
1 0 1 → binario 101 → decimal 5
r w -
1 1 0 → binario 110 → decimal 6Tres bits dan exactamente 8 combinaciones posibles (del 0 al 7). Y ocho valores es, literalmente, la definición de octal (base 8). Por eso los permisos se escriben en octal y no en decimal ni en hexadecimal: porque encajan como un guante, un dígito por bloque.
La forma rápida de calcularlo en la cabeza — el peso de cada letra:
Permiso | Valor |
|---|---|
| 4 |
| 2 |
| 1 |
Sumas las que quieras activar y ya está:
rwx= 4+2+1 = 7rw-= 4+2+0 = 6r-x= 4+0+1 = 5r--= 4+0+0 = 4---= 0
Y como hay tres bloques (user, group, others), pones tres dígitos:
chmod 754 archivo
│││
││└── others: 4 = r-- (leer)
│└─── group: 5 = r-x (leer y ejecutar)
└──── user: 7 = rwx (todo)Resultado: -rwxr-xr--.
Truco mental para no calcular nunca más: 4 es leer, 2 es escribir, 1 es ejecutar. Los tres valores son potencias de dos, así que cada combinación da un número único — no hay ambigüedad posible. 6 solo puede ser rw-. 5 solo puede ser r-x. Es un pequeño golpe de genialidad de diseño.
Para no quedarte solo con la teoría: la calculadora de abajo es real. Marca las casillas de usuario/grupo/otros y mira cómo cambian el octal, la cadena simbólica y el comando chmod en vivo. Sirve para dos cosas — verificar un modo antes de pegarlo en producción, o simplemente jugar hasta que 644/755/700 dejen de ser números mágicos.
Calculadora de permisos chmod
- r
- leer el contenido
- w
- modificar el contenido
- x
- ejecutarlo como programa
-rw-r--r--chmod 644 archivo.txt- setuid (4000) — se ejecuta con los permisos del dueño (ej. passwd).
- setgid (2000) — se ejecuta con los permisos del grupo.
- sticky (1000) — sin efecto aquí: sin efecto en Linux moderno.
6. Los números que vas a usar el 95% del tiempo
Puedes olvidarte de la tabla completa. En la vida real se repiten cuatro o cinco:
Octal | Letras | Para qué |
|---|---|---|
644 |
| Archivos normales. Yo escribo, el resto lee. El default de casi todo. |
755 |
| Directorios y ejecutables. Yo mando, el resto entra y ejecuta. |
600 |
| Secretos. |
700 |
| Carpetas privadas. El clásico de |
775 |
| Carpeta compartida por un equipo (el grupo también escribe). |
777 |
| El pecado. Ahora hablamos de esto. |
SSH es el profesor estricto de la clase. Si tu clave privada tiene permisos más laxos que 600, el cliente de SSH se niega a usarla y te suelta un WARNING: UNPROTECTED PRIVATE KEY FILE! en mayúsculas y todo. No es un capricho: una clave privada legible por otros es una clave privada que ya no es privada. chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519 y a dormir tranquilo.
7. Por qué 777 es el olor a código más caro de tu servidor
chmod 777 significa, con todas sus letras: cualquier usuario de esta máquina puede leer, modificar y ejecutar esto.
En tu portátil, "cualquier usuario" eres tú. No pasa nada. En un servidor con un proceso web escuchando en el puerto 443, "cualquier usuario" incluye:
- El usuario con el que corre tu servidor web (
www-data,nginx). - Cualquier proceso comprometido, incluida esa dependencia con 47 subdependencias que instalaste sin mirar.
- Cualquiera que consiga ejecutar código con el usuario más tonto del sistema.
El escenario clásico, y sigue pasando en 2026: carpeta de subidas con 777 + un formulario que no valida extensiones. Alguien sube shell.php, lo abre en el navegador y como la carpeta tiene x para todos, el servidor se lo ejecuta encantado. Enhorabuena, has regalado una remote code execution por 8 caracteres de comodidad.
777 es la deuda técnica en su forma más pura: te ahorra treinta segundos hoy y te cuesta un fin de semana entero dentro de ocho meses.
Y aquí el matiz que casi nadie cuenta: muchas veces 777 ni siquiera arregla el problema. Si el fallo real es que el dueño del archivo no es quien crees, lo que necesitas es chown, no chmod. Si el disco está montado con noexec, ningún permiso del mundo va a dejarte ejecutar nada. Si es SELinux o AppArmor, los permisos POSIX ni entran en la conversación. 777 es un martillo: cuando el problema no es un clavo, solo haces ruido y agujeros.
La receta correcta ante un Permission denied, en orden:
- Mira quién eres:
whoamiyid. - Mira de quién es el archivo:
ls -lha. - Si el dueño está mal →
chown usuario:grupo archivo. - Si el dueño está bien pero falta un permiso → dáselo solo a quien lo necesita:
chmod u+x,chmod g+w. 777no está en la lista. Nunca está en la lista.
8. El modo simbólico: azúcar sintáctica para humanos
chmod también acepta letras, y para el día a día es mucho mejor, porque modifica en lugar de sobrescribir. Es azúcar sintáctica de la buena: menos precisa que el octal, infinitamente más cómoda.
La gramática es [quién][operador][permisos]:
Quién: u (user), g (group), o (others), a (all)
Operador: + (añadir), - (quitar), = (dejar exactamente esto)
chmod u+x deploy.sh # añade "ejecutar" solo al dueño
chmod go-w config.json # quita "escribir" a grupo y otros
chmod a=r documento.txt # todos, exactamente lectura y nada más
chmod u+rwx,go-rwx secreto # combinado, separado por comas
chmod -R u+w carpeta/ # -R = recursivo, hacia dentroLa diferencia clave:
chmod 755 archivo→ borra los permisos anteriores y pone estos. Cirugía con motosierra.chmod u+x archivo→ toca solo ese bit y deja el resto como estaba. Cirugía con bisturí.
chmod -R 777 . ejecutado en el directorio equivocado es una de las grandes leyendas del gremio, junto a rm -rf / y el DELETE sin WHERE. La -R no pregunta, no avisa y no tiene deshacer. Respira hondo y lee la ruta dos veces antes de pulsar Enter.
Bonus: chmod -R en un proyecto, bien hecho
La forma elegante es con laX mayúscula de chmod, que significa "pon x solo si es un directorio o si ya tenía x alguien":
chmod -R a=rX,u+w .9. ¿De dónde salen los permisos por defecto? umask
Pregunta lógica: cuando creas un archivo nuevo, ¿quién decide que sea 644?
Un señor que se llama umask. Es una máscara que resta permisos a los que el sistema daría por defecto.
umask # normalmente devuelve 0022La cuenta:
- Archivos: base
666(rw-rw-rw-) −022=644 - Directorios: base
777(rwxrwxrwx) −022=755
Fíjate en el detalle: la base de los archivos es 666, no 777. Unix nunca da permiso de ejecución automáticamente a un archivo nuevo. Tiene todo el sentido del mundo: si crear un archivo lo hiciera ejecutable, descargar cualquier cosa de internet sería jugar a la ruleta rusa. Por eso todo script recién bajado necesita su chmod +x de bienvenida.
umask es una máscara de bits, no una resta de verdad — técnicamente es un AND con el complemento. Pero para permisos normales la resta da el mismo resultado y es mucho más fácil de recordar. Guárdate el dato para presumir en una code review.
10. Bonus track: los bits raros (s, s, t)
A veces, en lugar de una x, ves una letra rara:
-rwsr-xr-x 1 root root /usr/bin/passwd
drwxrwxrwt 10 root root /tmpSon los bits especiales, y viven en un cuarto dígito octal delante de los otros tres:
Bit | Valor | Dónde aparece | Qué hace |
|---|---|---|---|
setuid | 4 |
| El programa se ejecuta con los permisos de su dueño, no de quien lo lanza |
setgid | 2 |
| Igual con el grupo. En directorios: lo que se cree dentro hereda el grupo de la carpeta |
sticky | 1 |
| En directorios: solo puedes borrar lo tuyo |
El ejemplo canónico es passwd: el setuid deja que se ejecute momentáneamente como si fueras root, para poder escribir en /etc/shadow. Es un pase VIP temporal — y también un vector de ataque histórico, así que desconfía de cualquier binario con setuid que no reconozcas.
El setgid en directorios es el que más te va a servir en la práctica: en una carpeta compartida por un equipo, hace que todo lo que se cree dentro pertenezca automáticamente al grupo correcto, en vez de al grupo personal de quien lo creó.
chmod 2775 /srv/proyecto-compartido # el 2 de delante = setgid
chmod 1777 /tmp # el 1 de delante = stickySi ves una S o una T en mayúscula, es que falta la x debajo del bit especial — más error de configuración que obra de arte. Pruébalo tú mismo en la calculadora de más arriba: activa "Mostrar bits especiales" y juega con setuid/setgid/sticky en vivo — mira cómo x más el bit especial da minúscula, y sin x da mayúscula.
Cierre
Los permisos de Unix son 9 bits diseñados hace más de cincuenta años que siguen protegiendo prácticamente todos los servidores del planeta. No son un obstáculo entre tú y tu script: son la única razón por la que el proceso de tu servidor web no puede leer tus claves SSH.
Así que la próxima vez que veas Permission denied, resiste el impulso del 777. Haz un ls -lha, mira quién eres, mira de quién es el archivo, y dale a cada quien exactamente lo que necesita. Ni un bit más.
Se llama principio de mínimo privilegio, y es de esas ideas que, una vez la entiendes, ya no puedes dejar de ver.
Y ahora sí: chmod u+x deploy.sh. Con conocimiento de causa.
Comentarios
1Increíble contenido, muy interesante y fácil de leer. Felicitaciones al autor que nos ayuda a entender temas complejos de manera sencilla. ¡Gracias!