Heesung Yang

DEB(APT) Repository 만들기

일단 아무런 설명 없이 그대로 따라서 만들어 보자. 자세한 내용은 뒤에서 설명한다.

APT Repository 생성

  1. 아래와 같은 폴더 구조를 만든다.

    .
    ├── deb
    │   ├── dists
    │   │   └── stable
    │   │       └── main
    │   │           ├── binary-amd64
    │   │           └── binary-arm64
    │   └── pool
    │       └── main
    
    ~$ mkdir -p deb/dists/stable/main/binary-amd64
    ~$ mkdir -p deb/dists/stable/main/binary-arm64
    ~$ mkdir -p deb/pool/main
    
  2. deb/pool/main 폴더에 deb 파일들을 복사한다.

    ~$ cp *.deb deb/pool/main
    
  3. Repository 생성 시 필요한 유틸리티를 설치한다.

    ~$ sudo apt install apt-utils dpkg-dev
    
  4. Packages 파일을 생성한다.

    ~$ cd deb/
    ~$ dpkg-scanpackages -m --arch amd64 pool/ > dists/stable/main/binary-amd64/Packages
    ~$ dpkg-scanpackages -m --arch amd64 pool/ | gzip -9 > dists/stable/main/binary-amd64/Packages.gz
    ~$ dpkg-scanpackages -m --arch arm64 pool/ > dists/stable/main/binary-arm64/Packages
    ~$ dpkg-scanpackages -m --arch arm64 pool/ | gzip -9 > dists/stable/main/binary-arm64/Packages.gz
    
  5. Release 파일을 생성한다.

    ~$ cd dists/stable/
    ~$ cat > Release << EOF
    Origin: My Home
    Label: My Home
    Suite: stable
    Version: 1.0
    Architectures: amd64 arm64
    Components: main
    Description: my software repository
    EOF
    ~$ apt-ftparchive release . >> Release
    
  6. GPG Key Pair를 생성한다.

  7. 생성한 GPG Key 를 이용하여 Release 파일에 서명한다.

    # 5번 과정에서 Key Pair 생성 시 입력한 Real name 값이 mykey 인 경우
    ~$ cd deb/dists/stable
    ~$ gpg --clearsign -o InRelease --default-key mykey Release
    ~$ gpg -abs -o Release.gpg --default-key mykey Release
    
  8. 5번에서 생성한 GPG Key 의 공개키를 추출한 후 deb 저장소 최상단에 복사한다.

    # 5번 과정에서 Key Pair 생성 시 입력한 Real name 값이 mykey 인 경우
    ~$ gpg --armor --export mykey > pub.key
    
    ~$ mv pub.key deb/
    
  9. Web 서버를 실행한다. (여기서는 간단하게 python3를 이용)

    ~$ cd deb/
    ~$ python3 -m http.server
    Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
    

APT Repository 추가

위에서 생성한 Repository를 서버에 추가하는 과정이다. Repository 서버의 IP 주소가 1.1.1.1 이라고 가정하였다.

  1. public key 등록

    ~$ curl http://1.1.1.1:8000/pub.key | sudo apt-key add -
    
  2. sources.list 추가

    • 만약 arm64 기반이라면 [arch=arm64] 로 변경
    ~$ sudo cat > /etc/apt/sources.list.d/my.list <<EOF
    deb [arch=amd64] https://1.1.1.1:8000 stable main
    EOF
    
  3. apt 캐쉬 업데이트

    ~$ sudo apt update
    

개념

sources.list format

/etc/apt/sources.list 파일을 열어보면 다음과 같이 저장소가 정의되어 있다.

deb http://archive.ubuntu.com/ubuntu focal main restricted

위 파일의 포맷은 man sources.list 명령어로 확인할 수 있는데, 아래와 같이 설명되어 있다.

deb [ option1=value1 option2=value2 ] uri suite [component1] [component2] [...]
deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [...]

Types

첫 번째 항목으로, deb / deb-src 값 중 하나를 쓸 수 있다.

  • deb : binary package 저장소
  • deb-src : source code package 저장소

