infra
Platform

모듈 맵

[Linux] apt/yum/dnf 패키지 매니저로 서버 필수 도구 안전 설치

0 / 37 완료

펼치기
0 / 37 완료0%

Linux · 07 / 37

[Linux] apt/yum/dnf 패키지 매니저로 서버 필수 도구 안전 설치

배포판별 패키지 매니저와 리포지토리를 이해하고 의존성 충돌을 해결합니다

🚨INCIDENT ALERT
HIGH

새 서버에 배포 스크립트를 실행했는데 sudo apt install nginx 가 안 됩니다. 알고 보니 서버가 Rocky Linux라 apt 가 없습니다. 당황해서 인터넷에서 찾은 명령어를 복붙했더니 이번엔 GPG 에러가 뜨면서 막힙니다. 폐쇄망 서버에서는 dnf install 자체가 안 됩니다.

패키지 매니저를 제대로 이해하면 어떤 배포판 환경에서도 원하는 소프트웨어를 설치하고, 의존성 충돌을 해결하고, 폐쇄망에서도 운영할 수 있습니다.

패키지 관리 (apt / yum / dnf)

이번 챕터에서 배울 것
  • 1apt(Debian 계열)와 dnf(RHEL 계열)의 차이를 이해하고 환경에 맞는 명령어를 사용할 수 있다
  • 2패키지를 설치·업데이트·삭제하고 의존성 문제를 해결할 수 있다
  • 3서드파티 리포지토리를 GPG 키와 함께 안전하게 추가할 수 있다
  • 4폐쇄망 환경에서 오프라인 패키지 설치를 수행할 수 있다
  • 5패키지 버전을 고정(hold/versionlock)하고 자동 업데이트를 제어할 수 있다

실습 환경 준비
① 현재 배포판 계열 확인 (Ubuntu → apt 사용 / Rocky·RHEL → dnf+rpm 사용)
cat /etc/os-release | grep -E 'ID=|ID_LIKE='
② 패키지 목록 최신화 — apt 계열 (설치 전 항상 먼저 실행)
sudo apt update
② 패키지 목록 최신화 — dnf 계열 (설치 전 항상 먼저 실행)
sudo dnf check-update
③ 패키지 설치 — apt
sudo apt install <패키지명>
③ 패키지 설치 — dnf
sudo dnf install <패키지명>
③ .rpm 파일 직접 설치 — rpm 저수준 툴
sudo rpm -ivh <파일명>.rpm
💡개념

두 생태계의 차이: Debian 계열 vs RHEL 계열

팀에 합류해서 서버에 처음 접속했을 때, apt가 안 먹히는 경우가 있습니다. 회사에서 Ubuntu만 쓴다고 했는데 새 서버는 Rocky Linux였거나, 클라우드 환경이 AWS Amazon Linux 2였거나. 이때 yum이나 dnf를 써야 하는데, 명령어 이름만 다른 게 아니라 패키지 파일 형식도 다르고 리포지토리 설정 위치도 다릅니다. 두 계열의 차이를 모르면 인터넷에서 찾은 설치 명령어가 왜 안 되는지조차 파악하기 어렵습니다. 어떤 환경에 접속하든 당황하지 않으려면 두 생태계의 기본 구조를 한 번은 정리해둬야 합니다.

| 항목 | Debian 계열 | RHEL 계열 |

항목Debian 계열RHEL 계열
대표 배포판Ubuntu, Debian, Linux MintRHEL, CentOS Stream, Rocky Linux, AlmaLinux, Fedora
패키지 형식.deb.rpm
저수준 도구dpkgrpm
고수준 도구apt (구: apt-get)dnf (구: yum)
리포지토리 설정 위치/etc/apt/sources.list, /etc/apt/sources.list.d//etc/yum.repos.d/
캐시 위치/var/cache/apt/archives//var/cache/dnf/
잠금 파일/var/lib/dpkg/lock-frontend/var/cache/dnf/metadata_lock.pid

패키지 매니저 생태계 — Debian(apt) vs RHEL(dnf) 구조 비교

apt는 언제? Ubuntu Server, Debian이 기반인 환경 — 클라우드에서 AWS Ubuntu AMI, GCP Debian 이미지, 개인 개발 환경 등.

yum/dnf는 언제? 엔터프라이즈 환경의 대다수 — RHEL 구독 기반 서버, CentOS Stream, Rocky Linux, AWS AL2(Amazon Linux 2, yum), AL2023(Amazon Linux 2023, dnf).

yum vs dnf: RHEL 8/CentOS 8 이후 dnfyum을 대체했습니다. yum 명령어 자체는 dnf에 대한 심볼릭 링크로 동작하므로 기존 스크립트가 호환됩니다. 이 챕터에서는 dnf를 기본으로 설명하되 yum 동작과 차이점을 병기합니다.

💡개념

패키지 의존성(Dependency)이란?

패키지 의존성 트리 — nginx 설치 시 자동 해결되는 의존성 구조

인터넷이 없는 폐쇄망 서버에서 .deb 파일 하나를 dpkg -i로 설치했더니 "dependency problems" 오류가 뜨면서 설치가 안 됩니다. 파일 자체는 멀쩡한데 이 패키지가 내부적으로 다른 라이브러리를 필요로 하고, 그 라이브러리가 이 서버에 없기 때문입니다. 반대로 apt remove로 패키지 하나를 지웠는데 그걸 의존하던 다른 패키지가 같이 깨지기도 합니다. apt install이 간단해 보여도 내부에서는 수십 개의 패키지 간 의존 관계를 추적하고 자동으로 해결하고 있습니다. 오프라인 환경이나 의존성 충돌이 발생했을 때 당황하지 않으려면 이 구조를 이해해야 합니다.

패키지 A가 정상 동작하려면 패키지 B의 특정 버전 이상이 필요한 경우, B를 A의 **의존성(Dependency)**이라고 합니다. 패키지 매니저는 이 관계를 자동으로 파악해 함께 설치합니다.

TEXT
nginx 설치 요청
  └─ libc6 (>= 2.17) 필요
  └─ libpcre3 필요
       └─ libc6 (>= 2.4) 필요  ← 이미 충족됨
  └─ libssl3 필요
       └─ libcrypto3 필요

의존성은 필수 여부에 따라 여러 유형으로 나뉩니다.

유형설명apt 표현dnf 표현
Depends / Requires반드시 필요Depends:Requires:
Recommends / Weak권장하지만 없어도 동작Recommends:Recommends:
Suggests / Enhances선택적 기능 강화Suggests:Enhances:
Conflicts동시 설치 불가Conflicts:Conflicts:
Replaces다른 패키지 파일 대체Replaces:Obsoletes:

