파일 · 권한 · 사용자 관리 35 / 50 · Part 4. 사용자와 그룹 관리
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 18. Linux 사용자와 그룹
지금까지 계정 정보가 저장되는 파일들(passwd·shadow·group)을 봤다. 이번 글에서는 그 파일들을 한 번에 채우는 명령, useradd를 다룬다.
useradd는 겉으로는 명령 하나지만, 내부적으로 여러 파일을 동시에 수정 한다. /etc/passwd에 항목을 추가하고, /etc/shadow에 자리를 만들고, 기본 그룹을 생성하고, 홈 디렉터리를 만들어 /etc/skel의 초기 파일을 복사한다. 이 과정을 이해하면 계정 생성 시 무엇이 바뀌는지, 그리고 서비스 계정과 로그인 계정을 어떻게 구분해 만드는지 알 수 있다.
Rocky와 Ubuntu의 차이도 실측으로 확인한다.
| 파일/위치 | 변경 |
|---|---|
/etc/passwd | 계정 항목 추가 (UID 자동 할당) |
/etc/shadow | 비밀번호 자리 생성 (해시는 ! = 로그인 불가) |
/etc/group | 기본 그룹 생성(UPG) 또는 지정 그룹에 편입 |
/home/<user> | 홈 디렉터리 생성 + /etc/skel 복사 (-m) |
/var/spool/mail | 메일 스풀 (설정에 따라) |
| 옵션 | 의미 |
|---|---|
-m | 홈 디렉터리 생성 + skel 복사 |
-M | 홈 생성 안 함 |
-s SHELL | 로그인 셸 (nologin이면 로그인 차단) |
-r | 시스템 계정 (UID를 SYS_UID_MIN~SYS_UID_MAX에서 할당) |
-G g1,g2 | 보조 그룹 |
-c "설명" | GECOS |
-e YYYY-MM-DD | 계정 만료일 |
-D | 기본값 조회/변경 |
useradd만으로는 로그인할 수 없다. shadow의 해시 자리가 !(잠김)이기 때문이다. passwd <user>로 비밀번호를 설정해야 로그인 가능해진다. 반대로 서비스 계정은 비밀번호를 설정하지 않아 잠금 상태를 유지한다.

useradd -m appuser 한 줄이 실행하는 작업 순서:
/etc/login.defs의 UID_MIN~UID_MAX에서 비어 있는 다음 UID 를 찾아 할당/etc/passwd에 항목 추가/etc/shadow에 항목 추가(해시 !)-m이면 홈 디렉터리 생성 후 /etc/skel의 .bashrc 등을 복사배포판 차이(실측):
| 항목 | Rocky 9.8 | Ubuntu 24.04 |
|---|---|---|
| 홈 권한 | 700 | 750 |
useradd -D 기본 셸 | /bin/bash | /bin/sh |
| UPG 생성 | 예 | 예 |
| skel 파일 | .bash_profile, .bashrc, .bash_logout | .bashrc, .profile, .bash_logout |
Ubuntu에서 대화형으로 사용자를 만들 때는 useradd보다 adduser(비밀번호·정보를 물어보는 래퍼 스크립트)가 편리하다. useradd는 자동화·스크립트에 적합하다.
root 권한 실습. 격리된 테스트 컨테이너에서 진행한다.
# 1) 기본값 확인
useradd -D
# 2) 로그인 사용자 생성 (홈 포함)
useradd -m -s /bin/bash -c "App Service" appuser
getent passwd appuser
id appuser
ls -ld /home/appuser
ls -la /home/appuser | head # skel 복사 확인
# 3) 시스템(서비스) 계정 생성 — 로그인 불가
useradd -r -s /usr/sbin/nologin -M svcaccount 2>/dev/null || useradd -r -s /sbin/nologin -M svcaccount
getent passwd svcaccount # UID < 1000
# 4) 비밀번호 설정 전 = 로그인 불가 상태
passwd -S appuser 2>/dev/null || getent shadow appuser | cut -d: -f1,2
Rocky Linux 9.8

