Profile picture

[Linux] RHCSA v9 취득을 위한 문제 풀이 정리

JaehyoJJAng2025년 08월 01일

개요

인터넷에서 수집한 덤프를 각색하면서 생소한 내용이거나 어려웠던 문제들을 선별해 저만의 풀이법으로 기록하며 RHCSA 취득을 위한 여정에 떠나보겠습니다!


사실 자격증 취득이 급한게 아니기도 하고, 주말을 이용해 여유롭게 공부할 계획이라서 문제 풀이 업데이트가 조금 뜸할 수도 있습니다!


최종 목표는 CKAD, CKA까지! RHCSA부터 힘내서 같이 시작해 봅시다!


1. Network 설정

문제 01: ens18와 같은 네트워크 인터페이스에 대해 testprofile 이라는 이름의 NetworkManager 연결 프로필을 구성하세요. 다음의 정적 설정을 적용하시면 됩니다.

  • IPv4.Address: 192.168.0.1/24
  • IPv6.Address: fd01::101/64
  • IPv4 Default Gateway: 192.168.0.1
  • IPv6 Default Gateway: fd01::100
  • IPv4 DNS Servers: 8.8.8.8, 8.8.4.4
  • IPv6 DNS Server: fd01::111
  • DNS Search Domain: example.com

먼저, 현재 시스템에 구성된 인터페이스 상태를 확인해보겠습니다.

nmcli device status

DEVICE  TYPE      STATE          CONNECTION 
ens18   ethernet  연결됨         ens18      
lo      loopback  연결됨 (외부)  lo

현재 구성된 시스템에는 ens18 이라는 인터페이스가 존재하네요.


이제부터 네트워크 설정을 해보겠습니다.


  1. Connection Profile을 생성해주세요.
nmcli connection add type ethernet con-name testprofile if-name ens3

  1. IPv4 주소와 IPv6 주소를 할당해주겠습니다.
nmcli connection modify testprofile ipv4.addresses 192.168.0.1/24 ipv6.addresses fd01::101/64

IP 할당 해줄 때 서브넷 마스크도 필수로 작성해주셔야 합니다.


  1. IP 주소를 수동(manual)로 지정해줍시다.
nmcli connection modify testprofile ipv4.method manual ipv6.method manual

NetworkManager가 DHCP를 통해 IP 주소를 자동으로 획득하지 않도록 해야합니다.


  1. 기본 게이트웨이 설정하기
nmcli connection modify testprofile ipv4.gateway 192.168.0.1 ipv6.gateway fd01::100

  1. DNS 주소 설정하기
nmcli connection modify testprofile ipv4.dns "8.8.8.8 8.8.4.4" ipv6.dns fd01::111

  1. DNS search domain 추가하기
nmcli connection modify testprofile ipv4.dns-search example.com ipv6.dns-search example.com

  1. 위에서 생성한 testprofile 연결 활성화하기
nmcli connection up testprofile

검증 해보기

  1. 현재 connection이 active 상태인지 확인합시다.
nmcli connection show --active

  1. 생성한 testprofile 설정 확인하기
nmcli -p con show testprofile

  1. 인터페이스 주소가 정상적으로 변경 되었는지 확인하기
ip address show ens18

  1. 기본 게이트웨이 확인하기
ip route show

  1. DNS 주소 확인하기
cat /etc/resolv.conf

  1. 외부로 ping 날려보기
ping 8.8.8.8

2. 세컨더리 IP 설정

문제 01: testprofile이라는 이름의 연결 프로필에 다음 보조 IPv4를 정적으로 추가해주세요. 기존 설정을 손상시키지 않는 방식으로 이 작업을 수행하셔야 합니다.

  • 보조 IPv4 주소: 10.0.0.5/24

  1. 활성화된 네트워크 프로필 확인하기
nmcli connection show --active

현재 활성화된 모든 네트워크 연결 프로필을 출력해서 testprofile이 활성 상태인지 확인해볼게요.


  1. 보조 IPv4 주소 추가하기
nmcli connection modify testprofile +ipv4.addresses 10.0.0.5/24
  • +ipv4.addresses + 기호는 다른 구성을 덮어쓰지 않고 기존 주소에 새 IP를 추가합니다. (Secondary)

  1. 업데이트된 연결 활성화

네트워크를 다시 연결합니다.

nmcli connection up testprofile

또는 다음 명령어로 구성을 다시 로드할 수 있어요.

nmcli connection reload

  1. 새 IP 적용이 안되는 경우 NetworkManager 서비스를 재시작해주세요.
systemctl restart NetworkManager

3. root 비밀번호 복구 (rd.break, init=/bin/bash)

문제 01: 서버의 root 비밀번호를 분실하였습니다. 시스템에 다시 접근하기 위해서 root 비밀번호를 재설정하세요.


root 비밀번호를 복구하는 방법에는 rd.break, init=/bin/bash 두 가지 방식이 있습니다.


RHEL 9.0 버전으로 올라와서부터 rd.break가 안된다는 소문이 있어서,

제가 rhel.9.3에서 테스트를 진행해봤습니다.


rd.break, init=/bin/bash 두 가지 방식 모두 정상 동작합니다.

그러나 시험 환경에서는 안될 수도 있으므로, 두 가지 방식 다 모두 직접 실습해보는 것을 권장합니다.


이제부터 각각의 방식에 대한 풀이법을 기록해보겟습니다.


복구 모드(Rescue Mode) rd.break 방식


  1. 시스템 재부팅

GRUB 2 부팅 화면에서, 아래쪽 화살표 키를 사용하여 "Advanced options for Red Hat Enterprise Linux"를 선택합니다.
image


  1. 커널 부팅 옵션 편집

원하는 커널 버전 선택하고 e 키를 눌러서 부팅 옵션을 편집해야 합니다.
image


  1. 복구 모드 매개변수 추가