왜 의존성을 이해해야 하는가?

  • 수동 .deb/.rpm 설치 시 의존성이 자동 해결되지 않아 실패합니다.
  • 오프라인 환경에서 의존성 패키지를 누락하면 설치가 불완전해집니다.
  • 서로 다른 패키지가 같은 라이브러리의 호환되지 않는 버전을 요구할 때 충돌이 발생합니다.

2. 기본 패키지 작업 — 설치, 업데이트, 삭제, 검색

실습 전 디렉토리와 예제 파일을 먼저 준비합니다.

로컬 터미널
# 실습 디렉토리 준비
mkdir -p /tmp/linux/part2/exam_6 && cd /tmp/linux/part2/exam_6

# 패키지 정보 기록용 파일 생성
echo "# 패키지 관리 실습 기록" > /tmp/linux/part2/exam_6/pkg_notes.txt
echo "날짜: $(date)" >> /tmp/linux/part2/exam_6/pkg_notes.txt

이제 실습을 진행합니다.

apt 기본 명령어 (Ubuntu/Debian)

설치부터 삭제, 캐시 정리, 검색까지 실무에서 가장 자주 쓰는 apt 명령어 흐름입니다.

로컬 터미널
# 1. 패키지 목록 새로고침 (설치 전 항상 먼저 실행)
sudo apt update

# 출력 예시:
# Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
# Get:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
# Get:3 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
# Fetched 229 kB in 1s (185 kB/s)
# Reading package lists... Done
# Building dependency tree... Done
# Reading state information... Done
# 12 packages can be upgraded. Run 'apt list --upgradable' to see them.

# 2. 패키지 설치
sudo apt install nginx

# 3. 여러 패키지 동시 설치
sudo apt install curl wget git vim

# 4. 특정 버전 설치 (= 뒤에 버전 지정)
sudo apt install nginx=1.18.0-6ubuntu14.4

# 5. 설치된 패키지 업그레이드 (목록 새로고침 선행 필요)
sudo apt upgrade

# 6. 커널, 의존성 변경을 포함한 전체 업그레이드
sudo apt full-upgrade

# 7. 패키지 삭제 (설정 파일 보존)
sudo apt remove nginx

# 8. 패키지 + 설정 파일까지 완전 삭제
sudo apt purge nginx

# 9. 불필요한 의존성 패키지 자동 제거
sudo apt autoremove

# 10. 다운로드 캐시 정리
sudo apt clean          # 모든 캐시 삭제
sudo apt autoclean      # 오래된 캐시만 삭제

# 11. 패키지 검색
apt search nginx
apt-cache search "web server"

# 12. 패키지 상세 정보 조회
apt show nginx
# 출력 예시:
# Package: nginx
# Version: 1.18.0-6ubuntu14.4
# Priority: optional
# Section: web
# Origin: Ubuntu
# Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
# Installed-Size: 45.1 kB
# Depends: nginx-core (<< 1.18.0-6ubuntu14.4.1~) | nginx-full (<< 1.18.0-6ubuntu14.4.1~) | ...
# Homepage: https://nginx.net
# Description: small, powerful, scalable web/proxy server

# 13. 현재 설치된 패키지 목록
dpkg -l
dpkg -l | grep nginx

# 14. 특정 파일이 어느 패키지에 속하는지 확인
dpkg -S /usr/sbin/nginx
# nginx: /usr/sbin/nginx
🔍실행 후 확인할 것
  • sudo apt install nginx 완료 후 systemctl status nginx 로 서비스가 자동 시작된 것을 확인한다
  • dpkg -l | grep nginx 로 설치 상태 앞에 'ii'(설치됨)가 표시된다
  • dpkg -S /usr/sbin/nginx 로 특정 파일이 어느 패키지에서 왔는지 역추적할 수 있다
  • apt-cache show nginx 로 버전, 의존성, 설명 등 패키지 메타데이터를 확인한다
dnf/yum 기본 명령어 (RHEL/CentOS/Rocky)

dnfapt와 동작 방식이 유사합니다. 가장 큰 차이는 트랜잭션 히스토리를 기록해 특정 작업을 롤백할 수 있다는 점입니다.

로컬 터미널
# 1. 패키지 목록 새로고침 (dnf는 자동이지만 명시적으로 실행 가능)
sudo dnf check-update

# 출력 예시:
# Last metadata expiration check: 0:05:23 ago on Thu 26 Mar 2026 10:00:00 KST.
# nginx.x86_64       1:1.20.1-10.el9    appstream
# curl.x86_64        7.76.1-29.el9_4    baseos
# openssl.x86_64     1:3.0.7-27.el9     baseos

# 2. 패키지 설치
sudo dnf install nginx

# 3. 여러 패키지 동시 설치
sudo dnf install curl wget git vim

# 4. 특정 버전 설치
sudo dnf install nginx-1:1.20.1-10.el9

# 5. 설치된 패키지 전체 업그레이드
sudo dnf upgrade

# 6. 특정 패키지만 업그레이드
sudo dnf upgrade nginx

# 7. 패키지 삭제
sudo dnf remove nginx

# 8. 불필요한 의존성 자동 제거
sudo dnf autoremove

# 9. 캐시 정리
sudo dnf clean all

# 10. 패키지 검색
sudo dnf search nginx
sudo dnf search "web server"

# 11. 패키지 상세 정보 조회
sudo dnf info nginx
# 출력 예시:
# Available Packages
# Name         : nginx
# Epoch        : 1
# Version      : 1.20.1
# Release      : 10.el9
# Architecture : x86_64
# Size         : 37 k
# Source       : nginx-1.20.1-10.el9.src.rpm
# Repository   : appstream
# Summary      : A high performance web server and reverse proxy server
# URL          : https://nginx.org/
# License      : BSD
# Description  : ...

# 12. 설치된 패키지 목록
dnf list installed
dnf list installed | grep nginx

# 13. 특정 파일이 어느 패키지에 속하는지 확인
rpm -qf /usr/sbin/nginx
# nginx-1.20.1-10.el9.x86_64

# 14. 패키지에 포함된 파일 목록
rpm -ql nginx

# 15. 업그레이드 이력 확인 (dnf 고유 기능)
sudo dnf history
# ID  | Command line              | Date and time    | Action | Altered
# ----+---------------------------+------------------+--------+--------
#   5 | upgrade nginx             | 2026-03-26 09:45 | Upgrade|    1
#   4 | install vim               | 2026-03-25 14:22 | Install|    1

