Self-hosted Supabase API 도메인 연결
관련 시리즈
Self-hosted Supabase Google 로그인 설정 (1/3) - 개념과 Google Cloud 설정
Self-hosted Supabase Google 로그인 설정 (2/3) - 서버 설정
Self-hosted Supabase Google 로그인 설정 (3/3) - Web 연동과 테스트
Self-hosted Supabase를 외부에서 접근하려면 도메인, DNS, HTTPS 인증서, Nginx 프록시를 설정해야 합니다. 이 문서는 Google 로그인뿐만 아니라 모든 Supabase API 외부 연결에 적용되는 범용 인프라 가이드입니다.
예시 환경
- Supabase 외부 API 도메인:
sb.example.com - Supabase 설치 경로:
/root/supabase/docker - API Gateway: Kong (Docker 컨테이너, 포트 8000)
- 호스트 Nginx: 443 (HTTPS) → 8000 (Kong)
- 운영체제: Ubuntu 예시
중요: 이 문서의
example.com은 예제 도메인입니다. 실제 설정할 때는 자신이 소유한 도메인으로 모두 바꿔야 합니다.
1. 포트와 네트워크 구조 이해
Self-hosted Supabase의 요청 흐름을 이해하면 설정이 명확해집니다.
1.1 전체 요청 경로
인터넷 (브라우저)
↓ HTTPS :443
호스트 Nginx
↓ HTTP :8000 (loopback)
Docker Kong 컨테이너
↓ Docker Network
Supabase Auth/REST/Storage 컨테이너들
1.2 포트 종류
외부 HTTPS 포트 443
사용자 브라우저가 접속하는 공개 포트입니다.
https://sb.example.com:443
HTTPS의 기본 포트이므로 실제 URL에서는 :443을 생략합니다. 이 포트는 호스트 OS에서 실행 중인 Nginx가 사용합니다.
호스트 포트 8000
Docker가 Kong 컨테이너의 포트를 서버 호스트에 연결한 포트입니다.
서버 호스트의 localhost:8000
Nginx는 이 주소로 요청을 전달합니다.
Kong 컨테이너 포트 8000
Kong 컨테이너 내부에서 API 요청을 받는 포트입니다. Docker Compose의 ports가 호스트 포트와 컨테이너 포트를 연결합니다.
ports:
- ${KONG_HTTP_PORT}:8000/tcp
.env가 다음과 같다면:
KONG_HTTP_PORT=8000
실제 의미는 다음과 같습니다.
호스트 8000번 포트 → Kong 컨테이너 8000번 포트
Docker Compose의 일반적인 포트 표기법은 HOST_PORT:CONTAINER_PORT입니다.
Docker Network
Docker Compose로 실행한 컨테이너는 기본적으로 같은 전용 네트워크에 연결됩니다. 이 환경의 네트워크 이름은 supabase_default입니다.
같은 네트워크의 컨테이너는 IP 주소를 직접 외우지 않고 Compose 서비스 이름으로 서로를 찾을 수 있습니다.
Kong 컨테이너 → http://auth:9999
Kong 컨테이너 → http://rest:3000
Kong 컨테이너 → http://storage:5000
여기서 auth, rest, storage는 인터넷 도메인이 아니라 docker-compose.yml의 서비스 이름입니다. Docker 내부 DNS가 이름을 컨테이너 IP로 변환합니다.
1.3 실제 요청 이동 경로
브라우저가 다음 주소를 요청한다고 가정합니다.
https://sb.example.com/auth/v1/settings
요청은 다음 순서로 이동합니다.
[1] 사용자 브라우저
https://sb.example.com/auth/v1/settings
│
│ DNS: sb.example.com → 서버 공인 IP
▼
[2] 서버 호스트의 Nginx
0.0.0.0:443 (HTTPS 종료, 인증서 검증)
│
│ proxy_pass http://127.0.0.1:8000
▼
[3] Docker가 공개한 Kong 호스트 포트
127.0.0.1:8000
│
│ host port 8000 → container port 8000
▼
[4] supabase-kong 컨테이너
Kong :8000
│
│ /auth/v1/settings 경로 규칙 확인
│ Docker 내부 주소 http://auth:9999/settings
▼
[5] supabase-auth 컨테이너
GoTrue :9999
Nginx는 /auth/v1/settings의 의미를 해석하지 않습니다. 경로를 그대로 Kong에 전달합니다. 어떤 컨테이너로 보낼지 결정하는 프로그램은 Kong입니다.
1.4 호스트 Nginx와 컨테이너 Nginx의 차이
이 문서의 Nginx는 Docker 컨테이너가 아니라 서버 호스트에 설치된 Nginx입니다. 따라서 다음 주소를 사용합니다.
proxy_pass http://127.0.0.1:8000;
호스트 Nginx는 Docker 내부 서비스 이름 kong, auth를 기본적으로 해석할 수 없습니다. 다음 설정은 이 구성에서 사용하면 안 됩니다.
# 호스트 Nginx에서는 일반적으로 동작하지 않음
proxy_pass http://kong:8000;
proxy_pass http://auth:9999;
반대로 Nginx도 Docker 컨테이너로 실행하고 Supabase와 같은 Docker Network에 연결했다면 다음처럼 서비스 이름으로 접근할 수 있습니다.
# Nginx 역시 같은 Docker Network 안에 있을 때만 사용
proxy_pass http://kong:8000;
두 방식을 섞지 않는 것이 중요합니다.
2. DNS 설정
도메인 관리 서비스에서 Supabase API 하위 도메인을 서버 공인 IP로 연결합니다.
2.1 A 레코드 등록
유형: A
호스트/이름: sb
값: 서버의 공인 IPv4 주소
TTL: 자동 또는 300
등록 결과:
sb.example.com → 서버 공인 IP
2.2 DNS 확인
dig +short sb.example.com
서버 공인 IP와 같은 값이 나와야 합니다. DNS 전파에는 수분에서 수십 분이 걸릴 수 있습니다.
3. Kong 포트를 호스트에 공개하기
docker-compose.yml의 Kong 서비스에 포트 매핑이 있어야 합니다.
3.1 기본 포트 매핑
기본 예:
services:
kong:
ports:
- ${KONG_HTTP_PORT}:8000/tcp
- ${KONG_HTTPS_PORT}:8443/tcp
이 형식은 기본적으로 0.0.0.0:8000에 바인딩될 수 있어 방화벽 설정에 따라 인터넷에서 서버IP:8000으로 직접 접근될 가능성이 있습니다.
3.2 보안 강화: loopback 바인딩
Nginx와 Kong이 같은 서버에 있고 외부에서 Kong 포트에 직접 접근할 이유가 없다면, 다음처럼 loopback에만 바인딩하는 구성이 더 안전합니다.
services:
kong:
ports:
- "127.0.0.1:${KONG_HTTP_PORT}:8000/tcp"
- "127.0.0.1:${KONG_HTTPS_PORT}:8443/tcp"
3.3 변경 적용
변경 후 Kong을 다시 생성합니다.
cd /root/supabase/docker
docker compose up -d --force-recreate --no-deps kong
3.4 포트 확인
ss -lntp | grep -E ':(8000|8443)\b'
권장 결과:
127.0.0.1:8000
127.0.0.1:8443
8443은 Kong 자체 HTTPS 포트입니다. 이 구성에서는 Nginx가 공인 인증서와 HTTPS를 처리하므로 Nginx의 upstream은 일반 HTTP 127.0.0.1:8000을 사용합니다. 같은 서버 내부의 loopback 통신이기 때문에 이 구간을 다시 HTTPS로 암호화할 필요는 일반적으로 없습니다.
4. Nginx 설치
4.1 패키지 설치 (Ubuntu)
apt update
apt install -y nginx certbot python3-certbot-nginx
systemctl enable --now nginx
systemctl status nginx
4.2 방화벽 설정
방화벽을 사용한다면 HTTP/HTTPS를 허용합니다.
ufw allow 'Nginx Full'
ufw status
Kong의 8000, Auth의 9999 포트를 외부 방화벽에 열 필요는 없습니다.
5. HTTP 서버 블록 생성
인증서가 아직 없다면 인증서 경로를 포함한 HTTPS 설정부터 작성하면 Nginx가 시작되지 않습니다. 먼저 HTTP 전용 설정을 만듭니다.
5.1 최초 HTTP 설정
파일:
/etc/nginx/sites-available/sb.example.com
최초 설정:
server {
listen 80;
listen [::]:80;
server_name sb.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}
5.2 설정 활성화
ln -s /etc/nginx/sites-available/sb.example.com \
/etc/nginx/sites-enabled/sb.example.com
nginx -t
systemctl reload nginx
이미 심볼릭 링크가 있다면 File exists가 출력될 수 있으며 새로 만들 필요가 없습니다.
5.3 HTTP 연결 확인
curl -I http://sb.example.com/auth/v1/health
정상적인 경우 Supabase Auth의 응답을 받습니다.
6. Let's Encrypt 인증서 발급
DNS가 서버를 가리키고 Nginx의 80번 포트가 외부에서 접근 가능해야 합니다.
6.1 Certbot 실행
certbot --nginx -d sb.example.com
Certbot 질문에 따라:
- 이메일 입력
- 약관 동의
- HTTP → HTTPS 리디렉션 선택 (권장)
6.2 인증서 확인
certbot certificates
systemctl status certbot.timer
6.3 자동 갱신 테스트
certbot renew --dry-run
7. 최종 HTTPS 설정
인증서 발급 후 다음처럼 구성합니다.
7.1 최종 Nginx 설정
파일: /etc/nginx/sites-available/sb.example.com
# HTTP 요청을 HTTPS로 이동
server {
listen 80;
listen [::]:80;
server_name sb.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS 요청을 Kong으로 전달
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name sb.example.com;
ssl_certificate /etc/letsencrypt/live/sb.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sb.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
access_log /var/log/nginx/sb.example.com.access.log;
error_log /var/log/nginx/sb.example.com.error.log;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
# Realtime WebSocket 연결에도 필요한 헤더
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 원래 요청의 도메인, IP, HTTPS 정보를 Kong/서비스에 전달
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering off;
}
add_header Strict-Transport-Security \
"max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
}
7.2 각 핵심 지시문의 의미
listen 443 ssl: 외부 HTTPS 요청 수신server_name: 이 설정을 적용할 도메인ssl_certificate: 브라우저가 신뢰할 인증서location /: 모든 Supabase API 경로를 같은 upstream으로 전달proxy_pass: 호스트에 공개된 Kong 포트Host: 원래 도메인을 upstream에 전달X-Forwarded-Proto: 원래 요청이 HTTPS였음을 서비스에 전달Upgrade,Connection: Supabase Realtime WebSocket 지원
7.3 설정 적용
nginx -t
systemctl reload nginx
nginx -t가 실패하면 reload하지 말고 표시된 파일과 줄 번호를 먼저 수정합니다.
8. 브라우저에서 정상 접속 확인
Nginx 설정을 반영한 후 브라우저에서 다음 주소를 엽니다.
https://sb.example.com
다음 상태라면 Nginx에서 Supabase까지의 기본 연결은 정상입니다.
- ✓ HTTPS 자물쇠가 표시되고 인증서 경고가 없습니다.
- ✓ Supabase Dashboard 인증 창 또는 Supabase 화면이 표시됩니다.
- ✗
502 Bad Gateway, DNS 오류, 연결 시간 초과가 없습니다.
8.1 추가 확인
특정 API 엔드포인트 테스트:
curl -I https://sb.example.com/auth/v1/health
9. 외부에 열어야 하는 포트
일반적인 단일 서버 구성의 권장 범위:
80/tcp 외부 허용: Let's Encrypt ACME 챌린지와 HTTPS 리디렉션
443/tcp 외부 허용: Supabase HTTPS API
8000/tcp 외부 차단: Nginx만 loopback으로 접근
8443/tcp 외부 차단: 이 구성에서는 직접 사용하지 않음
9999/tcp 외부 차단: Docker 내부 Auth 전용
정리하면, 사용자는 https://sb.example.com의 443번 포트만 사용합니다. Nginx 뒤의 8000과 9999는 외부 사용자가 직접 접근할 포트가 아닙니다.
10. 일반적인 문제와 해결
10.1 브라우저에서 사이트를 찾을 수 없음
원인: DNS가 서버를 가리키지 않습니다.
해결:
dig +short sb.example.com
서버 공인 IP가 나와야 합니다. 결과가 없거나 다른 IP가 나온다면 DNS 레코드를 확인하고 전파를 기다립니다.
10.2 인증서 경고
원인:
- 인증서가 발급되지 않았거나 만료됨
- 도메인 불일치
해결:
certbot certificates
인증서 도메인과 만료일을 확인합니다. 필요하면 재발급:
certbot --nginx -d sb.example.com --force-renewal
10.3 502 Bad Gateway
원인: Nginx는 정상이지만 Kong이 응답하지 않습니다.
해결:
# Kong 컨테이너 상태 확인
cd /root/supabase/docker
docker compose ps kong
# Kong 로그 확인
docker compose logs --tail=100 kong
# Kong 재시작
docker compose restart kong
10.4 연결 시간 초과
원인:
- 서버 방화벽이 443 포트를 차단
- Nginx가 중지됨
해결:
# Nginx 상태 확인
systemctl status nginx
# 방화벽 확인
ufw status
# 포트 리스닝 확인
ss -lntp | grep :443
11. 보안 체크리스트
- Kong 포트는 loopback에만 바인딩되어 있습니다.
- 외부 방화벽에서 80, 443 외의 포트는 차단되어 있습니다.
- Let's Encrypt 자동 갱신이 활성화되어 있습니다.
- Nginx 로그 파일 권한이 적절히 제한되어 있습니다.
- HTTPS에서만 Supabase API에 접근합니다.
- Nginx에 HSTS 헤더가 설정되어 있습니다.
12. 다음 단계
인프라 설정이 완료되었다면 이제 Supabase의 특정 기능을 설정할 수 있습니다.
관련 시리즈:


주파수 소통방 (0)
로딩 중...