linux로 시작하는 줄로 이동하여 Ctrl+E를 눌러 줄 끝으로 넘어가주세요.


그리고 줄 끝에 rd.break를 추가합니다.
(선택 사항: 충돌을 피하기 위해서 console= 또는 vconsole=keymap= 옵션을 제거할 수 있어요.)
image


  1. 비상 셸로 부팅하기

Ctrl+X를 눌러서 수정된 매개변수로 부팅하면 비상 셸로 진입이 됩니다!
image


  1. 루트 파일시스템을 쓰기 가능으로 다시 마운트
mount -o remount,rw /sysroot

  1. chroot 환경으로 진입하기
chroot /sysroot

  1. Root 비밀번호 재설정
passwd root

  1. SELinux 리레이블링 활성화
touch /.autorelabel

  1. 종료 및 재부팅

Ctrl+D를 두 번 눌러 chroot와 비상 셸을 종료합니다.


시스템이 재부팅되고, SELinux가 파일 컨텍스트를 리레이블링하여 보안 규정을 준수하도록 합니다!


단일 사용자 모드 init=/bin/bash 방식 (대안)

  1. 재부팅 및 부팅 매개변수 편집

GRUB 2 부팅 화면에서 커널을 선택하고, e 키를 누른 뒤 linux로 시작하는 줄의 끝으로 이동합니다.


  1. 단일 사용자 모드를 위한 부팅 매개변수 수정

init=/bin/bash를 추가하고 rorw로 교체합니다. (선택 사항: console= 또는 vconsole.keymap= 옵션을 제거할 수 있습니다.)
image


  1. 단일 사용자 셸로 부팅

Ctrl+X를 눌러 변경된 내용으로 부팅합니다.


  1. Root 비밀번호 재설정
passwd root

  1. SELinux 리레이블링 활성화
touch /.autorelabel

  1. 시스템 재부팅
exec /sbin/init

4. YUM/DNF 레포지토리 설정

문제 01: /mnt 디렉토리에 마운트된 RHEL-9 ISO 이미지를 사용하여서 로컬 YUM/DNF 레포지토리를 설정하세요.


이 실습을 진행하려면 시스템에 RHEL-9 ISO 이미지가 있어야 합니다!


  1. RHEL-9 ISO 이미지 마운트하기

RHEL-9.iso 파일을 루프 장비(loop device)로 /mnt 디렉토리에 마운트합니다.

mount -o loop RHEL-9.iso /mnt
  • -o loop: ISO를 루프백 장치로 마운트하도록 지정합니다.
  • 루프 장치는 ISO를 물리적 디스크처럼 취급합니다.
  • 진행하기 전에 RHEL-9.iso 파일이 있는지 확인하세요.

  1. [선택 사항] 마운트 영구 설정

부팅 시 ISO가 자동으로 마운트되도록 설정하고 싶다면 /etc/fstab에 마운트 명령어를 다음과 같이 추가해줍시다.

echo "/path/to/RHEL-9.iso /mnt iso9660 loop 0 0" >> /etc/fstab
  • /path/to/RHEL-9.iso를 실제 ISO 파일 위치로 바꿔주세요.
  • 만약 "iso9660 defaults"를 사용하면, 시스템은 ISO9660 마운트를 위한 기본 옵션을 적용합니다.
  • 만약 "iso9660 loop"를 사용하면, ISO 이미지 마운트를 위해 루프백 장치를 사용하도록 명시적으로 지정합니다.
  • 두 접근 방식 모두 유효하지만, ISO 파일을 다룰 때는 마운트 과정에 루프백 장치가 사용된다는 것을 명확히 하기 위해 "iso9660 loop" 옵션이 명시적으로 자주 사용됩니다.

  1. 로컬 레포지토리 파일 생성

/mnt/media.repo 파일을 /etc/yum.repos.d/rhel9.repo로 복사하거나, 새로운 /etc/yum.repos.d/rhel9.repo 파일을 생성합니다

cp /mnt/media.repo /etc/yum.repos.d/rhel9.repo

  1. 파일 권한 설정

모든 사용자가 읽을 수 있도록 /etc/yum.repos.d/rhel9.repo의 권한을 설정합니다

chmod 644 /etc/yum.repos.d/rhel9.repo

  1. 레포지토리 파일 편집

텍스트 편집기(예: vim)로 /etc/yum.repos.d/rhel9.repo 파일을 엽니다.

기존 내용을 다음 내용으로 교체해주세요.

[InstallMedia-BaseOS]
name=RHEL 9 - BaseOS
metadata_expire=-1
gpgcheck=0
enabled=1
baseurl=file:///mnt/BaseOS/

[InstallMedia-AppStream]
name=RHEL 9 - AppStream
metadata_expire=-1
gpgcheck=0
enabled=1
baseurl=file:///mnt/AppStream/

  1. 시스템 캐시 정리

Yum/DNF 및 subscription-manager 캐시를 지웁니다

dnf clean all
subscription-manager clean

참고

"This system is not registered"라는 메시지가 나타날 수 있습니다.

이 메시지를 없애려면 /etc/yum/pluginconf.d/subscription-manager.conf 파일을 편집하여 enabled=0으로 설정해주세요.


  1. 리포지토리 설정 확인:

사용 가능한 리포지토리 목록을 확인해봅시다.

dnf repolist

image



문제 02: 아래 제공되는 링크로 YUM 레포지토리를 설정하세요.

  • BaseOS: http://content.example.com/rhel8.0/x86_64/dvd
  • AppStream: http://content.example.com/rhel8.0/x86_64/dvd/AppStream

/etc/yum.repos.d/rhcsa-test.repo 파일에 다음과 같이 입력하고 저장하기.

[BaseOS]
name=BaseOS
baseurl=http://content.example.com/rhel9.0/x86_64/dvd/BaseOS
enabled=1
gpgcheck=0

