1. Deploy FRP Server
1.1. Install FRP
Official Repository:FRP
Download the latest program for your operating system and architecture from the Release page. Here, we take linux amd64 as example:
wget
https://github.com/fatedier/frp/releases/download/v0.62.1/frp_0.62.1_linux_amd64.tar.gz
Then we can see:
root@cc:~/download# ls
frp_0.62.1_linux_amd64.tar.gz
Using tar to extract: more indormation about tar
root@cc:~/download# tar -zxvf ./frp_0.62.1_linux_amd64.tar.gz
frp_0.62.1_linux_amd64/
frp_0.62.1_linux_amd64/LICENSE
frp_0.62.1_linux_amd64/frps.toml
frp_0.62.1_linux_amd64/frpc
frp_0.62.1_linux_amd64/frps
frp_0.62.1_linux_amd64/frpc.toml
root@cc:~/download# ls
frp_0.62.1_linux_amd64 frp_0.62.1_linux_amd64.tar.gz
In order to use it conveniently:
root@cc:~/download# mv ./frp_0.62.1_linux_amd64 ./frp
root@cc:~/download# ls
frp frp_0.62.1_linux_amd64.tar.gz
At here, I Recommand you register frp to any bin directory.
Where:
If yo are root user(or with sudo) and would like install app for all users:
root@cc:~/download# cd frp/
root@cc:~/download/frp# mv frpc frps /usr/local/bin/
root@cc:~/download/frp# source ~/.bashrc
root@cc:~/download/frp# which frps
/usr/local/bin/frps
If you are a user without sudo
# Create this folder if it's doesn't exist.
mkdir -p ~/.local/bin
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
Notice: it’s not absolute, installing to $HOME/bin/ is also ok, but before that you need know what you are doning.
Notice: I take .bashrc as example, if your shell is different with me, you have to change it.
firstsnow@cc:~/Download/frp$ ls
frpc frpc.toml frps frps.toml LICENSE
firstsnow@cc:~/Download/frp$ cp frpc frps $HOME/.local/bin/
firstsnow@cc:~/Download/frp$ ls ~/.local/bin/
frpc frps
firstsnow@cc:~/Download/frp$ source ~/.bashrc
firstsnow@cc:~/Download/frp$ which frps
/home/firstsnow/.local/bin/frps
Now, you’ve installed frp successfully.
1.2. Set config file for frps
Set config file at ~/.config/frp for convenient management:
root@cc:~/download/frp# mkdir -p $HOME/.config/frp
root@cc:~/download/frp# cp frps.toml frpc.toml ~/.config/frp/
Edit frps.toml:
bindPort = 7000
# set to your port, default port is 7000
1.3. Run frps at background (Debian/Ubuntu)
NOTE: You need sudo authority.
More information: Run at background
We use systemd to manage our services app.
Now, we need prepare a service file frps.service for systemd:
[Unit]
Description=Frps Service
After=network.target
Wants=network.target
[Service]
Type=simple
WorkingDirectory=$HOME/.config/frp
ExecStart=frps -c $HOME/.config/frp/frps.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
You can use vim or other method write this service file to: /etc/systemd/system/
I offer a general method:
sudo bash -c 'cat > /etc/systemd/system/frps.service << EOF
[Unit]
Description=Frps Service
After=network.target
Wants=network.target
[Service]
Type=simple
WorkingDirectory=$HOME/.config/frp
ExecStart=frps -c $HOME/.config/frp/frps.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF'
Now, you can strat your frps service via:
# set auto start when booting
sudo systemctl enable frps.service
# start service
sudo systemctl start frps.service
1.4. Run frps at background (MacOS)
NOTE: You have no need for sudo authority, that is totally different from linux
The only difference is MacOS doesn’t manage service through systemd
Why MacOS no systemd
More information: click
But we can use launchd:
First, prepare .plist file for launchd:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>wayne.frps.service</string>
<key>ProgramArguments</key>
<array>
<string>frps</string>
<string>-c</string>
<string>$HOME/.config/frp/frps.toml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/log/frps.log</string>
<key>StandardErrorPath</key>
<string>/tmp/log/frps.err</string>
</dict>
</plist>
Note:
- Label name must be unique from all existing services. Therefore, I recommend you name your service after:
[username whoes create this service].[service name].plist. For example:wayne.frps.plist. You absolutely can name your service as you like. - Remember to set a log output path. Different from
Debian/Ubuntu, macOS doesn’t supportsystemd. Set a log path for easier management. I recommend/private/tmp/logor/tmp/logbecause temporary files are cleaned after restart. If logs are important for auditing, store them outsidetmp.
Second, echo your prepared .plist file to ~/Library/LaunchAgents
Note: MacOS’s default shell is zsh
I also offer the smae method:
zsh -c 'cat > ~/Library/LaunchAgents/[service name].plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>wayne.frps.service</string>
<key>ProgramArguments</key>
<array>
<string>frps</string>
<string>-c</string>
<string>$HOME/.config/frp/frps.toml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/log/frps.log</string>
<key>StandardErrorPath</key>
<string>/tmp/log/frps.err</string>
</dict>
</plist>
EOF'
Third, run your service:
launchctl load ~/Library/LaunchAgents/com.example.myservice.plist
If you’d like stop your service:
launchctl unload ~/Library/LaunchAgents/com.example.myservice.plist
1.5. Check your service
Linux
Check status:
systemctl status frps
root@cc:~/.config/frp# systemctl status frps
● frps.service - Frps Service
Loaded: loaded (/etc/systemd/system/frps.service; disabled; preset: enabled)
Active: active (running) since Sun 2025-05-18 21:52:56 CST; 4 days ago
Main PID: 152022 (frps)
Tasks: 4 (limit: 495)
Memory: 13.3M
CPU: 2min 4.976s
CGroup: /system.slice/frps.service
└─152022 /root/workspace/frp/frp/frps -c /root/workspace/frp/frp/frps.toml
Check log:
I recommend to use journalctl to check log output:
journalctl -u frps.service -f
root@cc:~/.config/frp# journalctl -u frps.service -f
May 23 14:25:23 cc.liweijun.online frps[152022]: 2025-05-23 14:25:23.774 [I] [proxy/proxy.go:204] [adda54ea2d549aaa] [file] get a user connection [[::1]:47108]
May 23 14:25:27 cc.liweijun.online frps[152022]: 2025-05-23 14:25:27.894 [I] [proxy/proxy.go:204] [adda54ea2d549aaa] [file] get a user connection [127.0.0.1:59564]
Check port occupation status:
lsof -i:7000
MacOS
Check status:
~ » launchctl list | grep "frp"
PID Status Label
84150 0 wayne.frpc.service
where, PID is a flag for whether the process running successfully, when pid=’-’ and Status=‘1’ means fail to run.
Check log:
Still remember I notice you to set a log output path?
~ tail -n 4 /tmp/log/[name].log
2025/05/23 11:49:21 /api/renew: 401 103.156.242.226 <nil>
2025/05/23 12:00:20 Caught signal terminated: shutting down.
2025/05/23 12:00:20 accept tcp [::]:8090: use of closed network connection
2025/05/23 12:00:33 Listening on [::]:8090
where, -n means number of line you need to print.
2. Deploy FRP Client
2.1. Install FRP
Same as above when installing FRP server.
2.2. Set config file for frpc
Your config file is at ~/.config/frp/frpc.toml, we already set it.
serverAddr = "[your server's public ip or domain]"
serverPort = 7000
# if you change the default server port, remember also change it here
proxies
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 2222
proxies
name = "wordpress"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 8080
proxies
name = "file"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8090
remotePort = 8090
proxies
name = "navidrome"
type = "tcp"
localIP = "127.0.0.1"
localPort = 4533
remotePort = 4533
Note: Avoid reflecting your local 22 port to remote 22 port:
- First, your remote 22 port must have been occupied by sshd.
- Second, for your data safety, 22 port should be hidden.
2.3. Run frpc at background
Register your .plist(MacOS) or .service(Linux) at corresponding location.
Linux:
[Unit]
Description=Frps Service
After=network.target
Wants=network.target
[Service]
Type=simple
WorkingDirectory=$HOME/.config/frp
ExecStart=frpc -c $HOME/.config/frp/frpc.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
MacOS
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>wayne.frps.service</string>
<key>ProgramArguments</key>
<array>
<string>frpc</string>
<string>-c</string>
<string>$HOME/.config/frp/frpc.toml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/log/frps.log</string>
<key>StandardErrorPath</key>
<string>/tmp/log/frps.err</string>
</dict>
</plist>
2.4. Check your service
Same as above.