서버 한 대에 여러 서비스를 올리는 프로덕션 운영
서비스가 늘어날 때마다 VPS를 한 대씩 더 사고 계신다면 비용이 서비스 수만큼 배가 됩니다. 거기에 도메인마다 SSL 인증서를 매년 사야 한다면 인증서 비용만 수십만 원입니다. Nginx 리버스 프록시와 Let’s Encrypt 무료 SSL을 쓰면 서버 한 대 위에 모든 서비스를 올리고 인증서는 평생 무료로 유지할 수 있습니다.
이 튜토리얼에서는 한 대의 VPS에 블로그·API·관리툴을 각각 다른 도메인으로 띄우고, Let’s Encrypt로 자동 갱신되는 SSL까지 붙이는 전체 과정을 다룹니다. W17/W23 단일 사이트 설정에서 한 단계 더 나아간 프로덕션 다중 서비스 라우팅입니다.
1. 리버스 프록시란?
프록시는 중간에서 대신 전달해 주는 역할입니다. 익숙한 포워드 프록시(회사/학교에서 외부로 나갈 때 거치는 것)와 반대로, 리버스 프록시는 인터넷에서 들어오는 요청을 서버 앞에서 받아 도메인을 보고 알맞은 내부 서비스로 보냅니다. 사용자는 앞에 프록시가 있다는 사실을 모른 채 도메인으로 접속하면 알아서 서비스가 응답합니다. Nginx는 이 분야의 사실상 표준입니다 — 가볍고 빠르고 설정이 단순하며 트래픽이 몰려도 안정적입니다.
2. server block으로 도메인 분리
Nginx는 들어온 요청의 도메인을 보고 어떤 server block을 쓸지 정합니다. server_name 지시어로 도메인을 매칭합니다. 예를 들어 blog.example.com과 api.example.com을 각각 별도 server block으로 만들면 서로 독립적으로 동작합니다.
# /etc/nginx/sites-available/blog.example.com
server {
listen 80;
server_name blog.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
설정 파일은 /etc/nginx/sites-available/에 도메인별로 만들고 /etc/nginx/sites-enabled/에 심볼릭 링크로 연결합니다. listen 80은 HTTP, 443은 HTTPS입니다 — 처음엔 80번으로 받고 SSL 발급 뒤에 443번으로 바꿉니다.
3. proxy_pass와 헤더 전달
location / 블록 안의 proxy_pass로 백엔드 주소를 적습니다. http://127.0.0.1:8080이면 이 도메인으로 들어온 요청이 8080번 포트의 서비스로 갑니다. API는 3000번, 관리툴은 5050번으로 보내면 각 서비스를 포트만 바꿔 라우팅할 수 있습니다.
주의할 점은 헤더 전달입니다. 프록시가 중간에 있으면 뒤의 서비스는 누가 요청했는지 모릅니다. 그래서 Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto 헤더를 함께 넘겨야 백엔드가 실제 클라이언트 정보를 알 수 있습니다. 이 헤더가 없으면 로그에 실제 사용자 IP가 안 남고 HTTPS가 HTTP로 인식됩니다.
또 proxy_pass 주소 끝에 슬래시를 붙이냐에 따라 경로 처리가 달라집니다. 붙이면 location 경로가 잘리고, 빼면 그대로 전달됩니다 — 이 차이를 헷갈리면 이미지나 API가 깨집니다.
4. Let’s Encrypt 무료 SSL 발급
SSL 인증서를 유료로 사는 시대는 지났습니다. Let’s Encrypt가 무료로 발급해 주고, 도구는 certbot 하나면 됩니다.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx --redirect -d blog.example.com -d api.example.com
--nginx 옵션을 주면 certbot이 Nginx 설정을 읽고 자동으로 인증서를 발급하고 설정 파일까지 고쳐 줍니다. --redirect를 붙이면 HTTP 요청을 HTTPS로 자동 이동시킵니다. 이 과정을 HTTP-01 챌린지라고 부릅니다 — Let’s Encrypt가 특정 주소로 접근해 보고 내 서버가 응답하면 인증서를 줍니다. 그러므로 80번 포트가 열려 있어야 합니다.
처음 설정이 꼬일 때는 --staging 옵션으로 테스트 발급을 받아보세요. 스테이징은 실패 횟수 제한에 안 걸립니다. 정식 발급이 확인되면 다시 정식으로 받으면 됩니다.
5. 자동 갱신 — certbot timer
인증서 유효기간은 90일입니다. 다행히 certbot을 설치하면 갱신 타이머도 같이 깔립니다.
systemctl status certbot.timer
# 하루에 두 번 갱신 시도, 기간 30일 남았을 때 실제 갱신
갱신 직후에 해야 할 일이 있으면 deploy hook으로 겁니다. 예를 들어 인증서가 바뀌면 Nginx를 다시 불러오도록 등록합니다.
sudo certbot renew --deploy-hook "systemctl reload nginx"
자동이라도 실패할 수 있으니 갱신 실패 시 이메일 알림을 켜 두면 만료 직전에 놓치지 않습니다. 이렇게 하면 인증서가 평생 무료로 유지됩니다.
6. 실전 배치 — 한 VPS에 세 서비스
한 대의 VPS에 세 개의 서비스를 올리는 예시:
- 블로그
blog.example.com→ 8080번 포트의 WordPress - API
api.example.com→ 3000번 포트의 Node.js 앱 - 관리툴
admin.example.com→ 5050번 포트의 pgAdmin
세 서비스가 각각 다른 도메인으로 한 서버에서 돌아갑니다. 비용은 서버 한 대 분량이고 인증서도 세 도메인 모두 무료입니다.
7. 트러블슈팅 — 자주 겪는 문제
설정을 바꿨으면 반드시 sudo nginx -t로 문법을 검사하고 sudo systemctl reload nginx로 다시 불러옵니다. restart가 아니라 reload면 끊김 없이 설정이 적용됩니다.
- 502 Bad Gateway: 뒤의 백엔드 서비스가 죽었을 때. 서비스가 켜져 있는지,
proxy_pass포트와 실제 포트가 같은지 확인. - 도메인이 Nginx에 연결 안 됨: DNS 전파가 끝났는지, 도메인이 서버 IP를 제대로 가리키는지 확인.
- 포트 충돌: 다른 서비스가 80/443번을 이미 쓰고 있을 수 있음.
- 인증서 발급 실패: 80번 포트가 방화벽에 막혀 있으면 HTTP-01 챌린지가 안 됨.
ufw allow 80으로 열어 줄 것.
마무리: 서버 한 대, 인증서 평생 무료
Nginx 리버스 프록시와 Let’s Encrypt로 서버 한 대에 여러 서비스를 안전하게 올렸습니다. 비용은 서버 한 대, 인증서는 평생 무료입니다. 블로그와 API와 관리툴이 각각 다른 도메인으로 돌아갑니다. 다음 글에서는 VPS에 PostgreSQL을 배포하고 백업까지 자동화하는 방법을 다룹니다.
추천 VPS: 이 튜토리얼은 Vultr(서울 리전, 100달러 크레딧), DigitalOcean, Hetzner 어디서나 동일하게 적용됩니다.



