[AppStream]
name=AppStream
baseurl=http://content.example.com/rhel9.0/x86_64/dvd/AppStream
enabled=1
gpgcheck=0

yum repo 리스트 확인하기

yum clean all
yum repolist -v

5. SELinux PORT 설정

문제 1: 비표준 포트 83번에서 실행 중인 웹 서버가 서비스 제공 시 문제를 겪고 있습니다. 다음 조건을 충족하도록 문제를 해결하세요.

  • 1. 시스템의 웹 서버가 /var/www/html에 있는 모든 기존 HTML 파일을 제공할 수 있어야 합니다.
  • 2. 웹 서버가 포트 83로 서비스가 되도록 하세요.
  • 3. 웹 서버가 시스템이 시작될 때 자동으로 시작되어야 합니다.

현재 테스트 중인 VM 서버에 아파치(httpd) 패키지를 설치해주도록 하겠습니다.

dnf install -y httpd

그리고 문제 요구사항에 맞게 httpd 서비스의 LISTEN 포트를 83번으로 변경해주도록 합시다.

관련 설정 파일은 /etc/httpd/conf/httpd.conf 입니다.


해당 파일에서 LISTEN 82LISTEN 83으로 변경해주시면 됩니다.


변경사항 적용을 위해 서비스를 재시작하겠습니다.

systemctl restart httpd

5-1. could not bind

httpd 서비스의 LISTEN 포트를 83번으로 변경하고 서비스를 재시작하니 다음과 같은 에러가 발생합니다.

$ journalctl -xeu httpd

