새벽 1시, 배포 직후 모니터링 알림이 울렸습니다. 앱이 설정 파일을 읽지 못해 시작에 실패하고 있습니다. 로그를 보니 PermissionError: [Errno 13] Permission denied: '/opt/myapp/config/app.yml'. 배포 스크립트에서 파일을 복사한 뒤 chown 단계를 빠뜨렸고, 서비스 계정이 설정 파일에 접근하지 못하는 상황입니다.
ls -la 한 줄로 문제가 어디에 있는지 보이고, chmod + chown 두 줄로 해결됩니다. 파일 권한 체계를 이해하면 Permission denied가 더 이상 미스터리가 아닙니다.
파일 권한 (File Permissions)
ls -la /etc/passwd /etc/shadow /usr/bin/passwd
which getfacl setfacl || sudo apt-get install -y acl
touch ~/test-perms.sh && mkdir -p ~/shared-dir
umask
Linux 파일 권한은 9비트로 표현됩니다. `ls -la` 출력의 첫 번째 필드를 읽는 법을 익히는 것이 출발점입니다.
-rwxr-xr-- 1 deploy www-data 4096 Mar 26 09:00 deploy.sh │└─┬─┘└─┬─┘└─┬─┘ │ owner group others │ └── 파일 타입: - = 일반파일, d = 디렉토리, l = 심볼릭링크
각 기호가 파일과 디렉토리에서 의미하는 바가 다릅니다. 특히 x 권한은 파일이면 실행, 디렉토리이면 진입(cd) 허용을 뜻한다는 점을 기억하세요.
| 기호 | 숫자 | 파일에서의 의미 | 디렉토리에서의 의미 |
|---|---|---|---|
r |
4 | 파일 내용 읽기 | 디렉토리 목록 조회 (ls) |
w |
2 | 파일 내용 수정 | 디렉토리 안에 파일 생성/삭제 |
x |
1 | 파일 실행 | 디렉토리 진입 (cd) |
- |
0 | 권한 없음 | 권한 없음 |
숫자 표기법: 각 주체의 권한을 더해서 표현합니다.
rwx= 4+2+1 = 7r-x= 4+0+1 = 5r--= 4+0+0 = 4755= owner(rwx=7) + group(r-x=5) + others(r-x=5)644= owner(rw-=6) + group(r--=4) + others(r--=4)600= owner(rw-=6) + group(---=0) + others(---=0)
실무에서 가장 자주 쓰는 조합:
755— 실행 가능한 스크립트, 디렉토리644— 설정 파일, 웹 콘텐츠600— SSH 키, 비밀번호 파일640— 그룹 구성원만 읽어야 하는 로그777— 절대 프로덕션에서 쓰면 안 됨
일반 rwx 9비트 외에 3개의 특수 비트가 있습니다. 보안 감사와 공유 디렉토리 설계에서 반드시 알아야 합니다.
SUID (Set User ID) — 비트값 4000
SUID가 설정된 실행 파일은, 실행하는 사람의 권한이 아닌 파일 소유자의 권한으로 실행됩니다.
bash# passwd 명령이 대표적인 SUID 예시 ls -la /usr/bin/passwd # -rwsr-xr-x 1 root root ... /usr/bin/passwd # ^ # s = SUID 비트 (소문자 s = 실행 권한 있음, 대문자 S = 실행 권한 없음)
일반 사용자는 /etc/shadow를 읽거나 쓸 수 없지만, passwd 명령은 root 소유에 SUID가 설정되어 있어 실행 시 root 권한으로 /etc/shadow를 수정할 수 있습니다.
보안 함의: SUID가 설정된 파일이 취약하면 권한 상승(privilege escalation) 공격 경로가 됩니다. 정기적으로 목록을 감사해야 합니다.
bash# 시스템 전체에서 SUID 파일 찾기 (보안 감사) find / -perm -4000 -type f 2>/dev/null
SGID (Set Group ID) — 비트값 2000
- 실행 파일에 설정: SUID와 동일하게 그룹 기준으로 동작
- 디렉토리에 설정: 해당 디렉토리 안에 생성되는 모든 파일이 디렉토리의 그룹을 상속
bash# 공유 디렉토리 설정 예시 ls -ld /opt/shared/ # drwxrwsr-x 2 root devteam 4096 ... /opt/shared/ # ^ # s = SGID 비트
Sticky Bit — 비트값 1000
디렉토리에 설정 시, 해당 디렉토리 안의 파일은 파일 소유자나 root만 삭제 가능합니다. 다른 사용자가 쓰기 권한이 있어도 남의 파일은 지울 수 없습니다.
bash# /tmp가 대표 예시 ls -ld /tmp # drwxrwxrwt ... /tmp # ^ # t = sticky bit (소문자 t = 실행 권한 있음)
/tmp는 모든 사용자가 파일을 만들 수 있지만(rwxrwxrwx), sticky bit 덕분에 자기 파일만 지울 수 있습니다.
특수 비트 숫자 표기법:
특수 비트는 일반 3자리 숫자 앞에 한 자리를 추가해서 표현합니다. 4000은 SUID, 2000은 SGID, 1000은 Sticky Bit입니다.
bashchmod 4755 /usr/local/bin/mytool # SUID + 755 chmod 2775 /opt/shared # SGID + 775 chmod 1777 /tmp # Sticky + 777
umask: 새 파일의 기본 권한
`umask`는 새 파일이나 디렉토리를 만들 때 자동으로 **제거할 권한 비트**를 지정합니다. "마스크"이므로 설정한 비트가 **없어지는** 권한입니다.
기본 생성 권한:
- 파일:
666(실행 권한은 기본 부여 안 함) - 디렉토리:
777
umask 022일 때:
파일: 666 - 022 = 644 (rw-r--r--) 디렉토리: 777 - 022 = 755 (rwxr-xr-x)
umask 027일 때:
파일: 666 - 027 = 640 (rw-r-----) 디렉토리: 777 - 027 = 750 (rwxr-x---)
bash# 현재 umask 확인 umask # 0022 # 기호 형식으로 확인 umask -S # u=rwx,g=rx,o=rx # umask 변경 (현재 세션만) umask 027 # 테스트 touch newfile.txt && ls -la newfile.txt # -rw-r----- ... (640 확인) # 영구 변경: ~/.bashrc 또는 /etc/profile에 추가 echo "umask 027" >> ~/.bashrc
실무 가이드라인:
- 개인 개발 서버:
022(기본값) - 보안이 중요한 서비스 계정:
027 - 매우 민감한 환경:
077(소유자만 접근)
서비스 계정의 umask를 강화하면 실수로 생성되는 파일의 권한 노출을 예방할 수 있습니다.
bash# 현재 umask 확인 umask # 0022 # 파일 생성 후 기본 권한 확인 touch with_default_umask.txt ls -la with_default_umask.txt # -rw-r--r-- (644) # umask를 027로 변경 umask 027 # 이제 새로 생성하는 파일의 권한 확인 touch with_secure_umask.txt ls -la with_secure_umask.txt # -rw-r----- (640) — others는 접근 불가 # systemd 서비스에서 umask 설정 예시 # /etc/systemd/system/myapp.service 에 추가: # [Service] # UMask=0027
ACL: rwx만으로 부족할 때
전통적인 rwx 모델은 소유자/그룹/기타의 3단계만 지원합니다. ACL을 사용하면 **특정 사용자나 그룹에 개별적으로 권한**을 부여할 수 있습니다.
ACL이 필요한 상황:
- nginx 프로세스(
www-data)는/app/config.yml을 읽어야 하는데, 파일 소유자는deploy팀 계정 - 감사팀 사용자
auditor에게만/var/log/app/의 읽기 권한 부여 - CI/CD 봇 계정이 특정 파일만 쓸 수 있도록 제한
bash# ACL 조회 getfacl /app/config.yml # 예시 출력: # file: app/config.yml # owner: deploy # group: deploy # user::rw- # group::r-- # other::--- # user:www-data:r-- ← ACL로 추가된 항목
ls -la에서 ACL이 설정된 파일은 권한 필드 끝에 + 기호가 붙습니다:
-rw-r-----+ 1 deploy deploy 1024 ... config.yml
ACL을 사용해 특정 서비스 계정에만 파일 접근 권한을 부여합니다.
bash# ACL 지원 여부 확인 (파일시스템이 ACL 마운트 옵션 필요) mount | grep -i acl # 또는 tune2fs -l /dev/sda1 | grep "Default mount options" # 특정 사용자에게 읽기 권한 부여 setfacl -m u:www-data:r /app/config.yml # 특정 그룹에게 읽기+실행 권한 부여 setfacl -m g:auditors:rx /var/log/app/ # 재귀적으로 디렉토리 전체에 ACL 적용 setfacl -R -m u:www-data:rx /app/static/ # 기본 ACL 설정 (새로 생성되는 파일에도 자동 적용) setfacl -d -m u:www-data:r /app/config/ # ACL 확인 getfacl /app/config.yml # ACL 제거 (특정 사용자) setfacl -x u:www-data /app/config.yml # ACL 전체 제거 setfacl -b /app/config.yml
실무 팁: ACL 설정 후 getfacl 출력을 파일로 저장해두면 나중에 setfacl --restore로 일괄 복원할 수 있습니다.
bash# 디렉토리 전체 ACL 백업 getfacl -R /app/ > /backup/app_acl_backup.txt # 복원 setfacl --restore=/backup/app_acl_backup.txt
다음 모듈에서는 패키지 관리 — apt와 dnf로 소프트웨어를 설치·업데이트하고 저장소를 관리하는 방법을 다룹니다.
'Linux' 카테고리의 다른 글
| [Linux] tmux & 백그라운드 세션 관리 (0) | 2026.05.22 |
|---|---|
| [Linux] 패키지 관리 (apt/yum/dnf) (0) | 2026.05.22 |
| [Linux] 사용자와 그룹 관리 (0) | 2026.05.22 |
| [Linux]텍스트 편집 기초 — vim과 nano (0) | 2026.05.22 |
| [Linux] 파일시스템 탐색 (0) | 2026.05.22 |