Introduction
If you self-host services at home or on a private network, you’ve likely run into the challenge of securely exposing them to the internet. FRP (Fast Reverse Proxy) provides a lightweight, reliable way to tunnel traffic from a public VPS to your internal services without opening inbound ports on your home router. This guide walks you through a minimal, production-friendly setup using systemd on Linux for both the server (frps) and client (frpc).
What you’ll set up
- A public VPS running the FRP server (frps).
- A client machine behind NAT running the FRP client (frpc).
- Persistent services managed by systemd on both sides.
- Example TCP tunnels for Emby and Home Assistant.
Prerequisites
- A Linux VPS with a public IP.
- A Linux client machine in your private network.
- Root/sudo access on both machines.
Installation Steps
Install FRP on your machines
Download the latest release tarball for your architecture from the official repository: https://github.com/fatedier/frp/releases
Example (Linux amd64, v0.65.0):
$ wget https://github.com/fatedier/frp/releases/download/v0.65.0/frp_0.65.0_linux_amd64.tar.gz $ tar -xzvf frp_0.65.0_linux_amd64.tar.gz $ cd frp_0.65.0_linux_amd64 $ sudo mv frp? /usr/bin/ $ sudo mkdir -p /etc/frp && sudo mv *.toml /etc/frp/
This places the binaries (frps
, frpc
) in /usr/bin
and example TOML configs in /etc/frp
.
Configure and run the FRP server (VPS)
Create a systemd unit for the server at /etc/systemd/system/frps.service
with these contents:
[Unit]
Description=FRP Server
After=network.target
[Service]
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frps -c /etc/frp/frps.toml
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
Then load and start the service:
sudo systemctl daemon-reload
sudo systemctl enable frps.service
sudo systemctl start frps.service
Notes:
- Ensure
/etc/frp/frps.toml
exists and defines the server’s bind port (default7000
) and any desired auth/tls options. LimitNOFILE
raises file descriptor limits to handle many connections.
Configure and run the FRP client (home/private machine)
Edit your client config at /etc/frp/frpc.toml
with the address and port of your VPS and the proxies you want to expose. Example:
serverAddr = "example.com"
serverPort = 7000
[[proxies]]
name = "emby" ## Emby
type = "tcp"
localIP = "192.168.1.11"
localPort = 8096
remotePort = 8096
[[proxies]]
name = "ha" ## Home Assistant
type = "tcp"
localIP = "192.168.1.12"
localPort = 8123
remotePort = 8123
This configuration:
- Connects the client to the FRP server at
example.com:7000
. - Exposes two TCP services:
- Emby from
192.168.1.11:8096
mapped to the VPS’s port8096
. - Home Assistant from
192.168.1.12:8123
mapped to the VPS’s port8123
.
- Emby from
Create a systemd unit for the client at /etc/systemd/system/frpc.service
:
[Unit]
Description=FRP Client
After=network.target
[Service]
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frpc -c /etc/frp/frpc.toml
ExecReload=/usr/bin/frpc reload -c /etc/frp/frpc.toml
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
Then enable and start the client:
$ sudo systemctl daemon-reload
$ sudo systemctl enable frpc.service
$ sudo systemctl start frpc.service
You can later apply config changes without downtime using:
$ sudo systemctl reload frpc
Verifying your tunnels
- On the VPS, ensure
frps
is listening (e.g.,sudo ss -lntp | grep frps
or check journal logs). - From the internet, try connecting to the VPS on the mapped
remotePort
values (e.g.,http://example.com:8096
for Emby). - On the client, check logs with:
sudo journalctl -u frpc -f
- On the server, check logs with:
sudo journalctl -u frps -f
Operational tips
- Restart policies: The provided systemd units auto-restart on failure to improve resilience.
- Resource limits:
LimitNOFILE
helps avoid “too many open files” errors under load.
Security considerations (recommended)
- Authentication: Set a token in both
frps.toml
andfrpc.toml
to prevent unauthorized clients from connecting. - TLS: Enable TLS between
frpc
andfrps
where possible to protect traffic in transit (especially important for credentials and cookies). - Principle of least exposure: Only expose the ports you need; prefer HTTP(S) with an authenticated reverse proxy (e.g., Caddy, Nginx) on the VPS for web apps.
- Updates: Keep FRP updated to the latest stable release.
Troubleshooting checklist
- Connectivity: Ensure the client can reach
serverAddr:serverPort
(no outbound firewall blocks). - Port conflicts: Confirm
remotePort
values aren’t already in use on the VPS. - Logs: Use
journalctl
on both sides to inspect connection attempts and errors. - SELinux/AppArmor: If enabled, consider policy adjustments for FRP binaries and config paths.