You can achieve this with FRP! FRP is suitable for scenarios where you have a public IP (local/router or online server). Compared to Cloudflare Tunnel, it's more flexible and controllable, and does not require reliance on third-party domain hosting. Here are the precise, implementable FRP solution details, compatible with your technology stack (Docker + local service + online website), focusing on configuration standardization, security, and stability:
https://gofrp.org/zh-cn/docs/setup/
Core Logic of the FRP Solution
- Role Division:
- "Server (frps)": Deployed on an online server (with public IP, such as your website server), responsible for receiving public requests and forwarding them;
- "Client (frpc)": Deployed on a local idle computer (running Umami in Docker environment), responsible for forwarding the local Umami service (
localhost:3000) to the server; - "Reverse Proxy": The online server uses Nginx/Caddy to configure HTTPS, forwarding domain requests to the FRP server's mapped port, avoiding direct exposure of ports.
- Data Flow: Online website → Public domain (HTTPS) → Online server Nginx → FRP server → FRP client → Local Umami service.
Prerequisites
- Online Server:
- Has public IP, open 3 ports (FRP communication port: e.g., 7000; Umami mapped port: e.g., 8080; optional FRP panel port: e.g., 7500);
- Installed Nginx/Caddy (for HTTPS reverse proxy);
- Has applied a domain name (e.g.,
umami.your-domain.com), and has resolved the domain to this server's public IP.
- Local Computer:
- Already deployed Umami via Docker Compose (refer to the previous Docker configuration, ensuring
localhost:3000is accessible); - Installed FRP client (version consistent with the server).
- Already deployed Umami via Docker Compose (refer to the previous Docker configuration, ensuring
- Network Permissions:
- Local computer can access the internet (can connect to the online server's FRP communication port);
- Router allows local computer to externally access (no additional port mapping required, FRP is active connection mode).
Detailed Implementation Steps (Split into Server/Client/Reverse Proxy)
Step 1: Deploy FRP Server (frps) on Online Server
Download FRP
Choose the latest stable version (recommended v0.50+, to avoid compatibility issues), download the corresponding server architecture (e.g., Linux x86_64):
# Execute on online server (Linux x86_64 example)
wget https://github.com/fatedier/frp/releases/download/v0.52.3/frp_0.52.3_linux_amd64.tar.gz
tar -zxvf frp_0.52.3_linux_amd64.tar.gz
mv frp_0.52.3_linux_amd64 /usr/local/frp
cd /usr/local/frp
Configure FRP Server (frps.ini)
Create/modify frps.ini, core configuration for authentication, ports and logs, ensuring security and monitorability:
[common]
# 1. Basic communication configuration
bind_port = 7000 # FRP client-server communication port (must open server firewall)
token = your_strong_frp_token # Authentication token (must be set, prevent unauthorized connections, recommend ≥16 random characters)
# 2. Optional: FRP management panel (for viewing connection status)
dashboard_port = 7500 # Panel access port
dashboard_user = frp_admin # Panel login username
dashboard_pwd = your_dashboard_password # Panel login password (strong password)
# 3. Log configuration (for problem troubleshooting)
log_file = /var/log/frps.log
log_level = info # Log level: info/warn/error
log_max_days = 7 # Log retention for 7 days
# 4. Connection optimization (reduce disconnections)
tcp_keepalive = 60 # Send heartbeat every 60s
max_pool_count = 5 # Maximum connection pool size
1.3 Configure FRP Server to Start Automatically (System Service)
Create a system service file to ensure frps runs automatically after server restart:
sudo tee /etc/systemd/system/frps.service <<EOF
[Unit]
Description=FRP Server (frps)
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/usr/local/frp
ExecStart=/usr/local/frp/frps -c /usr/local/frp/frps.ini
Restart=always # Auto-restart on failure
RestartSec=5 # Restart interval of 5s
[Install]
WantedBy=multi-user.target
EOF
# Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable frps
sudo systemctl start frps
# Verify status (ensure no errors)
sudo systemctl status frps
Open Server Ports (Firewall)
Example for Ubuntu (ufw), open FRP communication port, mapped port, and panel port:
# Open FRP communication port (7000), Umami mapped port (8080), and panel port (7500)
sudo ufw allow 7000/tcp
sudo ufw allow 8080/tcp
sudo ufw allow 7500/tcp
sudo ufw reload
# Verify port openness
sudo ufw status
Step 2: Deploy FRP Client (frpc) on Local Computer
Download FRP (Version consistent with server)
Download the corresponding version based on local computer system (Linux/macOS/Windows):
# Example: Download for Linux/macOS (x86_64)
wget https://github.com/fatedier/frp/releases/download/v0.52.3/frp_0.52.3_linux_amd64.tar.gz
tar -zxvf frp_0.52.3_linux_amd64.tar.gz
mv frp_0.52.3_linux_amd64 ~/frp # Move to user directory
cd ~/frp
Configure FRP Client (frpc.ini)
Core configuration: connect to server, forward local Umami service, add identity authentication and connection optimization:
[common]
# 1. Server information (must match frps configuration)
server_addr = your online server public IP # e.g., 123.45.67.89
server_port = 7000 # Same as frps's bind_port
token = your_strong_frp_token # Must be exactly the same as frps's token (case-sensitive)
# 2. Log configuration
log_file = ~/frp/frpc.log
log_level = info
log_max_days = 7
# 3. Connection optimization (prevent disconnections)
tcp_keepalive = 60
pool_count = 3
connect_timeout = 30 # Connection timeout of 30s
# 4. Umami service forwarding rules (core)
[umami-tcp] # Rule name (custom, unique)
type = tcp # Protocol type (Umami is HTTP service, use tcp for stability)
local_ip = 127.0.0.1 # Local Umami service IP (Docker mapped to local, so it's 127.0.0.1)
local_port = 3000 # Local Umami service port (same as Docker Compose mapped port)
remote_port = 8080 # Online server exposed port (same as server firewall opened 8080)
use_compression = true # Enable data compression (reduce bandwidth usage)
use_encryption = true # Enable data encryption (prevent eavesdropping)
2.3 Configure FRP Client to Start Automatically (System-specific)
Ensure frpc starts automatically after local computer restart:
Linux/macOS (system service)
# Create system service file (Linux)
sudo tee /etc/systemd/system/frpc.service <<EOF
[Unit]
Description=FRP Client (frpc)
After=network.target docker.service # Wait for network and Docker to start before starting
Requires=docker.service
[Service]
Type=simple
User=jin # Replace with your local username (e.g., jin)
WorkingDirectory=/home/jin/frp # Replace with frpc directory
ExecStart=/home/jin/frp/frpc -c /home/jin/frp/frpc.ini
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable frpc
sudo systemctl start frpc
# Verify status
sudo systemctl status frpc
Windows (Task Scheduler)
- Create a batch file
start_frpc.bat, content:@echo off cd /d "C:\Users\jin\frp" # Replace with frpc directory frpc.exe -c frpc.ini - Open "Task Scheduler" → "Create Basic Task":
- Name:
FRP Client, trigger set to "At startup", action select "Start a program", choose the above batch file; - Check "Run whether the user is logged on or not" and "Run with highest privileges", then test start.
- Name:
### Step 3: Configure Reverse Proxy (HTTPS) on Online Server
After FRP forwarding, the online server's port 8080 is HTTP protocol, needs to configure Nginx/Caddy for HTTPS (to avoid browser blocking Umami tracking scripts).
#### Apply Free HTTPS Certificate (Let's Encrypt)
Use Certbot to quickly apply certificate (example with Nginx):
```bash
# Install Certbot
sudo apt update && sudo apt install certbot python3-certbot-nginx -y
# Apply certificate (replace with your domain)
sudo certbot --nginx -d umami.your-domain.com
The certificate will be automatically saved to /etc/letsencrypt/live/umami.your-domain.com/.
Nginx Configuration (Recommended)
Create Nginx configuration file umami.conf:
server {
listen 80;
server_name umami.your-domain.com;
# Force redirect to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name umami.your-domain.com;
# HTTPS certificate configuration
ssl_certificate /etc/letsencrypt/live/umami.your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/umami.your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; # Only support secure protocols
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# Reverse proxy to FRP mapped port (8080)
location / {
proxy_pass http://127.0.0.1:8080; # Point to local FRP server's remote_port
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # Pass HTTPS protocol identifier
proxy_connect_timeout 60s; # Connection timeout optimization
proxy_read_timeout 60s;
}
# Security headers (prevent XSS, CSRF etc.)
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
}
Start Nginx and Verify
# Check configuration file syntax
sudo nginx -t
# Restart Nginx
sudo systemctl restart nginx
# Verify HTTPS access
curl -I https://umami.your-domain.com
Return 200 OK and Server: nginx indicates the configuration is successful, browser access to this domain should open the Umami login page.
Step 4: Integrate Umami Tracking Code into Online Website
Same as previous solution, log in to Umami backend (https://umami.your-domain.com), copy tracking code, modify script path and add to online website's <head> or <body> tag:
<!-- Replace with your Tracking ID and domain -->
<script async src="https://umami.your-domain.com/analytics.js" data-website-id="Your Tracking ID"></script>
- Verification: Access the online website, Umami backend "Realtime" page should show real-time access data.
Key Optimization Configurations (Stability + Security)
Stability Optimization (Avoid Disconnections/Data Loss)
- FRP Connection Keepalive:
- Both client/server configure
tcp_keepalive = 60, send heartbeat every 60s to prevent operator disconnection of long connections; - Local computer disable sleep/hibernation (refer to previous solution), ensure FRP client continuously runs.
- Both client/server configure
- Umami Data Persistence:
- Ensure Docker Compose's
postgres-datadirectory is correctly mounted (ls ~/docker/umami/postgres-datashould have files); - Regularly back up
postgres-datadirectory (e.g., weekly, compress and upload to cloud storage).
- Ensure Docker Compose's
- FRP Log Monitoring:
- Regularly check server/client logs to troubleshoot disconnection issues:
# Check server log sudo tail -f /var/log/frps.log # Check client log tail -f ~/frp/frpc.log
- Regularly check server/client logs to troubleshoot disconnection issues:
Security Optimization (Prevent Unauthorized Access)
- FRP Authentication Strengthening:
tokenmust be a strong password (≥16 characters, letters + numbers + special characters), avoid leakage;- Disable FRP panel (if not needed) or allow only your IP to access the panel:
# Add panel IP whitelist in frps.ini dashboard_addr = 0.0.0.0 allow_ports = 8080 # Only allow mapped port 8080 (limit port range)
- Umami Backend Access Restriction:
- Nginx configure IP whitelist, only allow your IP to access Umami backend (
/admin/*path):# Add in 443 server block location ^~ /admin/ { allow 你的公网 IP; # e.g., 111.222.333.444 deny all; # Deny other IPs proxy_pass http://127.0.0.1:8080; # Other proxy_set_header configurations as above } - Disable Umami public statistics page ("Settings" → "General" → uncheck "Public Sharing").
- Nginx configure IP whitelist, only allow your IP to access Umami backend (
- Prohibit Direct Access to Port 8080:
- Server firewall only allows Nginx process access to port 8080, prohibit external direct access (optional, already indirectly achieved via Nginx reverse proxy).
Five. Common Problem Troubleshooting (Precise Localization)
- FRP Client Connection Failure:
- Check server IP/port:
server_addrandserver_portare correct, server firewall opens port 7000; - Check token consistency: client/server's
tokenmust be exactly the same (case-sensitive); - Check network connectivity: local computer execute
telnet serverIP 7000ornc -zv serverIP 7000, confirm port is reachable.
- Check server IP/port:
- Public Access to Umami Returns 502 Error:
- Check local Umami service:
curl http://localhost:3000accessible (ensure Docker container running); - Check FRP forwarding status: log in FRP panel (
https://serverIP:7500), checkumami-tcprule shows "Online"; - Check Nginx configuration:
proxy_passpoints to127.0.0.1:8080, no typos.
- Check local Umami service:
- Online Website Data Not Displayed:
- Check tracking script path: ensure
srcishttps://umami.your-domain.com/analytics.js(consistent with Docker'sTRACKER_SCRIPT_NAME); - Check browser console: F12 view "Network" panel, if
analytics.jsfails to load (ad blockers may block, temporarily disable testing); - Check Umami logs:
docker-compose logs -f umami-appcheck for tracking request records.
- Check tracking script path: ensure
- FRP Connection Unstable (Frequent Disconnections):
- Enable
use_compression = trueanduse_encryption = true, reduce network fluctuation impact; - Adjust
tcp_keepaliveto 30s, increase heartbeat frequency; - Check local network: Wi-Fi may cause disconnection, recommend switching to wired network.
- Enable
Summary
The FRP solution fully adapts to your needs, core advantages: Autonomous control (no reliance on third-party tunnel services), low latency (direct forwarding), flexible configuration. Through "FRP server/client" + "Nginx HTTPS reverse proxy" combination, it can realize stable service provision of local Umami, online website does not need to modify core architecture, only needs to add tracking code for integration.
Key focus areas are FRP parameter consistency, HTTPS certificate configuration, IP whitelist restrictions, following the above steps, stability and security can meet long-term usage needs for personal websites.