JetBrains Gateway 远程开发怎么先验收后端服务跑在内网机器上用 cpolar 临时预览接口和页面远程开发最容易卡住的地方不是 IDE 能不能连上而是服务跑起来以后别人怎么验收。我遇到过很多次这种场景代码在公司内网开发机上JetBrains Gateway 连进去写得很舒服接口也能在机器上跑通。但产品、测试、前端同事不在同一个网络里他们只想点开一个地址看看页面、调一下接口、确认这版功能是不是能过。这篇就记录一个比较稳的流程用 JetBrains Gateway 连接远端开发机在内网机器上启动后端服务然后用 cpolar 临时生成 HTTPS 预览地址把接口、Swagger 或前端页面发给同事验收。重点是只开放应用预览端口不开放 SSH、数据库和 IDE 管理入口。适用于谁这套流程适用于下面几类人后端服务跑在办公室内网、家里小主机、测试机或云上私有网段里日常用 IntelliJ IDEA、PyCharm、WebStorm 这类 JetBrains IDE想用 JetBrains Gateway 做远程开发而不是把项目完整拉到本机需要让同事临时验收接口、Swagger、管理页面、前端页面或 Storybook不想为了临时验收去改防火墙、配公网 IP、折腾 Nginx 反代。如果你只是自己本机开发浏览器打开localhost就够了。这篇的价值在于服务在内网机器上验收人在外部网络里两边不在同一个局域网。最终效果跑完之后会得到三层访问关系JetBrains Gateway - 远端开发机 - 后端服务端口 同事浏览器 - cpolar HTTPS 地址 - 远端开发机上的服务端口举个例子后端服务在远端开发机监听8080http://127.0.0.1:8080/health http://127.0.0.1:8080/swagger-ui/index.html通过 cpolar 映射后同事拿到的是类似这样的 HTTPS 地址https://demo-service.cpolar.top/health https://demo-service.cpolar.top/swagger-ui/index.html同事不需要知道 SSH 地址不需要装 JetBrains Gateway也不需要进你的开发环境。他只访问应用预览入口。环境准备我这里用一个最小 Spring Boot 服务做演示Node、Python、Go 后端也一样核心只看端口。准备环境本机安装 JetBrains Gateway远端开发机Linux/macOS 均可能 SSH 登录远端开发机安装 JDK 17 和 Git远端开发机安装 cpolar项目一个能在远端机器启动的后端服务。检查远端机器基础环境java -version git --version curl --version如果你用 Maven 项目确认 Maven 可用mvn -version如果项目自带 Maven Wrapper直接用./mvnw -versioncpolar 安装完成后在远端开发机上检查版本cpolar version登录 cpolar 账号后配置认证 tokencpolar authtoken 你的_authtoken这里的 token 在 cpolar 控制台里获取。配置一次即可后面启动隧道就不用反复登录。JetBrains Gateway 远程开发场景说明JetBrains Gateway 的核心思路很简单IDE 后端跑在远端开发机本地只负责显示界面和输入交互。这和 code-server 那种“浏览器里打开 IDE”不是一类体验。Gateway 更适用于已经习惯 JetBrains 全家桶的人比如 IDEA 写 Java、PyCharm 写 Python、WebStorm 写前端。基本流程是打开 JetBrains Gateway选择SSH连接方式填写远端开发机地址、端口、用户名和认证方式选择远端项目目录选择对应 IDE例如 IntelliJ IDEA等 Gateway 在远端安装 IDE 后端并打开项目。连接成功后你在本地看到的是熟悉的 JetBrains IDE但代码、依赖、构建和服务进程都在远端机器上。这时要分清两件事Gateway 负责开发体验cpolar 负责临时预览应用服务。不要把 JetBrains Gateway 的管理端口、SSH 端口、数据库端口暴露给公网。验收只需要应用端口比如8080、3000、5173、6006。后端服务本地启动进入远端项目目录cd ~/projects/demo-api如果是 Spring Boot 项目用 Maven 启动./mvnw spring-boot:run没有 Maven Wrapper 就用本机 Mavenmvn spring-boot:run启动成功后先在远端开发机上验收一次健康检查curl http://127.0.0.1:8080/actuator/health正常返回类似{status:UP}再检查业务接口curl http://127.0.0.1:8080/api/ping示例返回{message:pong}如果项目提供 Swagger直接在远端浏览器或 Gateway 的端口转发里打开http://127.0.0.1:8080/swagger-ui/index.html如果你是 Node 服务启动命令一般是npm install npm run dev -- --host 0.0.0.0 --port 3000如果你是 Python FastAPIpip install -r requirements.txt uvicorn app.main:app --host 0.0.0.0 --port 8000这里有个细节服务监听127.0.0.1时cpolar 在同一台机器上也能转发服务监听0.0.0.0时更适用于容器和局域网场景。临时验收不要求对局域网开放能被本机访问即可。接口和页面先在开发机验收我做法在开放公网地址之前先做一个内部验收清单。这样发给同事的链接才不会一打开就是 500。接口检查curl -i http://127.0.0.1:8080/health curl -i http://127.0.0.1:8080/api/users?page1 curl -i -X POST http://127.0.0.1:8080/api/login \ -H Content-Type: application/json \ -d {username:demo,password:demo123456}页面检查curl -I http://127.0.0.1:8080/ curl -I http://127.0.0.1:8080/swagger-ui/index.html如果是前后端分离前端开发服务假设跑在5173cd ~/projects/demo-web npm install npm run dev -- --host 0.0.0.0 --port 5173本机先验收curl -I http://127.0.0.1:5173/接口能返回、页面能打开、日志没有明显错误再进入下一步。用 cpolar 临时生成 HTTPS 预览地址现在服务已经在远端开发机上跑起来了。我们只把应用端口临时映射出去。映射后端8080cpolar http 8080终端里会看到类似输出Forwarding https://xxxx.cpolar.top - http://localhost:8080把 HTTPS 地址复制出来拼上接口路径https://xxxx.cpolar.top/health https://xxxx.cpolar.top/swagger-ui/index.html https://xxxx.cpolar.top/api/ping如果要映射前端页面5173另开一个终端窗口cpolar http 5173这样同事就能直接访问前端页面https://yyyy.cpolar.top/如果你希望每次地址固定使用 cpolar 的固定域名能力把隧道写进配置文件。示例# ~/.cpolar/cpolar.yml authtoken: 你的_authtoken tunnels: demo-api: proto: http addr: 8080 bind_tls: true demo-web: proto: http addr: 5173 bind_tls: true启动指定隧道cpolar start demo-api同时启动两个隧道cpolar start demo-api demo-web临时验收时我更喜欢先用cpolar http 8080这种方式简单、直观窗口一关入口就回收。需要多人反复看再配置固定域名。发给同事的验收说明不要只丢一个链接。最好顺手发一段验收说明减少来回沟通。示例本次验收地址 - Swaggerhttps://xxxx.cpolar.top/swagger-ui/index.html - 健康检查https://xxxx.cpolar.top/health - 前端页面https://yyyy.cpolar.top/ 验收范围 1. 登录 demo/demo123456 2. 用户列表分页查询 3. 新建用户表单校验 4. 详情页返回字段展示 说明这是内网开发机的临时预览地址只用于本次验收今晚 22:00 关闭。这种说明很朴素但很有用。对方知道看哪里、测什么、什么时候结束。安全边界只开放应用预览这一步要敲黑板。cpolar 用来做临时应用预览很方便但不要把它用成“什么端口都往公网丢”。我自己的规则是不开放22也就是 SSH不开放 MySQL、PostgreSQL、Redis、MongoDB不开放 JetBrains Gateway、IDE 后端、Docker Socket不开放后台管理端口除非本次验收必须看并且有账号保护不在演示环境里放真实生产数据不把管理员账号、数据库密码、API Key 写在页面上验收结束立刻关闭 cpolar 隧道。如果接口需要登录创建专门的 demo 账号。权限只给本次验收用到的范围不要偷懒拿管理员账号测。如果接口会修改数据准备一份测试库或测试租户。验收入口是公网 HTTPS 地址数据边界一定要想清楚。常见问题和排错1. Gateway 能连上但页面打不开先确认服务端口真的在远端机器监听ss -lntp | grep 8080macOS 上用lsof -iTCP:8080 -sTCP:LISTEN再确认本机 curl 能访问curl -i http://127.0.0.1:8080/health本机都访问不了就先看应用日志不要急着查 cpolar。2. cpolar 地址打开是 502502 通常说明 cpolar 已经收到请求但转发到本地服务失败。检查三件事ps aux | grep cpolar curl -i http://127.0.0.1:8080/health cpolar http 8080如果服务重启后换了端口cpolar 也要映射新端口。3. Swagger 能打开接口请求失败看浏览器控制台和后端日志。常见原因是接口里写死了回调地址、跨域配置或 Cookie 域名。Spring Boot 可以先给验收域名加 CORSregistry.addMapping(/**) .allowedOriginPatterns(https://*.cpolar.top) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true);这里只做法用于测试环境。生产环境要写明确域名不要长期放通通配规则。4. 前端页面打开空白前端开发服务经常有 host 检查。Vite 项目做法这样启动npm run dev -- --host 0.0.0.0 --port 5173如果页面请求后端接口前端环境变量也要指向 cpolar 的后端 HTTPS 地址VITE_API_BASE_URLhttps://xxxx.cpolar.top npm run dev -- --host 0.0.0.0 --port 5173或者在前端开发服务器里配置代理把/api转到本机后端端口。5. 同事说链接一会儿能打开一会儿打不开先看 cpolar 进程是否还在跑再看远端机器是否休眠、网络是否断开。ps aux | grep cpolar curl -I http://127.0.0.1:8080/如果你用的是笔记本当远端开发机把自动休眠关掉。开发机一睡隧道和服务都会断。一个我常用的验收脚本为了少打命令我会在项目里放一个scripts/check-preview.sh#!/usr/bin/env bash set -euo pipefail BASE_URL${1:-http://127.0.0.1:8080} echo check health: ${BASE_URL}/health curl -fsS ${BASE_URL}/health echo echo check ping: ${BASE_URL}/api/ping curl -fsS ${BASE_URL}/api/ping echo echo check swagger: ${BASE_URL}/swagger-ui/index.html curl -fsSI ${BASE_URL}/swagger-ui/index.html | head -n 1本机检查bash scripts/check-preview.sh http://127.0.0.1:8080cpolar 地址检查bash scripts/check-preview.sh https://xxxx.cpolar.top这样能快速确认本地服务没挂公网预览也能转发到正确端口。收尾验收结束关闭公网入口验收结束后别忘了收口。如果你是直接运行cpolar http 8080在对应终端按Ctrl C如果你用的是配置启动cpolar start demo-api找到进程并停止ps aux | grep cpolar pkill -f cpolar start demo-api也可以直接停止所有 cpolar 进程pkill cpolar然后再确认公网地址已经不可访问并把群里的临时链接标记为已关闭。我现在更常用把这套流程写进团队的开发验收文档里Gateway 负责远程写代码服务先在开发机自检通过 cpolar 临时发 HTTPS 预览地址验收完成立刻关闭。它不花哨但能解决很多“我这边跑通了你那边看不到”的尴尬问题。