How to Use frp Client Plugins for HTTP Proxy and Static File Serving

frp client plugins enable the frpc binary to tunnel traffic through upstream HTTP proxies and serve local directories as static web servers without installing separate software like Nginx or Squid.

The fatedier/frp repository ships with a built-in client-side plugin system that extends frpc beyond raw TCP/UDP forwarding. By configuring these plugins in your TOML configuration files, you can route connections through corporate HTTP proxies or expose filesystem directories via HTTP directly from the client host.

How frp Client Plugins Work

The plugin architecture in frp follows a strict registration and implementation pattern defined in the source code.

Plugin Type Registration

When frpc parses its configuration, it maps plugin type strings to concrete Go structs using the clientPluginOptionsTypeMap defined in [pkg/config/v1/proxy_plugin.go](https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy_plugin.go). This registry links the user-facing type field to the appropriate options structure:

var clientPluginOptionsTypeMap = map[string]reflect.Type{
    PluginHTTPProxy:        reflect.TypeOf(HTTPProxyPluginOptions{}),
    PluginStaticFile:       reflect.TypeOf(StaticFilePluginOptions{}),
    // …
}

Configuration Unmarshalling

Each plugin type has a dedicated options struct that defines valid configuration fields. The HTTPProxyPluginOptions and StaticFilePluginOptions structs, also located in [pkg/config/v1/proxy_plugin.go](https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy_plugin.go), specify the JSON/TOML keys available to users:

type HTTPProxyPluginOptions struct {
    Type         string `json:"type,omitempty"`
    HTTPUser     string `json:"httpUser,omitempty"`
    HTTPPassword string `json:"httpPassword,omitempty"`
}

type StaticFilePluginOptions struct {
    Type         string `json:"type,omitempty"`
    LocalPath    string `json:"localPath,omitempty"`
    StripPrefix  string `json:"stripPrefix,omitempty"`
    HTTPUser     string `json:"httpUser,omitempty"`
    HTTPPassword string `json:"httpPassword,omitempty"`
}

Runtime Implementation

During client startup, frpc instantiates the plugin implementation based on the configured type. The http_proxy logic resides in [pkg/plugin/client/http_proxy.go](https://github.com/fatedier/frp/blob/dev/pkg/plugin/client/http_proxy.go), while the static_file logic is in [pkg/plugin/client/static_file.go](https://github.com/fatedier/frp/blob/dev/pkg/plugin/client/static_file.go). Both satisfy the ClientPlugin interface, intercepting inbound connections from the frps server to perform proxy negotiation or HTTP file serving before forwarding data.

Configuring the HTTP Proxy Plugin

The http_proxy plugin routes frpc's outbound traffic through an upstream HTTP, HTTPS, SOCKS5, or NTLM proxy. This is essential for environments where direct internet access is blocked and all traffic must traverse a corporate proxy server.

Add the plugin to your frpc.toml by defining a TCP proxy with a nested [proxies.plugin] table:

[[proxies]]
name = "http_proxy"
type = "tcp"
remotePort = 6000

[proxies.plugin]
type = "http_proxy"
httpUser = "proxy_username"
httpPassword = "proxy_password"
  • Set the upstream proxy address via the transport.proxyURL field in your client configuration or the http_proxy environment variable.
  • The httpUser and httpPassword fields map to HTTPUser and HTTPPassword in HTTPProxyPluginOptions, providing credentials for proxy authentication.
  • When active, frpc forwards all traffic arriving at remotePort through the configured upstream proxy before reaching the final destination.

Configuring the Static File Plugin

The static_file plugin transforms frpc into a lightweight HTTP file server, exposing a local directory to the internet without requiring Apache or Nginx.

Configure the plugin in frpc.toml by specifying the directory path and optional access controls:

[[proxies]]
name = "static_file"
type = "tcp"
remotePort = 6006

[proxies.plugin]
type = "static_file"
localPath = "/var/www/blog"
stripPrefix = "static"
httpUser = "admin"
httpPassword = "secret"
  • localPath: Required. Specifies the absolute path to the directory on the client machine that will be served.
  • stripPrefix: Optional. Removes the specified prefix from the request URL before mapping to the filesystem (e.g., requesting /static/file.txt serves /var/www/blog/file.txt when stripPrefix = "static").
  • httpUser and httpPassword: Optional. Enables HTTP Basic Authentication, prompting browsers for credentials before serving files.

When frpc runs with this configuration, visiting http://<frps_host>:6006/static/ serves the contents of /var/www/blog on the client host.

Summary

Frequently Asked Questions

Can I use multiple frp client plugins in a single frpc instance?

Yes. Each [[proxies]] block in your configuration is independent. You can define one proxy using the http_proxy plugin and another using the static_file plugin within the same frpc.toml file, and frpc will initialize both plugins during startup according to the clientPluginOptionsTypeMap logic.

Does the HTTP proxy plugin support SOCKS5 or NTLM authentication?

Yes. The implementation in pkg/plugin/client/http_proxy.go handles negotiation with upstream HTTP proxies, SOCKS5 proxies, and NTLM proxies. You provide credentials via the httpUser and httpPassword fields in the plugin configuration, which correspond to the HTTPUser and HTTPPassword fields in the source struct.

How do I remove URL path prefixes when serving static files?

Use the stripPrefix parameter in your static_file plugin configuration. This field in StaticFilePluginOptions tells the plugin to remove the specified prefix from the incoming request path before resolving it against the localPath directory. For example, with stripPrefix = "docs" and localPath = "/files", a request to /docs/readme.txt serves /files/readme.txt.

Where are the plugin options defined in the frp source code?

Plugin option structs are defined in [pkg/config/v1/proxy_plugin.go](https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy_plugin.go). The HTTPProxyPluginOptions and StaticFilePluginOptions structs specify the available configuration fields (such as localPath, stripPrefix, httpUser, and httpPassword) and are mapped to type strings via the clientPluginOptionsTypeMap variable.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →