# 블로그를 Ubuntu 16.04에서 10년 동안 운영하다가 FreeBSD로 마이그레이션함

> Clean Markdown view of GeekNews topic #29801. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29801](https://news.hada.io/topic?id=29801)
- GeekNews Markdown: [https://news.hada.io/topic/29801.md](https://news.hada.io/topic/29801.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-24T00:49:54+09:00
- Updated: 2026-05-24T00:49:54+09:00
- Original source: [crocidb.com](https://crocidb.com/post/this-blog-ran-on-ubuntu-16-04-for-10-years-i-migrated-it-to-freebsd/)
- Points: 1
- Comments: 1

## Topic Body

- **Ubuntu 16.04 LTS** 기반 DigitalOcean VPS는 지원 종료와 보안 부담이 있었지만, 종료 시점까지 1491일 업타임을 유지함
- 새 서버는 독일 **Hetzner VPS**와 FreeBSD 14.3으로 옮겼고, 기존 월 $13 서버보다 강한 사양을 월 6유로 미만에 사용함
- **Jails**와 Bastille로 사이트별 격리 환경을 만들고, Caddy Jail이 SSL과 리버스 프록시를 맡아 각 nginx Jail로 전달함
- 부하 테스트에서 새 FreeBSD 서버는 10,000 동시 연결을 위해 `kern.ipc.somaxconn`을 조정한 뒤 요청 처리량이 3~11배 높게 나옴
- 전환에는 **네트워킹**과 FreeBSD 설정 학습이 필요했지만, 중앙화된 설정과 문서 품질 덕분에 예상보다 구성하기 쉬웠음

---

### 마이그레이션 배경
- 기존 블로그는 **DigitalOcean VPS**에서 10년 넘게 운영됐고, 뉴욕 데이터센터의 **Ubuntu 16.04 LTS**를 사용했음
  - Ubuntu 16.04 LTS는 최소 5년 전부터 지원이 끝난 상태였고, `apt` 패키지 저장소 업데이트를 받을 수 없었음
  - 오래된 시스템은 보안상 불리하며, 과거 별도 WordPress 블로그가 오래된 VPS에서 카지노·도박 링크 삽입 공격을 겪은 적이 있음
- 기존 서버는 블로그 외에도 몇 개의 사이트를 함께 제공했지만 대부분 **정적 사이트**였음
  - 가장 인기 있는 블로그도 보통 월 몇천 페이지뷰 수준이었고, Hacker News에서 몇몇 글이 바이럴된 경우를 제외하면 트래픽은 많지 않았음
  - 서버는 `nginx/1.10.3`로 정적 파일을 제공했고, 사이트별 설정은 `/etc/nginx/sites-available`에 있었음
  - 블로그는 **Hugo**로 생성됐고, 기존 배포 절차는 로컬 작성 → 저장소 커밋·푸시 → 서버 SSH 접속 → 저장소 pull → `hugo` 실행이었음
- 기존 VPS는 초기에 테스트와 프로그래밍 용도로도 쓰여 오래된 소프트웨어가 많이 남아 있었음
  - 그래도 정상적으로 동작했고, 종료 시점의 **업타임은 1491일**로 약 4년 동안 재부팅 없이 운영됨
- 새 서버는 독일의 **Hetzner VPS**로 옮겼고, 기존보다 사양이 높으면서 월 비용은 절반 이하였음
  - 기존 DigitalOcean 서버는 RAM 2GB, vCPU 1개, 디스크 50GB, 월 트래픽 2TB, 월 $13였음
  - Hetzner의 가장 저렴한 서버도 기존보다 메모리와 CPU가 두 배였고, 저장공간은 약간 적지만 트래픽은 10배였음
  - 최종 선택한 Hetzner 구성은 월 6유로 미만의 더 강한 사양이었음

### FreeBSD를 선택한 이유
- **FreeBSD**는 새로운 시스템을 실제 운영 환경에서 시험해보고 싶어 선택됨
  - 통합 설계, 안정성, 보안, **Jails**가 장점으로 꼽힘
- **Jails**는 FreeBSD에 25년 넘게 포함된 가상화·컨테이너화 기능임
  - 호스트 시스템에 접근하지 못하는 “미니 시스템”을 샌드박스처럼 실행할 수 있음
  - Docker 같은 컨테이너 솔루션은 프로그램 패키징에 더 적합하고 일시적·불변적인 성격을 갖는 반면, Jails는 같은 커널을 공유하는 서브시스템이나 미니 VM에 가깝게 다뤄짐
- **ZFS**도 서버용 파일시스템으로 매력적인 선택지였음
  - 데이터 무결성과 스냅샷 기능이 있고, Linux 쪽의 Btrfs와 유사한 면이 있음
  - ZFS는 Btrfs보다 훨씬 성숙한 것으로 평가됐고, 자주 스냅샷을 남기면 VPS 제공자의 유료 스냅샷·백업 시스템에 덜 의존할 수 있음
- 목표 구조는 사이트마다 하나의 **Jail**을 두고, 각 Jail 안에 필요한 빌드 도구와 nginx를 넣는 방식이었음
  - 메인 웹 서버용 Jail은 외부와 연결되는 리버스 프록시를 맡음
  - 특정 Jail이 침해되면 해당 Jail을 삭제하고 새로 만들 수 있는 구조를 의도함

### FreeBSD 설치와 Bastille 도입
- Hetzner의 VM 생성 화면에는 기본 OS 이미지가 제한적이어서 BSD가 바로 보이지 않았음
  - [FreeBSD 공식 YouTube 채널의 Hetzner 설치 영상](https://www.youtube.com/watch?v=8RGbstrTWUo)을 참고함
  - Hetzner는 FreeBSD ISO 이미지를 제공하지만, VM 생성 후 콘솔의 **ISO Images** 탭에서 마운트해야 했음
  - 설치에는 **FreeBSD 14.3** ISO가 사용됐고, 공식 영상의 설치 흐름을 따라 시스템을 구성함
- **Bastille**은 Jails 관리를 쉽게 하기 위해 선택됨
  - 수동 Jail 생성에 필요한 여러 단계를 `bastille` 명령으로 처리할 수 있음
  - 예시 명령은 `bastille list`, `bastille create`, `bastille console`임
  - 설치와 활성화는 [Bastille 시작 문서](https://bastillebsd.org/getting-started/) 기준으로 진행됨
```sh
pkg install bastille
sysrc bastille_enable="YES"
```

### 네트워크와 리버스 프록시 구조
- 전체 스택은 **Caddy Jail** 하나가 모든 도메인과 SSL 인증서를 처리하고, 사이트별 Jail로 트래픽을 리버스 프록시하는 구조임
  - 각 사이트 Jail은 사이트를 빌드하고 제공하는 데 필요한 도구만 포함함
  - 같은 네트워크 안의 여러 가상 머신과 비슷한 구조로 볼 수 있음
- 내부 가상 네트워크 인터페이스는 `bastille0`로 만들었음
```sh
sudo sysrc cloned_interfaces+="lo1"
sudo sysrc ifconfig_lo1_name="bastille0"
sudo service netif cloneup
sudo sysrc ifconfig_bastille0="inet 10.0.0.1 netmask 255.255.255.0"
```
  - 루프백 인터페이스를 복제해 `bastille0`라는 이름을 붙이고 `10.0.0.1/24` 네트워크를 할당함
  - Jail들은 이 네트워크 인터페이스에서 동작함
- 외부 HTTP·HTTPS 요청은 **PF(Packet Filter)** 규칙으로 Caddy Jail에 전달됨
  - `/etc/pf.conf`에는 외부 인터페이스 `vtnet0`, 내부 인터페이스 `bastille0`, `tailscale1`이 설정됐음
  - `80`, `443` 포트 트래픽은 Caddy 서버가 될 `10.0.0.5`로 리다이렉트됨
```pf
ext_if = "vtnet0"
int_if = "bastille0"
vpn_if = "tailscale1"
set skip on $int_if
set skip on $vpn_if
nat on $ext_if from 10.0.0.0/24 to any -> ($ext_if)
rdr pass on $ext_if proto tcp from any to any port {80, 443} -> 10.0.0.5
block all
pass out quick on $ext_if keep state
```
- PF와 게이트웨이는 다음 명령으로 활성화됨
```sh
sysrc pf_enable="YES"
service pf start
sysrc gateway_enable="YES"
```

### Caddy와 사이트별 Jail 구성
- 기존 서버는 **nginx**를 오래 사용했지만, 새 구성에서는 SSL 인증서 관리를 자동화하기 위해 **Caddy**를 선택함
  - 기존 nginx 환경에서는 `certbot`으로 인증서를 주기적으로 갱신해야 했고, 갱신을 놓친 일이 여러 번 있었음
- Caddy Jail을 만들기 전에 FreeBSD 릴리스를 Bastille에 부트스트랩함
```sh
bastille bootstrap 14.3-RELEASE
```
- Caddy Jail은 `10.0.0.5` IP로 생성됨
```sh
bastille create caddy 14.3-RELEASE 10.0.0.5 bastille0
bastille start caddy
```
  - Jail 이름은 `caddy`, 릴리스는 `14.3-RELEASE`, 인터페이스는 `bastille0`임
  - `bastille list`로 실행 상태를 확인하고, `bastille console caddy`로 Jail 내부 셸에 들어갈 수 있음
- Caddy 설치와 서비스 활성화는 Jail 내부에서 진행됨
```sh
pkg install caddy
sysrc caddy_enable="YES"
service caddy start
```
- Caddy 설정 파일은 Jail 내부의 `/usr/local/etc/caddy/Caddyfile`에 있음
  - 호스트에서 설정 파일을 관리하려면 호스트 디렉터리를 Jail 안으로 마운트할 수 있음
  - 예시에서는 `nullfs`와 읽기 전용 `ro` 옵션으로 Caddy가 설정을 변경하지 못하게 마운트함
```sh
bastille mount caddy /usr/local/etc/my-caddy-config /usr/local/etc/caddy nullfs ro 0 0
```

### 사이트와 블로그 배포
- 첫 번째 배포 대상은 `es.cro.to`였고, 사이트 저장소는 [GitHub 저장소](https://github.com/crocidb/escroto)로 관리됨
  - 호스트의 `/usr/local/www/escroto`에 저장소를 두고, 사이트 Jail에는 해당 디렉터리를 읽기 전용으로 마운트함
  - 모든 사이트는 호스트의 `/usr/local/www` 아래에 두는 방식으로 정리됨
- `escroto` Jail은 nginx Bastille 템플릿으로 만들었음
```sh
bastille bootstrap https://github.com/bastillebsd/templates
bastille create escroto 14.3-RELEASE 10.0.0.11 bastille0
bastille template escroto www/nginx
```
  - IP는 `10.0.0.11`로 지정됨
  - nginx 기본 페이지는 FreeBSD 관례대로 `/usr/local/www/nginx`에서 제공됨
- 호스트의 사이트 디렉터리는 Jail에 읽기 전용으로 마운트됨
```sh
bastille mount escroto /usr/local/www/escroto /usr/local/www/escroto nullfs ro 0 0
```
- 저장소의 `.git` 디렉터리가 웹으로 제공되지 않도록 배포 스크립트를 사용함
```sh
rm -fr /usr/local/www/nginx/*
cp -R /usr/local/www/escroto/* /usr/local/www/nginx/
rm -fr /usr/local/www/nginx/.git
```
  - 새 버전 배포는 호스트에서 저장소를 갱신한 뒤 Jail 안의 배포 스크립트를 실행하는 방식임
```sh
cd /usr/local/www/escroto
git pull
bastille cmd escroto /root/deploy.sh
```
- Caddy 설정은 `cro.to`를 `es.cro.to`로 영구 리다이렉트하고, `es.cro.to`를 `10.0.0.11`로 프록시함
```caddy
cro.to {
    redir https://es.cro.to{uri} permanent
}
es.cro.to {
    reverse_proxy 10.0.0.11
}
```
- 블로그는 **Hugo**를 사용하며 [GitHub 저장소](https://github.com/crocidb/blog)로 관리됨
  - 저장소는 호스트의 `/usr/local/www/blog`에 클론됨
  - `blog` Jail은 `escroto`와 비슷하게 생성됐고, IP는 `10.0.0.12`로 지정됨
```sh
bastille create blog 14.3-RELEASE 10.0.0.12 bastille0
bastille template blog www/nginx
bastille mount blog /usr/local/www/blog /usr/local/www/blog nullfs ro 0 0
```
- Hugo는 `blog` Jail 안에 설치됨
```sh
bastille pkg blog update
bastille pkg blog install gohugo
```
- 블로그 배포 스크립트는 nginx 웹 루트를 비우고 Hugo 출력물을 `/usr/local/www/nginx`에 생성함
```sh
rm -fr /usr/local/www/nginx/*
cd /usr/local/www/blog
hugo -d /usr/local/www/nginx
```
- DNS를 옮기기 전에는 기존 도메인 대신 `crocidb.cro.to`를 새 블로그 서버에 연결해 테스트함
```caddy
crocidb.cro.to {
    reverse_proxy 10.0.0.12
}
```

### 벤치마크와 부하 테스트
- DNS 레코드를 바꾸기 전에 기존 서버 `crocidb.com`과 새 서버 `crocidb.cro.to`의 부하 처리 능력을 비교함
  - 블로그 방문자는 주로 북미, 그다음 유럽과 남미에서 오기 때문에 새 독일 서버의 지연시간이 일부 사용자에게 약간 길어질 수 있음
  - 핵심 관심사는 정적 사이트 제공 속도와 큰 부하를 견디는 능력이었음
- [GTMetrix](https://gtmetrix.com), [Pingdom](https://pingdom.com), [WebPageTest](https://www.catchpoint.com/webpagetest) 같은 무료 온라인 도구도 사용했지만, 두 서버의 차이는 대부분 지연시간 정도였음
- HTTP 부하 벤치마크 도구로 [wrk](https://github.com/wg/wrk)와 [hey](https://github.com/rakyll/hey)를 사용함
  - 두 도구는 대량의 동시 요청을 생성하고 요청 지연시간, 오류 응답, 초당 전송량 등을 수집함
- 같은 Hetzner의 다른 VPS에서 `wrk`를 실행했을 때 새 서버가 크게 앞섰음
```sh
wrk -t4 -c100 -d30s --latency https://crocidb.com/
```
  - 옵션은 4스레드, 100개 동시 연결, 30초 실행이었음
  - 기존 서버는 평균 지연시간 `89.63ms`, 초당 요청 `833.41`, 전송량 `8.29MB/s`였음
  - 새 서버는 평균 지연시간 `6.75ms`, 초당 요청 `12260.10`, 전송량 `130.80MB/s`였음
  - 테스트 머신이 새 서버와 같은 데이터센터에 있어 공정한 비교는 아니었음
- Proton VPN을 이용해 여러 지역에서 `wrk`를 돌리는 방식도 시도했지만 결과는 기대보다 낮았음
  - 기존 서버 평균은 초당 약 `300` 요청, 새 서버 평균은 초당 약 `800` 요청으로 기록됨
  - 최종적으로 일반 사용자용 VPN 대신 여러 지역의 실제 VPS를 만드는 방식으로 바뀜

### Vultr VPS 기반 지역별 테스트
- 서버가 올라간 DigitalOcean·Hetzner와 다른 인프라를 쓰기 위해 **Vultr**가 선택됨
  - 지역은 수동 작업 부담 때문에 **London**, **São Paulo**, **Silicon Valley**, **Tokyo** 네 곳으로 제한됨
  - 각 지역에 가장 저렴한 Fedora VM을 만들고 테스트를 실행함
- 최종 테스트 도구는 `hey`가 더 적합하다고 판단됨
```sh
./hey_linux_amd64 -n 1000000 -c 10000 -t 10 -z 5m -h2 https://crocidb.com/ > crocidb.com.log
./hey_linux_amd64 -n 1000000 -c 10000 -t 10 -z 5m -h2 https://crocidb.cro.to/ > crocidb.cro.to.log
```
  - 설정은 총 `1,000,000` 요청, 동시 요청 `10,000`, 타임아웃 `10초`, 총 실행 시간 `5분`, HTTP/2 사용이었음
  - 현실적인 블로그 트래픽보다 훨씬 큰 부하였음
- 첫 실행에서 새 FreeBSD 서버는 **10,000개 동시 연결**을 감당하지 못해 초반에 실패함
  - `netstat -Lan`으로 소켓 큐 크기를 확인하자 모두 `128`로 나타남
  - 기본값 `kern.ipc.somaxconn`이 `128`이어서 다음처럼 늘림
```sh
sysctl kern.ipc.somaxconn=16384
```
- São Paulo 테스트에서 두 서버 모두 상당한 오류를 반환했지만, FreeBSD 서버는 기대한 `1,000,000` 요청에 대응했고 Ubuntu 서버는 `20,000` 요청도 반환하지 못했음
  - 기존 Ubuntu 서버는 전체 요청의 약 `7%`만 완료함
  - 새 FreeBSD 서버는 약 `94%`를 완료함
  - Tokyo에서는 새 서버의 성공률이 약간 낮았지만, 크게 우려할 수준은 아니라고 판단됨
- 초당 요청 수 기준으로 새 서버는 기존 서버보다 최소 **3배**, 최대 **11배** 나았음
  - 지연시간 백분위에서는 새 서버가 약 `90%` 지점까지 더 선형적으로 증가해 예측 가능성이 더 높았음
  - 높은 부하에서도 전 세계 대부분 지역에서 블로그 메인 페이지 콘텐츠를 **3.5초 미만**에 받을 수 있는 결과였음
- Tokyo 결과는 깊게 분석하지 않았음
  - `hey`의 요청 단계별 분석에서는 일본으로 향하는 트래픽이 더 느릴 가능성이 나타남
  - 두 번째 도메인의 DNS dial-up·lookup 값이 비정상적으로 낮아 보였고, CNAME 레코드 영향 가능성이 있었음
  - `resp wait`와 `resp read` 값도 이상하게 높았는데, 성공한 요청만 집계했기 때문에 기존 서버가 초기에 빠르게 응답하다가 이후 새 요청을 사실상 막았을 가능성이 있었음

### 최종 전환과 핵심 교훈
- 벤치마크는 답하지 못한 부분이 많았지만, 결과에 만족해 DNS 레코드를 새 서버로 전환함
  - 이 블로그는 이후 FreeBSD 기반 Hetzner 서버에서 공식적으로 운영됨
- FreeBSD로 사이트 호스팅 머신을 구성하는 일은 여러 시간의 실험, 수정, 빌드, 실패를 거쳤지만 예상보다 복잡하지 않았음
  - 요구 조건을 만족하는 웹 호스팅 서비스를 사용할 수도 있었고, 예시로 [OpenBSD Amsterdam](https://openbsd.amsterdam/)이 나옴
  - [Proxmox](https://www.proxmox.com/en/)로 컨테이너와 관리 대시보드를 사용할 수도 있었음
  - FreeBSD 쪽 대안으로 [Sylve](https://sylve.io/)도 거론됨
  - 직접 구성한 경로는 많은 학습을 제공했기 때문에 만족스러운 선택이었음
- 기존 **Ubuntu 서버**도 매우 견고했음
  - 10년 동안 사이트 부하를 잘 처리했고, 마지막 4년은 재부팅 없이 운영됨
  - 설정에 큰 노력을 들이지 않고도 안정적으로 동작함
- **FreeBSD 설정**은 예상보다 쉬웠고, 시스템 설정을 한곳에 중앙화하는 방식과 온라인 문서 품질이 좋았음
- 직접 블로그 호스팅 머신을 구성하려면 게임 개발자가 아는 범위를 넘어서는 **네트워킹 지식**이 필요했음
  - 다른 시스템을 배우는 과정이 즐거웠고, 다음에는 OpenBSD나 NetBSD를 시도할 수도 있음
  - 블로그 트래픽 대부분이 AI 시스템의 크롤링에서 온다는 점에서, 이 모든 작업의 실용성은 제한적이라고 마무리됨

## Comments



### Comment 58119

- Author: neo
- Created: 2026-05-24T00:49:54+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=48227397) 
- 내가 한 가장 큰 실수는 **높은 가동 시간**이었음  
  arjie.com이 Hetzner VPS에서 10년 넘게 떠 있다 보니, Hetzner가 그 기반 머신을 종료하려 할 때 10대 시절의 내가 뭘 설정해뒀는지 전혀 알 수 없었음  
  백업은 있지만 사이트는 10년째 내려가 있음  
  요즘은 옮겨 다닐 수 있게 만들고, 실제로 몇 번 옮겨 봐서 동작하는지 확인함
  - “가장 큰 실수는 높은 가동 시간”이라는 말이 맞음  
    예전에는 머신 가동 시간이 명예 훈장처럼 여겨지던 시절도 기억함  
    나이만 들고 딱히 더 현명해지진 않았지만, 요즘은 **서비스 가동 시간**을 봄  
    예전에도 MX 같은 DNS 레코드가 그런 목적에 가까웠고, 오래된 클러스터는 꽤 난해했지만 split brain 같은 교훈이 남아 지금도 Proxmox 2노드 클러스터가 왜 망가지는지, 왜 추가 **witness**를 권하는지 계속 설명하게 됨  
    VMware가 예전에 2노드 HA 클러스터 문제를 큰 임시방편으로 덮은 것도 틀렸고, 그 방식이 아직 남아 있다면 여전히 틀렸을 가능성이 큼  
    높은 가동 시간은 패치를 안 했다는 뜻이고, 패치는 다들 좋아하는 일임
  - 일본의 **이세 신궁**이 떠오름  
    20년마다 완전히 해체했다가 다시 짓는데, 최근 읽은 Dan Wang의 Breakneck에서 이런 재건 관행이 시간이 지나면 사라질 지식을 보존한다고 설명함  
    Wang은 이세 신궁과 Notre Dame을 대비시키는데, Notre Dame 지붕 재건이 꽤 어려운 이유 중 하나가 지식 손실일 수 있다고 봄  
    두 건축물에 충분히 익숙하지 않아 공정한 비교인지는 모르겠지만, 원칙 자체는 마음에 듦  
    책에서는 작은 비유일 뿐이고, 전체적으로는 강력 추천함
  - VM에서 **높은 가동 시간**은 별 의미가 적음  
    재부팅은 몇 초면 끝나고, 업그레이드는 새 인스턴스로 DNS만 바꾸면 무중단으로 가능함  
    쉽게 복제할 수 없는 물리 머신은 이야기가 다름
  - 큰 **Ansible 플레이북 저장소**에 설정을 넣기 시작했음  
    전부 Ansible로 완전 관리할 필요는 없고, 주로 초기 설정만 거기에 두며 아직도 손으로 관리하는 일이 많음
  - 개인 프로젝트에도 가끔 **Architectural Decision Records**를 남김  
    좀 우스꽝스럽게 느껴지지만, 예상보다 자주 도움이 됨

- 개인/취미 용도는 대체로 **Caddy 앞단 + Docker Compose** 조합으로 운영함  
  단순 웹사이트면 Caddy가 콘텐츠를 직접 서빙하고, “웹 앱”이면 거의 전부 컨테이너화한 뒤 Caddy가 TLS 종료와 Docker 아래 앱으로의 역방향 프록시를 맡음  
  보통 `~/apps/appname` 구조이고, 각 앱 디렉터리에 Docker Compose 파일과 마운트된 데이터 디렉터리를 둠  
  `compose down` 후 (s)ftp로 데이터를 꺼내 장기 보관하거나 사이트/서비스를 옮길 수 있음  
  한때 전용 서버에서 여러 VM을 돌렸지만 OVH의 별도 VPS들로 옮겼고, OVH에서 메일을 돌리려면 메일 호스팅을 허용하지 않는 local zone VM은 피해야 함  
  환경에 따라 다를 수 있음
  - 한 프로젝트에서 **Traefik**을 쓰기 시작했는데 nginx proxy manager보다 좋은 업그레이드였음  
    NPM도 훌륭하고 웹 GUI도 괜찮지만, Traefik은 Docker Compose 파일에 원하는 동작만 적으면 끝남
  - 내 홈 설정도 비슷함  
    다만 Unraid가 컨테이너를 돌리고, 그중 하나가 다른 서비스들을 역방향 프록시하도록 설계된 nginx 계열 도구임
  - 나도 거의 같은 방식으로 함  
    Debian에서 **Flatcar**처럼 컨테이너 우선이고 불변 시스템/OS인 쪽으로 바꿀지 고민 중임  
    FreeBSD에는 흥미로운 기술적 장점이 있지만, 좋든 싫든 많은 오픈소스 소프트웨어의 기본값은 Docker이고, 모든 걸 FreeBSD jail로 옮길 시간도 의욕도 없음

- 몇 주 전에 나도 같은 일을 했음  
  서버는 2015년쯤 이후 업데이트되지 않았고, 그 시절 Ghost 블로그와 `node 0.10`이 설치돼 있었음  
  나는 좀 더 거칠게 처리했는데, 백업만 뜬 뒤 Hermes 에이전트(Gemini 3.1 Pro)를 풀어놨음  
  필요한 모든 업그레이드와 패치를 하고, 최신 대응 항목으로 마이그레이션까지 진행했음  
  이후 서버 강화와 안 쓰는 서비스 제거도 꽤 진행됐고, **AI 지원**이 없었다면 아마 계속 미뤘을 것 같음
  - AI 없이도 업데이트 자체는 아주 쉽게 할 수 있음  
    진짜 문제는 무언가 깨질 위험이고, 그건 **백업**이 완화해 줌

- 개인 서버에 **FreeBSD**를 써본 건 즐거웠음  
  뭔가 멋지고, 깔끔하고, 단순하며 “펑크 록” 같은 느낌이 있었음  
  하지만 주요 고통 지점 때문에 포기했음: PM2가 FreeBSD에서 버그가 있었고 프로세스 관리에 쓰던 도구였음, 대안으로 `rc.d`로 데몬을 돌리려 했지만 로그 설정이 너무 어려웠음, 방화벽은 ICMP를 어떻게 할지 같은 보안 모범 사례까지 맞추려면 직접 설정할 게 너무 많았고 UFW 기본값 같은 템플릿이 아쉬웠음
  - FreeBSD에도 그런 기본 템플릿이 포함돼 있음  
    PF가 아니라 IPFW로 구현돼 있음  
    `rc.conf`의 `firewall_type` 키를 보면 됨: [https://cgit.freebsd.org/src/tree/libexec/rc/rc.conf?id=8e08...](<https://cgit.freebsd.org/src/tree/libexec/rc/rc.conf?id=8e08080ee581dfd30c128d032035da7b6ae44463#n157>)  
    단일 머신 방화벽을 쉽게 구성하려면 `firewall_type=client`를 쓰거나, 뭔가 호스팅하려면 `firewall_type=workstation`을 쓸 수 있음  
    후자의 경우 `firewall_myservices`와 `firewall_allowservices`가 어떤 포트를 열지, 어떤 네트워크/IP가 접근 가능한지를 제어함  
    아주 단순한 NAT 게이트웨이는 `firewall_type=simple`과 `firewall_simple_(iif|inet|oif|onet)(_ipv6)?`로 ISP 쪽/내부 쪽 인터페이스 이름과 IPv4/IPv6 네트워크 범위를 설정하면 됨  
    각 옵션이 정확히 뭘 하는지는 `/etc/rc.firewall`에 구현돼 있음: [https://cgit.freebsd.org/src/tree/libexec/rc/rc.firewall?id=...](<https://cgit.freebsd.org/src/tree/libexec/rc/rc.firewall?id=8e08080ee581dfd30c128d032035da7b6ae44463>)
  - 감시(supervision) 용도로 PM2를 쓴 건지 궁금함  
    `rc.d` 데몬 로그는 유닉스 방식으로 단순 메시지면 `logger(1)`를 쓰고, 파일로 리다이렉션한 뒤 `newsyslog(8)`로 크기를 관리하면 됨  
    방화벽은 **The Book of PF**[0]를 추천함  
    FreeBSD의 PF는 OpenBSD의 pf와 문법 차이가 있지만, 방화벽이 어떻게 동작하는지 감을 잡고 어떤 규칙을 써야 할지 이해하기엔 충분함  
    [0]: [https://nostarch.com/book-of-pf-4e](<https://nostarch.com/book-of-pf-4e>)
  - PM2는 어떤 OS에서 쓰든 항상 버그가 있었음  
    처음엔 엄청 편하지만 동시에 쓰기 불쾌한 소프트웨어였고, 배포 시 **환경 변수 업데이트**가 의도대로 된 적이 한 번도 없었음
  - 내 주요 고통은 정전 뒤에 버티지 못한다는 점이었음  
    전원이 나가면 재부팅 후 파일시스템을 수동으로 `fsck`하라고 요구함

- 약간 다른 이야기지만, 지금 **지원 주기**가 가장 긴 무료 Linux 배포판은 무엇인지 궁금함  
  한동안 작은 VM들에는 CentOS 7을 썼는데, 보안 업데이트가 아주 오래 제공됐고 업데이트로 무언가 깨질 위험도 최소였음  
  조금 찾아보니 현재는 Alma/Rocky Linux가 가장 나은 선택 같고 10년 지원이 제공됨  
  다만 잘 유지보수되고 있는지는 궁금함
  - 나도 10년 넘게 장기 안정성과 마음의 평화를 기대하며 서버에 **CentOS**를 돌렸음  
    그런데 그렇게 긴 기간이 지나면 생태계가 크게 drift하고, OS 위에서 애플리케이션을 최신으로 유지해 실행하는 일이 점점 어려워짐  
    `glibc`, Python/Apache 조합, GCC 같은 인프라 패키지가 최신 애플리케이션 스택과 서서히 맞지 않게 됨  
    이후 버전 업그레이드도 고통스러웠는데, 이상한 패키지 혼합으로 스스로 구석에 몰렸기 때문만이 아니라 업그레이드 경로 자체가 늘 최선 노력 수준이었음  
    6에서 7로 넘어가다 포기했던 것 같고, 결국 내게 필요한 건 Fedora였다고 깨달음  
    1년 또는 반년 주기 업데이트면 배포판 패키지와 싸울 필요가 없고, 구성은 최신으로 유지되며 동작하고, 주요 배포판 업그레이드도 매끄럽고, 중단 시간도 최소임  
    다시는 “서버 배포판”으로 돌아갈 생각이 없음
  - Alma는 이제 RHEL 소스 호환이 아니어서 약간의 여지가 있음  
    예를 들어 **권한 상승 취약점** 수정 커널 업데이트를 더 빨리 낼 수 있음  
    Rocky는 RHEL에서 내려오기를 기다리는 동안 익스플로잇 완화를 제공하는 선택형 보안 저장소로 대응했음  
    최근 사건만 놓고 보면 둘 다 꽤 잘 유지보수되는 편으로 보임
  - 개인 서버에 **롤링 릴리스 배포판**을 쓰지 않을 이유를 잘 모르겠음  
    모든 서비스는 컨테이너에서 돌리고, 기본 OS는 필요한 만큼 자주 자동 업데이트하게 두면 됨  
    나는 openSUSE MicroOS를 골랐고, 거의 매일 업데이트와 재부팅을 해서 서버가 건강하다고 꽤 확신할 수 있음  
    원자적 업데이트라 뭔가 깨져도 당장 처리하기 싫으면 Cockpit에서 롤백 버튼을 누르고 시간 날 때 보면 됨
  - 호스팅하는 것이 업그레이드 주기보다 오래 살지 않을 것이라고 베팅하는 셈임  
    결국 업그레이드가 오면 꽤 고통스러울 가능성이 큼  
    오래 지나 모든 게 바뀐 뒤 큰 점프를 하는 것보다, 더 작은 버전 점프를 자주 하는 편이 낫다고 봄
  - 완전 무료를 원하거나 머신이 많다면 Alma와 Rocky가 맞음  
    Red Hat에 등록해도 괜찮다면 **RHEL**도 있고, 등록 계정당 10대까지 업데이트 접근을 무료로 줌  
    RHEL은 확실히 주요 배포판 중 가장 안정적이고, Alma와 Rocky는 본질적으로 RHEL의 다운스트림 클론임

- 나도 같은 배를 타고 있음  
  “너무” 오래 방치한 낡은 서버가 2대 있고, 이제 업데이트하려고 건드리기가 두려움  
  다만 Linux 배포판들이 나이 확인/증명 쪽에서 벌이는 소동을 보면 아예 떠날까도 생각 중임  
  Artix도 시도했지만, 지난주 재시작 후 깨졌고 이전 커널 업데이트에서 뭔가 잘못됐던 듯해서 rescue ISO까지 꺼내야 했음  
  그래서 그 장비는 Devuan으로 바꿨지만 아직 판단 보류임  
  큰 불만은 없지만 아직 burn-in 단계임  
  노트북에는 Arch를 돌리고 있는데, 커뮤니티가 검열 문제로 좀 적대적으로 느껴져서 주말 시간이 나면 밀고 다른 걸 설치하려고 기다리는 중임  
  소프트웨어에 **정치적 드라마**는 원하지 않음  
  흥미롭게도 이번이 새 노트북을 사서 Windows로 한 번도 부팅하지 않고 바로 Linux를 설치한 첫 사례였고, 모든 것이 “그냥 동작”했음  
  이제 Linux를 신나게 써보려는 시점에 큰 플레이어들이 AI everywhere, 나이 증명/확인, 기본 켜짐 원격 측정 같은 프라이버시 침식 단계를 받아들이는 게 슬픔  
  그런 쪽과의 상호작용은 그냥 “nope” 하려 함
  - 예전에 Ubuntu 서버를 10년 방치했다가 20분 만에 고통 없이 업데이트한 적이 있음  
    그 서버는 지금도 최신 LTS로 계속 돌고 있음  
    시작이 Ubuntu 4였는지 6이었는지도 모르겠지만, 쭉 무난했음  
    어쩌면 느린 업그레이드가 초기 도입자 고통을 피하게 해줬을 수도 있음  
    요즘은 Debian을 훨씬 더 많이 씀  
    공급망 공격이 많은 상황에서 **Debian Stable**은 정말 보석 같고, 더 최신 버전이 필요해서 따로 처리해야 하는 패키지가 몇 개 있더라도 구식의 담백한 엔지니어링 정신이 좋음
  - 나이 확인/증명 관련해서는 잘못 인도된 것 같음
  - 이전 **커널 업데이트**가 잘못돼 재시작 후 깨진 건 대체로 Arch/Artix의 문제임  
    둘은 최신 흐름을 가장 빨리 따라가는 쪽이고, 안정성에는 항상 최선이 아님  
    하지만 롤링 배포판이 항상 모든 것의 최신 버전만 제공해야 한다는 뜻은 아님  
    지난 몇 달간 Void Linux를 쓰고 있는데, 롤링 배포판이지만 LTS 커널을 사용하고 메인라인도 선택 가능하며, 유지보수자들은 빠른 업데이트보다 안정적인 앱 버전에 더 집중함
  - 내 서버/VM은 보통 FreeBSD나 Alpine을 돌림  
    필요한 곳에는 Debian도 조금 있음, 예를 들면 Proxmox, Alpine을 지원하지 않는 VPS, 회사 관련 장비 등임  
    Chimera를 돌리는 테스트 시스템도 몇 대 있지만 안정판이 나오기 전까지는 많이 의존하지 않을 생각임  
    AerynOS도 조금 실험 중임
  - FreeBSD의 지원 주기가 더 길었으면 좋겠음  
    릴리스 지원 수명이 1년 미만이라 업그레이드 창을 놓치면 이후 업그레이드가 Debian Stable 같은 다른 배포판보다 더 어려워짐

- 서버 용도는 Debian과 Ubuntu로 옮겼지만, 젊었을 때인 2000년대 중반에는 **FreeBSD**에 빠져 있었음  
  실제로 유용한 일을 하기보다 설정하고 세팅하는 데 더 많은 시간을 썼음  
  그때는 BSD 계열을 제공하는 전용 서버나 VPS를 찾기 어려웠고, Panix.com 같은 곳으로 정착했던 것 같음  
  그전에는 뉴저지 쪽 NAC였던 듯한 15MinuteServers라는 회사가 BSD를 제공했던 기억도 있음  
  이제는 그냥 추억을 주절거리는 중임
  - 요즘은 내 제공업체들에서 설치가 꽤 간단함  
    Hetzner와 OVH에서 FreeBSD를 쓰고 있고, 예전에는 Vultr도 써봤음
  - OVH에는 **FreeBSD 템플릿**이 있음  
    그리고 대부분의 KVM VM/VPS 제공업체는 콘솔 접근과 사용자 ISO 마운트를 허용하므로 원하는 것을 설치할 수 있음

- fastfetch가 실제보다 메모리를 더 많이 사용한다고 보고하는 건 아마 **ZFS ARC** 때문일 가능성이 큼  
  Linux의 페이지 캐시와 비슷하게 언제든 회수될 수 있고, 도구마다 이름을 다르게 붙임: [https://www.linuxatemyram.com/](<https://www.linuxatemyram.com/>)

- 누군가 Docker를 처음 설명해줬을 때 “아, jail 말하는 거야?”라고 답했던 기억이 있음  
  글에서 설명하듯이 완전히 같지는 않음  
  `kqueue`도 큰 승리였음  
  FreeBSD 개발자들에게 정말 고마움  
  첫 회사를 15년 동안 **FreeBSD** 위에서 운영했고, 가동 시간과 회복탄력성이 놀라웠음

- 나도 업데이트하기 두려운 **Ubuntu 16.04** 서버가 있음  
  현재 가동 시간이 1281일이고, 이쯤 되니 재부팅하기가 미안해짐
  - 파일시스템을 다른 머신에 `dd`로 복사한 뒤 `qemu` 같은 에뮬레이터로 부팅해서 **예행연습**을 해보면 됨  
    자동 시작되는 것 중 외부로 접속하는 게 있으면 조심해야 함
  - 무엇이 두려운 건지 모르겠음  
    백업은 있지 않나?  
    Debian/Ubuntu 시스템은 정기적으로 자동 업데이트와 재부팅을 하도록 쉽게 설정할 수 있고, 수동 유지보수는 더 큰 버전 업그레이드 때만 남게 됨
  - 내 가장 오래된 서버는 8.04에 있음