Ubuntu 24.04.5

텍스트 원본(실제 출력) — Rocky:
[root@rocky9-lab ~]# echo "=== useradd 기본값 ==="
=== useradd 기본값 ===
[root@rocky9-lab ~]# useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=yes
[root@rocky9-lab ~]# echo "=== 사용자 생성 (홈 생성 포함) ==="
=== 사용자 생성 (홈 생성 포함) ===
[root@rocky9-lab ~]# useradd -m -s /bin/bash -c "App Service" appuser
[root@rocky9-lab ~]# echo "생성 후:"
생성 후:
[root@rocky9-lab ~]# getent passwd appuser
appuser:x:1001:1001:App Service:/home/appuser:/bin/bash
[root@rocky9-lab ~]# id appuser
uid=1001(appuser) gid=1001(appuser) groups=1001(appuser)
[root@rocky9-lab ~]# ls -ld /home/appuser
drwx------ 2 appuser appuser 4096 Sep 24 14:43 /home/appuser
[root@rocky9-lab ~]# echo "=== 홈 디렉터리 초기 파일 (skel 복사) ==="
=== 홈 디렉터리 초기 파일 (skel 복사) ===
[root@rocky9-lab ~]# ls -la /home/appuser | head
total 20
drwx------ 2 appuser appuser 4096 Sep 24 14:43 .
drwxr-xr-x 1 root root 4096 Sep 24 14:43 ..
-rw-r--r-- 1 appuser appuser 18 Apr 30 2024 .bash_logout
-rw-r--r-- 1 appuser appuser 141 Apr 30 2024 .bash_profile
-rw-r--r-- 1 appuser appuser 492 Apr 30 2024 .bashrc
[root@rocky9-lab ~]# echo "=== UID 자동 할당 확인 ==="
=== UID 자동 할당 확인 ===
[root@rocky9-lab ~]# getent passwd appuser | awk -F: '{print "할당된 UID: "$3", GID: "$4}'
할당된 UID: 1001, GID: 1001
[root@rocky9-lab ~]# echo "=== 시스템 계정 생성 (-r, 로그인 불가) ==="
=== 시스템 계정 생성 (-r, 로그인 불가) ===
[root@rocky9-lab ~]# useradd -r -s /usr/sbin/nologin -M svcaccount 2>/dev/null || useradd -r -s /sbin/nologin -M svcaccount
[root@rocky9-lab ~]# getent passwd svcaccount
svcaccount:x:998:998::/home/svcaccount:/usr/sbin/nologin
[root@rocky9-lab ~]# echo "=== 비밀번호 설정 전 상태 (로그인 불가) ==="
=== 비밀번호 설정 전 상태 (로그인 불가) ===
[root@rocky9-lab ~]# passwd -S appuser 2>/dev/null || getent shadow appuser | cut -d: -f1,2
appuser LK 2026-09-24 0 99999 7 -1 (Password locked.)
| 출력 | 해석 |
|---|---|
useradd -D | 기본 GROUP·HOME·SHELL·SKEL 등. Rocky 셸 /bin/bash, Ubuntu /bin/sh |
appuser:x:1001:1001:App Service:/home/appuser:/bin/bash | UID 1001 자동 할당, GECOS "App Service" |
id appuser → groups=1001(appuser) | UPG로 같은 이름의 기본 그룹 생성 |
Rocky drwx------ /home/appuser | 홈 권한 700 |
Ubuntu drwxr-x--- /home/appuser | 홈 권한 750 |
| skel 파일 복사됨 | .bashrc 등이 홈에 복사됨 |
svcaccount:x:999:...:/usr/sbin/nologin | -r로 UID 999(1000 미만), 로그인 불가 셸 |
appuser L 2026-09-24 | passwd -S의 L = Locked(비밀번호 미설정, 로그인 불가) |
appuser L이 핵심이다. -m으로 홈까지 만들었지만 비밀번호가 없어 아직 로그인할 수 없다. 이 상태가 서비스 계정에는 오히려 안전한 기본값이다.
| 원칙 | 방법 |
|---|---|
| 서비스 계정은 로그인 차단 | -r -s /usr/sbin/nologin -M |
| 비밀번호 미설정 유지 | 서비스 계정에 passwd 실행 안 함 |
| 최소 권한 | 필요한 보조 그룹만 -G |
| 만료 정책 | -e로 임시 계정 만료일 지정 |
| 홈 권한 | 다중 사용자 서버는 750/700 |
과장 금지: 계정 생성 자체는 정상 관리 작업이다. 문제가 되는 것은 비인가 계정 생성, 특히 UID 0 계정이나 관리자 그룹 편입이다(48·49편). 정상 계정 생성과 공격을 구분하는 것은 "누가·언제·왜"이며, 이는 로그로 확인한다.
[Detection] auditd/로그: useradd 실행 (secure/auth.log)
grep -E 'useradd|new user' /var/log/secure # Rocky
grep -E 'useradd|new user' /var/log/auth.log # Ubuntu
↓
[판단] 업무 시간 외 계정 생성 / 관리자 그룹 동시 편입 / UID 0
↓
[Evidence] /etc/passwd·shadow·group ctime, 생성 계정의 홈·셸·그룹
↓
[Timeline] 생성 전후 sudo/su 로그, 로그인 IP
↓
[Response] 비인가 계정 잠금(passwd -l)·삭제(37편), 침입 경로 조사
| 관점 | 내용 |
|---|---|
| 로그 | useradd는 /var/log/secure(Rocky)·auth.log(Ubuntu)에 기록된다 |
| IOC | 비정상 시간대 생성, 관리자 그룹 즉시 편입, 로그인 셸 부여된 서비스명 계정 |
| Baseline | 정상 계정 목록과 비교(31편) |
| 실수 | 결과 | 예방 |
|---|---|---|
| 서비스 계정에 로그인 셸·비밀번호 부여 | 탈취 시 셸 | -r -s nologin -M, 비밀번호 미설정 |
-m 누락 후 홈 없음에 당황 | 홈 디렉터리 없음 | 로그인 계정은 -m |
| Ubuntu에서 대화형에 useradd 사용 | 비밀번호 미설정으로 로그인 불가 | adduser 또는 이후 passwd |
| UID 수동 지정 시 중복 | 소유권 충돌 | 자동 할당 권장, 필요 시 미사용 UID 확인 |
| 계정 생성만 하고 정책 미설정 | 만료·잠금 누락 | chage로 정책 적용 |
[ ] useradd -D 로 기본값을 확인했다
[ ] useradd -m 이 홈과 skel 을 만드는 것을 확인했다
[ ] UID 가 자동 할당되는 것을 확인했다
[ ] -r 로 시스템 계정을 만들었다 (UID<1000)
[ ] 비밀번호 미설정 계정이 Locked 상태임을 확인했다
[ ] Rocky/Ubuntu 홈 권한·기본 셸 차이를 확인했다
useradd는 passwd·shadow·group·홈을 한 번에 만든다.login.defs 범위에서 자동 할당된다.!(Locked)라 비밀번호를 설정해야 로그인 가능하다.-r -s nologin -M + 비밀번호 미설정으로 로그인을 차단한다.700, Ubuntu 750이고 기본 셸도 다르다.다음 글 「36. usermod로 사용자 관리」 에서는 기존 계정의 UID·그룹·셸·홈을 변경하는 usermod를 다룬다. 특히 -aG의 -a를 빠뜨리면 기존 보조 그룹이 삭제되는 위험과, 셸을 nologin으로 바꿔 계정을 비활성화하는 방법을 실습한다.