Guide

NAS에 code-server를 올릴 때 가장 위험한 설정: 개발환경과 Production 권한을 분리하는 법

code-server를 NAS에 설치하면 브라우저만으로 VS Code와 유사한 개발환경을 사용할 수 있다.

노트북에 별도 개발환경을 만들지 않아도 되고 NAS에 저장된 프로젝트를 직접 편집할 수 있어 편리하다.

하지만 code-server는 단순 텍스트 편집기가 아니다.

Terminal을 열 수 있고, 해당 프로세스가 접근할 수 있는 파일을 읽고 수정할 수 있으며, 구성에 따라 Git credential이나 Docker daemon까지 제어할 수 있다.

따라서 운영에서 가장 중요한 질문은 설치방법이 아니라 이 개발환경이 침해되었을 때 NAS의 어디까지 제어할 수 있는가?다.

code-server 자체보다 실행계정의 권한이 중요하다

code-server가 root 권한으로 실행되고 NAS 전체 filesystem이 mount돼 있다면 브라우저 IDE 하나가 사실상 NAS 전체 관리권한을 갖게 된다.

반대로 전용 사용자로 실행하고 필요한 project directory만 연결하면 사고범위를 크게 줄일 수 있다.

기본 원칙은:

개발자에게 필요한 파일만 workspace에 제공하고, NAS 관리권한은 별도로 유지한다.

Workspace와 Production Data를 같은 폴더로 만들지 않는다

예를 들어 production WordPress의 database data directory와 source workspace를 같은 tree에 두고 code-server에 전체 경로를 writable mount했다고 하자.

터미널에서 잘못된 명령 하나만 실행해도 database file이나 production uploads까지 수정될 수 있다.

더 안정적인 구조는:

/workspace/
  project-a/
  project-b/

/production-data/
  database/
  uploads/

/secrets/
  ...

/backup/
  ...

처럼 역할을 분리하고 code-server에는 기본적으로 /workspace만 write 가능하게 제공하는 것이다.

Config와 Workspace도 lifecycle이 다르다

code-server 공식 Docker 예제도 user configuration과 project directory를 container 밖에 mount해 보존한다.

운영에서는 최소한 다음을 분리하는 편이 좋다.

영역 예 보존정책
Application image code-server image 재생성 가능
IDE config settings·extensions 필요 시 backup
Workspace source code Git + backup
Credential SSH key·token 별도 secret 관리
Build cache package cache 등 대부분 재생성 가능

Git이 있다고 NAS Backup이 필요 없는 것은 아니다

Source code가 GitHub나 다른 remote repository에 push돼 있다면 code 자체는 다시 받을 수 있다.

하지만 다음 데이터는 Git에 없을 수 있다.

  • 아직 commit하지 않은 작업
  • local-only configuration
  • IDE 설정
  • 개발용 database
  • local documentation

반대로 secret을 backup하기 위해 Git repository에 넣는 것은 더 큰 문제를 만들 수 있다.

따라서 Git과 NAS backup은 서로 대체관계가 아니라 서로 다른 자산을 보호한다.

Docker Socket을 Mount하는 순간 권한 수준이 크게 달라진다

code-server 공식 FAQ는 container 안에서 host Docker를 사용하려면 /var/run/docker.sock을 mount할 수 있다고 설명한다.

기능적으로는 편리하다.

IDE terminal에서 바로 image를 build하고 container를 실행할 수 있기 때문이다.

하지만 Docker socket 접근권한은 단순히 “Docker 명령을 쓸 수 있다”는 정도로 보면 안 된다.

Host filesystem을 mount한 새로운 container를 만들거나 privileged configuration을 사용할 수 있는 환경이라면 사실상 host에 매우 강한 권한을 행사할 수 있다.

따라서 production NAS에서는 code-server에 Docker socket을 제공하기 전에 정말 필요한지 먼저 판단해야 한다.

개발환경과 Production 배포권한을 분리한다

개발자가 코드를 수정할 수 있는 권한과 production을 변경할 수 있는 권한은 같은 것이 아니다.

예를 들어 다음 두 흐름은 위험도가 다르다.

A. code-server → source 수정 → Git commit → 별도 deployment process

B. code-server → production directory 직접 수정 → Docker restart

B는 빠르지만 누가 어떤 변경을 했는지 추적하기 어렵고, 잘못된 수정이 즉시 production에 반영된다.

Production 환경일수록 A와 같이 build/deploy 단계를 분리하는 편이 rollback과 audit에 유리하다.

