You can use FRP! FRP is suitable for scenarios with 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 tech stack (Docker + local service + online website), focusing on configuration standardization, security, and stability:

https://gofrp.org/zh-cn/docs/setup/

1. Core Logic of the FRP Solution

  1. Role Division:
    • “Server side (frps)”: Deployed on an online server (with public IP, such as your website’s server), responsible for receiving public requests and forwarding them;
    • “Client side (frpc)”: Deployed on a local idle computer (running Umami in Docker environment), responsible for forwarding the local Umami service (localhost:3000) to the server side;
    • “Reverse Proxy”: The online server uses Nginx/Caddy to configure HTTPS, redirecting domain requests to the FRP server’s mapped port, avoiding direct exposure of ports.
  2. Data Flow: Online website → Public domain (HTTPS) → Online server Nginx → FRP server → FRP client → Local Umami service.

2. Prerequisites

  1. Online Server:
    • Has a 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 the server’s public IP.
  2. Local Computer:
    • Already deployed Umami via Docker Compose (refer to the previous Docker configuration, ensuring localhost:3000 is accessible);
    • Installed FRP client (consistent version with the server).
  3. Network Permissions:
    • Local computer can access the internet (can connect to the online server’s FRP communication port);
    • Router allows local computer to access externally (no additional port mapping required, as FRP uses active connection mode).

3. Detailed Implementation Steps (Server-side/Client-side/Reverse Proxy)

Step 1: Deploy FRP Server (frps) on Online Server

1.1 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

1.2 Configure FRP Server (frps.ini)

Create/modify frps.ini, core configuration for authentication, ports, and logs to ensure 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 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 disconnection)
tcp_keepalive = 60  # Send heartbeat packets 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  # Automatic 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

1.4 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

2.1 Download FRP (Consistent with Server Version)

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

2.2 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 disconnection)
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 (Depending on System)

Ensure frpc starts automatically after local computer restart:

(1) 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
(2) Windows (Task Scheduler)
  1. 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
    
  2. 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.

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 interception of Umami tracking scripts).

3.1 Apply Free HTTPS Certificate (Let’s Encrypt)

Quickly apply certificate with Certbot (example for Nginx):

# 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/.

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";
}

3.3 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 successful configuration, browser access to the domain should open 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 online website, Umami backend “Realtime” page should show real-time visit data.

4. Key Optimization Configurations (Stability + Security)

4.1 Stability Optimization (Avoid Disconnection/Data Loss)

  1. FRP Connection Keepalive:
    • Both client/server configure tcp_keepalive = 60, send heartbeat packets every 60s to prevent operator disconnection of long connections;
    • Local computer disable sleep/hibernation (refer to previous solution), ensure FRP client continuously runs.
  2. Umami Data Persistence:
    • Ensure Docker Compose’s postgres-data directory is correctly mounted (ls ~/docker/umami/postgres-data should have files);
    • Regularly back up postgres-data directory (e.g., weekly, compress and upload to cloud storage).
  3. 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
      

4.2 Security Optimization (Prevent Unauthorized Access)

  1. FRP Authentication Strengthening:
    • token must be a strong password (≥16 characters, letters + numbers + special characters), avoid leakage;
    • Disable FRP panel (if not needed), or only allow 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)
      
  2. 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”).
  3. Prohibit Direct Access to Port 8080:
    • Server firewall only allows Nginx process access to port 8080, prohibit external direct access (optional, achieved indirectly via Nginx reverse proxy).

5. Common Troubleshooting (Precise Diagnosis)

  1. FRP Client Connection Failure:
    • Check server IP/port: server_addr and server_port are correct, server firewall opens port 7000;
    • Check token consistency: client/server’s token must be exactly the same (case-sensitive);
    • Check network connectivity: local computer execute telnet serverIP 7000 or nc -zv serverIP 7000, confirm port is reachable.
  2. Public Access to Umami Returns 502 Error:
    • Check local Umami service: curl http://localhost:3000 accessible (ensure Docker container running);
    • Check FRP forwarding status: log in FRP panel (https://serverIP:7500), check umami-tcp rule shows “Online”;
    • Check Nginx configuration: proxy_pass points to 127.0.0.1:8080, no typos.
  3. Online Website Data Not Displayed:
    • Check tracking script path: ensure src is https://umami.your-domain.com/analytics.js (consistent with Docker’s TRACKER_SCRIPT_NAME);
    • Check browser console: F12 view “Network” panel, check if analytics.js fails to load (ad blockers may block, temporarily disable testing);
    • Check Umami logs: docker-compose logs -f umami-app for tracking request records.
  4. FRP Connection Unstable (Frequent Disconnection):
    • Enable use_compression = true and use_encryption = true, reduce network fluctuation impact;
    • Adjust tcp_keepalive to 30s, increase heartbeat frequency;
    • Check local network: Wi-Fi may cause disconnections, recommend switching to wired network.

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. By combining “FRP server/client” + “Nginx HTTPS reverse proxy”, you can achieve stable external service provision of local Umami, online website does not need to modify core architecture, only needs to add tracking code for integration.

Key configurations focus on FRP parameter consistency, HTTPS certificate configuration, IP whitelist restrictions, following the above steps ensures stability and security meet long-term personal website usage needs.