Dev Tunnels (Self-hosted ngrok) β
We run a self-hosted tunneling service that exposes your local dev servers to the internet via HTTPS. This replaces ngrok.
How it works β
localhost:5173 β frpc (your machine) β frps (GCP VM) β https://yourname.dev.review-time.info- frps (server) runs on a GCP VM with Caddy for automatic HTTPS (Let's Encrypt wildcard certificate)
- frpc (client) runs on your machine and creates a tunnel to the server
- Each dev gets unique subdomains under
*.dev.review-time.info
Setup β
1. Install frpc β
brew install frpc2. Create your config β
Copy the example config from the repo root:
cp frpc.example.toml frpc.tomlEdit frpc.toml:
- Replace
yournamewith your first name (e.g.vincent,alex) - Adjust
localPortto match your dev server
3. Set your auth token β
Ask a team member for the FRP token, then export it:
export FRP_TOKEN="the-shared-token"TIP
Add this to your ~/.zshrc so you don't have to export it every time:
echo 'export FRP_TOKEN="the-shared-token"' >> ~/.zshrc4. Start the tunnel β
frpc -c frpc.tomlYour local server is now available at your personal tunnel URL.
How to construct your URL β
Your tunnel URL follows this pattern:
https://{yourname}.dev.review-time.info/For example, if your name is Vincent, your URL is:
https://vincent.dev.review-time.info/Multiple proxies β
You can expose multiple local services at once. Add more [[proxies]] blocks to your frpc.toml:
[[proxies]]
name = "vincent-front"
type = "http"
localPort = 5173
subdomain = "vincent"
[[proxies]]
name = "vincent-api"
type = "http"
localPort = 3000
subdomain = "vincent-api"
[[proxies]]
name = "vincent-mobile"
type = "http"
localPort = 8081
subdomain = "vincent-mobile"Each subdomain must be unique across the team. Convention: {yourname}-{service}.
Infrastructure details β
For maintainers who need to manage the server.
Server location β
- GCP project:
tell-ia-dev - VM:
frp-tunnelineurope-west1-b - IP:
34.62.32.239(remember to reserve it so it doesn't change)
SSH into the server β
gcloud compute ssh frp-tunnel --zone=europe-west1-bServices β
All services run in /opt/frp/ via Docker Compose:
| Service | Role |
|---|---|
| frps | FRP server β accepts client connections on port 7000, serves HTTP on port 8080 |
| caddy | Reverse proxy β handles HTTPS (port 443) with auto Let's Encrypt wildcard cert, forwards to frps |
Common operations β
cd /opt/frp
# Check status
docker compose ps
# View logs
docker compose logs -f caddy
docker compose logs -f frps
# Restart after config change
docker compose restart frps # if frps.toml changed
docker compose restart caddy # if Caddyfile changed
# Full restart
docker compose down && docker compose up -dConfig files on the server β
| File | Purpose |
|---|---|
frps.toml | FRP server config (port, auth token, subdomain host) |
Caddyfile | Caddy reverse proxy + TLS config |
.env | AWS credentials for Route 53 DNS challenge |
Dockerfile.caddy | Custom Caddy build with Route 53 DNS plugin |
docker-compose.yml | Orchestrates frps + caddy |
DNS β
Two A records in AWS Route 53 (hosted zone review-time.info):
| Record | Value |
|---|---|
dev.review-time.info | 34.62.32.239 |
*.dev.review-time.info | 34.62.32.239 |
Changing the auth token β
- Generate a new token:
openssl rand -hex 32 - Update
frps.tomlon the server docker compose restart frps- Share the new token with the team