927 12:32:08 localhost.localdomain httpd[1005]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:83
927 12:32:08 localhost.localdomain httpd[1005]: (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:83

리눅스에서 1024 이하 포트는 root만 바인딩할 수 있고,

httpd는 보통 apache 사용자로 실행되기 때문에 SELinux 보안 정책 때문에 차단이 되어버린 것 같습니다.


RHEL 계열에서 httpd는 기본적으로 80, 82, 443 같은 몇 개의 포트만 허용이 되니까,

다른 포트를 사용하려면 SELinux 설정에 83번 포트를 추가해줘야 합니다.


현재 SELinux 설정을 확인해볼까요?

$ semanage port -l | grep http_port_t
http_port_t                    tcp      82, 80, 81, 443, 488, 8008, 8009, 8443, 9000

역시나 83번 포트는 허용되어 있지 않네요.


아래 명령을 실행하여 포트를 추가해주겠습니다.

semanage port -a -t http_port_t -p tcp 83

그리고 다시 httpd 서비스를 재시작 해주세요.

systemctl restart httpd


그럼 이제 문제 요구사항에 맞게 실습을 진행해보겠습니다.


83번 포트 추가하기

# 허용 포트 확인
semanage port -l | grep http_port_t

# 83번 포트 추가
semanage port -a -t http_port_t -p tcp 83

# 추가됐는지 다시 확인
semanage port -l | grep http_port_t

방화벽(firewalld) 추가 및 재시작

firewall-cmd --permanent --add-port=83/tcp
firewall-cmd --reload

테스트

curl http://localhost:83

6. 사용자 계정 생성

문제 1: 아래 요구사항에 맞게 사용자 및 그룹을 생성하세요.

  • sysadms라는 그룹을 생성하시오.
  • natashaharry라는 사용자를 생성하고, 이들은 보조 그룹 sysadms의 멤버가 되도록 하시오.
  • sarah라는 사용자를 생성하되, 이 사용자는 비대화형(non-interactive) 셸을 사용해야 하며, sysadms 그룹의 멤버가 아니어야 한다.
  • 모든 사용자의 비밀번호는 trootent로 설정하시오.
  • sysadms 그룹은 서버에서 useradd 명령을 사용할 수 있는 권한을 가져야 한다.
  • harry 사용자는 sudo 비밀번호 입력 없이 다른 사용자의 비밀번호를 설정할 수 있어야 한다.

sysadms 그룹 생성하기.

groupadd sysadms

natashaharry 유저 생성하고 해당 유저를 sysadms에 소속시키기.

useradd -G sysadms natasha
useradd -G sysadms harry

sarah 사용자 생성

useradd -s /sbin/nologin sarah

유저 패스워드 설정

$ passwd <user name>

# 또는
$ echo "trootent" | passwd --stdin natasha
$ echo "trootent" | passwd --stdin harry
$ echo "trootent" | passwd --stdin sarah

sysadms 그룹에 및 harry 사용자에 대한 sudo 권한 설정

$ visudo

# 다음 내용 추가
%sysadms ALL=(ALL) NOPASSWD:ALL
harry ALL=(ALL) NOPASSWD:/usr/bin/passwd


문제 2: 아래 요구사항에 맞게 사용자를 생성하세요.

  • 그룹 ID가 1010halo_team 이라는 그룹을 생성하세요.
  • 사용자 ID가 1010halo를 생성하고, 이 사용자는 halo_team의 멤버로 생성되도록 하세요.
    • 또한 해당 사용자는 /bin/bash 쉘을 사용하며, 홈 디렉토리가 자동으로 생성되어야 합니다.
  • 패스워드는 echo로 지정하세요.
# 그룹 생성
groupadd -g 1010 halo_team

# 사용자 생성
useradd -u 1010 -s /bin/bash -g halo_team -m halo

# 패스워드 설정
echo "echo" | passwd --stdin halo

7. Crontab

문제 1: natasha 사용자로서, 2분마다 실행되며 logger "EX200 in progress" 명령을 수행하는 크론 잡을 설정하시오.


crond 서비스 활성화 중인지 확인

systemctl status crond

# 없으면 설치
dnf install -y cronie
systemctl enable --now cronie

crontab 정책 설정

crontab -u natasha -e

# 아래 내용 추가
*/2 * * * * logger "EX200 in progress"
  • *(분) *(시) *(일) *(월) *(요일)

로그 확인해보기

tail /var/log/messages

8. 협업 디렉토리

문제 1: 협업 디렉토리를 아래 요구사항에 맞게 설정 하시오.

  • /home/manager 디렉터리를 다음과 같은 조건으로 생성하시오.
  • /home/manager의 그룹 소유권은 sysadms 그룹으로 설정되어야 한다.
  • sysadms 그룹의 모든 구성원은 해당 디렉터리에 대해 전체 권한을 가져야 하지만, root를 제외한 다른 사용자들은 접근할 수 없어야 한다.
  • 앞으로 /home/manager 하위에 생성되는 모든 파일은 동일한 그룹 소유권(sysadms)을 가져야 한다.

/home/manager 디렉토리 생성

mkdir /home/manager

그룹 소유권 변경

chgrp sysadms /home/manager

디렉토리 권한 수정

chmod 2770 /home/manager

검증

$ ls -ld /home/manager
drwxrws---. 2 root sysadms 6  92713:20 /home/manager/

# 파일 생성해보기
$ touch /home/manager/test.txt
-rw-r--r--. 1 root sysadms 0  92713:49 test.txt

보면 test.txt 파일의 그룹이 sysadms로 자동 적용되어 생성되는 것을 볼 수 있다.


9. NTP 설정

문제 1: 아래 요구사항에 맞게 NTP를 설정하시오.

  • 시스템의 시간을 ntp.example.com 서버와 동기화하세요.

RHEL 7 버전부터는 시간 동기화를 위해 기본적으로 Chrony 데몬(chronyd)을 사용합니다.


1-1. Chrony 패키지 설치 확인

rpm -q chrony

# 없으면 설치
yum install -y chrony

1-2. chrony 설정 파일 수정

NTP 서버 지정을 위해 Chrony 설정 파일을 다음과 같이 수정해주세요.

vim /etc/chrony.conf

# 기본 서버 주소 ntp.example.com로 변경
# Please consider joining the pool (https://www.pool.ntp.org/join.html).
# pool 2.centos.pool.ntp.org iburst # 수정 전
server ntp.example.com iburst # 수정 후
  • iburst
    • 시스템 부팅 시 시간 동기화 속도 높여주는 옵션입니다.

1-3. Chrony 서비스 재시작 및 활성화

systemctl enable --now chronyd
systemctl status chronyd

1-4. 동기화 상태 확인 및 시간 동기화

chronyc sources 명령어 사용 시 현재 동기화 중인 시간 서버의 상태 확인이 가능합니다.

$ chronyc sources

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp.example.com              2   6   377    11   -480us[-483us] +/- 15ms

# 시간 동기화 활성화
timedatectl set-ntp true


10. Autofs 설정

문제 1: Autofs를 설정해야 합니다. 다음 요구사항을 기반으로 Autofs을 설정해주세요.

  • 1. materials.example.com (172.25.254.254) 에는 NFS 공유 드렉토리 /rhome 있습니다. 이 파일 시스템에는 사용자 remoteuser1 대해 사전 구성된 홈 디렉터리가 포함됩니다.
  • 2. remoteuser1의 홈 디렉터리는 materials.example.com:/rhome/remoteuser1입니다.
  • 3. remoteuser1의 홈 디렉터리는 로컬의 /rhome 디렉토리 하위의 /rhome/remoteuser1로 자동으로 마운트 되어야 합니다.
  • 4. 홈 디렉토리는 해당 사용자가 쓰기(writable) 가능해야 합니다.
  • remoteuser1의 비밀번호는 flectrag입니다.

해당 문제의 핵심은 사용자가 /rhome/remoteuser1 디렉토리에 접근하려고 할 때,

시스템이 자동으로 materials.example.com 서버의 /rhome/remoteuser1 디렉토리를 NFS로 연결(마운트)하도록 설정하는 것입니다.


아래 단계를 차근차근 따라하여 Autofs을 설정합시다.



10-1. [서버] 설정

시험 환경에서는 NFS 서버 설정이 되어 있을 것으로 예상이 됩니다만,

저는 전체적인 구성에 대해 이해하기 위하여 서버 설정까지 해보기로 하였습니다.


1. nfs 서버 설정하기

먼저 원격 사용자의 홈 디렉토리를 제공할 NFS 서버를 설정해야 합니다.

1-1. nfs 서버 설치

dnf install -y nfs-utils

1-2. 공유할 디렉토리 및 사용자 홈 디렉토리 생성

# 공유할 최상위 디렉토리 생성
mkdir /rhome

# 문제의 사용자인 remoteuser1의 홈 디렉토리 생성
mkdir /rhome/remoteuser1

# 테스트를 위해 해당 사용자를 서버에 생성해주고, 홈 디렉토리 소유권 부여
useradd remoteuser1
chown -R remoteuser1:remoteuser1 /rhome/remoteuser1

# 비밀번호 설정
echo "flectrag" | passwd --stdin remoteuser1

1-3. NFS 공유 설정 파일 수정 (/etc/exports)

vim /etc/exports

# 맨 아래에 다음 내용을 추가합니다. 클라이언트가 읽고 쓸 수 있도록(rw) 허용하는 설정입니다.
/rhome *(rw,sync)

1-4. NFS 서비스 시작 및 활성화

systemctl enable --now nfs-server

1-5. 방화벽 설정

firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=mountd
firewall-cmd --permanent --add-service=rpcbind
firewall-cmd --reload

이제 서버 준비는 끝났습니다!


10-2. [클라이언트] 설정

1. Autofs 설치

dnf install -y autofs
systemctl enable --now autofs

2. 메인 설정 파일 수정 (/etc/auto.master)

auto.master 파일은 Autofs의 "총괄 지도"라고 보면 됩니다.

"어떤 경로에 접근하면, 어떤 세부 지도를 참고해라" 라고 알려주는 역할을 합니다.

vim /etc/auto.master

위 파일 맨 아래에 다음 내용을 추가해주세요.

# [마운트 포인트] [세부 설정 파일(맵 파일)]
/rhome  /etc/auto.rhome
  • 의미: /rhome 이라는 디렉토리 하위의 어떤 경로로든 접근이 시도되면, /etc/auto.rhome 파일을 참고해서 처리해라!

3. 세부 설정 파일(맵 파일) 생성 및 수정 (/etc/auto.rhome)

auto.rhome 파일은 /rhome 경로에 대한 "세부 지도"입니다.

실제 어떤 서버의 어떤 디렉토리를 연결할 지 상세 규칙을 정합니다.

vim /etc/auto.rhome

위 파일 맨 아래에 다음 내용을 추가해주세요.

# [키(하위 디렉터리명)] -[마운트 옵션]      [서버:/원격/경로]
remoteuser1           -fstype=nfs,rw,sync materials.example.com:/rhome/remoteuser1
  • remoteuser1 (키): /rhome 바로 밑에 생성될 하위 디렉터리 이름입니다.
    • 즉, /rhome/remoteuser1에 접근할 때 이 규칙이 적용됩니다. * (와일드카드)를 사용하면 모든 사용자에게 일괄 적용할 수도 있습니다.
    • * -fstype=nfs,rw,sync materials.example.com:/rhome/&

  • -fstype=nfs,rw,sync (옵션)
    • fstype=nfs: 파일 시스템 타입은 NFS입니다. (nfs4도 가능)
    • rw: 읽고 쓰기(Read/Write)가 가능해야 합니다. (문제 요구사항)
    • sync: 데이터 변경 시 즉시 서버에 기록합니다. 안정적이지만 약간 느릴 수 있습니다.

  • materials.example.com:/rhome/remoteuser1 (위치): 연결할 NFS 서버의 주소와 공유 디렉터리 경로입니다.

4. Autofs 재시작

설정 파일을 변경했으니 Autofs 서비스에 다시 읽어오라고 알려줘야 합니다.

systemctl restart autofs

5. 검증

이제 모든 설정이 끝났습니다. Autofs가 마법을 부리는 순간을 확인해 봅시다.


① 접근 전 확인: /rhome 디렉토리로 가보면 아무것도 없습니다. 아직 remoteuser1 디렉토리는 보이지 않는 것이 정상!

ls -l /rhome

② 자동 마운트 트리거: 이제 해당 디렉토리를 사용하기 위한 시도를 하면 됩니다.

ls -l /rhome/remoteuser1

위 명령을 실행하는 순간! Autofs/etc/auto.rhome 규칙을 보고 materials.example.com 서버에 접속하여 디렉토리를 마운트합니다.


③ 마운트 확인: mount로 현재 마운트된 목록을 확인해 보면, 방금 우리가 설정한 내용이 마운트된 것을 볼 수 있습니다.

mount | grep remoteuser1

# 결과 예시:
# materials.example.com:/rhome/remoteuser1 on /rhome/remoteuser1 type nfs4 (...)

④ 쓰기 권한 테스트: 문제의 요구사항대로 쓰기가 가능한지 파일을 생성해 봅시다.

touch /rhome/remoteuser1/testfile
ls -l /rhome/remoteuser1

testfile이 성공적으로 생성되었다면 모든 설정이 완벽하게 이루어졌습니다!


10-3. 트러블슈팅

autofs를 이용하여 원격 서버의 홈 디렉토리를 /rhome/remoteuser1로 자동 마운트하는 데 성공했습니다.

mount 명령어로 확인해도 잘 붙어있고, ls로 디렉토리를 보는 것까지도 완벽했죠..

/etc/auto.rhome on /rhome type autofs (rw,relatime,fd=12,pgrp=2889,timeout=300,minproto=5,maxproto=5,indirect,pipe_ino=29882)

192.168.219.111:/rhome/remoteuser1 on /rhome/remoteuser1 type nfs4 (rw,relatime,sync,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.219.107,local_lock=none,addr=192.168.219.111)

하지만 파일을 생성하려는 순간, 차가운 메시지가 저를 반겼습니다.

[root@client ~]# touch /rhome/remoteuser1/test.txt
touch: '/rhome/remoteuser1/test.txt'touch 명령 실행 불가: 허가 거부

분명 마운트 옵션에 쓰기(rw)권한도 줬는데 왜 안되는 걸까요? 지금부터 범인 추적 들어갑니다.



1. 뒤바뀐 소유자(UID/GID) 불일치

가장 먼저 의심해야 할 것은 파일 시스템의 소유 권한 입니다.

클라이언트에서 마운트된 디렉토리의 소유자를 확인해 봤습니다.

# 클라이언트에서 실행
ls -ld /rhome/remoteuser1

drwxr-xr-x. 2 natasha sysadms 36 10421:23 /rhome/remoteuser1

서버에서는 분명 remoteuser1로 소유권 및 그룹을 지정해줬었는데, 클라이언트에서는 뜬금없이 natasha라는 사용자가 주인으로 나오고 있네요?


🕵️‍♀️ 원인

이유는 NFS가 사용자를 이름(Name)이 아닌 숫자 ID(UID, GID)로 인식하기 때문입니다.


  • 서버: "이 디렉토리 주인은 UID 1005번이야. 내 시스템에서는 remoteuser1이지."
  • 클라이언트: "오케이, UID 1005번 소유의 디렉토리를 받았어. 내 시스템에서는 UID 1005번은 natasha네? 그럼 natasha 소유라고 보여줘야겠다."

즉, 소유권이 바뀐게 아니라, 같은 ID 번호에 매핑된 사용자 이름이 서버와 클라이언트 간 달랐기 때문에 발생한 문제인 겁니다.


✅ 해결

서버와 클라이언트 사용자 ID를 동기화해야 합니다.

id <사용자명> 명령으로 각 시스템의 UID/GID를 확인하고, usermod, groupmod 또는 useradd -u <UID> 등의 명령으로 양쪽 ID를 동일하게 맞춰줍니다.


저는 서버의 remoteuser1 ID를 기준으로 클라이언트의 사용자 ID 설정을 맞춰주었습니다.

# 서버에서 클라이언트에서 생성한 remoteuser1 계정의 uid,gid 값을 맞춰주었음.
groupmod -g 1005 remoteuser 1
usermod -u 1004 -g 1005 remoteuser1

그 결과, ls -ld 명령의 결과가 드디어 깔끔하게 나왔습니다!

drwxr-xr-x. 2 remoteuser1 remoteuser1 36 10421:23 /rhome/remoteuser1

2. 관리자(root)의 함정, root_squash

이제 소유자도 완벽하게 일치하니 모든 게 끝났다고 생각했습니다.

하지만 클라이언트의 root 계정으로 다시 파일을 생성해보니 .. 여전히 "허가 거부" 메시지가 발생하네요.


👮‍♂️ 원인

이것은 오류가 아닌, NFS의 아주 중요한 보안 기능인 root_squash 때문입니다.

NFS 서버는 기본적으로 "클라이언트의 root는 믿을 수 없다" 는 정책을 가집니다.


그래서 클라이언트의 root가 보낸 요청을 서버에서는 아무 권한 없는 nfsnobody라는 사용자의 요청으로 강등시켜 버립니다.


당연히 권한 없는 nfsnobodyremoteuser1의 디렉토리에 파일을 쓸 수 없겠죠.


⭐ 해결

문제의 원인은 root로 작업을 시도했기 때문이겠죠?

그렇다면 해결책은 매우 간단합니다.


바로 디렉토리의 실제 주인인 remoteuser1 사용자로 작업을 실행하면 되는겁니다.

# 클라이언트에서 root 사용자로 있을 때
[root@client ~]# whoami
root

# su 명령으로 remoteuser1으로 변신!
[root@client ~]# su - remoteuser1
Password:

# 사용자가 remoteuser1으로 변경됨
[remoteuser1@client ~]$ whoami
remoteuser1

# 드디어 파일 생성 성공!
[remoteuser1@client ~]$ touch /rhome/remoteuser1/hello_nfs.txt
[remoteuser1@client ~]$ ls -l /rhome/remoteuser1
-rw-r--r--. 1 remoteuser1 remoteuser1 0 10521:44 hello_nfs.txt


11. 파일 찾기 (find)

문제 1: harry가 소유한 모든 파일을 찾아서 그 복사본을 /root/harry/findfiles 디렉토리에 넣으세요.

find / -user harry -type f -exec cp -a {} /root/harry/findfiles \; 2>/dev/null
``

<br>

확인 결과
```shell
[root@rhcsa-test ~]# ls -alhtr /root/harry/findfiles/

합계 16K
-rw-r--r--. 1 harry harry  522 20241029일 .bashrc
-rw-r--r--. 1 harry harry  144 20241029일 .bash_profile
-rw-r--r--. 1 harry harry   18 20241029일 .bash_logout
-rw-rw----. 1 harry mail     0  92713:08 harry
-rw-r--r--. 1 harry harry    0 10610:07 harry_009.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_008.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_007.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_006.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_005.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_004.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_003.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_002.txt
-rw-r--r--. 1 harry harry    0 10610:07 harry_001.txt
drwxr-xr-x. 3 root  root    23 10610:08 ..
drwxr-xr-x. 2 root  root  4.0K 10610:09 .

12. 문자열 찾기 (grep)

문제 1: 아래 요구사항을 바탕으로 문제를 해결하세요.

  • 파일 /usr/share/centos-release/EULA에서 문자열 CentOS가 포함된 모든 행을 찾아서 이 모든 행을 원래 순서대로 /root/list 파일에 복사하세요.
  • /root/list에는 빈 행이 없어야 합니다.
  • 모든 행은 /usr/share/centos-release/EULA 파일의 원래 행과 정확히 일치해야 합니다.

grep "CentOS" /usr/share/centos-release/EULA > /root/list

13. 아카이브 생성

문제 1: /usr/local의 내용을 포함하는 tar 아카이브를 생성하고, 이를 bzip2로 압축하여 /root/backup/backup.tar.bz2로 저장하세요.

tar -cvjf /root/backup/backup.tar.bz2 /usr/local

압축 내역 확인하기

[root@rhcsa-test ~]# tar -tf /root/backup/backup.tar.bz2 

usr/local/
usr/local/bin/
usr/local/etc/
usr/local/games/
usr/local/include/
usr/local/lib/
usr/local/lib64/
usr/local/lib64/bpf/
usr/local/libexec/
usr/local/sbin/
usr/local/share/
usr/local/share/applications/
usr/local/share/info/
usr/local/share/man/
usr/local/share/man/man1/
usr/local/share/man/man1x/
usr/local/share/man/man2/
usr/local/share/man/man2x/
usr/local/share/man/man3/
usr/local/share/man/man3x/
usr/local/share/man/man4/
usr/local/share/man/man4x/
usr/local/share/man/man5/
usr/local/share/man/man5x/
usr/local/share/man/man6/
usr/local/share/man/man6x/
usr/local/share/man/man7/
usr/local/share/man/man7x/
usr/local/share/man/man8/
usr/local/share/man/man8x/
usr/local/share/man/man9/
usr/local/share/man/man9x/
usr/local/share/man/mann/
usr/local/src/

함정 조심

실습 서버에 bzip2가 설치되어 있지 않은 경우 tar -j 옵션을 줘서 bzip2로 압축하더라도 정상적으로 처리되지 않음.


즉, tar -cvjf <압축파일명> <압축할타겟> 이런식으로 명령을 넘기더라도 압축파일 자체는 생성이 되지만, bzip2 패키지가 설치되지 않았기 때문에 압축은 되지 않음.


그렇기 때문에 압축한 이후에 꼭 tar -tf <압축한파일명>으로 압축이 정상적으로 진행되었는지 검증 과정을 놓치지 말아야 함!


해결 방법은 단순히 dnf install -y bzip2bzip2 패키지를 설치해주고 다시 아카이브를 생성해주는 명령어를 실행하면 된다.



14. 파일 권한 설정 (setfacl)

문제 1: /etc/fstab 파일을 /var/tmp 디렉토리로 복사하세요. 그리고 /var/tmp/fstab 파일의 권한을 아래 요구사항에 맞게 설정하세요.

  • /var/tmp/fstab 파일의 소유자는 root 사용자여야 합니다.
  • /var/tmp/fstab 파일의 소유 그룹은 root 그룹이어야 합니다.
  • /var/tmp/fstab 파일은 그 누구도 실행할 수 없어야 합니다.
  • natasha 사용자는 /var/tmp/fstab 파일을 읽고 쓸 수 있어야 합니다.
  • harry 사용자는 /var/tmo/fstab 파일을 읽거나 쓸 수 없어야 합니다.
  • 위 사용자를 제외한 다른 모든 사용자들(현재 및 미래의 사용자 포함)은 /var/tmp/fstab 파일을 읽을 수만 있어야 합니다.


[파일 복사]

cp /etc/fstab /var/tmp

[/var/tmp/fstab 소유권 설정]

chown root:root /var/tmp/fstab

[/var/tmp/fstab 권한 설정]

chmod 644

[ACL을 이용한 권한 설정]

natashaharry 사용자에 대한 개별 권한은 표준 권한만으로는 설정할 수 없습니다!

이럴 때 사용하는 것이 바로 ACL(Access Control List) 입니다.


리눅스에서는 setfacl 명령어를 사용해요.

# 1. natasha 사용자에게 읽기(r)와 쓰기(w) 권한 부여
setfacl -m u:natasha:rw- /var/tmp/fstab

# 2. harry 사용자에게 부여된 모든 권한 제거
setfacl -m u:harry:--- /var/tmp/fstab
  • -m: ACL 설정을 수정(modify) 하겠다는 옵션
  • u:[사용자명]:[권한]: 특정 사용자(user)에게 권한을 부여하는 형식

[검증]

getfacl 명령어로 상세 ACL 확인

[root@rhcsa-test tmp]# getfacl /var/tmp/fstab 

getfacl: Removing leading '/' from absolute path names
# file: var/tmp/fstab
# owner: root
# group: root
user::rw-
user:natasha:rw-
user:harry:---
group::r--
mask::rw-
other::r--

15. 패스워드 유효 기간 설정

문제 1: 패스워드의 유효기간을 최대 20일로 설정하세요.

vim /etc/login.defs

아래 변수를 다음과 같이 수정하세요.

PASS_MAX_DAYS 20

문제 2: natasha 유저의 패스워드 유효기간을 최대 20일로 설정하세요

chage 명령어 활용

chage -M 20 natasha

16. 로그인 메시지 출력

문제 1: natasha 사용자로 로그인했을 때 메시지를 출력하는 rhcsa 라는 일므의 애플리케이션(스크립트)을 만드세요.


로그인 메시지를 출력하는 스크립트 작성

vim /usr/local/bin/rhcsa

# 스크립트 작성
echo "Welcome to rhcsa!"

스크립트 권한 설정

chmod +x /usr/local/bin/rhcsa

natasha 사용자의 .bashrc 설정

vim /home/natasha/.bashrc

# 위에서 생성한 스크립트 실행하도록 설정
if [ -f /usr/local/bin/rhcsa ]; then
  /usr/local/bin/rhcsa
fi

17. Umask 설정

umask는 파일이나 디렉토리가 생성될 때 부여되는 기본 권한을 제어하는 설정 값입니다.


자세하게 들어가면 써야할 내용이 너무 많으니 간략하게 설정하는 방법만 작성하도록 하겠습니다!


시스템에는 파일과 디렉토리를 만들 때 적용하려는 '최대 권한'이 정해져 있습니다.

umask는 이 최대 권한에서 특정 권한을 제거(masking) 하는 역할을 한다고 보시면 됩니다.


17-1. umask 계산법

umask의 계산법은 간단한 "뺄셈"으로 이해할 수 있습니다.

  • 최대 기본 권한 - umask 값 = 최종 권한

여기서 중요한 점은 파일과 디렉토리의 최대 기본 권한이 다르다 는 것입니다.


파일의 최대 권한: 666 (rw-rw-rw)

파일은 기본적으로 실행 권한(x)을 가질 필요가 없기 때문에, 보안상 x 권한이 빠진 666이 최대치입니다.


디렉토리의 최대 권한: 777 (rwxrwxrwx)

디렉토리는 내용을 보거나 접근(cd)하기 위해 실행 권한(x)이 반드시 필요하므로 777이 최대치입니다.



예시: 가장 흔한 umask: 022

대부분의 리눅스 시스템은 기본 umask 값으로 022를 사용합니다.

이 값의 의미는 "그룹(group)과 다른 사용자(others)에게서 쓰기(write,2) 권한을 빼앗겠다"는 뜻이죠.


  • 파일 생성 시: 666 - 022 = 644 (rw-r--r--)
  • 디렉토리 생성 시: 777 - 022 = 755 (rwx-r-xr-x)

결과적으로 사용자는 파일을 만들면 rw-r--r-- 권한을, 디렉토리를 만들면 rwxr-xr-x 권한을 갖게 되는거죠!


이제 문제를 풀어보며 umask를 어떻게 사용하는지 다시 한 번 이해해봅시다.


문제 1: 사용자 natasha가 파일과 디렉토리를 생성했을 때, 다음과 같은 권한이 설정되도록 구성하세요.

  • 파일 생성 시 기본 권한: rw-------
  • 디렉토리 생성 시 기본 권한: rwx------

이 권한을 만들기 위한 umask 값을 계산해봅시다.



[파일로 계산]

  • 최대 권한 666에서 어떤 값을 빼야 600이 됩니까?
  • 666 - ? -> ? = 066

[디렉토리로 계산]

  • 최대 권한 777에서 어떤 값을 빼야 700이 됩니까?
  • 777 - ? -> ? = 077

파일과 디렉토리 요구사항을 모두 만족시키려면 더 엄격한 값인 077umask로 사용해야 합니다.

umask 값을 077로 설정하면 그룹과 다른 사용자의 모든 권한(rwx)을 제거하게 됩니다.


[umask 077 적용 시 최종 권한]

  • 파일: 666 - 077 = 600
  • 디렉토리: 777 - 077 = 700

이제 계산은 전부 끝냈으니 설정 하러 가보죠?


umask는 특정 사용자에게 영구 적용되어야 하므로, 해당 사용자의 셸 시작 파일에 설정해야 합니다.


RHEL 계열에서는 보통 ~/.bash_profile에 설정합니다.

vim /home/natasha/.bash_profile

# 아래 내용 추가
umask 077

[검증]

# natasha로 로그인
su natasha

[natasha@rhcsa-test ~]$ touch testfile
[natasha@rhcsa-test ~]$ mkdir testdir
[natasha@rhcsa-test ~]$ ls -lhtr
합계 0
-rw-------. 1 natasha natasha 0 10612:04 testfile
drwx------. 2 natasha natasha 6 10612:04 testdir

[natasha@rhcsa-test ~]$ umask
0077


18. Podman build

문제 1: 아래 요구사항에 맞춰 컨테이너를 빌드하세요.

  • natasha 사용자로 http://classroom/Containerfile 을(를) 다운로드하세요.
  • 다운로드 받은 파일의 내용을 수정하지 말고, 이미지 이름을 pdf로 하여 빌드하세요.


먼저 실습 환경과 동일하게 맞춰주기 위해서 nginx 서버를 구축해주도록 하겠습니다.

nginx 서버에서는 간단한 정적 파일(Containerfile을 제공해줄겁니다.

즉, nginx/Containerfile URL 요청을 받으면, /usr/share/nginx/html/containerfiles (혹은 다른 경로)에 있는 실제 파일을 내려주면 되겠죠?


우선 nginx가 제공할 경로에 Containerfile을 복사해 둡니다.

mkdir -p /usr/share/nginx/html/containerfiles
cp /path/to/Dockerfile /usr/share/nginx/html/containerfiles/Containerfile
chmod 644 /usr/share/nginx/html/containerfiles/Containerfile

그리고 nginx 설정을 수정해주겠습니다.

기본 서버 블록(/etc/nginx/conf.d/default.conf) 또는 /etc/nginx/sites-available/default을 열어서 다음처럼 설정해주세요.

location /Containerfiles/ {
    alias /usr/share/nginx/html/containerfiles/;
    autoindex on;  # 파일 목록 표시
}

테스트 해볼게요.
image


이제 클라이언트 측에서 Containerfile을 다운로드 받고 컨테이너 이미지를 빌드해보겠습니다.


podman 서비스 활성화

systemctl enable --now podman.socket

사용자 natasha로 컨테이너 다운로드

# SSH 로그인
ssh natasha@node

# Containerfile 다운로드
# wget http://classroom/Containerfile
# 테스트용으로 구축한 nginx 서버에서 다운로드 받기
wget http://192.168.219.107/Containerfiles/Containerfile

컨테이너 이미지 빌드

podman build --tag pdf --file Containerfile .

이미지 빌드 확인

podman images

19. Container - rootless, systemd 등록

문제 1: 아래 요구사항에 맞춰서 컨테이너 생성 및 systemd를 등록하세요.

  • 컨테이너 이름: test_container
  • Podman build에서 생성한 pdf 컨테이너 이미지를 활용하세요.
  • 수동 개입 없이 시스템 재부팅 시 자등으로 서비스를 시작합니다.
  • 컨테이너 시작 시 호스트와 컨테이너의 디렉토리가 자동 마운트 되도록 설정하세요.
    • host (/opt/file) <-> container (/dir1)
    • host (/opt/processed) <-> container (/dir2)

systemd user manager (=Linger) 활성화

loginctl enable-linger natasha

디렉토리 생성 및 권한 설정하고 natasha로 로그인

mkdir -p /opt/{file,processed}
chown natasha:natasha /opt/{file,processed}
su - natasha

컨테이너 실행하기

podman run -d -it --name test_container -v /opt/file:/dir1:Z -v /opt/processed:/dir2:Z localhost/pdf

컨테이너 상태 확인

podman ps

CONTAINER ID  IMAGE                 COMMAND         CREATED        STATUS        PORTS       NAMES
b79936da9c1b  localhost/pdf:latest  sleep infinity  7 seconds ago  Up 7 seconds              test_container

systemd 유닛 파일 생성 및 저장

# test_container 컨테이너의 systemd 파일 생성
podman generate systemd --name test_container --files

# 설정 파일 관리할 디렉토리 생성
mkdir -p ~/.config/systemd/user

# 서비스 파일 옮기기
mv /home/natasha/container-test_container.service ~/.config/systemd/user

systemd 서비스 관리

systemctl --user enable --now container-test_container.service

재부팅 후 검증

podman ps -a
    Tag -

Loading script...