# 16. 특정 트랜잭션 롤백
sudo dnf history undo 5
rpm 직접 명령어 (RHEL 계열 저수준 툴)

dnf가 리포지토리 + 의존성 자동 해결까지 해주는 고수준 툴이라면, rpm.rpm 파일을 직접 다루는 저수준 툴입니다. 인터넷 없는 환경에서 단일 파일 설치, 설치된 패키지 상세 조회, 파일 무결성 검증 등에 사용합니다.

언제 rpm을 쓰나?

  • 인터넷 없이 .rpm 파일을 직접 받아 설치할 때
  • 설치 전 패키지 내용/의존성을 미리 확인할 때
  • 특정 파일이 어느 패키지 소속인지 역추적할 때
  • 패키지 파일 변조 여부를 검증할 때
로컬 터미널
# ─── 설치 / 업그레이드 / 삭제 ───

# 설치 (-i: install, -v: verbose, -h: 진행률 # 표시)
sudo rpm -ivh nginx-1.20.1-10.el9.x86_64.rpm

# 출력 예시:
# Verifying...                          ################################# [100%]
# Preparing...                          ################################# [100%]
# Updating / installing...
#    1:nginx-1:1.20.1-10.el9            ################################# [100%]

# 업그레이드 (이미 설치된 경우 교체, 없으면 신규 설치)
sudo rpm -Uvh nginx-1.24.0-1.el9.x86_64.rpm

# 다운그레이드 (이전 버전으로 되돌리기)
sudo rpm -Uvh --oldpackage nginx-1.20.1-10.el9.x86_64.rpm

# 삭제 (-e: erase)
sudo rpm -e nginx

# 의존성 오류 무시하고 강제 삭제 (주의: 다른 패키지가 깨질 수 있음)
sudo rpm -e --nodeps nginx

# 여러 파일 한 번에 설치
sudo rpm -ivh *.rpm

# ─── 조회 (설치 전 파일 검사) ───

# 설치 전 .rpm 파일 정보 확인 (-p: package file 대상)
rpm -qpi nginx-1.20.1-10.el9.x86_64.rpm
# Name        : nginx
# Version     : 1.20.1
# Release     : 10.el9
# Architecture: x86_64
# Install Date: (not installed)
# Group       : System Environment/Daemons
# Size        : 1580594
# License     : BSD
# Signature   : RSA/SHA256, ...
# Summary     : A high performance web server and reverse proxy server

# 설치 전 패키지에 포함된 파일 목록 미리 보기
rpm -qpl nginx-1.20.1-10.el9.x86_64.rpm
# /etc/logrotate.d/nginx
# /etc/nginx/nginx.conf
# /usr/lib/systemd/system/nginx.service
# /usr/sbin/nginx

# 설치 전 의존성 확인
rpm -qpR nginx-1.20.1-10.el9.x86_64.rpm
# /bin/sh
# libcrypto.so.3()(64bit)
# libpcre.so.1()(64bit)

# ─── 조회 (설치된 패키지 조회) ───

# 특정 패키지 설치 여부 확인
rpm -q nginx
# nginx-1.20.1-10.el9.x86_64  (설치됨)
# package nginx is not installed  (미설치)

# 설치된 패키지 상세 정보
rpm -qi nginx
# Name        : nginx
# Version     : 1.20.1
# Install Date: Thu 26 Mar 2026 10:00:00 KST
# ...

# 설치된 패키지가 포함하는 파일 목록
rpm -ql nginx
# /etc/nginx/nginx.conf
# /usr/sbin/nginx
# /usr/lib/systemd/system/nginx.service

# 특정 파일이 어느 패키지 소속인지 역추적 (-f: file)
rpm -qf /usr/sbin/nginx
# nginx-1.20.1-10.el9.x86_64

rpm -qf /etc/passwd
# setup-2.13.7-9.el9.noarch

# 설치된 모든 패키지 목록
rpm -qa
rpm -qa | grep nginx
rpm -qa | sort | less

# ─── 검증 ───

# 패키지 파일 변조 여부 검증 (원본 체크섬과 비교)
rpm -V nginx
# S.5....T.  c /etc/nginx/nginx.conf  ← 설정 파일이 변경된 경우 표시
# (아무 출력 없으면 변조 없음)

# 출력 문자 의미:
# S: 파일 크기 변경
# M: 권한/파일 타입 변경
# 5: MD5 체크섬 불일치
# T: 수정 시간 변경
# c: 설정 파일(config)

# 설치된 모든 패키지 무결성 검증
rpm -Va 2>/dev/null | grep -v "^..5....T  c "  # 설정 파일 변경은 제외

상황에 따라 rpm을 직접 쓸지 dnf를 쓸지 기준이 달라집니다.

상황사용 도구
리포지토리에서 인터넷으로 설치dnf install
.rpm 파일 직접 설치 (의존성 자동 해결 포함)dnf install ./파일.rpm
.rpm 파일 직접 설치 (의존성 수동 관리)rpm -ivh 파일.rpm
패키지 파일 내용 미리 조회rpm -qpl 파일.rpm
설치된 파일 역추적rpm -qf /경로
무결성 검증rpm -V 패키지명

팁: dnf install ./파일.rpm 방식으로 로컬 .rpm을 설치하면 dnf가 의존성까지 자동으로 리포지토리에서 받아줍니다. 순수 rpm -ivh는 의존성을 수동으로 모두 갖춰야 합니다.


3. 리포지토리 추가와 GPG 키 인증

apt 리포지토리 추가 (/etc/apt/sources.list.d/)

공식 Ubuntu 리포지토리에 없는 소프트웨어(최신 nginx, Docker, HashiCorp 도구 등)는 서드파티 리포지토리를 추가해야 합니다.

sources.list 형식:

TEXT
deb [옵션] URI Suite Component [Component...]
TEXT
# 예시: Ubuntu 22.04 (jammy) 공식 리포지토리
deb http://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse

Docker 공식 리포지토리 추가 (현대적 방식):

로컬 터미널
# 1. 필요한 도구 설치
sudo apt install ca-certificates curl gnupg

# 2. GPG 키 저장 디렉토리 생성
sudo install -m 0755 -d /etc/apt/keyrings

# 3. Docker GPG 공개키 다운로드 및 저장
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 4. 리포지토리 파일 생성 (/etc/apt/sources.list.d/ 하위)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. 패키지 목록 새로고침 후 설치
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

# 결과 확인
cat /etc/apt/sources.list.d/docker.list
# deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable

HashiCorp Terraform 리포지토리 추가:

