code server
라고 들어보셨나요? 웹 브라우저를 통해 VSCode를 구동할 수 있도록 도와주는 라이브러리입니다. 나온지는 제법 오래 됐으므로 많은 분들이 이미 사용하고 계실지도 모르겠습니다만, 저는 최근에서야 이것의 존재를 알게 됐습니다.
맥북을 들고 다니기에는 무겁고, 그냥 가벼운 코드 수정이나 테스트 코드를 구동시켜보고 싶을 때, 아이패드로 작업을 하고 싶었거든요. 집에서 구동 중인 NAS는 사양이 너무 딸려서 도저히 실사용이 불가능할 것으로 판단한 저는 클라우드 서비스로 눈을 돌렸습니다.
많은 서비스를 비교해봤지만, 역시 갓마존의 AWS만한 게 없었어요. 하지만 저의 Freetier는 이미 만료된 상황이었습니다. gcp는 무료 사용 가능한 인스턴스의 사양이 너무 부족했습니다.
1기가도 안되는 램이라니요..
게다가 고정 IP를 무료로 제공해주지도 않았고, 미국 내 Region에 한해서만 무료로 사용이 가능했습니다.
그래서 고심을 하던 중 Oracle에서 클라우드 서비스를 제공한다는 사실을 뒤늦게 알게 됐고, 꽤나 공격적인 마케팅을 하더라는 것도 알 수 있었습니다. AWS의 Freetier로 사용 가능한 t2.micro 정도의 사양을 평생 무료로 제공한다는 꿀정보를 얻었는데, 심지어 인스턴스도 2대까지 돌릴 수 있다고 하더라구요. 무엇보다도 고정 IP를 무료로 제공한다는 점, Seoul Region을 사용할 수 있다는 점이 매력적이어서 큰 고민없이 Oracle(OCI; Oracle Cloud Infrastructure)로 결정했습니다.
OCI 설정
일단 OCI에 가입을 한 뒤, VM 인스턴스를 생성해 줍니다. 이미지는 익숙한 Ubuntu 20.04로 구성하고, 머신 성능은 OCPU 1, 1GB Mem
으로 구성했습니다. SSH 설정도 잊지 마시구요.
그렇게 생성이 완료된 뒤에는 고정 IP 등록을 해줘야 하는데요, 우선은 사용할 IP를 예약해주도록 합니다. 네트워킹 -> 공용 IP
메뉴에서 예약이 가능합니다.
그러고나서는 해당 IP를 아까 생성한 인스턴스와 연결해주는 작업이 필요한데요, 인스턴스 관리 페이지에서 손쉽게(?) 변경할 수 있습니다. 인스턴스 세부정보
-> 연결된 VNIC
를 통해서 변경이 가능한데요, 인스턴스 이름을 클릭하고 IP 주소를 클릭하면 전용 IP 주소 편집이라는 창이 뜨는데, 거기서 우선 공용 IP 없음
을 선택해 업데이트를 해줍니다. 임시 IP가 할당돼있으면 안되더라구요. 그러고나서 다시 편집 화면을 통해 예약된 공용 IP
를 선택하시면 아까 예약한 공용 IP가 보일겁니다.
일반적으로는 이정도만 설정해줘도 되겠지만, 저는 http(s)://
를 통해서 인스턴스에 접근이 가능해야 하기 때문에 네트워크 방화벽을 열어줄 필요가 있었습니다. 네트워킹 -> 가상 클라우드 네트워크
를 통해서 설정이 가능한데요, 저는 기존에 있는 VCN 서브넷에 규칙을 추가해주는 방향으로 설정했습니다. 소스는 0.0.0.0/0
으로 모든 네트워크에 대해서 허용해주도록 하고, 대상 포트 범위를 80, 443
으로 설정했습니다.
이정도만 설정해주면 아마 OCI에서 더 건드릴 부분은 없을 걸로 생각되네요.
이제 ssh를 통해 인스턴스에 접근이 가능합니다.
ssh -i ${.pem 파일 경로} ${인스턴스 Username - 보통은 ubuntu}@${IP Address}
혹시 Username을 모른다면, OCI -> 인스턴스 세부정보 -> 인스턴스 액세스
에서 사용자 이름
을 확인할 수 있습니다.
이제 본격적으로 인스턴스 내부를 설정해봅시다.
우선 iptables
를 통해 인스턴스 내부에서 방화벽을 열어주도록 합시다.
sudo iptables -I INPUT 5 -i ens3 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
sudo iptables -I INPUT 5 -i ens3 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
이러고 나면 sudo iptables --list
명령어로 잘 등록되었는지 확인해볼 수 있습니다.
다만, 이 설정은 재부팅 시에는 초기화 되기 때문에 추가적인 설정이 필요한데요, 다음과 같은 명령어로 저장이 가능합니다.
sudo apt-get install netfilter-persistent
netfilter-persistent save
이제, 재부팅을 해도 방화벽 설정이 유지됩니다.
nginx 설정
우리는 어디서나 손쉽게 접근할 수 있는 환경이 필요한 것이므로 nginx
를 통해 proxy redirection을 처리해줄 필요가 있습니다. 왜냐하면 code-server는 localhost의 특정 포트에서 구동이 되기 때문이에요. localhost에서만 사용할 거라면 굳이 클라우드를 설정해줄 필요도, 고정 IP를 설정해줄 필요도 없었을겁니다. 고정 IP를 통해서 접속을 시도하면 nginx를 통해서 내부의 localhost로 Redirection 시켜줍니다.
nginx는 다음 명령어로 아주 쉽게 설치가 가능합니다.
sudo apt-get update
sudo apt-get install nginx
설치가 완료되면 아까 설정한 IP 주소를 브라우저에 입력해봅시다. 아래와 같은 화면이 보이면 성공이에요.
자, 이제 nginx 설정 파일을 조금 만져줄 차례입니다.
우선은 80포트(http)로 접속했을 때 code-server까지 잘 연결되도록 해줘야겠죠?
sudo vim /etc/nginx/sites-available/code-server.conf
upstream code-server {
server 127.0.0.1:8080;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name code;
location / {
proxy_pass http://code-server;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Host $host;
proxy_set_header Accept-Encoding gzip;
}
}
upstream code-server
로 연결되는 proxy_pass
를 보시면 127.0.0.1:8080
으로 되어있습니다. 이건 code-server 설정이 default로 그렇게 되어있기 때문이에요. 특별한 이유가 있는게 아니라면 그냥 둡시다. 만약 이것을 변경할 거라면 아래에서 설명할 code-server의 설정 파일에서 bind-addr 값도 같이 수정해주면 됩니다.
code-server.conf를 만들었으니 이제 site-enable에 symlink를 설정해줍시다. site-available
에 있는 설정들은 말 그대로 available한 상태이므로 site-enabled
로 링크해서 관리하는 것이 일반적입니다.
sudo ln -s /etc/nginx/sites-available/code-server.conf /etc/nginx/sites-enabled/code-server.conf
직접 site-enabled
에 설정 파일을 만들어서 넣어도 동작은 하겠지만, 이는 매우 권장되지 않습니다. 관련 stackoverflow 답변을 첨부합니다.
Nginx - Do I really need sites-available and sites-enabled folders? - Stackoverflow
링크가 잘 생성됐다면 문법에 오류가 없는지 확인한 뒤 nginx를 재시작합니다.
sudo nginx -t
sudo systemctl restart nginx
그럼 이제 드디어 code-server를 설정할 차례입니다.
code-server 설정
다음 명령어를 통해서 손쉽게 code-server를 설치할 수 있습니다.
curl -fsSL https://code-server.dev/install.sh | sh
만약에 실제로 설치하기 전에 dry-run을 수행해보고 싶다면 마지막 단락에 -s -- --dry-run
을 붙여서 수행해주면 됩니다.
설치가 완료되었다면 ~/.config/code-server/config.yaml
이라는 파일이 있을겁니다. 이게 code-server의 설정파일이에요. 아래와 같이 생겼습니다.
bind-addr: 127.0.0.1:8080
auth: password
password: ${임시 비밀번호}
cert: false
nginx 설정에서 설명했듯 기본적으로는 8080포트에서 돌아가도록 되어있고, 접속 시 password를 통해 인증하도록 되어있습니다. 아무래도 VSCode는 terminal이 오픈되기 때문에 해당 페이지에 아무나 접근 가능하도록 하는 것은 매우매우매우 위험합니다.
여기까지 확인했다면 code-server
를 입력해 실행할 수 있습니다....만, 이왕이면 서비스에 등록해서 사용하는 편이 좋습니다. 인스턴스에 문제가 생겨서 재부팅이라도 하면 또 shell에 접속해서 설정을 해줘야할테니까요.
systemctl --user enable --now code-server
이제 고정 IP를 입력하면 브라우저를 통해서 바로 code-server에 접속할 수 있게 됐습니다 :)
문제 발생
그런데 한 가지, ssh 연결이 끊어지면 code-server에도 접속이 되지 않게 된다는 문제가 발견됩니다. 502 Bad Gateway
가 나타나요.
잠깐 멘붕이었지만, 다행히도 저 화면이 나타난다는 건 nginx는 정상적으로 돌아가고 있다는 뜻입니다. nginx도 죽었다면 저 화면조차 나타나지 않았을테니까요. 그럼 모종의 이유로 code-server
만 끊어진단 얘긴데, 그렇다면 아마 User-Level의 systemctl로 등록되는 바람에 User session이 끊어지면 같이 서버가 내려가는 것 같았습니다.
그럼 User session이 끊어지지 않도록 해주면 될 것 같아, loginctl
을 사용하기로 했습니다.
loginctl enable-linger ${username}
이제 ssh 접속을 종료해도 code-server가 끊어지지 않아요 :D 만세!
SSL 설정
다만, code-server는 http 환경에서는 몇 가지 제한이 걸립니다. https를 사용하고 싶다면 인증서가 필요할텐데, 인증서는 아시다시피 돈이 들게 마련입니다. 게다가 도메인 네임도 따로 구입해야 하고요. 여러가지 고민을 한 끝에 저는 freenom
에서 도메인 이름을 발급받았습니다. 무료로 사용할 수 있는데, 그럭저럭 쓸만합니다. 인증서는 Certbot
을 통해서 설정해보도록 할게요. 아래 명령어를 통해 certbot을 설치해줍니다.
sudo apt install certbot python3-certbot-nginx
sudo certbot -d ${도메인 이름} --manual --preferred-challenges dns certonly
설치를 하다보면 만료 알람을 받을 메일 주소를 입력하라든가 하는 질문이 나타납니다. 적당히 대답해주도록 합시다. 다만 Are you OK with your IP being logged?
라는 질문에는 반드시 Y를 입력해야 하는 듯합니다. 안 그러면 진행이 안되던데요. 그러고나면 DNS TXT record에 name과 value를 입력하라고 알려줍니다. 발급받은 도메인 설정에서 알려준 값을 넣어주도록 합시다. 저장하고 바로 인식하지 못하는 경우가 있는데, 보통 1분 이내로 인식하는 것 같습니다. 너무 서둘러서 하면 찾을 수 없다면서 인증서 생성이 종료되고 위의 프로세스를 반복해야 하는 일이 생기므로 마음의 여유를 가져보도록 합시다.
제대로 진행이 됐다면 Congratulations!!! 라면서 key를 발급해줍니다. /etc/letsencrypt/live/${도메인 이름}
안에 저장되는데, 신경쓰지 않으셔도 됩니다. 어차피 certbot이 알아서 설정을 건드려줄거예요.
sudo certbot --nginx -d ${도메인 이름}
이제 https
를 통해 code-server에 접속이 가능하며, code-server의 모든 기능을 이용할 수 있습니다 :)