SSH Key를 Workspace에 복사하지 않는다

Git remote 접속을 위해 private key를 project folder에 넣으면 repository backup이나 archive를 통해 key까지 복사될 위험이 있다.

Credential은 source와 별도 위치에서 최소권한으로 제공하는 편이 낫다.

가능하다면:

  • repository별 최소권한 token
  • read/write 범위를 제한한 key
  • SSH agent forwarding 또는 별도의 credential mechanism

을 검토한다.

중요한 것은 개발편의를 위해 NAS 전체를 열어주는 credential을 IDE 안에 상주시켜서는 안 된다는 점이다.

code-server를 인터넷에 그대로 노출하지 않는다

code-server 공식 문서는 인증과 암호화 없이 인터넷에 직접 노출하면 terminal을 통해 시스템이 장악될 수 있으므로 그렇게 하지 말라고 명확히 안내한다.

기본 configuration은 localhost에 bind하고 password authentication을 사용하는 방향이다.

외부접속이 필요하다면:

  • SSH port forwarding
  • VPN/private network
  • TLS가 적용된 Reverse Proxy
  • 필요한 경우 추가 external authentication

같은 방식을 사용한다.

NAS 관리용 개발환경이라면 public internet 전체에 공개해야 할 이유가 있는지부터 다시 생각하는 편이 좋다.

Reverse Proxy를 쓴다면 WebSocket도 정상 동작해야 한다

code-server의 browser session은 일반적인 정적 웹페이지만 제공하는 것이 아니다.

WebSocket을 사용하기 때문에 reverse proxy가 upgrade header와 장시간 연결을 올바르게 전달해야 한다.

로그인은 되는데 terminal이나 UI 연결이 반복적으로 끊긴다면 application 자체보다 proxy configuration을 함께 확인해야 한다.

브라우저에서 실행한 개발서버가 자동으로 공개되지 않게 한다

code-server는 개발 중 실행한 local web application의 port를 browser에서 접근할 수 있게 proxy할 수 있다.

개발에는 편리하지만 이 기능 때문에 test application이 예상보다 넓은 사용자에게 노출될 수 있다.

특히 authentication이 없는 임시 API나 admin tool을 실행했다면 proxy route의 노출범위를 이해해야 한다.

필요하지 않은 automatic port forwarding 기능을 최소화하는 것도 하나의 방법이다.

Extension도 Supply Chain의 일부다

브라우저 IDE에서도 여러 extension을 설치할 수 있다.

Extension은 source code와 workspace를 읽을 수 있고 경우에 따라 terminal command와 외부통신을 사용할 수 있다.

따라서 production data와 가까운 개발환경일수록:

  • 필요한 extension만 설치
  • 출처와 유지상태 확인
  • 불필요한 extension 제거
  • 업데이트 후 이상행동 확인

이 필요하다.

개발환경 Backup에서 Cache와 Credential을 섞지 않는다

code-server 전체 home directory를 무조건 백업하면 쉽게 복구될 것 같지만 불필요한 cache와 credential까지 하나의 archive에 섞일 수 있다.

더 나은 방식은:

  • Source → Git + 필요한 backup
  • IDE configuration → 선택적 backup
  • Secret → 별도 안전한 보관
  • Cache → 재생성

으로 나누는 것이다.

NAS에서 개발환경을 운영할 때 가장 중요한 장애경계

NAS가 동시에 production service도 운영한다면 code-server는 같은 hardware 안의 별도 failure domain이 아니다.

개발 중 CPU·RAM·I/O를 많이 사용하는 build를 실행하면 production database나 web service 성능에도 영향을 줄 수 있다.

따라서:

  • container resource limit
  • build workspace 위치
  • 대규모 compilation 시간대
  • production volume과의 I/O 분리

를 검토하는 것이 좋다.

결론

NAS의 code-server를 잘 운영한다는 것은 브라우저에서 VS Code가 열리는 것이 아니다.

핵심은:

Workspace → Credential → Docker 권한 → Production 접근 → External Access → Backup

을 각각 분리하는 것이다.

특히 code-server에 Docker socket, production filesystem, SSH key를 모두 제공하면 편리함과 함께 매우 강한 관리권한이 한 화면에 집중된다.

개발환경은 코드를 만들 수 있어야 하지만 실수나 침해 하나로 production NAS 전체를 바꿀 수 있는 control plane이 될 필요는 없다.