로컬 또는 서버
# GPG 키 등록
wget -O- https://apt.releases.hashicorp.com/gpg | \
  sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

# 리포지토리 추가
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
  https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
  sudo tee /etc/apt/sources.list.d/hashicorp.list

sudo apt update && sudo apt install terraform

# 버전 확인
terraform --version
# Terraform v1.8.5
# on linux_amd64
dnf 리포지토리 추가 (/etc/yum.repos.d/)

RHEL 계열에서 리포지토리는 /etc/yum.repos.d/ 하위의 .repo 파일로 정의합니다.

.repo 파일 형식:

INI
[repo-id]
name=리포지토리 이름
baseurl=https://패키지-서버-URL/$releasever/$basearch/
enabled=1
gpgcheck=1
gpgkey=https://패키지-서버-URL/gpg-key.pub

EPEL(Extra Packages for Enterprise Linux) 추가:

로컬 터미널
# RHEL/CentOS 9 기준
sudo dnf install epel-release

# 또는 직접 URL 지정
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm

# 설치 확인
dnf repolist
# repo id          repo name
# appstream        Rocky Linux 9 - AppStream
# baseos           Rocky Linux 9 - BaseOS
# epel             Extra Packages for Enterprise Linux 9 - x86_64
# extras           Rocky Linux 9 - Extras

HashiCorp 리포지토리 추가 (RPM):

로컬 터미널
# 리포지토리 파일 직접 생성
sudo tee /etc/yum.repos.d/hashicorp.repo <<EOF
[hashicorp]
name=HashiCorp Stable - \$basearch
baseurl=https://rpm.releases.hashicorp.com/RHEL/\$releasever/\$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://rpm.releases.hashicorp.com/gpg
EOF

# GPG 키 가져오기 (자동)
sudo dnf install terraform

# 특정 리포지토리만 활성화/비활성화
sudo dnf config-manager --enable epel
sudo dnf config-manager --disable epel

# 리포지토리 우선순위 확인
dnf repolist -v

리포지토리 변수($releasever, $basearch):

로컬 터미널
# $releasever: 현재 배포판 주 버전 (예: 9)
# $basearch: 아키텍처 (예: x86_64)

python3 -c "import dnf; db = dnf.dnf.Base(); print(db.conf.substitutions)"
# {'releasever': '9', 'basearch': 'x86_64'}

4. GPG 키 인증 원리

💡개념

패키지 서명과 GPG 인증 흐름

GPG 패키지 서명 인증 흐름 — 배포자 서명 → 리포 업로드 → apt 검증 → 설치/거부

서드파티 리포지토리를 추가할 때 "NO_PUBKEY" 경고나 "GPG error" 가 뜨면서 설치가 막히는 상황을 만납니다. 또는 반대로 curl ... | sudo apt-key add - 같은 명령어를 별 생각 없이 실행하게 됩니다. 이게 단순한 절차가 아니라, 패키지 배포자가 자신의 패키지에 서명하고 사용자는 그 서명을 검증한다는 신뢰 체계입니다. 이 메커니즘이 없으면 리포지토리 서버가 해킹당해 악성 패키지가 올라와도 패키지 매니저가 걸러낼 수 없습니다. GPG 흐름을 이해하면 키 에러가 왜 나는지, 어떻게 해결하는지, gpgcheck=0이 왜 위험한지를 납득할 수 있습니다.

패키지 매니저가 리포지토리에서 소프트웨어를 받을 때, 변조 여부를 검증하는 메커니즘이 GPG(GNU Privacy Guard) 서명입니다.

인증 흐름:

TEXT
패키지 배포자                          사용자 시스템
─────────────                          ─────────────
1. 개인키(Private Key)로               2. 공개키(Public Key)를 미리 등록
   패키지에 서명                          /etc/apt/keyrings/  (apt)
   nginx-1.24.deb + 서명 해시             /etc/pki/rpm-gpg/   (dnf)

3. 리포지토리 서버에 업로드

4. apt/dnf가 패키지 다운로드 시:
   - 서명 해시 추출
   - 등록된 공개키로 검증
   - 불일치 시 설치 거부 (중간자 공격 방어)

apt에서 GPG 키 관리:

로컬 터미널
# 등록된 키 목록 확인 (레거시 방식)
sudo apt-key list

# 경고: apt-key는 deprecated. 대신 /etc/apt/keyrings/ 사용 권장
# W: Key is stored in legacy trusted.gpg keyring...

# 현대적 방식: 개별 .gpg 파일로 관리
ls /etc/apt/keyrings/
# docker.gpg  hashicorp-archive-keyring.gpg

# GPG 키 내용 확인
gpg --no-default-keyring \
  --keyring /etc/apt/keyrings/docker.gpg \
  --list-keys
# pub   rsa4096 2021-10-25 [SC]
#       9DC858229FC7DD38854AE2D88D81803C0EBFCD88
# uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
# sub   rsa4096 2021-10-25 [E]

dnf에서 GPG 키 관리:

로컬 터미널
# GPG 키 파일 위치
ls /etc/pki/rpm-gpg/
# RPM-GPG-KEY-Rocky-9  RPM-GPG-KEY-EPEL-9  RPM-GPG-KEY-hashicorp

# 수동으로 키 가져오기
sudo rpm --import https://rpm.releases.hashicorp.com/gpg

# 등록된 키 확인
rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n'
# gpg-pubkey-6f2d4623-638afa42  gpg(HashiCorp Security (HashiCorp Package Signing) <security+packaging@hashicorp.com>)
# gpg-pubkey-350d275d-628c1f8e  gpg(Rocky Linux (Rocky Linux Official Signing Key) <releng@rockylinux.org>)

# gpgcheck=0은 절대 금지 (테스트 후 반드시 복구)
# 내부 미러 서버도 자체 GPG 키 서명 권장

보안 핵심 원칙: gpgcheck=0(dnf) 또는 [trusted=yes](apt) 옵션은 GPG 검증을 비활성화합니다. 인터넷 연결 환경에서 이 옵션을 사용하는 것은 중간자 공격에 무방비 상태를 만드는 것과 같습니다. 내부망 미러서버라도 자체 서명 키를 사용하는 것이 권장됩니다.


5. 소스 빌드 설치 (./configure && make && make install)

소스 코드로 직접 빌드하여 설치하기

패키지 리포지토리에 없거나, 특정 컴파일 옵션이 필요하거나, 최신 버전을 써야 할 때 소스 빌드를 사용합니다.

빌드 도구 준비:

로컬 터미널
# Ubuntu/Debian
sudo apt install build-essential autoconf libtool pkg-config

