원 글과 비교하여, 몇가지 내용이 추가되었다. 원 글은 비교를 위해 그냥 남겨두기로 한다.
- var(@var) – NoCoW 설정
- 서브볼륨 세분화
- /var/lib/dpkg root 로 link(ln -s)
우분투 서버 이미지에는 두가지가 있다. live 가 붙은 것과, 그렇지 않은 것.
서버 설치 프로그램면에선 live/비 live 가 확연히 다른데, 정작 설치된 서버 자체는 미묘한 차이만 있는 듯 하다.
아무튼, 이 글은 ‘Ubuntu Server 20.04.1 Live’ 판을 기준으로 작성했다.
우분투 서버를 설치할 때, 파일시스템을 Btrfs 로 선택할 순 있지만, 서브볼륨을 설정하고 사용할 순 없다. OpenSuse 는 설치프로그램이 정말 완벽하다할 수 있을 정도인데, 우분투는 이 부분이 많이 아쉽다.
이를 극복하려면, 마치 ArchLinux 를 설치할 때처럼 약간의 지식이 필요하다.
이 글에서 간단하게 그 방법을 정리해보기로 한다.
다음 글에서 도움을 얻었다.
Ubuntu Server 18.04 btrfs raid1 (optionnal)
Ubuntu Live Server 디스크 이미지로 설치 진행
우분투 서버 설치 디스크로 부팅한 후 진행하다가, 파티션 작업에서 두가지를 해줘야 한다.
- / 를 btrfs 로 설정
- /boot 를 ext4 로 설정. (약 1GB)
디스크 파티션에서, /boot 영역(1GB 정도)을 따로 만드는게 Btrfs 를 사용할 때 여러모로 편리한 면이 있으므로, /boot 파티션을 따로 만들고, 파일시스템은 ext4 로 해준다. (예전에 어떤 책에서는 ext2 를 추천했었는데, 여기선 아예 ext2 를 선택할 수 조차 없다.)
** /boot 파티션(ext4)은 꼭 해야하는 필수사항은 아니다.
UEFI 시스템에서 어떤 파티션이든 하나라도 만들면, EFI(/boot/efi) 파티션은 자동으로 생성된다.

그리고 끝까지 진행한다.
** 파티션 작업이 은근히 불편하다. 꼭 저 화면에서만 파티션 작업을 해야 한다. (미리 나눠놓은 파티션은 인식은 하지만, 마운트 할당등은 불가능하다.)
계속 진행하다가, 마지막 단계(12/12, 또는 13/13) 가 되었을 때, Reboot Now 를 택하지 말고, Ctrl-Alt-F2(VBox 의 경우, 메뉴 – 입력 – 키보드 – Soft Keyboard) 를 입력한 뒤 두번째 가상 콘솔로 이동한다.

이곳으로 가면, 이제 자유롭게(?) 명령어들을 입력할 수 있다.
좀 더 원활하게 하기 위해 Dvorak 으로 전환한다. (20.04 부터는 아래 작업을 안해도 설치 시에 Dvorak 을 선택했다면 그냥 Dvorak 이 적용된다.)
sudo dpkg-reconfigure keyboard-configuration ... 일련의 설정을 끝내고.. sudo setupcon
setupcon 을 해줘야 변경이 즉각 반영된다.
** 모든 명령은 sudo -i
후 관리자 권한으로 진행한다.
이제 여기서 해야할 일은 다음과 같다.
- Btrfs 압축을 원한다면, defrag 실행.
- Btrfs Subvolume 생성
- 생성된 Subvolume 으로, 설치 프로그램이 만든 파일들 복사
- 서브볼륨을 사용해 새 루트 시스템 mount 후, chroot 작업
- fstab 수정
- 부트로더 수정
복잡해보이지만, ArchLinux 는 저런 식으로 설치해야만 한다. 그것에 비하면 훨씬 간단한(?) 작업이다.
작업을 편하게 하기 위해 sudo -i
로 관리자로 전환한다.
원 글에서는 /target 을 나중에 umount 하라고 되어 있는데, run 디렉토리 때문에 그럴 수가 없었다(오류 발생). 따라서 그냥 umount 는 없이 진행한다.
/target 확인
우분투 서버 설치 프로그램은 /target 디렉토리에, 위에서 작업한 일련의 파티션들을 마운트 한 후 시스템을 구성한다. 따라서 먼저 저 디렉토리를 확인해본다.
ll /target # 잘 설치되어 있는지 확인한다.
그 뒤 lsblk 로 현재 디스크 상황도 파악한다.

