홈서버 터미널에서 전체적인 파일 구조를 파악하거나 대량의 코드를 수정하기엔 생산성이 떨어져 vscode를 설치하기로 결정.
code-server를 도커로 띄우고, Cloudflare Tunnel을 통해 포트 개방 없이 안전하게 연결할 것이다.
우선 도커를 설치 및 실행한다. 터미널에 아래와 같이 입력한다.
# 1. 시스템 업데이트 및 Docker 설치
sudo yum update -y
sudo yum install -y docker
# 2. Docker 서비스 시작 및 자동 실행 설정
sudo systemctl start docker
sudo systemctl enable docker
# 3. 사용자 권한 부여
sudo usermod -aG docker $USER
# 4. Docker Compose 설치 (플러그인 방식)
sudo yum install -y docker-compose-plugin
이제 vim 편집기를 통해 docker-compose.yml 파일을 생성.
vi docker-compose.yml
아래 내용을 추가한다. 이 파일로 vscode와 보안 터널을 동시에 관리한다.
services:
code-server:
image: linuxserver/code-server:latest
container_name: code-server
environment:
- PUID=${VSCODE_PUID}
- PGID=${VSCODE_PGID}
- TZ=Asia/Seoul
- PASSWORD=${VSCODE_PW}
volumes:
- ./config:/config
- ${PJ_PATH}:/config/workspace
restart: unless-stopped
tunnel:
image: cloudflare/cloudflared:latest
container_name: cloudflare-tunnel
restart: unless-stopped
command: tunnel run
environment:
- TUNNEL_TOKEN=${CF_TUNNEL_TOKEN}
알아둘 내용만 정리하자면
- PUID, PGID: 컨테이너 내부에서 만든 파일이 서버(Host)에서도 권한 문제 없이 읽히도록 설정한다.
- Volumes: vscode 컨테이너 내부의 /config/workspace에 연결된 ${PJ_PATH}에 데이터가 저장된다. 설정을 해주지 않으면 컨테이너 내부의 자원은 서버와 격리되어 있다.
- Restart: 어떤 상황에서 다시 시작할지 선택하는 옵션이다. 옵션에 대해서 아래의 표에 정리하겠다.
| 옵션 | 서버 재부팅 시 자동 실행 | 수동 중지 후 재부팅 시 | 특징 |
| no (기본값) | X | X | 컨테이너가 꺼지면 중지. |
| always | O | O | 수동 중지 시에도 서버 켜지면 다시 실행. |
| unless-stopped | O | X | (권장옵션) 수동 중지가 아니라면 다시 실행. |
| on-failure | X | X | 에러(Exit Code가 0이 아닌 경우)로 중지 시 재시작. |
민감한 정보는 보안을 위해 .env 파일에 저장한다.
vi .env
VSCODE_PUID=1000
VSCODE_PGID=1000
VSCODE_PW=사용할_비밀번호
PJ_PATH=/home/ec2-user/projects
CF_TUNNEL_TOKEN=클라우드플레어_토큰값
설정이 완료되면 docker를 올린다.
docker compose up -d
현재 vscode로 접속하면 비밀번호를 입력하여 서버 내부의 파일들을 편집할 수 있게 되어있다.
하지만 비밀번호 시도 횟수 제한이 없어 브루트포스 공격을 받아 금새 뚫릴 수 있다.
보안을 위해 cloudflare tunnel에 구글 로그인을 추가하겠다.
google cloud에 들어가서 해당 부분 클릭하여 새 프로젝트 들어가서 프로젝트를 생성.

API 및 서비스 -> 사용자 인증 정보 클릭

사용자 인증 정보 만들기 -> OAuth 클라이언트 ID 클릭

애플리케이션 유형은 웹 애플리케이션, 알아보기 쉬운 이름 작성해주고
승인된 JavaScript 원본에는 https://도메인명.cloudflareaccess.com (도메인명은 your-domain.com이라면 your-domain)
승인된 리디렉션 URI에는 https://도메인명.cloudflareaccess.com/cdn-cgi/access/callback 이후 저장

완성되면 나오는 클라이언트 ID와 클라이언트 비밀 키를 따로 저장해둔다.
다시 cloudflare로 돌아와서 zero trust -> Access controls -> Access settings -> Manage your App Launcher 클릭.

아마 One-time PIN 밖에 없을건데 나는 이미 Google login을 만들어서 Google 표시가 있다. 이걸 만들 예정.
Login methods -> Manage login methods 클릭

Add an Identity provider -> Google 클릭
App ID에 저장해뒀던 클라이언트 ID, client secret에 비밀 키를 넣어주고 저장.

이제 만든 보안 정책을 등록해보자.
zero trust -> Access controls -> Applications -> Add an application

Application name에 알아보기 쉬운 이름을 지정해주고 원하는 Session Duration을 지정해준다.
Add public hostname을 눌러 내가 뚫어준 tunnel 도메인명을 입력해주고
create new policy를 클릭한다.

policy name을 google login으로 한 뒤 Action과 Session duration은 그대로 뒀다.
Add rules에서 Login Methods 선택, Google 선택, 저장

트러블 슈팅
- 문제 1: 접속 불가 (Connection Refused)
- 원인: Cloudflare 대시보드에서 서비스 주소를 localhost:8443으로 설정함. 도커 컨테이너는 서로 독립된 가상 환경이라 localhost로 찾을 수 없음. 도커에서는 별도로 url을 지정해주지 않으면 컨테이너 명으로 자동 지정된다.
- 해결: 대시보드 도메인 명을 컨테이너 이름인 code-server 로 변경. 즉, http://code-server:8443으로 변경.
- 문제 2: 파일이 안 보임
- 원인: 도커는 서버의 폴더를 명시적으로 연결(Mount)해주지 않으면 볼 수 없음.
- 해결: volumes 설정을 통해 서버의 프로젝트 경로를 컨테이너 내부 /config/workspace에 매핑.