# RHEL/Rocky
sudo dnf groupinstall "Development Tools"
sudo dnf install autoconf libtool pkg-config

예시: nginx를 소스에서 빌드 (추가 모듈 포함)

로컬 터미널
# 1. 의존성 설치
sudo apt install libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev libgd-dev

# 2. 소스 다운로드
cd /usr/local/src
sudo wget https://nginx.org/download/nginx-1.26.0.tar.gz
sudo tar -xzf nginx-1.26.0.tar.gz
cd nginx-1.26.0

# 3. 빌드 옵션 구성 (configure)
sudo ./configure \
  --prefix=/etc/nginx \
  --sbin-path=/usr/sbin/nginx \
  --modules-path=/usr/lib64/nginx/modules \
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.log \
  --pid-path=/var/run/nginx.pid \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_gzip_static_module \
  --with-stream

# configure 출력 예시:
# checking for OS
#  + Linux 5.14.0-570.52.1.el9_6.x86_64 x86_64
# checking for C compiler ... found
# ...
# Configuration summary
#   + using system PCRE library
#   + using system OpenSSL library
#   + using system zlib library
#
#   nginx path prefix: "/etc/nginx"
#   nginx binary file: "/usr/sbin/nginx"

# 4. 컴파일 (CPU 코어 수만큼 병렬 빌드)
sudo make -j$(nproc)

# 출력 예시:
# make -f objs/Makefile
# cc -c -pipe -O -W -Wall -Wpointer-arith ...
# cc -o objs/nginx objs/src/core/nginx.o ...

# 5. 설치 (기본 설치 위치로 파일 복사)
sudo make install

# 6. 버전 확인
/usr/sbin/nginx -v
# nginx version: nginx/1.26.0

/usr/sbin/nginx -V 2>&1 | grep configure
# configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx ...

소스 빌드의 장단점:

장점단점
원하는 모듈/옵션만 포함 가능패키지 매니저로 관리 불가
최신 버전 즉시 사용 가능업데이트 시 재빌드 필요
최적화 컴파일 옵션 적용의존성 수동 관리
특수 환경(임베디드 등) 대응보안 패치 자동화 어려움

소스 설치 후 제거:

로컬 터미널
# Makefile에 uninstall 타겟이 있으면:
sudo make uninstall

# 없으면 직접 삭제 (설치 위치 파악 필요)
# 이것이 소스 빌드의 단점 — 패키지처럼 깔끔하게 제거하기 어려움
sudo checkinstall  # deb/rpm 패키지로 감싸서 설치하는 대안 도구

6. 폐쇄망 환경에서의 오프라인 패키지 설치

인터넷이 없는 환경에서 패키지 설치하기

금융, 공공, 국방 분야의 서버는 보안상 인터넷 접속이 차단된 폐쇄망(Air-gap) 환경에서 운영됩니다. 이 경우 패키지를 미리 준비하거나 내부 미러를 구축해야 합니다.

방법 1: 개별 패키지 파일 직접 설치

로컬 터미널
# [인터넷 연결 서버] 패키지 파일만 다운로드 (설치 안 함)
# Ubuntu/Debian
apt download nginx
# 다운로드: nginx_1.18.0-6ubuntu14.4_amd64.deb

# 의존성 포함 전체 다운로드
apt-get install --print-uris -qq nginx | grep "^'" | \
  cut -d"'" -f2 | wget -i - -P ./nginx-offline/

# RHEL/Rocky
dnf download nginx
dnf download --resolve nginx   # 의존성 포함 다운로드

# [폐쇄망 서버] USB/SCP 전송 후 설치
# Ubuntu/Debian
sudo dpkg -i nginx_1.18.0-6ubuntu14.4_amd64.deb
# 의존성 미해결 오류 발생 시:
sudo apt install -f   # 로컬에서 해결 가능한 의존성 처리

# RHEL/Rocky
sudo rpm -ivh nginx-1.20.1-10.el9.x86_64.rpm
# 의존성 포함 설치:
sudo rpm -ivh *.rpm

방법 2: 로컬 리포지토리 구축 (권장)

로컬 터미널
# [인터넷 연결 서버] 미러링 도구로 리포지토리 복제
# Ubuntu/Debian - apt-mirror
sudo apt install apt-mirror
sudo tee /etc/apt/mirror.list <<EOF
set base_path    /srv/apt-mirror
set nthreads     20
set _tilde 0

deb http://archive.ubuntu.com/ubuntu jammy main restricted universe
deb http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe
EOF
sudo apt-mirror  # 수십 GB 다운로드

# 또는 더 가벼운 방법: 필요한 패키지만 로컬 리포지토리로
mkdir -p /srv/local-repo
apt download nginx curl wget vim
sudo mv *.deb /srv/local-repo/
cd /srv/local-repo && dpkg-scanpackages . | gzip > Packages.gz

# [폐쇄망 서버] 로컬 리포지토리 등록
echo "deb [trusted=yes] file:///srv/local-repo ./" | \
  sudo tee /etc/apt/sources.list.d/local.list
sudo apt update
sudo apt install nginx  # 로컬에서 설치

# RHEL/Rocky - 로컬 리포지토리
sudo dnf install createrepo_c
mkdir -p /srv/local-repo
# RPM 파일들을 /srv/local-repo/ 에 복사 후:
sudo createrepo_c /srv/local-repo/

sudo tee /etc/yum.repos.d/local.repo <<EOF
[local]
name=Local Repository
baseurl=file:///srv/local-repo/
enabled=1
gpgcheck=0
EOF

sudo dnf install nginx

방법 3: 내부 패키지 미러 서버 구축

로컬 터미널
# Nexus Repository Manager 또는 Artifactory를 사용하는 기업 환경
# 또는 nginx로 단순 HTTP 미러 구축

# 패키지 디렉토리를 nginx로 서비스
sudo tee /etc/nginx/conf.d/local-mirror.conf <<EOF
server {
    listen 8080;
    server_name mirror.internal;
    root /srv/packages;
    autoindex on;
    location / {
        try_files \$uri \$uri/ =404;
    }
}
EOF

# 폐쇄망 서버에서 내부 미러 등록
echo "deb [trusted=yes] http://mirror.internal:8080/ubuntu jammy main" | \
  sudo tee /etc/apt/sources.list.d/internal-mirror.list

7. 의존성 충돌(Broken Packages) 해결

상황: sudo apt install some-package 실행 중 의존성 오류가 발생하고 설치가 중단됩니다. 이전에 패키지를 강제 제거하거나 인터넷 연결이 끊긴 상태에서 설치를 시도했을 때 자주 발생합니다.

