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

chmod 777을 치면 해결된다는 선배의 조언, 사실 엄청 위험한 짓이었습니다. rwx와 숫자의 비밀.
내 서버는 왜 걸핏하면 뻗을까? OS가 한정된 메모리를 쪼개 쓰는 처절한 사투. 단편화(Fragmentation)와의 전쟁.

미로를 탈출하는 두 가지 방법. 넓게 퍼져나갈 것인가(BFS), 한 우물만 팔 것인가(DFS). 최단 경로는 누가 찾을까?

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

이름부터 빠릅니다. 피벗(Pivot)을 기준으로 나누고 또 나누는 분할 정복 알고리즘. 왜 최악엔 느린데도 가장 많이 쓰일까요?

리눅스 초보 시절, 뭐만 하면 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 맞는지 확인해야겠다"로 바로 대응할 수 있게 됐습니다.