TL;DR

  • Portspan은 HTTP 개발 서비스를 대상으로 예측 가능한 호스트 이름과 와일드카드 서브도메인을 제공하는 자체 호스팅 ngrok 대안임.
  • 개발자는 tunnel --port 3000 --domain app 명령으로 로컬 포트를 https://app.<your-base-domain>에 노출할 수 있음.
  • 구성은 DNS 와일드카드 → Nginx → 루프백 전용 frp 가상 호스트 → 인증된 frpc TLS 연결 → 로컬 애플리케이션 순서임.
  • frp는 서브도메인 라우팅과 토큰 인증, 암호화된 클라이언트·서버 전송을 담당하고, Nginx는 공개 TLS를 종료함.
  • 저장소는 서버·클라이언트 설치, 보안 설정, 운영 점검, 인증서 갱신, 롤백 절차를 제공하지만 도메인·DNS·계정 자격 증명·비밀 복사는 자동화하지 않음.

Portspan

  • Portspan은 HTTP 개발 서비스를 위한 소규모 자체 호스팅 ngrok 대안임.
  • 개발자는 다음 명령으로 로컬 포트를 예측 가능한 호스트 이름에 노출할 수 있음.
  • tunnel --port 3000 --domain app
  • 주소는 https://app.<your-base-domain> 형식임.
  • 스택은 직접 관리하는 서버를 기준으로 설계됨.
  • 브라우저
  • *.tunnel.example.com DNS 레코드
  • Nginx :80/:443
  • frps 루프백 가상 호스트 :18080
  • 인증된 frpc TLS 연결 :7000
  • 로컬 애플리케이션
  • frp는 서브도메인 라우팅, 토큰 인증, 암호화된 클라이언트·서버 전송을 제공함.
  • Nginx는 공개 TLS를 종료하고 HTTP를 루프백 전용 frp 가상 호스트로 전달함.
  • 이 구성으로 frp 제어 포트와 애플리케이션 트래픽이 서로 다른 경계에 놓임.

코딩 에이전트를 위한 안내

  • 실제 서버에 Portspan을 설정하는 코딩 에이전트는 먼저 AGENTS.md를 읽고 전용 코딩 에이전트 설정 점검표를 따라야 함.
  • 점검표에는 사전 환경 확인, 공식 문서 점검, 안전한 순서, 보고할 증거, 비밀 처리, 롤백 경계가 포함됨.
  • 세부 명령 수준의 실행 절차는 운영 안내서를 사용함.

저장소 구성

  • bin/tunnel — 검증, IPv4·IPv6 로컬 호스트 지원, 호스트 헤더 재작성, 임시 설정 파일을 제공하는 이식 가능한 클라이언트 래퍼임.
  • config/ — 실행 중인 비밀을 포함하지 않는 안전한 설정 예시임.
  • deploy/frps, Nginx, systemd, 인증서 갱신용 템플릿임.
  • scripts/install-client.sh — 버전이 고정되고 체크섬으로 검증되는 frpc 설치 스크립트임.
  • scripts/install-server.sh — 멱등적인 리눅스 frps 설치 스크립트임.
  • scripts/check.sh — 로컬 셸·설정 위생 점검 스크립트임.
  • docs/architecture.md — 구성 요소, 포트, 요청 흐름 문서임.
  • docs/operations.md — 설정, 검증, 문제 해결, 롤백 문서임.
  • docs/security.md — 위협 모델, 비밀 처리, 교체 지침 문서임.

빠른 시작

DNS 준비

  • 기본 도메인을 관리하는 영역에 DNS 전용 에이 레코드 두 개를 생성함.
  • *.tunnel.example.comYOUR_SERVER_PUBLIC_IP
  • control.tunnel.example.comYOUR_SERVER_PUBLIC_IP
  • 같은 이름의 기존 레코드를 교체하지 않음.
  • 특정 레코드는 와일드카드보다 우선하므로 제어 영역과 애플리케이션 이름을 의도적으로 유지함.
  • 자세한 내용은 클라우드플레어의 와일드카드 DNS 문서를 참고함.

서버 설치

  • 지원되는 리눅스 서버에서 루트 권한으로 실행함.
  • 서버 토큰이 아직 없으면 설치 스크립트가 해당 서버에서 토큰을 로컬로 생성함.
  • sudo env TUNNEL_BASE_DOMAIN=tunnel.example.com /path/to/portspan/scripts/install-server.sh
  • 서버가 수신하는 포트는 다음과 같음.
  • 7000/tcp — TLS와 토큰 인증으로 보호되는 frpc 제어 연결임.
  • 127.0.0.1:18080 — Nginx를 통해서만 접근 가능한 HTTP 가상 호스트 트래픽임.
  • 보호된 채널을 통해 서버 토큰을 각 클라이언트로 복사함.
  • 토큰을 깃, 명령 인자, 채팅 메시지에 절대 넣지 않음.
  • 토큰 디렉터리와 파일은 각각 다음 권한으로 설치함.
  • ~/.config/tunnel 디렉터리는 권한 700임.
  • ~/.config/tunnel/token 파일은 권한 600임.

클라이언트 설치

  • ./scripts/install-client.sh로 클라이언트를 설치함.
  • ~/.config/tunnel 디렉터리를 권한 700으로 생성하고 config/client.env.example~/.config/tunnel/config로 복사한 뒤 권한을 600으로 설정함.
  • ~/.config/tunnel/config에 서버 주소와 기본 도메인을 입력함.
  • 토큰은 권한 600~/.config/tunnel/token에 저장한 뒤 다음 명령을 실행함.
  • tunnel --port 3000 --domain app
  • 래퍼의 기본 대상은 로컬 호스트이므로 IPv6 ::1에만 바인딩하는 애플리케이션과 IPv4 127.0.0.1에 바인딩하는 애플리케이션 모두에서 동작함.
  • 백엔드 호스트 헤더는 기본적으로 localhost로 재작성되며, 이를 통해 일반적인 비트·개발 서버 호스트 점검을 피할 수 있음.
  • 필요한 경우 다음과 같이 재정의함.
  • tunnel --port 3000 --domain app --host-header app.local

먼저 HTTP 활성화

  • deploy/nginx-http.conf를 기본 도메인의 Nginx 사이트로 설치하고 활성화함.
  • nginx -t를 실행한 뒤 Nginx를 다시 불러옴.
  • 다음 명령으로 전체 공개 경로를 확인함.
  • curl -v --max-time 15 http://app.tunnel.example.com/

HTTPS 추가

  • 대상 영역으로 범위를 제한한 클라우드플레어 API 토큰을 생성하며 권한은 Zone:ReadDNS:Edit임.
  • 토큰은 docs/security.md에 기록된 루트 소유 경로에만 저장함.
  • deploy/nginx-https.conf를 활성화하기 전에 레고 갱신 유닛을 실행함.
  • 레고 클라우드플레어 DNS 제공자는 와일드카드 인증서에 DNS-01을 사용함.

설계 선택

  • 클라우드플레어 터널은 고정형 인그레스에 탁월하지만, 명령으로 --domain app 흐름을 사용하려면 새 라벨마다 디스패처 또는 제어 영역 갱신이 필요함.
  • Portspan은 frp의 네이티브 서브도메인 라우팅을 사용하므로 각 frpc 프로세스가 하나의 인증된 연결을 통해 자체 라벨을 등록함.
  • 공식 frp HTTP·HTTPS 문서와 사용자 지정 서브도메인 문서를 참고함.

상태와 범위

  • 이 저장소는 의도적으로 도메인 프로비저닝, DNS 레코드 생성, 계정 자격 증명 교체, 비밀 자동 복사를 수행하지 않음.
  • 해당 작업은 환경마다 다르며 운영자 실행 안내서에서 다룸.