OUTPUT
Reading package lists... Done
Building dependency tree... Done
You might want to run 'apt --fix-broken install' to correct these.
The following packages have unmet dependencies:
 libssl-dev : Depends: libssl3 (= 3.0.2-0ubuntu1.15) but 3.0.2-0ubuntu1.18 is installed
 python3-dev : Depends: python3.10 (= 3.10.12-1~22.04.7) but 3.10.12-1~22.04.9 is installed
E: Broken packages

원인: dpkg 의존성 데이터베이스 불일치입니다. 패키지 설치/제거가 중간에 중단되거나 dpkg --force-* 로 강제 조작한 경우, 설치 완료 전에 연결이 끊긴 경우 발생합니다.

진단: 어느 패키지가 깨진 상태인지 확인합니다.

로컬 터미널
# H=half-installed, U=unpack-only 상태인 패키지 확인
dpkg -l | grep -E "^.{1}[HU]"

# dpkg 데이터베이스 전체 일관성 검사
dpkg --audit

# 의존성 충돌 상세 확인
apt-cache depends libssl-dev
apt-cache rdepends libssl3   # 역방향: 누가 이 패키지에 의존하는가

해결:

로컬 터미널
# 1단계: apt 자동 복구 시도
sudo apt --fix-broken install

# 2단계: dpkg 미완료 설정 마무리
sudo dpkg --configure -a

# 3단계: 문제 패키지 강제 제거 후 재설치
sudo dpkg --remove --force-remove-reinstreq 문제패키지명
sudo apt install 문제패키지명

# 4단계: 캐시 초기화 후 재시도
sudo apt clean
sudo rm -rf /var/lib/apt/lists/*
sudo apt update
sudo apt --fix-broken install

상황: sudo dnf install python3-requests 실행 중 의존성 충돌 에러가 발생합니다. 서드파티 리포지토리를 추가한 뒤 시스템 Python 패키지와 버전이 맞지 않을 때 흔하게 나타납니다.

OUTPUT
Error:
 Problem: package python3-urllib3-1.26.5-3.el9.noarch requires python3-six, but none of the providers can be installed
  - package python3-six-1.15.0-9.el9.noarch conflicts with python3-six < 1.16
  - cannot install the best candidate for the job
(try to add '--skip-broken' to skip uninstallable packages
 or '--nobest' to use not only best candidate packages)

원인: 설치하려는 패키지의 의존성 버전이 현재 설치된 패키지와 충돌합니다. 서드파티 리포 추가 이후 패키지 버전 범위가 달라지거나, AppStream 모듈 스트림이 충돌하는 경우 발생합니다.

진단: 어느 패키지가 충돌을 일으키는지 파악합니다.

로컬 터미널
# 충돌 의존성 상세 확인
dnf deplist python3-requests

# 여러 버전 후보 목록 확인
dnf repoquery --available python3-six

# 현재 설치된 버전 확인
dnf list installed | grep python3-six

해결:

로컬 터미널
# 방법 1: 최우선 후보가 아닌 버전도 허용 (가장 빠른 해결)
sudo dnf install python3-requests --nobest

# 방법 2: 충돌 패키지를 제외하고 설치
sudo dnf install python3-requests --exclude=python3-six

# 방법 3: AppStream 모듈 스트림 전환 (RHEL 8+ 환경)
sudo dnf module list python3
sudo dnf module switch-to python3:3.11
sudo dnf install python3-requests

상황: Nginx 같은 소프트웨어를 소스에서 빌드하던 중 ./configure 단계에서 라이브러리를 찾지 못해 멈춥니다. 패키지 관리자로 설치할 수 없는 최신 버전이나 커스텀 옵션이 필요할 때 소스 빌드를 시도하다 만나는 전형적인 에러입니다.

OUTPUT
./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl=<path> option.

원인: 런타임 라이브러리(libssl)는 설치되어 있지만 컴파일에 필요한 헤더 파일(.h)이 포함된 개발용 패키지(-dev/-devel)가 없습니다. 소스 빌드는 반드시 개발용 패키지가 필요합니다.

진단: 필요한 헤더 파일이 어느 패키지에 포함되어 있는지 확인합니다.

로컬 터미널
# OpenSSL 개발 패키지 설치 여부 확인
dpkg -l | grep libssl-dev        # Ubuntu/Debian
rpm -q openssl-devel             # RHEL/Rocky

# pkg-config로 헤더 경로 확인 (설치됐다면 경로가 출력됨)
pkg-config --cflags --libs openssl

# make 중 "No such file or directory" 에러 시 — 해당 헤더 제공 패키지 검색
apt-file search crypt.h          # Ubuntu: apt-file install 필요
dnf provides '*/crypt.h'         # RHEL/Rocky

해결:

로컬 터미널
# Ubuntu/Debian: 개발용 헤더 패키지 설치
sudo apt install libssl-dev libxcrypt-dev build-essential

# RHEL/Rocky: 개발용 패키지 설치
sudo dnf install openssl-devel libxcrypt-devel gcc make

# 패키지 설치 후 configure 재실행
./configure --with-http_ssl_module
make -j$(nproc)
sudo make install

8. 고급 패키지 관리 기법

패키지 고정(Hold)과 버전 관리

특정 패키지를 현재 버전에서 고정하여 자동 업그레이드를 막아야 하는 경우가 있습니다(예: 검증된 커널 버전, 특정 앱 버전 고정).

로컬 터미널
# Ubuntu/Debian: 패키지 고정
sudo apt-mark hold nginx
# nginx set on hold.

# 고정된 패키지 확인
apt-mark showhold
# nginx

# 고정 해제
sudo apt-mark unhold nginx

# 고정 상태에서 업그레이드 시도 시:
sudo apt upgrade
# The following packages have been kept back:
#   nginx
# 0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.

# dpkg로 직접 고정
echo "nginx hold" | sudo dpkg --set-selections
dpkg --get-selections | grep hold
# nginx                   hold

# RHEL/Rocky: 패키지 버전 잠금
sudo dnf install 'dnf-command(versionlock)'
sudo dnf versionlock add nginx
# Adding versionlock on: nginx-1:1.20.1-10.el9.*

# 잠금 목록 확인
sudo dnf versionlock list
# nginx-1:1.20.1-10.el9.*

# 잠금 해제
sudo dnf versionlock delete nginx
패키지 관리 자동화와 보안 업데이트
로컬 터미널
# Ubuntu: 보안 업데이트 자동 적용 설정
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades

# 설정 파일 확인
cat /etc/apt/apt.conf.d/50unattended-upgrades
# Unattended-Upgrade::Allowed-Origins {
#     "${distro_id}:${distro_codename}-security";
#     "${distro_id}ESMApps:${distro_codename}-apps-security";
# };
# Unattended-Upgrade::Mail "admin@example.com";
# Unattended-Upgrade::Automatic-Reboot "false";

# 자동 업데이트 주기 설정
cat /etc/apt/apt.conf.d/20auto-upgrades
# APT::Periodic::Update-Package-Lists "1";     // 매일 목록 새로고침
# APT::Periodic::Unattended-Upgrade "1";       // 매일 자동 업데이트

# 드라이런으로 미리 확인
sudo unattended-upgrade --dry-run --debug

# RHEL: dnf-automatic으로 자동 업데이트
sudo dnf install dnf-automatic

sudo tee /etc/dnf/automatic.conf <<EOF
[commands]
upgrade_type = security   # security 또는 default (전체)
apply_updates = yes
emit_via = email
email_to = admin@example.com
EOF

sudo systemctl enable --now dnf-automatic.timer
systemctl status dnf-automatic.timer
# ● dnf-automatic.timer - dnf-automatic timer
#      Loaded: loaded (/usr/lib/systemd/system/dnf-automatic.timer; enabled)
#      Active: active (waiting)
#     Trigger: Fri 2026-03-27 06:00:00 KST; 19h left

9. 현업 적용 — 실무 시나리오

💼
실무 맥락인프라 엔지니어의 패키지 관리 전략
현업 패턴

시나리오: 새 운영 서버 프로비저닝

신규 서버를 구성할 때 패키지 관리는 IaC(Infrastructure as Code)와 함께 자동화됩니다.

로컬 터미널
#!/bin/bash
# server-bootstrap.sh — 서버 초기 구성 스크립트

set -euo pipefail

# OS 감지
if [ -f /etc/debian_version ]; then
    PKG_MANAGER="apt"
elif [ -f /etc/redhat-release ]; then
    PKG_MANAGER="dnf"
fi

bootstrap_ubuntu() {
    echo "[INFO] Ubuntu 서버 초기화 시작"

    # 패키지 목록 최신화
    apt update -qq

    # 보안 업데이트 우선 적용
    apt upgrade -y -o Dpkg::Options::="--force-confdef" \
                    -o Dpkg::Options::="--force-confold"

    # 기본 도구 설치
    apt install -y \
        curl wget git vim \
        htop iotop nethogs \
        unzip jq \
        ca-certificates gnupg \
        ufw fail2ban \
        logrotate

    # Docker 리포지토리 추가 및 설치
    install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
        gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    echo \
        "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] \
        https://download.docker.com/linux/ubuntu \
        $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
        tee /etc/apt/sources.list.d/docker.list > /dev/null
    apt update -qq
    apt install -y docker-ce docker-ce-cli containerd.io

    echo "[INFO] 초기화 완료"
}

bootstrap_rhel() {
    echo "[INFO] RHEL 계열 서버 초기화 시작"

    dnf upgrade -y --security

    dnf install -y \
        curl wget git vim \
        htop iotop \
        unzip jq \
        ca-certificates \
        firewalld fail2ban

    # EPEL 설치
    dnf install -y epel-release

    # Docker (또는 Podman 권장)
    dnf install -y podman podman-compose

    echo "[INFO] 초기화 완료"
}

if [ "$PKG_MANAGER" = "apt" ]; then
    bootstrap_ubuntu
elif [ "$PKG_MANAGER" = "dnf" ]; then
    bootstrap_rhel
fi

보안 패치 정책 예시 (기업 환경):

패치 분류적용 기준적용 주기
Critical CVECVSS 9.0 이상24시간 내 긴급 적용
High CVECVSS 7.0~8.91주일 내
Medium CVECVSS 4.0~6.9다음 정기 패치
Low/InformationalCVSS 0~3.9분기별 패치
💼
실무 맥락폐쇄망 환경의 패키지 관리 아키텍처
현업 패턴

대형 금융사, 공공기관 운영 환경에서의 현실적인 패키지 관리 체계입니다.

전형적인 폐쇄망 아키텍처:

TEXT
인터넷  ──▶  DMZ 서버(패키지 미러)  ──▶  내부망 넥서스/Artifactory
                                              │
                                    ┌─────────┴─────────┐
                                    ▼                   ▼
                              개발 서버군           운영 서버군
                         (dnf/apt 내부 미러 사용)

Nexus Repository Manager로 프록시 미러 구성 (개념):

로컬 터미널
# 각 서버에서 내부 미러를 바라보도록 설정
# Ubuntu 서버
sudo tee /etc/apt/sources.list <<EOF
deb http://nexus.internal.company.com/repository/ubuntu-proxy/ jammy main restricted
deb http://nexus.internal.company.com/repository/ubuntu-proxy/ jammy-updates main restricted
deb http://nexus.internal.company.com/repository/ubuntu-security/ jammy-security main restricted
EOF

# RHEL 서버
sudo tee /etc/yum.repos.d/internal.repo <<EOF
[baseos]
name=Internal BaseOS Mirror
baseurl=http://nexus.internal.company.com/repository/rhel-baseos/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

[appstream]
name=Internal AppStream Mirror
baseurl=http://nexus.internal.company.com/repository/rhel-appstream/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
EOF

# 검증
sudo dnf repolist
# repo id          repo name
# appstream        Internal AppStream Mirror
# baseos           Internal BaseOS Mirror

sudo dnf install nginx
# (내부 미러에서 설치됨)

운영 체크리스트:

  • 내부 미러 동기화 주기 설정 (일 1회 자동 동기화 권장)
  • 미러 서버 디스크 사용량 모니터링 (Ubuntu 전체 미러 ~1.5TB)
  • 승인된 패키지만 넥서스에 허용 (화이트리스트 정책)
  • 패키지 설치 이력 감사 로그 보존
  • 정기 취약점 스캔 (Trivy, Grype 등으로 설치된 패키지 점검)

10. 요약 — 명령어 치트시트

apt vs dnf 명령어 대조표:

작업apt (Ubuntu/Debian)dnf (RHEL/Rocky)
목록 새로고침apt updatednf check-update
패키지 설치apt install pkgdnf install pkg
패키지 삭제apt remove pkgdnf remove pkg
완전 삭제apt purge pkgdnf remove pkg (설정도 삭제)
업그레이드apt upgradednf upgrade
패키지 검색apt search termdnf search term
패키지 정보apt show pkgdnf info pkg
파일→패키지dpkg -S /path/to/filerpm -qf /path/to/file
설치 목록dpkg -ldnf list installed
자동정리apt autoremovednf autoremove
캐시 정리apt cleandnf clean all
이력 확인zcat /var/log/apt/history.log.gzdnf history
이력 롤백(없음)dnf history undo <id>
패키지 고정apt-mark hold pkgdnf versionlock add pkg