설정한 대로, ESP, boot, / 모두 잘 만들어져있다.
Btrfs Compression
만약, Btrfs 의 Compression 기능을 원한다면, 이 시점에서 /target 을 압축해줘야 한다. 후에 fstab 에서 btrfs compression 을 줄 경우, 추후에 생성되는 파일들에 대해서만 압축이 이뤄진다. 따라서, 이왕 할거라면 지금 압축 작업을 해주는게 좋다. (물론, 나중에 시스템이 완성된 후에 해도 된다. 아마도.)
btrfs filesystem defragment -r -v -clzo /target
-clzo
가 핵심인데, 현재 Btrfs 는 zlib, lzo, zstd 세가지 압축 방식을 지원하고 있다. 여기서, 압축효율과 속도를 감안하여 가장 추천(?)하는게 lzo 라고 한다. 기본값은 zlib 이다.
압축 시간은 몇분 걸리지 않는다.
압축이 됐는지 여부는, 나중에 compsize(apt install btrfs-compsize)를 통해 알아볼 수 있다.
Sub Volume 생성
이제 /target 으로 이동하여 Btrfs Subvolume 을 생성한다.
우분투는, @ 을 시스템 루트(/)로, @home 을 /home 으로 사용한다.
헌데, OpenSuse 를 보니 보다 다양한 서브볼륨을 사용하고 있었다. 서브볼륨을 사용한다는 의미는 결국 Snapshot 을 활용한다는 뜻이 되므로, 적절히 추가하는게 효과와 효율면에서 더 나은 선택이 될 수 있다고 본다.
물론, ‘관리’가 가능하다는 전제 하에.
하여, OpenSuse 를 최대한 참고하고, Snapper 를 사용한다는 전제하여 다음과 같이 서브볼륨을 사용하기로 했다.
왼쪽은 서브볼륨, 오른쪽은 마운트 포인트.
- @ : /
- @home : /home
- @var : /var
- @tmp : /tmp
- @srv : /srv
- @root : /root
- @opt : /opt
OpenSuse 와 다른 점은, usr/local 서브볼륨이 없고, 서브볼륨 구조가 Nested(OpenSuse)가 아닌 Flat 형이라는 점이다.
또, 저 서브볼륨들을 독립된 파티션에 만들 것인지, 아니면 한 파티션에 서브볼륨으로만 만들 것인지도 고민이 됐는데, 그냥 한 파티션만 사용하기로 했다.
만약 파티션이 다르다면, 아래에 서술할 mount 작업에서 적절히 바꿔주기만 하면 되겠다.
cd /target # /target 은, 우분투 설치 프로그램이 작성한 새 시스템 디스크 영역의 / 다. btrfs subvolume create @ btrfs subvolume create @home btrfs subvolume create @var btrfs subvolume create @tmp btrfs subvolume create @srv btrfs subvolume create @root btrfs subvolume create @opt # set default 는 해주는게 좋다. btrfs subvolume set-default @
set-default 에 관한 설명은 나중에.
@var NoCoW 설정 및 파일 복사.
@var 에는 NoCoW 를 설정하는게 권장된다고 하므로, 다음과 같이 설정한다.
chattr +C /target/@var
다음 단계에선 파일을 이동(mv)해야 하지만, 여기선 복사를 해줘야 한다. 이유는 NoCoW.
NoCoW 를 시행하려면, 파일을 새로 복사해야하고, 기존의 파일을 그냥 옮기면 아무 효과가 없다.
복사를 한 뒤에는 /var 밑의 파일들은 필요없으므로 지운다.
cp -rp /target/var/. /target/@var rm -rf /target/var
/var/lib/dpkg 위치 새롭게 설정
Snapper 사용 시 사소한 dpkg 문제가 생길 수 있다. 이를 위해선 이 디렉토리를 루트 Snapshot 에 포함시켜야 하는데, 뭔가 다른 방법이 있을 수도 있겠지만, 간단하게 이런 식으로 처리하기로 했다.
방법 : /var-dpkg 를 만들고, /var/lib/dpkg 를 심볼릭링크로 걸어준다.
실제 작업은 chroot 이후에 해준다.
/target 디렉토리 서브볼륨으로 복사/삭제
위 작업(@var)과 같지만, NoCoW 는 하지 않는다.
현 시점에서 home, opt, srv 는 비어있으므로 복사를 해줄 필요는 없다.
(mv 를 해도 되는데, 그랬을 때 /target/root 아래 있는 .bashrc 등을 어떻게 옮겨야 하는지 방법을 알아내지 못했다. 게다가, 어차피 디렉토리(tmp, root 등)를 지워야 하므로, 그냥 복사후 삭제를 택했다.)
# 복사 cp -rp /target/tmp/. /target/@tmp cp -rp /target/root/. /target/@root # 삭제 rm -rf /target/tmp/* find /target/root -mindepth 1 -delete
/target/root 에는 . 으로 시작하는 파일들이 있는데, 이걸 rm 으로 지우기가 쉽지 않아서 find 를 사용했다.
/target 내부 파일 서브볼륨 @ 으로 이동
이제, /target 안에 생성되어 있는 파일들을, 서브볼륨 @ 안으로 적절히 이동시킨다.
그에 앞서, /target/boot 와 /target/boot/efi 는 마운트 해제해줘야 한다. 이건 독립 파티션이므로, 이동(mv)시킬 필요가 없다.
순서는 efi 를 먼저, boot 를 나중에.
** cdrom 디렉토리는 /target/cdrom 이 아닐 수도 있다. 확인 후 적절히 umount 해줘야 한다.
Unmount 작업
umount /target/boot/efi umount /target/boot umount /target/cdrom 또는 umount /target/run/cdrom
파일 이동
mv -t @ b* d* e* h* l* m* o* p* root s* t* u*
run 디렉토리는 mv 가 안된다. 굳이 이 디렉토리를 이동해줘야 할 필요는 없기에 아예 이동시키질 않았다. (예전엔 r* 로 root, run 을 모두 이동시켰지만, root 만 해줬다.)
만약 이동해주면, 아래에서 할 chroot 이후에도 네트웍 관련 작업(apt 등)을 그대로 할 수 있게 된다.
따라서, 이 작업이 필요하다면, 그리고 mv 시 run 디렉토리 관련 오류가 난다면, mv 말고 run 디렉토리를 ‘복사’ 해준다.
cp -rp /target/run /target/@
만약, run 디렉토리가 mv 로 오류없이 이동한다면 그대로 하면 된다.
내 상식으로는, run 디렉토리는 시스템 첫 부팅 시에 새로 만들어지기 때문에, 굳이 남겨놓을 필요는 없다.
서브볼륨을 사용한 /target 재구성
/new-target 을 생성하여 새롭게 시스템을 재구성한다.
워낙엔 /target 을 마운트 해제하고 작업했는데, run 디렉토리로 인해 이게 불가능하게 됐다. (Busy 오류가 나오면서 마운트 해제가 되지 않을 경우가 있다.)
따라서 굳이 umount 를 하지 말고, /new-target 등을 새로 만든 후 그 이하로 아래 작업을 시행하면 된다.
home, opt 는 지금은 mount 해주지 않아도 된다. (현 시점에선 쓸모가 없다.)
또, 원 글에서는 여기에 mount compress 옵션을 줬는데, /target 이 umount 가 되지 않는 상황에선 이 옵션을 줘도 의미가 없다. 게다가 굳이 지금 compress 를 줄 필요도 없다.
나중에 fstab 에서만 옵션을 주면 된다.
cd / umount /target #(오류가 나면 하지 말고, mkdir /target2 를 만든 뒤 아래를 모두 target 2 로 바꾼다.) mkdir /target2 #(또는 new-target 등, 원하는대로) # /, 즉 @ 가 있는 디스크/파티션 mount /dev/nvme0n1p3 /target2 -o subvol=@ # set-default 를 해줬기 때문에 subvol 은 굳이 없어도 되지만. # /boot 가 있는 디스크/파티션 mount /dev/nvme0n1p2 /target2/boot # ESP 가 있는 디스크/파티션 mount /dev/nvme0n1p1 /target2/boot/efi # @var 가 있는 디스크/파티션 mount /dev/nvme0n1p3 /target2/var -o subvol=@var # 기타 @srv 등은 지금은 필요없다. mount --bind /proc /target2/proc mount --bind /dev /target2/dev mount --bind /sys /target2/sys
만약, 위에서 set-default 를 해주지 않았다면, 다음과 같이 @ 를 명시해주는게 여러모로 편하다.
mount /dev/nvme0n1p3 /target -o subvol=@
fstab 수정
이젠, fstab 을 수정해줘야 한다.
chroot 한 뒤 해도 되지만, 지금도 할 수 있다.
lsblk 를 참고하여, fstab 을 아래와 같이 고친다.
맨 먼저 / 를 마운트 해야 하고, 그 후에 home 등을 해주면 된다. (당연하지만, 여기선 반드시 home, opt, var 등 Subvolume 으로 만든 모든 것들을 포함시켜줘야 한다.)
Btrfs 의 현재 제약으로 인해, 마운트 옵션을 서브볼륨별로 달리 줄 수가 없다. 따라서, compress 등 옵션은, 맨 첫 서브볼륨(루트)에만 주고, 나머지엔 써주지 않아도 모두 동일한 옵션이 적용된다.
/boot 를 먼저, /boot/efi 를 나중에 해야 함도 잊지 말 것.
lsblk -f NAME FSTYPE LABEL UUID MOUNTPOINT nvme0n1 ├─nvme0n1p1 vfat zzzz /target/boot/efi ├─nvme0n1p2 ext4 yyyy /target/boot └─nvme0n1p3 btrfs xxxx /target vim /target2/etc/fstab UUID=xxxx / btrfs defaults,compress=lzo,subvol=@ 0 0 UUID=xxxx /home btrfs subvol=@home 0 0 UUID=xxxx /var btrfs subvol=@var 0 0 UUID=xxxx /opt btrfs subvol=@opt 0 0 UUID=xxxx /srv btrfs subvol=@srv 0 0 UUID=xxxx /root btrfs subvol=@root 0 0 UUID=xxxx /tmp btrfs subvol=@tmp 0 0 UUID=yyyy /boot ext4 defaults 0 0 UUID=zzzz /boot/efi vfat defaults 0 0
밑밥은 끝났다. chroot 로 가상 시스템으로 접근한 뒤, /var/lib/dpkg 를 / 로 이동시켜주고, 링크를 만든 뒤, 부트로더 관련 작업들을 해주면 긴 장정이 끝나게 된다.
chroot 작업
chroot /target2 # dpkg 디렉토리 이동 mkdir /var-dpkg cp -rp /var/lib/dpkg/* /var-dpkg rm -rf /var/lib/dpkg ln -s /var-dpkg /var/lib/dpkg # 혹시 몰라서.. (/run 이 없으면 부팅 시에 오류 발생 가능성이 있다.) mkdir /run # 커널 등록 update-initramfs -u -k all grub-install --recheck update-grub
** cryptsetup 관련 오류 (Ubuntu 18.04 까지)
update-initramfs 을 하고 나면, cryptsetup 관련 오류가 발생한다.
이것은 ext4 로 설치했을 땐 생기지 않는데, 아마도 Btrfs 관련한 오작동으로 보인다.cryptsetup 2.0.2 까지 이 버그가 있다고 하는데, 우분투 18.04 까지는 2.0.2 가 제공되고 있기에, 피해갈 방법은 없다.
그냥, cryptsetup 꾸러미를 지워버리는게 가장 단순하지만 효과 만점인 해결책이었는데.. 2020년 2월 현재, 이 꾸러미를 지우면, ubuntu-server 꾸러미도 지워진다.
따라서, 그냥 이 문제는 그냥 무시하고 넘길 수 밖에 없다.
데비안 보고에 따르면, 2.0.3 부터는 해결이 된 모양인데, 우분투 20.04에는 2.2.x 가 들어있었고, 그래서인지 이 문제는 없었다.
이렇게 끝!exit
후, 원래 콘솔로 돌아가서 reboot
를 택해주면 된다.
Swap 설정?
만약, 스왑파티션을 만들지 않았다면, 설치 관리자는 자연스럽게 /swap.img 를 만든다. Ext4 에선 괜찮지만, Btrfs 에서 이 파일을 그냥 쓰면 여러가지 문제가 발생할 수 있다.
따라서, 다소 귀찮더라도 그냥 Swap Partition 을 만드는게 여러모로 좋은 방법이라고 생각한다.
그게 불가능하다면, 다른 Ext4 파티션에 파일을 만들어 쓰는 방법도 좋다.
Btrfs 에는 가능한한 만들지 않는게 정신건강상 좋고, 굳이 만들려면 ArchLinux 문서를 참고하면 될텐데.. 글쎄?
설치가 끝나고 할 일!
위 설치에서 약간 찌꺼기(?)가 남는다. FS_Root(파일시스템 root)에 run, cdrom 디렉토리가 지워지지 않고 그대로 남아있게 된다.
이건 그냥 부팅해서는 볼 수가 없고, 이 디스크를 다시 마운트 해줘야 볼 수 있는데, subvolume set-default 를 했다면, 마운트 시에 subvolid=5 를 추가해줘야만 이 디렉토리들을 볼 수 있게 된다.
이 작업은, 새로 만든 시스템으로 부팅한 후 해야 한다.
sudo mount /dev/xxxx /mnt -o subvolid=5 ll /mnt drwxr-xr-x 1 root root 238 2020-01-29 00:30 @ drwxr-xr-x 1 root root 30 2020-01-16 17:22 @home drwxr-xr-x 1 root root 0 2020-01-13 22:37 @opt drwxr-xr-x 1 root root 128 2020-01-22 15:57 @var drwxr-xr-x 1 root root 128 2020-01-22 15:57 @root drwxr-xr-x 1 root root 128 2020-01-22 15:57 @srv drwxr-xr-x 1 root root 128 2020-01-22 15:57 @tmp drwxr-xr-x 1 root root 0 2020-01-13 22:37 cdrom drwxr-xr-x 1 root root 128 2020-01-22 15:57 run
이런 식으로 cdrom 과 run 이 남아있을 가능성이 있다. 불필요하므로 지워준다.
또, cloud-init 꾸러미도 (적어도 내겐) 불필요하다. 저게 뭔지 설명을 읽어봤음에도 이해를 못하겠다.
sudo apt purge cluod-init --autoremove
이후, 여러가지 작업이 필요하겠지만, 로캘(locale) 설정, 시간대 설정이 가장 최우선이다.
로캘설정은 몇가지 방법이 있겠지만, dpkg-reconfigure 를 이용하는게 편하다.
sudo dpkg-reconfigure locales
시간대 설정도 같은 명령으로 가능하다.
sudo dpkg-reconfigure tzdata
이제 서버를 원활하게 사용하기 위한 세부 설정이 남아있다!!