
리눅스 권한 체계: chmod와 chown
chmod 777을 치면 해결된다는 선배의 조언, 사실 엄청 위험한 짓이었습니다. rwx와 숫자의 비밀.

chmod 777을 치면 해결된다는 선배의 조언, 사실 엄청 위험한 짓이었습니다. rwx와 숫자의 비밀.
이름부터 빠릅니다. 피벗(Pivot)을 기준으로 나누고 또 나누는 분할 정복 알고리즘. 왜 최악엔 느린데도 가장 많이 쓰일까요?

클래스 이름 짓기 지치셨나요? HTML 안에 CSS를 직접 쓰는 기괴한 방식이 왜 전 세계 프론트엔드 표준이 되었는지 파헤쳐봤습니다.

매번 3-Way Handshake 하느라 지쳤나요? 한 번 맺은 인연(TCP 연결)을 소중히 유지하는 법. HTTP 최적화의 기본.

프론트엔드 개발자가 알아야 할 4가지 저장소의 차이점과 보안 이슈(XSS, CSRF), 그리고 언제 무엇을 써야 하는지에 대한 명확한 기준.

리눅스 초보 시절, 뭐만 하면 Permission denied가 떴습니다.
파일 읽으려고 해도, 스크립트 실행하려고 해도, 심지어 폴더 들어가려고 해도 그 메시지만 날 괴롭혔죠.
그때 선배가 알려준 마법의 주문: "안되면 chmod 777 때려봐."
진짜 다 되더군요. 저는 그게 해결책인 줄 알았습니다. (나중에 보안 팀한테 혼나기 전까진요.)
지금 생각하면 아찔합니다. chmod 777은 "우리 집 대문 활짝 열어두고 비밀번호도 현관에 붙여두기"와 같은 짓이었으니까요.
Docker 컨테이너에서 볼륨 마운트하면 자꾸 권한 에러가 나는 거예요.
로그 파일 못 쓰고, 설정 파일 못 읽고. 매번 sudo로 땜빵하다가 "이거 제대로 이해 안 하면 계속 막힐 것 같다"는 생각이 들었습니다.
그래서 리눅스 권한 체계를 파헤쳐봤어요. rwx가 뭔지, 숫자 755가 무슨 뜻인지, chmod와 chown의 차이가 뭔지. 막연했던 게 명확해지니까, 에러 메시지 보는 순간 "아, 이 권한 문제구나" 딱 보이더라고요.
ls -l 치면 이런 게 나옵니다.
-rw-r--r-- 1 ubuntu dev 1024 Feb 6 12:34 config.txt
drwxr-xr-x 2 ubuntu dev 4096 Feb 6 12:35 logs
뭔가 규칙이 있을 것 같은데 외계어처럼 보였어요.
-rw-r--r--은 뭐고, 왜 숫자 1024도 있고, ubuntu dev는 또 뭔가요?
특히 헷갈렸던 건 폴더의 x 권한이었습니다. "실행 권한이 있어야 폴더에 들어갈 수 있다"는 게 처음엔 이해가 안 갔어요. 폴더는 프로그램도 아닌데 왜 실행 권한이 필요한 거지?
그리고 chmod 644는 되는데 chmod 777은 위험하다는데, 왜 그런지 명확히 와닿지 않았습니다.
리눅스 파일 시스템을 아파트 건물로 생각하니까 와닿았습니다.
이 3계층 구조가 리눅스 권한의 핵심입니다.
리눅스에서 파일(또는 폴더)에 할 수 있는 행동은 딱 3가지입니다.
ls 명령어로 목록을 볼 수 있다.cd 명령어).폴더에 x 권한이 없으면 cd 자체가 안 됩니다. 이게 와닿았던 이유는, "아파트 복도에 진입 권한이 없으면 복도에 뭐가 있든 못 들어간다"로 받아들였기 때문이에요.
rwx를 숫자로 바꾸는 게 처음엔 신기했는데, 결국 이거였습니다.
더하면 됩니다.
rwx = 4 + 2 + 1 = 7 (읽고, 쓰고, 실행 다 됨)rw- = 4 + 2 + 0 = 6 (읽고, 쓰기만. 실행 불가)r-x = 4 + 0 + 1 = 5 (읽고, 실행만. 수정 불가)r-- = 4 + 0 + 0 = 4 (읽기만)--- = 0 + 0 + 0 = 0 (아무것도 못 함)예를 들어, 755는:
반대로 ls -l에서 -rwxr-xr-x를 보면, "아, 755 권한이구나" 바로 알 수 있습니다.
$ ls -l
-rw-r--r-- 1 ubuntu dev 1024 Feb 6 12:34 config.txt
drwxr-xr-x 2 ubuntu dev 4096 Feb 6 12:35 logs
-rwxr-xr-x 1 ubuntu www 12288 Feb 6 12:36 deploy.sh
각 열의 의미를 정리해본다.
-는 파일, d는 디렉토리.rwx 3개씩 (Owner / Group / Others).ubuntu dev - 주인과 그룹.config.txt는 rw-r--r-- (644):
logs 폴더는 rwxr-xr-x (755):
deploy.sh 스크립트는 rwxr-xr-x (755):
가장 직관적인 방법입니다.
$ chmod 755 deploy.sh
# 주인 - rwx(7), 그룹: r-x(5), 외부인: r-x(5)
$ chmod 644 config.txt
# 주인 - rw-(6), 그룹: r--(4), 외부인: r--(4)
$ chmod 600 ~/.ssh/id_rsa
# SSH 개인키는 주인만 읽고 쓸 수 있어야 함
# 그룹과 외부인: ---(0)
SSH 키 권한이 잘못되면 SSH가 "권한이 너무 느슨하다"며 거부합니다. 실제로 chmod 644 ~/.ssh/id_rsa 하면 ssh 명령어가 "UNPROTECTED PRIVATE KEY FILE!" 에러를 내뱉습니다.
기존 권한에서 일부만 수정하고 싶을 때 씁니다.
$ chmod u+x script.sh
# User(주인)에게 eXecute 권한 추가
$ chmod g-w config.txt
# Group에게서 Write 권한 제거
$ chmod o-rwx secret.txt
# Others(외부인)에게서 모든 권한 제거
$ chmod a+r readme.txt
# All(주인+그룹+외부인) 모두에게 Read 권한 추가
u = User (Owner)
g = Group
o = Others
a = All
+ = 권한 추가
- = 권한 제거
= = 권한 설정 (기존 권한 무시)
예를 들어:
$ chmod u=rwx,g=rx,o=r script.sh
# 주인 - rwx, 그룹: r-x, 외부인: r--
# 숫자로 치면 754
폴더 안의 모든 파일/폴더에 적용하려면 -R 옵션을 씁니다.
$ chmod -R 755 /var/www/html
# 웹 서버 디렉토리 전체를 755로 설정
주의: -R은 강력한 만큼 조심해야 합니다. 잘못 쓰면 시스템 파일 권한 망가질 수 있어요.
$ chown ubuntu config.txt
# config.txt의 주인을 ubuntu로 변경
$ chown ubuntu:dev config.txt
# 주인은 ubuntu, 그룹은 dev로 변경
$ chown :www deploy.sh
# 그룹만 www로 변경 (주인은 그대로)
Nginx나 Apache 웹 서버는 보통 www-data 유저로 실행됩니다.
$ sudo chown -R www-data:www-data /var/www/html
$ sudo chmod -R 755 /var/www/html
이렇게 하면:
만약 웹 서버가 로그 파일을 써야 한다면:
$ sudo chown www-data:www-data /var/log/nginx
$ sudo chmod 755 /var/log/nginx
chown :그룹 대신 chgrp를 써도 됩니다.
$ chgrp dev config.txt
# config.txt의 그룹을 dev로 변경
실제에선 chown :dev config.txt가 더 자주 쓰이긴 합니다.
Docker 컨테이너 안에서 파일을 만들면, 호스트에서 그 파일에 접근 못 할 때가 있습니다.
$ docker run -v $(pwd)/data:/app/data myapp
# 컨테이너 안에서 /app/data/output.log 생성
컨테이너 안에선 root로 실행되는데, 호스트에선 내가 ubuntu 유저라서 권한 충돌이 생기는 거예요.
해결법:
# Dockerfile에서 유저 지정
RUN useradd -m -u 1000 appuser
USER appuser
또는 호스트에서:
$ sudo chown -R $(whoami):$(whoami) ./data
이런 삽질을 몇 번 겪고 나니, "컨테이너와 호스트의 UID/GID가 일치해야 한다"는 개념이 와닿았습니다.
파일 실행 시, 주인의 권한으로 실행됩니다.
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 /usr/bin/passwd
s가 보이죠? 이게 SUID입니다.
passwd 명령어는 /etc/shadow를 수정해야 하는데, 이 파일은 root만 쓸 수 있어요. SUID 덕분에 일반 유저가 passwd 실행하면 root 권한으로 실행돼서 비밀번호 변경이 가능합니다.
$ chmod u+s script.sh
# 또는
$ chmod 4755 script.sh
숫자 맨 앞에 4를 붙이면 SUID입니다.
파일 실행 시, 그룹 권한으로 실행됩니다. 폴더에 SGID를 걸면, 그 폴더 안에 생성되는 모든 파일이 폴더의 그룹을 상속받습니다.
$ chmod g+s shared_folder
# 또는
$ chmod 2755 shared_folder
숫자 맨 앞에 2를 붙이면 SGID입니다.
예를 들어, 팀 프로젝트 폴더:
$ mkdir /project
$ chgrp dev /project
$ chmod 2775 /project
이제 누가 /project 안에 파일을 만들든, 그 파일의 그룹은 자동으로 dev가 됩니다.
폴더에 설정하면, 폴더 안의 파일은 주인만 삭제할 수 있습니다.
/tmp 폴더가 대표적입니다.
$ ls -ld /tmp
drwxrwxrwt 10 root root 4096 /tmp
맨 끝에 t가 보이죠? Sticky bit입니다.
누구나 /tmp에 파일을 만들 수 있지만, 남이 만든 파일은 못 지웁니다.
$ chmod +t shared_folder
# 또는
$ chmod 1777 shared_folder
숫자 맨 앞에 1을 붙이면 Sticky bit입니다.
파일을 새로 만들 때 자동으로 적용되는 권한이 있습니다. 이게 umask입니다.
$ umask
0022
umask는 "빼는" 개념입니다.
666 (rw-rw-rw-)777 (rwxrwxrwx)umask 0022는:
실제로 확인해볼까요?
$ umask 0022
$ touch newfile.txt
$ mkdir newfolder
$ ls -l
-rw-r--r-- 1 ubuntu dev 0 newfile.txt
drwxr-xr-x 2 ubuntu dev 4096 newfolder
딱 644, 755로 생성됐습니다.
만약 umask 0077로 바꾸면:
$ umask 0077
$ touch private.txt
$ ls -l private.txt
-rw------- 1 ubuntu dev 0 private.txt
주인만 읽고 쓸 수 있는 파일이 됩니다.
umask는 보통 ~/.bashrc나 ~/.zshrc에 설정해둡니다.
# ~/.bashrc
umask 0022
SSH 개인키는 반드시 600 권한이어야 합니다.
$ chmod 600 ~/.ssh/id_rsa
$ ls -l ~/.ssh/id_rsa
-rw------- 1 ubuntu ubuntu 1679 ~/.ssh/id_rsa
만약 권한이 잘못되면:
$ chmod 644 ~/.ssh/id_rsa
$ ssh user@server
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/ubuntu/.ssh/id_rsa' are too open.
SSH는 "개인키가 남에게 노출되면 안 된다"는 원칙 때문에, 권한이 느슨하면 아예 거부합니다.
공개키는 644로 해도 됩니다.
$ chmod 644 ~/.ssh/id_rsa.pub
Nginx 웹 서버를 운영한다고 가정해봤다.
$ sudo chown -R www-data:www-data /var/www/html
$ sudo find /var/www/html -type f -exec chmod 644 {} \;
$ sudo find /var/www/html -type d -exec chmod 755 {} \;
이렇게 하면:
644 (주인만 쓰기 가능, 나머지는 읽기만)755 (주인만 쓰기 가능, 나머지는 읽기+진입)웹 서버가 업로드 폴더에 파일을 써야 한다면:
$ sudo chmod 775 /var/www/html/uploads
$ sudo chown www-data:www-data /var/www/html/uploads
이제 웹 서버가 uploads 폴더에 파일을 쓸 수 있습니다.
777은 "너도 나도 쟤도, 읽고 쓰고 지우고 실행까지 맘대로 해라"라는 뜻입니다.
예를 들어, 웹 서버 설정 파일이 777이라면:
$ chmod 777 /etc/nginx/nginx.conf
이러면:
nginx.conf를 수정해서 악성 코드를 심을 수 있고,x 권한까지 있으니 스크립트를 실행할 수도 있습니다.실제로 제가 예전에 Docker 컨테이너에서 Permission denied 에러가 자꾸 나니까, 귀찮아서 chmod -R 777 /app을 쳤었어요.
보안 팀에서 로그 분석하다가 발견해서 "이거 누가 한 거냐"고 추궁당했습니다. 부끄러웠어요.
가급적:
644 (주인만 쓰기)755 (주인만 쓰기, 나머지는 실행 가능)600 (주인만 읽기/쓰기)이 정도로 막아두는 게 국룰입니다.
cd가 안 된다.이 개념들이 정리되고 나니, Permission denied 에러가 나면 "아, 이 파일 권한 확인해봐야겠다" 또는 "컨테이너 UID 맞는지 확인해야겠다"로 바로 대응할 수 있게 됐습니다.