<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MoonProxyHQ</title>
    <description>The latest articles on DEV Community by MoonProxyHQ (moonproxyhq).</description>
    <link>https://dev.to/moonproxyhq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F13913%2F9a901b06-3edf-4230-ac2c-3d6f27259c96.png</url>
      <title>DEV Community: MoonProxyHQ</title>
      <link>https://dev.to/moonproxyhq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moonproxyhq"/>
    <language>en</language>
    <item>
      <title>How to Put a Local Service on the Public Internet with FRP (Without Losing Your Mind Over Config Files)</title>
      <dc:creator>ChenXX</dc:creator>
      <pubDate>Wed, 08 Jul 2026 12:10:52 +0000</pubDate>
      <link>https://dev.to/moonproxyhq/how-to-put-a-local-service-on-the-public-internet-with-frp-without-losing-your-mind-over-config-1o4m</link>
      <guid>https://dev.to/moonproxyhq/how-to-put-a-local-service-on-the-public-internet-with-frp-without-losing-your-mind-over-config-1o4m</guid>
      <description>&lt;p&gt;The problem every self-hoster hits&lt;/p&gt;

&lt;p&gt;You built something. A local API. A Minecraft world for your friends. A self-hosted dashboard. An ERP running on the office machine. It works great — on your LAN.&lt;/p&gt;

&lt;p&gt;The moment you want someone outside to reach it, the fun begins:&lt;/p&gt;

&lt;p&gt;Port forwarding? Good luck if you're behind CGNAT, a corporate firewall, or an ISP that doesn't give you a public IP.&lt;br&gt;
VPN? Now every person who wants access has to install a client, join a network, and stay connected. Overkill for "let me show you this one page."&lt;br&gt;
Cloud deploy? Now you're maintaining two environments, paying for a VPS you didn't need, and shipping data somewhere it doesn't have to live.&lt;/p&gt;

&lt;p&gt;What most people actually want is simpler: take this one local port, give it a public address, done.&lt;/p&gt;

&lt;p&gt;That's exactly what FRP does.&lt;/p&gt;

&lt;p&gt;What FRP is&lt;/p&gt;

&lt;p&gt;FRP (Fast Reverse Proxy) is an open-source tool by fatedier that exposes a local service behind a NAT or firewall to the public internet. It's battle-tested, written in Go, and has been the go-to answer in self-hosting communities for years.&lt;/p&gt;

&lt;p&gt;The model is clean — two pieces:&lt;/p&gt;

&lt;p&gt;frps (the server) — runs on a machine with a public IP (a $5 VPS is plenty).&lt;br&gt;
frpc (the client) — runs on your local machine, the one with the service you want to expose.&lt;/p&gt;

&lt;p&gt;The client opens an outbound tunnel to the server. The server listens on a public port and forwards traffic back through the tunnel. NAT and firewalls don't matter because the connection is initiated from inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Visitor] → [frps on public VPS:7000] ⇄ tunnel ⇄ [frpc on your laptop] → [localhost:8080]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole idea. It works for TCP, UDP, HTTP, HTTPS. People run Minecraft servers, remote desktops, internal dashboards, and dev previews through it every day.&lt;/p&gt;

&lt;p&gt;The catch: config files&lt;/p&gt;

&lt;p&gt;FRP works great. The friction isn't the protocol — it's the workflow.&lt;/p&gt;

&lt;p&gt;To run frpc, you write a TOML config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;serverAddr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"203.0.113.10"&lt;/span&gt;
&lt;span class="py"&gt;serverPort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7000&lt;/span&gt;
&lt;span class="py"&gt;auth.token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"your-secret-key"&lt;/span&gt;

&lt;span class="nn"&gt;[[proxies]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"my-web"&lt;/span&gt;
&lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"tcp"&lt;/span&gt;
&lt;span class="py"&gt;localIP&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
&lt;span class="py"&gt;localPort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;span class="py"&gt;remotePort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you launch it from a terminal. Change a port? Edit the file, restart the process. Add a second tunnel? Edit again, restart again. Want to know if it's actually working? Check the terminal output — or don't, because you closed that tab two hours ago.&lt;/p&gt;

&lt;p&gt;This is fine if you live in the terminal. It's a wall for everyone else — a small-business owner running an ERP, a parent hosting Minecraft for their kid, a designer sharing a local mockup.&lt;/p&gt;

&lt;p&gt;MoonProxy: a GUI for FRP&lt;/p&gt;

&lt;p&gt;&lt;a href="https://moonproxy.app" rel="noopener noreferrer"&gt;MoonProxy&lt;/a&gt; is an MIT-licensed desktop client for FRP. It wraps frpc in a GUI so you don't have to touch config files or terminals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it adds over plain frpc:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Form-based tunnel config&lt;/strong&gt; — no toml/ini files. Add a tunnel like filling out a form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-click start/stop&lt;/strong&gt; — a toggle button with real connection state, derived from frpc output (not an optimistic flag).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint health polling every 3s&lt;/strong&gt; — catches a dead local service before your users do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System tray resident&lt;/strong&gt; — close the window, the tunnel keeps running. Launch at login, silent start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled tunnels&lt;/strong&gt; — set weekday + time window. Hot-reloaded, no restart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engine self-update&lt;/strong&gt; — pulls new frpc from upstream FRP releases, SHA256-verifies, atomically swaps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built with &lt;strong&gt;Tauri v2 + Vue 3 + Rust + TypeScript&lt;/strong&gt;. The frpc binary is bundled via Tauri sidecar — no separate FRP install. macOS (Apple Silicon + Intel) and Windows x64.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You bring your own frps&lt;/strong&gt; (self-hosted VPS or a community node you trust). MoonProxy only manages the client side — it doesn't relay your traffic through any third-party infrastructure. Auth key stays with you.&lt;/p&gt;

&lt;p&gt;It's independent of fatedier/frp — that project deserves all the credit for the protocol. This is just a GUI layer.&lt;/p&gt;

&lt;p&gt;Getting started&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download from &lt;a href="https://moonproxy.app" rel="noopener noreferrer"&gt;moonproxy.app&lt;/a&gt; or &lt;a href="https://github.com/MoonProxyHQ/moonproxy-desktop/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt; (DMG for macOS, EXE for Windows).&lt;/li&gt;
&lt;li&gt;On macOS first launch, right-click → Open, or run &lt;code&gt;xattr -cr "/Applications/MoonProxy Desktop.app"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set up your frps on a VPS (plenty of community tutorials exist).&lt;/li&gt;
&lt;li&gt;Open MoonProxy, add a tunnel, click start.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. Your local service now has a public address.&lt;/p&gt;

&lt;p&gt;Project links&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://moonproxy.app" rel="noopener noreferrer"&gt;moonproxy.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source&lt;/strong&gt;: &lt;a href="https://github.com/MoonProxyHQ/moonproxy-desktop" rel="noopener noreferrer"&gt;github.com/MoonProxyHQ/moonproxy-desktop&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License&lt;/strong&gt;: MIT, permanently free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not trying to replace the CLI — if you're happy scripting frp, keep doing that. This is for folks who want a tray icon and a toggle instead of a terminal window.&lt;/p&gt;

&lt;p&gt;Happy to answer questions in the comments!&lt;/p&gt;

</description>
      <category>frp</category>
      <category>selfhosting</category>
      <category>opensource</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