리포지토리 관리 위치:

항목aptdnf
주 설정 파일/etc/apt/sources.list(없음)
추가 리포지토리/etc/apt/sources.list.d/*.list/etc/yum.repos.d/*.repo
GPG 키 위치/etc/apt/keyrings/*.gpg/etc/pki/rpm-gpg/
패키지 캐시/var/cache/apt/archives//var/cache/dnf/

💡개념

apt signed-by 키링 기반 리포 신뢰 모델 — deprecated apt-key 대체

apt-key(deprecated) vs signed-by(권장) — 글로벌 키링 vs 리포별 키링 신뢰 모델 비교

Docker나 HashiCorp 공식 설치 가이드를 따라 curl ... | sudo apt-key add -를 실행하면 "Warning: apt-key is deprecated"가 뜹니다. Ubuntu 22.04부터 apt-key 방식은 보안상 문제가 있어 deprecated 처리됐기 때문입니다. 기존 방식은 하나의 키링 파일에 모든 외부 리포 키가 섞여서, 특정 리포에서 받은 키가 시스템 전체 패키지를 신뢰하는 구조였습니다. 새 방식은 리포마다 별도 .gpg 파일을 만들어 /etc/apt/keyrings/에 두고, sources.list에서 signed-by= 옵션으로 해당 리포에만 연결합니다. 스크립트나 자동화 코드를 작성할 때 이 구분을 모르면 오래된 방식으로 짜게 됩니다.

Ubuntu 22.04+부터 apt-key는 deprecated입니다. 새로운 방식은 각 리포마다 전용 키링 파일을 사용합니다.

새 방식 (권장):

로컬 터미널
# 1. 키링 저장 디렉토리 생성
sudo mkdir -p /etc/apt/keyrings

# 2. GPG 키 다운로드 및 저장
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
    sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 3. sources.list.d에 signed-by 옵션으로 리포 등록
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
    https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 4. 업데이트 및 설치
sudo apt update
sudo apt install docker-ce docker-ce-cli

apt-key (구식, 보안 취약):

로컬 또는 서버
# 이렇게 하면 안 됨 — 모든 리포에서 해당 키 신뢰
curl -fsSL https://example.com/key.gpg | sudo apt-key add -  # deprecated!
💡개념

apt pinning — 특정 버전 고정과 우선순위 제어

apt pinning 우선순위 값 — 1000(강제)/990(설치)/500(기본)/100(수동)/음수(금지) 와 preferences 설정 예시

apt upgrade를 실행했더니 Nginx 버전이 올라가면서 설정 파일 문법이 바뀌어 서비스가 내려간 적이 있습니다. 또는 Python이나 Node.js 관련 패키지가 자동 업그레이드되면서 의존하는 앱이 갑자기 깨지는 경우도 흔합니다. 운영 환경에서는 검증되지 않은 버전 업그레이드가 곧바로 장애로 이어질 수 있기 때문에, 특정 패키지는 버전을 고정해두는 게 안전합니다. apt-mark hold가 가장 간단한 방법이고, 더 세밀한 제어가 필요할 때는 apt pinning으로 우선순위를 직접 지정합니다. 커널 버전 고정, 특정 외부 리포 패키지 우선순위 조정 등에서 이 기능이 실제로 쓰입니다.

운영 서버에서 패키지 버전을 고정해 자동 업데이트로 인한 장애를 방지합니다.

apt pinning (/etc/apt/preferences.d/):

로컬 터미널
# nginx를 특정 버전으로 고정
sudo tee /etc/apt/preferences.d/nginx << 'EOF'
Package: nginx
Pin: version 1.24.*
Pin-Priority: 1001
EOF

# 리포지토리 전체 우선순위 낮추기 (외부 리포 패키지가 시스템 패키지 덮어쓰지 않도록)
sudo tee /etc/apt/preferences.d/docker << 'EOF'
Package: *
Pin: origin download.docker.com
Pin-Priority: 500
EOF

# 현재 pin 상태 확인
apt-cache policy nginx
# nginx:
#   Installed: 1.24.0-1
#   Candidate: 1.24.0-1      ← 최신도 이 버전으로 고정됨
#   Pin: (not pinned)

Pin-Priority 값 의미:

동작
< 0절대 설치하지 않음
1-99이미 설치된 경우에만
100설치되어 있지 않으면 설치 안 함
500기본값
1001현재보다 낮은 버전도 강제 설치
로컬 터미널
# apt-mark hold (가장 간단한 버전 고정)
sudo apt-mark hold nginx
sudo apt-mark showhold  # 고정된 패키지 목록

# 해제
sudo apt-mark unhold nginx

dnf versionlock (RHEL/Rocky):

로컬 터미널
sudo dnf install 'dnf-command(versionlock)'
sudo dnf versionlock add nginx    # 현재 버전 고정
sudo dnf versionlock list         # 고정 목록
sudo dnf versionlock delete nginx # 해제

다음 모듈에서는 tmux로 터미널 세션을 유지하고, 화면을 분할하여 여러 작업을 동시에 관리하는 방법을 다룹니다.

지식 확인

퀴즈 — 5문제

Q1

Ubuntu 서버에서 패키지 목록을 최신화한 후 설치 가능한 업그레이드를 모두 적용하는 올바른 명령어 순서는?

Q2

apt로 설치된 패키지의 설정 파일까지 완전히 제거하는 명령어는?

Q3

특정 패키지가 자동 업그레이드되지 않도록 버전을 고정(hold)하는 apt 명령어는?

Q4

설치된 .deb 파일을 dpkg로 직접 설치하는 명령어는?

Q5

Rocky Linux(RHEL 계열)에서 패키지 이름으로 검색하는 dnf 명령어는?

0 / 5 답변

🧪 실습으로 확인하기

새 서버 인수인계 — 처음 30분

초급

낯선 Linux 서버를 인수받았을 때 OS, 서비스, 로그를 빠르게 파악하는 루틴을 직접 수행한다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

linux입문 · 50
[Linux] 서버 설정의 기초인 export, .bashrc, .profile 완벽 정리
Linux 트랙 계속
docker입문 · 30
[Docker] 백엔드 개발자에게 Docker와 컨테이너 가상화가 필수인 이유
Docker 트랙 시작점