꼭 써볼 생각임. systemd 기반 서비스를 배포하려고 직접 만든 시스템의 더 다듬어진 버전처럼 보임
튜토리얼을 보니 좋아 보이는데, 로컬 상태는 어떻게 다루는 게 좋을지 궁금함. 예를 들어 앱의 sqlite 데이터베이스는 어디에 저장해야 하는지 문서에서 찾지 못했음
또 앱 바이너리를 서버로 전송해서 systemd 유닛에서 쓰게 하는 방법이 있는지도 궁금함. 없다면 바이너리 배포는 어떻게 처리하는지 알고 싶음
서버 쪽이라면 보통 저장하던 곳에 두면 되고, 표준 위치는 /var/lib/<yourapp> 임
애플리케이션을 systemd 유닛으로 실행한다면 StateDirectory=를 써서 systemd가 올바른 사용자 소유로 디렉터리를 만들게 할 수 있음
Deptool만으로는 바이너리 전송을 하지 않음
내가 운영하는 애플리케이션은 이 Nix 기반 스크립트로 작은 EROFS 이미지로 빌드하고, 그 스크립트가 이미지를 서버에 푸시하는 기능도 포함. 예전에는 별도 단계였지만 지금은 빌드와 푸시를 한 단계로 묶었고, 고유 디렉터리에 들어가서 여러 버전이 공존할 수 있음
빌드 결과에는 파일 경로가 담긴 JSON도 포함되며, 이를 클러스터 설정으로 가져와 systemd 유닛으로 렌더링한 뒤 Deptool로 배포함. 즉 한 도구는 이미지 배포를 맡고, Deptool은 활성화를 맡는 구조임
컨테이너를 쓴다면 보통 레지스트리에 푸시하고, 서버에는 무엇을 가져올지 지정하는 설정 파일만 있으므로 그 부분은 Deptool만으로 관리 가능함
다른 접근으로는 bootable containers를 쓰는 방법도 꽤 괜찮음
아직 아쉬운 건 적절한 호스트에서 실제로 bootc update --apply 를 실행해주는 무언가가 없다는 점임. 자동 업데이트 메커니즘은 있지만 조율되지 않기 때문에 클러스터에서는 원하지 않는 방식임
지금은 손으로 하고 있지만, 결국 실행해야 하는 건 bootc 명령 하나라서 나중에 스크립트로 만들기는 쉬워 보임
새 배포 도구가 나올 때마다 조금 회의적으로 보게 되지만, 이건 설계가 좋고 잘 다듬어진 것 같음 ssh 명령을 직접 쓰는 것도 올바른 선택으로 보임. 사용자가 가진 이 ssh가 실제로 동작한다는 걸 알고 있고, 아주 특수한 설정이나 패치된 ssh 바이너리를 쓰고 있을 수도 있음
외부 라이브러리로 ssh를 직접 구현하려는 도구는 일부 사용자에게 방해가 될 가능성이 큼
EROFS를 어떻게, 왜 쓰는지 더 자세히 알고 싶음
Nginx와 몇몇 애플리케이션을 Flatcar에 배포하는 데 쓰고 있으며, 사람들이 이 용도로 OCI 이미지를 쓰는 방식과 거의 비슷함
Flatcar에는 패키지 관리자가 없어서 소프트웨어와 의존성을 어떻게든 직접 올려야 하고, 자체 완결적인 파일시스템 이미지가 그 방법 중 하나임
OCI 이미지는 Podman이나 Docker 같은 별도 도구가 tar를 어딘가에 풀고 오버레이 마운트 스택을 구성해야 하지만, 이미 파일시스템 이미지라면 RootImage=로 systemd 유닛에서 바로 실행할 수 있음 Nix로 이미지를 빌드해서 정말 최소 구성만 들어감. Nginx 바이너리, LibreSSL, libc, 몇몇 공유 라이브러리만 있고 Bash도 없음
이건 심층 방어의 일부임. Nginx에 원격 코드 실행 취약점이 있어도 공격자가 다음 단계 익스플로잇을 만들 재료가 거의 없는 파일시스템 네임스페이스 안에서 실행되고, 전체 파일시스템은 읽기 전용임. 단순히 읽기 전용으로 마운트했기 때문이 아니라 EROFS에는 쓰기 자체가 없음
예전에는 Squashfs를 썼고 잘 동작했지만, 그 파일시스템은 라이브 CD 시대를 기준으로 설계됐음. EROFS는 오늘날 시스템에 더 맞는 절충을 택하지만, 솔직히 내 용도에서는 측정 가능한 차이는 없을 듯함
이미지가 더 작긴 한데 그건 압축 설정을 다르게 쓰기 때문임. 이론적으로는 EROFS가 버전이 다른 이미지 사이에서 데이터를 재사용하려는 경우 내용 정의 청킹에 더 적합하지만, 아직 이미지 전송에 실제로 쓰고 있지는 않음
마침 친구와 단순한 배포 전략을 논의하던 중에 이 글이 올라왔고, 우리가 도달하던 결론과 꽤 가까움
다만 이 구성에서 비밀값 관리는 어떻게 하는지 궁금함
LLM으로 코드를 생성한다면, 여러 면에서 오히려 Rust를 선호함
좋게 말하면 Rust는 “규율 있는” 언어이고, 강한 관례와 도구 체계가 있음. 둘 다 LLM에 도움이 됨
이상하게도 LLM은 적어도 약간 유도해주면 어떤 언어들보다 Rust에서 더 짧은 프로그램을 생성하는 경향이 있음. 어차피 모든 코드를 읽고 손볼 생각이라서, 나에게는 짧은 쪽이 더 좋음
이걸로 비밀값은 어떻게 처리하는지 궁금함. 선호하는 작업 흐름이 따로 있는지, EROFS 이미지에 넣는지 아니면 systemd로 주입하는지 알고 싶음
지금 비밀값은 TLS 인증서뿐인데, 한 서버에만 있으면 되고 Lego가 거기에 직접 배치함
해당 디렉터리는 Lego 유닛에서는 읽기-쓰기로 마운트하고, Nginx 유닛에서는 읽기 전용으로 마운트함
Lobste.rs 의견들
이 프로젝트에 LLM 생성 텍스트를 넣지 않았다고 공개한 점이 정말 반가움: not putting LLM-generated text anywhere near this
도구 자체도 잘 다듬어지고 설계가 좋아 보이지만, 나는 당분간 NixOS를 계속 쓸 듯함
꼭 써볼 생각임. systemd 기반 서비스를 배포하려고 직접 만든 시스템의 더 다듬어진 버전처럼 보임
튜토리얼을 보니 좋아 보이는데, 로컬 상태는 어떻게 다루는 게 좋을지 궁금함. 예를 들어 앱의 sqlite 데이터베이스는 어디에 저장해야 하는지 문서에서 찾지 못했음
또 앱 바이너리를 서버로 전송해서 systemd 유닛에서 쓰게 하는 방법이 있는지도 궁금함. 없다면 바이너리 배포는 어떻게 처리하는지 알고 싶음
/var/lib/<yourapp>임애플리케이션을 systemd 유닛으로 실행한다면
StateDirectory=를 써서 systemd가 올바른 사용자 소유로 디렉터리를 만들게 할 수 있음내가 운영하는 애플리케이션은 이 Nix 기반 스크립트로 작은 EROFS 이미지로 빌드하고, 그 스크립트가 이미지를 서버에 푸시하는 기능도 포함. 예전에는 별도 단계였지만 지금은 빌드와 푸시를 한 단계로 묶었고, 고유 디렉터리에 들어가서 여러 버전이 공존할 수 있음
빌드 결과에는 파일 경로가 담긴 JSON도 포함되며, 이를 클러스터 설정으로 가져와 systemd 유닛으로 렌더링한 뒤 Deptool로 배포함. 즉 한 도구는 이미지 배포를 맡고, Deptool은 활성화를 맡는 구조임
컨테이너를 쓴다면 보통 레지스트리에 푸시하고, 서버에는 무엇을 가져올지 지정하는 설정 파일만 있으므로 그 부분은 Deptool만으로 관리 가능함
다른 접근으로는 bootable containers를 쓰는 방법도 꽤 괜찮음
아직 아쉬운 건 적절한 호스트에서 실제로
bootc update --apply를 실행해주는 무언가가 없다는 점임. 자동 업데이트 메커니즘은 있지만 조율되지 않기 때문에 클러스터에서는 원하지 않는 방식임지금은 손으로 하고 있지만, 결국 실행해야 하는 건 bootc 명령 하나라서 나중에 스크립트로 만들기는 쉬워 보임
새 배포 도구가 나올 때마다 조금 회의적으로 보게 되지만, 이건 설계가 좋고 잘 다듬어진 것 같음
ssh명령을 직접 쓰는 것도 올바른 선택으로 보임. 사용자가 가진 이ssh가 실제로 동작한다는 걸 알고 있고, 아주 특수한 설정이나 패치된 ssh 바이너리를 쓰고 있을 수도 있음외부 라이브러리로 ssh를 직접 구현하려는 도구는 일부 사용자에게 방해가 될 가능성이 큼
EROFS를 어떻게, 왜 쓰는지 더 자세히 알고 싶음
Flatcar에는 패키지 관리자가 없어서 소프트웨어와 의존성을 어떻게든 직접 올려야 하고, 자체 완결적인 파일시스템 이미지가 그 방법 중 하나임
OCI 이미지는 Podman이나 Docker 같은 별도 도구가 tar를 어딘가에 풀고 오버레이 마운트 스택을 구성해야 하지만, 이미 파일시스템 이미지라면
RootImage=로 systemd 유닛에서 바로 실행할 수 있음Nix로 이미지를 빌드해서 정말 최소 구성만 들어감. Nginx 바이너리, LibreSSL, libc, 몇몇 공유 라이브러리만 있고 Bash도 없음
이건 심층 방어의 일부임. Nginx에 원격 코드 실행 취약점이 있어도 공격자가 다음 단계 익스플로잇을 만들 재료가 거의 없는 파일시스템 네임스페이스 안에서 실행되고, 전체 파일시스템은 읽기 전용임. 단순히 읽기 전용으로 마운트했기 때문이 아니라 EROFS에는 쓰기 자체가 없음
예전에는 Squashfs를 썼고 잘 동작했지만, 그 파일시스템은 라이브 CD 시대를 기준으로 설계됐음. EROFS는 오늘날 시스템에 더 맞는 절충을 택하지만, 솔직히 내 용도에서는 측정 가능한 차이는 없을 듯함
이미지가 더 작긴 한데 그건 압축 설정을 다르게 쓰기 때문임. 이론적으로는 EROFS가 버전이 다른 이미지 사이에서 데이터를 재사용하려는 경우 내용 정의 청킹에 더 적합하지만, 아직 이미지 전송에 실제로 쓰고 있지는 않음
마침 친구와 단순한 배포 전략을 논의하던 중에 이 글이 올라왔고, 우리가 도달하던 결론과 꽤 가까움
다만 이 구성에서 비밀값 관리는 어떻게 하는지 궁금함
“Prompting the deployment tool I wish I had”라고 했는데,
https://codeberg.org/ruuda/deptool/…
어떤 의미에서는 부동소수점들이 Rust를 쓰도록 설득했다는 점이 대단하긴 함
좋게 말하면 Rust는 “규율 있는” 언어이고, 강한 관례와 도구 체계가 있음. 둘 다 LLM에 도움이 됨
이상하게도 LLM은 적어도 약간 유도해주면 어떤 언어들보다 Rust에서 더 짧은 프로그램을 생성하는 경향이 있음. 어차피 모든 코드를 읽고 손볼 생각이라서, 나에게는 짧은 쪽이 더 좋음
이걸로 비밀값은 어떻게 처리하는지 궁금함. 선호하는 작업 흐름이 따로 있는지, EROFS 이미지에 넣는지 아니면 systemd로 주입하는지 알고 싶음
해당 디렉터리는 Lego 유닛에서는 읽기-쓰기로 마운트하고, Nginx 유닛에서는 읽기 전용으로 마운트함