이 레포가 무엇을 하는 물건인가.
CasaOS는 Linux 위에 올라가는 개인 클라우드 플랫폼이다. 설치하면 웹 브라우저로 접근 가능한 대시보드가 생기고, 거기서 Nextcloud, Jellyfin, Home Assistant, AdGuard 같은 앱을 클릭 한 번으로 설치할 수 있다. 뒷단은 순수 Go 바이너리 여러 개가 systemd 서비스로 돌아가는 마이크로서비스 구조다.
하드웨어를 가리지 않는다 — ZimaBoard, Raspberry Pi, 중고 NUC, 심지어 10년 된 데스크탑도 된다.
docker run이 실행되어 앱이 격리된 환경에서 실행된다. Docker Hub의 10만 개 이상 이미지 중 CasaOS가 검증한 앱들이 카탈로그에 올라온다.트렌딩 이유 · 경쟁 제품 대비 차별점.
셀프호스팅(self-hosting) 커뮤니티는 2020년대 초부터 꾸준히 성장해 왔다. 데이터 프라이버시 우려, 클라우드 구독료 인상, Raspberry Pi 5 같은 저렴한 SBC 보급이 맞물린 결과다. 그 흐름에서 CasaOS는 "기술을 모르는 일반인도 셀프호스팅"이라는 포지션으로 빠르게 성장했다. GitHub ★29k+, Discord 커뮤니티 수만 명이 그 증거다.
| 플랫폼 | 설치 방법 | 앱 설치 | 하드웨어 요구 | 가격 |
|---|---|---|---|---|
| Synology DSM | 전용 NAS 구매 후 자동 | 패키지 센터 (GUI) | Synology 전용 하드웨어 | 하드웨어 60~300만 원 |
| TrueNAS Scale | ISO 부팅 설치 | TrueCharts (복잡) | x86 전용, RAM 8GB+ | 무료 (하드웨어 직접 구매) |
| Unraid | USB 부팅 | Community Apps | x86, RAM 4GB+ | $49~99 라이선스 필요 |
| CasaOS | curl 한 줄 | 웹 클릭 1번 | arm/x86, RAM 1GB+ | 완전 무료·오픈소스 |
| Umbrel | 이미지 또는 스크립트 | 앱 스토어 | arm/x86 | 무료 (일부 유료 앱) |
CasaOS는 기본적으로 로컬 네트워크에서 동작하도록 설계됐다. 라우터에서 포트포워딩으로 외부에 노출하면 무차별 대입 공격의 표적이 된다. 공식적으로는 ZimaOS 또는 별도 VPN(WireGuard 등)을 통한 원격 접근을 권장한다.
또한 CasaOS는 설치 스크립트가 sudo로 실행되며 시스템 전반에 깊이 개입한다. 운영 중인 서버에 설치하기보다 전용 기기에 쓰는 것이 안전하다.
Docker Compose 문법을 몰라도, systemd 서비스를 몰라도 된다. 웹 UI에서 앱 카드를 클릭하면 컨테이너가 뜬다. 파일 탐색기로 스토리지를 관리하고, 위젯으로 CPU·RAM·네트워크를 한눈에 본다. 기술 문턱을 낮춘 UX 설계가 핵심 경쟁력이다.
백엔드 · 인프라 · 프론트엔드 · 클라우드 드라이버 상세.
| 구성 요소 | 기술 | 역할 |
|---|---|---|
| 언어 | Go 1.21 | 단일 바이너리 컴파일, 낮은 메모리 사용량 |
| HTTP 프레임워크 | Echo v4 | REST API 서버, JWT 미들웨어, Gzip 압축 |
| API 스펙 | OpenAPI 3.0 (openapi.yaml) | 코드 자동 생성(oapi-codegen), Swagger UI 내장 |
| 데이터베이스 | SQLite (glebarez/sqlite) | 설정·앱 메타데이터 저장, CGO 없는 순수 Go 구현체 사용 |
| 캐시 | go-cache (메모리) + Redis(선택) | 버전 정보·시스템 상태 캐싱 |
| 실시간 통신 | Socket.IO (go-socket.io) | 설치 진행률·알림을 브라우저에 실시간 푸시 |
| 인증 | JWT (ECDSA 키) | 로컬 IP에서는 JWT 스킵, 원격은 필수 |
| 크론 스케줄러 | robfig/cron v3 | 버전 체크·헬스 체크 주기적 실행 |
| systemd 연동 | coreos/go-systemd | SD_NOTIFY, 서비스 상태 확인 |
| 로깅 | zap (Uber) + logrus | 구조화 로그, 파일 로테이션(lumberjack) |
| ORM | GORM v2 | SQLite 모델 매핑 |
| 압축 | UPX (빌드 후) | 바이너리 크기 40~60% 감소 |
이 레포(CasaOS)는 메인 서비스이지만, 실제 운영 시스템은 여러 서비스가 협력한다.
| 서비스 | GitHub 레포 | 역할 |
|---|---|---|
| Gateway | IceWhaleTech/CasaOS-Gateway | 리버스 프록시, 외부 요청을 각 서비스로 라우팅 (Nginx 기반) |
| User Service | IceWhaleTech/CasaOS-UserService | 사용자 계정, ECDSA 키 쌍 관리, JWT 발급 |
| App Management | IceWhaleTech/CasaOS-AppManagement | Docker 컨테이너 생명주기(설치/삭제/업데이트), 앱 스토어 |
| Local Storage | IceWhaleTech/CasaOS-LocalStorage | 디스크/USB 마운트, Samba 공유, rclone 클라우드 드라이브 |
| Message Bus | IceWhaleTech/CasaOS-MessageBus | 서비스 간 이벤트 버스 (Redis 기반) |
| Common | IceWhaleTech/CasaOS-Common | 공유 유틸리티 라이브러리 (JWT, HTTP, 파일 등) |
| 드라이버 | 지원 서비스 | 구현 |
|---|---|---|
| Google Drive | 구글 드라이브 | OAuth2, 빌드 시 Client ID/Secret 주입 |
| OneDrive | Microsoft OneDrive | OAuth2, MSAL 플로우 |
| Dropbox | Dropbox | OAuth2, API v2 |
| 항목 | 내용 |
|---|---|
| 레포 | IceWhaleTech/CasaOS-UI (Git 서브모듈로 연결) |
| 프레임워크 | Vue.js 3 (추정, UI 레포 기준) |
| 빌드 | Yarn + TypeScript (Makefile: cd CasaOS-UI && yarn install && yarn build) |
| API 클라이언트 SDK | TypeScript + Axios 자동 생성 (package.json의 openapi-typescript-codegen) |
| 번들 통합 | 빌드 결과물을 Go 바이너리에 //go:embed로 포함 |
게이트웨이 패턴 · 서비스 간 통신 · 핵심 설계 결정.
api/casaos/openapi.yaml을 단일 진실 원천으로 두고, go generate로 서버 스텁 코드(codegen/casaos_api.go)와 TypeScript 클라이언트 SDK를 동시에 자동 생성한다. API 문서와 구현이 항상 동기화된다.
각 서비스는 /var/run/casaos/ 아래 Unix 도메인 소켓 파일로 통신한다. TCP 포트를 쓰지 않아 포트 충돌이 없고, 루트 권한이 있는 같은 호스트에서만 접근 가능해 보안 면에서도 유리하다.
User-Service가 EC 키 쌍을 생성하고 공개 키를 /var/run/casaos/jwt-public-key.pem에 저장한다. 다른 서비스들은 이 파일을 읽어 JWT 검증에 사용한다. 중앙 인증 서버 없이도 서비스 간 신뢰가 성립한다. 단, 로컬 IP(127.0.0.1, ::1)에서 오는 요청은 JWT 검증을 건너뛴다.
service/socket.go에서 googollee/go-socket.io를 초기화한다. Docker 앱 설치 시 컨테이너 이미지 다운로드 진행률을 Socket.IO 이벤트로 브라우저에 실시간 전달한다. 폴링 없이도 UI가 즉시 업데이트된다.
.goreleaser.yaml은 amd64 · arm64 · armv7 세 아키텍처를 한 번에 크로스 컴파일한다. 이후 UPX로 바이너리를 압축해 최종 크기를 40~60% 줄인다. Pi 4나 구형 ARM 보드에서도 동작하는 이유다.
이 레포(메인 서비스)의 파일 배치와 역할.
이 레포는 마치 호텔 프런트 데스크다. 손님(브라우저)은 프런트(이 서비스)와만 대화하지만, 실제 객실 청소·식사·주차는 각자 팀(App-Management·Local-Storage·User-Service)이 맡는다. 프런트는 요청을 받아 적절한 팀에 전달하고, 공용 메시지 보드(Message-Bus)로 팀들이 서로 소통한다.
이 레포에서 무엇을 배울 수 있는가.
CasaOS 코드베이스는 교과서적 Go 마이크로서비스 패턴의 실제 구현이다.
service/service.go의 MyService는 모든 서비스 인터페이스를 담는 컨테이너다. SystemService, FileService 등을 인터페이스로 정의하고, 실제 구현체를 주입한다. 단위 테스트 시 mock 구현체로 교체할 수 있다.
// service/service.go 패턴
type Services interface {
System() SystemService
File() FileService
Storage() StorageService
}
// 실제 사용: MyService.System().GetCpuPercent()
YAML로 API를 먼저 설계하고, go generate로 서버 인터페이스를 자동 생성한다. 핸들러는 생성된 인터페이스를 구현하기만 하면 되므로, API 스펙과 구현이 언제나 일치한다.
// main.go 상단의 go:generate 지시자
//go:generate bash -c "mkdir -p codegen && go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen \
-generate types,server,spec -package codegen \
api/casaos/openapi.yaml > codegen/casaos_api.go"
Swagger UI HTML과 설정 파일 샘플을 //go:embed로 바이너리에 포함시킨다. 배포 시 추가 파일 없이 단일 바이너리만 복사하면 된다.
// main.go
//go:embed api/index.html
_docHTML string
//go:embed api/casaos/openapi.yaml
_docYAML string
//go:embed build/sysroot/etc/casaos/casaos.conf.sample
_confSample string
go-systemd/daemon을 사용해 서비스 준비 완료를 systemd에 알린다. Type=notify로 설정된 systemd 유닛이 이 신호를 기다렸다가 "READY" 상태로 전환한다. 실제 서버 데몬 개발에 반드시 필요한 패턴이다.
shirou/gopsutil v3은 OS에 관계없이 CPU·메모리·디스크·네트워크 정보를 Go API로 읽는다. service/system.go에서 실전 사용법을 볼 수 있다.
// CPU 사용률, 메모리, 디스크, 네트워크 인터페이스 조회
cpu.Percent(0, false)
mem.VirtualMemory()
disk.Usage("/")
net.IOCounters(true)
App-Management 서비스는 Go Docker SDK(docker/docker)를 사용해 컨테이너 이미지 풀, 컨테이너 생성·시작·중지·삭제를 프로그래밍 방식으로 제어한다. GUI 뒤에서 실제로는 Docker API 호출이 일어나는 구조다.
코드를 읽고 바로 써볼 수 있는 소규모 프로젝트:
하드웨어·OS 요구사항과 한 줄 설치 명령.
| 아키텍처 | 대상 기기 예시 | 비고 |
|---|---|---|
| amd64 / x86-64 | 일반 PC, NUC, 서버, VM | 가장 빠른 성능 |
| arm64 / aarch64 | Raspberry Pi 4/5, Apple M1 (Linux VM), ZimaBoard | 저전력 운용 적합 |
| armv7 | Raspberry Pi 3B+, 구형 ARM 보드 | 32비트, 제한적 지원 |
| 항목 | 최소 | 권장 |
|---|---|---|
| RAM | 1 GB | 4 GB 이상 (앱 여러 개 동시 실행 시) |
| 저장 공간 | 16 GB (OS + CasaOS) | 512 GB+ SSD (데이터용 별도 디스크 추천) |
| 네트워크 | 100 Mbps | 1 Gbps 이더넷 (Wi-Fi보다 유선 권장) |
| 전력 | 5W (Pi 제로) | ~15W (Pi 5, 일반 운용) |
| OS | 상태 | 비고 |
|---|---|---|
| Debian 12 | 공식 지원 (권장) | 가장 안정적 |
| Ubuntu Server 20.04/22.04 | 공식 지원 | LTS 버전 권장 |
| Raspberry Pi OS | 공식 지원 | Pi 전용 최적화 이미지 |
| Armbian 22.04 | 커뮤니티 지원 | ARM SBC에 유용 |
| Alpine / ArchLinux | 미완성 테스트 | 비권장 |
신규 설치 (지원 OS가 새로 설치된 기기에서 실행):
wget -qO- https://get.casaos.io | sudo bash
# 또는
curl -fsSL https://get.casaos.io | sudo bash
업데이트:
wget -qO- https://get.casaos.io/update | sudo bash
버전 확인:
casaos -v
설치 후 같은 네트워크의 브라우저에서 http://[기기IP]로 접속하면 웹 UI가 뜬다. 설치 스크립트는 내부적으로 다음 작업을 수행한다:
curl | sudo bash 패턴은 편리하지만, 인터넷에서 받은 스크립트를 루트로 실행하는 것이므로 신뢰할 수 있는 출처인지 확인이 필요하다. 가능하면 스크립트를 먼저 다운로드해 내용을 확인한 뒤 실행하는 습관을 들이자.
난이도별 3~5개 과제. LV.1부터 순서대로 도전.
Debian/Ubuntu VM이나 Raspberry Pi에 CasaOS를 설치하고, 앱스토어에서 Jellyfin(미디어 서버), Nextcloud(파일 동기화), AdGuard Home(광고 차단 DNS) 세 가지를 설치해 본다.
docker ps로 실행 중인 컨테이너 목록을 직접 확인해 볼 것.http://[기기IP]/doc/v2/casaos에 접속하면 Swagger UI가 뜬다. 헬스 체크 엔드포인트 GET /v2/casaos/health/services와 GET /v2/casaos/health/ports를 브라우저에서 직접 실행해 각 서비스의 상태를 확인한다.
curl http://[IP]/v2/casaos/health/servicesCasaOS의 service/system.go를 참고해, Go로 CPU·RAM·디스크 사용량을 1초 간격으로 출력하는 CLI 도구를 작성한다. gopsutil v3 패키지를 직접 써 본다.
// 핵심 import
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/disk"
net.IOCounters로 네트워크 트래픽도 표시.CasaOS 방식을 따라 openapi.yaml을 먼저 작성하고, oapi-codegen으로 Go 서버 코드를 생성한 뒤, Echo 프레임워크로 핸들러를 구현한다. 간단한 "메모장 API"(CRUD)를 만들고 SQLite + GORM으로 저장한다.
CasaOS 앱스토어에 없는 Docker 이미지를 CasaOS의 "커스텀 앱 설치" 기능으로 등록한다. docker-compose.yml을 작성하거나 UI의 커스텀 앱 양식을 채워 본인이 만든 LV.4 서비스를 컨테이너화해 CasaOS 대시보드에서 관리한다.
CasaOS를 깊이 이해하기 위한 주차별 커리큘럼.
| 주차 | 주제 | 학습 내용 | 참고 자료 |
|---|---|---|---|
| 1~2주 | Go 기초 | 변수·함수·인터페이스·고루틴·채널, Go 모듈 시스템 | Tour of Go, Effective Go |
| 3주 | HTTP 서버 (Echo) | 라우팅, 미들웨어, 바인딩, 에러 핸들링, JWT 미들웨어 | Echo 공식 문서 |
| 4주 | OpenAPI & 코드 생성 | OpenAPI 3.0 스펙 작성, oapi-codegen, Swagger UI | OpenAPI Specification, oapi-codegen GitHub |
| 5주 | SQLite & GORM | ORM 개념, 마이그레이션, 관계 모델링, 쿼리 | GORM 공식 문서 |
| 6주 | Docker 기초 | Dockerfile, 이미지/컨테이너 개념, docker-compose, 볼륨 | Docker 공식 튜토리얼 |
| 7주 | Docker Go SDK | Go에서 Docker API 호출, 컨테이너 생명주기 프로그래밍 | docker/docker/client 패키지 |
| 8주 | systemd & 리눅스 데몬 | 유닛 파일 작성, SD_NOTIFY, 서비스 의존성 관리 | systemd man page, coreos/go-systemd |
| 9주 | 실시간 통신 (Socket.IO) | WebSocket 기초, Socket.IO 프로토콜, 이벤트 기반 설계 | go-socket.io GitHub |
| 10주 | 마이크로서비스 설계 | 서비스 분리 원칙, Unix Socket IPC, API 게이트웨이 패턴 | 마이크로서비스 아키텍처 (샘 뉴먼) |
| 11주 | 보안 (JWT + ECDSA) | JWT 구조, ECDSA 키 생성, 로컬 신뢰 모델 | jwt.io, Go crypto/ecdsa |
| 12주 | 크로스 컴파일 & CI/CD | GoReleaser, 크로스 컴파일, UPX, GitHub Actions | .goreleaser.yaml 분석 |
이 레포를 읽으면서 만나는 용어들의 짧은 정의.
| 키워드 | 한 줄 정의 |
|---|---|
| Echo (Go) | Go용 고성능 HTTP 웹 프레임워크. Express.js의 Go 버전이라고 생각하면 된다. |
| oapi-codegen | OpenAPI YAML에서 Go 서버 인터페이스·타입 코드를 자동 생성하는 도구. |
| go:embed | 컴파일 시 파일을 Go 바이너리에 포함시키는 지시자. 배포 파일 수를 줄인다. |
| GORM | Go 객체-관계 매핑(ORM) 라이브러리. SQL 없이 Go 구조체로 DB를 다룬다. |
| gopsutil | OS에 무관하게 CPU·RAM·디스크 등 시스템 정보를 읽는 Go 라이브러리. |
| Socket.IO | WebSocket 위에서 이벤트 기반 실시간 통신을 구현하는 프로토콜·라이브러리. |
| SD_NOTIFY | systemd에 "나 준비됐어"를 알리는 프로토콜. Type=notify 서비스에 필요. |
| ECDSA | 타원 곡선 디지털 서명 알고리즘. RSA보다 짧은 키로 동등한 보안 강도. |
| JWT | JSON Web Token. 서명된 JSON으로 인증 정보를 전달하는 표준. |
| Unix Socket | 파일 시스템 경로를 통해 같은 호스트 내 프로세스끼리 통신하는 IPC 방법. |
| rclone | 클라우드 스토리지(S3, Google Drive 등)를 로컬 파일시스템처럼 마운트하는 툴. |
| UPX | 실행 파일 압축 도구. 바이너리 크기를 50~70% 줄인다. 실행 시 자동 해제. |
| GoReleaser | Go 프로젝트의 멀티 플랫폼 빌드·릴리즈 자동화 도구. |
| Docker Engine API | Docker 데몬이 제공하는 REST API. Go SDK를 통해 컨테이너를 프로그래밍으로 제어. |
| ZimaOS | IceWhaleTech가 ZimaBoard 전용 하드웨어를 위해 CasaOS를 기반으로 만든 파생 OS. |
| API 게이트웨이 | 클라이언트 요청을 받아 적절한 백엔드 서비스로 라우팅하는 진입점 컴포넌트. |
| SBC (Single Board Computer) | 하나의 보드에 CPU·RAM·스토리지가 모두 붙은 소형 컴퓨터. 라즈베리 파이가 대표적. |
출처와 추가 학습 자료.