Types Options

두 번째 항목으로, 생략 시 default option이 적용된다. 각 옵션은 공백으로 구분한다. 아래와 같이 [] 안에 옵션 값을 설정한다.

deb [arch=amd64 trusted=yes] https://download.docker.com/linux/ubuntu   focal stable

자주 접하는 옵션만 설명한다. 모든 옵션은 man sources.list 에서 확인하자.

  • arch
    • string
    • 어떤 architecture에 대한 저장소인지 설정한다. 생략 시 모든 architecture에 대한 저장소로 설정된다.
  • allow-insecure
    • boolean (yes/no)
    • 저장소에 Release 파일이 없거나 서명되지 않은 Release 파일이 있는 경우, apt update 명령 실행 시 데이터를 다운로드 받지 않는다. 그러나 해당 옵션 적용 시 warning 메시지만 띄우고 데이터를 다운로드 한다.
  • trusted
    • boolean (yes/no)
    • 저장소에 Release 파일이 없거나 서명되지 않은 Release 파일이 있는 경우에도 warning 메시지 없이 데이터를 다운로드 한다.

URI

세 번째 항목으로, 저장소의 root url을 지정한다. 사용가능한 URI 타입은 다음과 같다.

  • http

  • https

  • mirror, mirror+scheme

  • file

    • 디스크의 특정 경로를 저장소로 사용할 경우 사용한다. 아래와 같이 설정한다.

      file:/home/apt/debian
      
  • cdrom

  • ftp

  • copy

  • rsh, ssh

Suites, Component

Suites가 네 번째, 그 이후 Component는 몇 개든 쓸 수 있다. Suties 값은 보통 배포판의 codename을 사용하거나 stable과 같은 값을 사용한다. 실제로는 저장소 root 의 하위 폴더 이름을 의미한다. 아래 예를 보자.

deb http://archive.ubuntu.com/ubuntu focal main restricted

위 예에서 Suites는 focal, Component는 mainrestricted이다. 실제 서버의 폴더 구조는 아래와 같다.

.
└── ubuntu                    << URI Root
    └── dists
        └── focal             << Suites
            ├── main          << Component1
            └── restricted    << Component2

Suites과 Component는 모든 패키지 파일을 한 폴더에서 관리하지 않고 폴더 별로 나눠서 관리하기 위한 방법이라 생각하자.

Meta data

Release, InRelease

apt 명령어로 패키지를 다운로드할 때, 가장 먼저 이 파일을 다운로드 받는다. 이 파일은 아래 위치(Suites 하위)에 존재해야 한다.

deb http://archive.ubuntu.com/ubuntu focal main restricted

.
└── ubuntu                    << URI Root
    └── dists
        └── focal             << Suites
            ├── InRelease
            ├── Release
            ├── main          << Component1
            └── restricted    << Component2

Release 파일은 저장소의 파일들의 hash 정보를 기록한 텍스트 파일이다. (다운로드한 파일의 무결성 체크를 위해 사용) Release 파일은 Release.gpg 파일 또한 함께 제공되어야 하는데, Release 파일에 대한 서명 정보이다. InRelease 파일은 Relase + Release.gpg 라고 생각하면 된다. (두 개의 파일을 하나로 합침)

Packages

Packages 파일은 실제 deb 파일들에 대한 Meta 정보가 포함되어 있는 텍스트 파일이다. apt 명령어 실행 시 이 파일을 읽어서 패키지 정보를 알아내는 것으로 추정한다. Packages 파일은 아래 위치한다.

.
├── dists
│   └── stable
│       ├── InRelease
│       ├── main
│       │   ├── binary-amd64
│       │   │   ├── Packages      <<---
│       │   │   └── Packages.gz   <<---
│       │   └── binary-arm64
│       │       ├── Packages      <<---
│       │       └── Packages.gz   <<---
│       ├── Release
│       └── Release.gpg
├── pool
    └── main

Reference