Fix: Support remote NPM (NPM on different machine)

Changes:

- Updated portainer-stack.yml - npm-network commented out by default

- Updated docker-compose.yml - exposes ports on host for remote NPM

- Added REMOTE_NPM.md with configuration guide for remote NPM setup

- Added Cloudflare Tunnel as alternative option

- Added Tailscale/WireGuard mesh option

Ports 7575 and 3001 now accessible from other machines for NPM proxy
This commit is contained in:
Roberth Rajala 2026-02-03 10:55:35 +01:00
parent 3ca7d4407e
commit 21e80ab883
3 changed files with 202 additions and 26 deletions

157
REMOTE_NPM.md Normal file
View File

@ -0,0 +1,157 @@
# 🌐 Remote NPM Configuration Guide
Your NPM is on a different machine. Here are your options:
## Option 1: NPM → Host IP (Recommended)
Since ports are exposed on the host, configure NPM to proxy to this machine's IP.
### Step 1: Find This Machine's IP
```bash
# On the Homarr machine
ip addr show | grep "inet " | head -5
# or
hostname -I
```
Example: `192.168.1.50`
### Step 2: Configure NPM
In your NPM (on the other machine), add these Proxy Hosts:
#### Dashboard (Homarr)
| Setting | Value |
|---------|-------|
| Domain Names | `dashboard.lemonlink.eu` |
| Scheme | `http` |
| Forward Hostname/IP | `192.168.1.50` (Homarr machine IP) |
| Forward Port | `7575` |
| Cache Assets | ✅ |
| Block Common Exploits | ✅ |
#### System Monitor (Dash.)
| Setting | Value |
|---------|-------|
| Domain Names | `system.lemonlink.eu` |
| Scheme | `http` |
| Forward Hostname/IP | `192.168.1.50` (Homarr machine IP) |
| Forward Port | `3001` |
**SSL Tab:** Request SSL certificate, Force SSL ✅
### Step 3: Firewall
Ensure the Homarr machine allows connections from NPM machine:
```bash
# On Homarr machine (if using UFW)
sudo ufw allow from NPM_MACHINE_IP to any port 7575
sudo ufw allow from NPM_MACHINE_IP to any port 3001
# Or allow from local network
sudo ufw allow from 192.168.1.0/24 to any port 7575
sudo ufw allow from 192.168.1.0/24 to any port 3001
```
---
## Option 2: Cloudflare Tunnel (No NPM Needed)
If you don't want to use NPM at all, use Cloudflare Tunnel:
### Step 1: Create Tunnel in Cloudflare
1. Go to [Cloudflare Zero Trust](https://one.dash.cloudflare.com)
2. Access → Tunnels → Create Tunnel
3. Choose **Cloudflared**
4. Name: `homarr-tunnel`
5. Copy the **token** (looks like: `eyJh...`)
### Step 2: Configure Stack
Edit `portainer-stack.yml`:
1. Uncomment the `cloudflared` service section
2. Add tunnel token to environment variables
### Step 3: Add Public Hostnames
In Cloudflare dashboard, add:
| Public Hostname | Service |
|-----------------|---------|
| `dashboard.lemonlink.eu` | `http://homarr:7575` |
| `system.lemonlink.eu` | `http://dash:3001` |
---
## Option 3: Tailscale/WireGuard Mesh
If both machines are on Tailscale:
1. Find Homarr machine's Tailscale IP: `tailscale ip -4`
2. Use that IP in NPM instead of LAN IP
3. More secure - encrypted tunnel
---
## 🔒 Security Considerations
### With Remote NPM
- Use firewall rules to restrict port access
- Consider VPN/Tailscale between machines
- Don't expose ports 7575/3001 to internet directly
### Recommended: Bind to Specific Interface
If you want to be extra secure, edit `portainer-stack.yml`:
```yaml
ports:
- '127.0.0.1:7575:7575' # Only localhost (need reverse proxy on same machine)
# OR
- '10.0.0.5:7575:7575' # Bind to specific internal IP only
```
---
## ✅ Checklist
- [ ] Find Homarr machine IP
- [ ] Add Proxy Hosts in NPM
- [ ] Configure firewall rules
- [ ] Test access via domain
- [ ] Enable SSL certificates
---
## 🆘 Troubleshooting
### Connection refused from NPM
```bash
# On Homarr machine, check if ports are listening
ss -tlnp | grep -E '7575|3001'
# Check if binding to all interfaces or just localhost
docker inspect homarr | grep -A 5 "Ports"
```
### Firewall blocking
```bash
# Check UFW status
sudo ufw status verbose
# Check iptables
sudo iptables -L -n | grep 7575
```
### Wrong IP in NPM
Make sure you're using the IP that's reachable from the NPM machine:
- Same LAN: Use local IP (192.168.x.x)
- Different networks: Use Tailscale IP or VPN IP

View File

@ -3,6 +3,10 @@
# Storage: /opt/homarr #
# Repo: git.lemonlink.eu/impulsivefps/homarr-dashboard #
#======================================================================#
#
# FOR REMOTE NPM: Ports are exposed on host IP for NPM to reach
# FOR LOCAL NPM: Uncomment npm-network lines
#
services:
homarr:
@ -18,10 +22,11 @@ services:
- AUTH_PROVIDERS=${AUTH_PROVIDERS:-credentials}
- NODE_ENV=production
ports:
- '${HOMARR_PORT:-7575}:7575'
- '7575:7575' # Exposed for remote NPM or direct access
networks:
- homarr-network
- npm-network
# Uncomment if NPM is on SAME machine:
# - npm-network
depends_on:
- dash
@ -45,10 +50,11 @@ services:
- DASHDOT_RAM_LABEL_LIST=brand,size,type,frequency
- DASHDOT_NETWORK_LABEL_LIST=type,speed_up,speed_down,interface_speed
ports:
- '${DASH_PORT:-3001}:3001'
- '3001:3001' # Exposed for remote NPM or direct access
networks:
- homarr-network
- npm-network
# Uncomment if NPM is on SAME machine:
# - npm-network
watchtower:
container_name: watchtower
@ -68,5 +74,6 @@ services:
networks:
homarr-network:
driver: bridge
npm-network:
external: true
# Uncomment if NPM is on SAME machine:
# npm-network:
# external: true

View File

@ -1,16 +1,14 @@
#======================================================================#
# Portainer Stack - Homarr Dashboard #
# Repo: git.lemonlink.eu/impulsivefps/homarr-dashboard #
# Storage: /opt/homarr #
#======================================================================#
#
# Deploy instructions:
# 1. In Portainer: Stacks → Add Stack
# 2. Name: homarr
# 3. Copy this file to Web Editor
# 4. Ensure /opt/homarr directory exists on host
# 5. Deploy the stack
#
# Storage location: /opt/homarr
# DEPLOY OPTIONS:
# Option A: With NPM on same machine - uncomment npm-network lines
# Option B: NPM on different machine - use host ports (default)
# Option C: Cloudflare Tunnel - use cloudflared sidecar
#
#------------------------------------------------------------------#
version: '3.8'
@ -32,14 +30,14 @@ services:
- AUTH_PROVIDERS=${AUTH_PROVIDERS:-credentials}
- NODE_ENV=production
ports:
# Expose on host for remote NPM or direct access
- '7575:7575'
networks:
- homarr-network
- npm-network # Connect to NPM for reverse proxy
# Uncomment if NPM is on SAME machine:
# - npm-network
depends_on:
- dash
labels:
- "com.homarr.description=Homarr Dashboard"
#------------------------------------------------------------------#
# Dash. - System Monitoring #
@ -64,12 +62,12 @@ services:
- DASHDOT_RAM_LABEL_LIST=brand,size,type,frequency
- DASHDOT_NETWORK_LABEL_LIST=type,speed_up,speed_down,interface_speed
ports:
# Expose on host for remote NPM or direct access
- '3001:3001'
networks:
- homarr-network
- npm-network
labels:
- "com.homarr.description=System Monitor"
# Uncomment if NPM is on SAME machine:
# - npm-network
#------------------------------------------------------------------#
# Watchtower - Auto-update containers #
@ -84,16 +82,30 @@ services:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_POLL_INTERVAL=${WATCHTOWER_INTERVAL:-86400}
- WATCHTOWER_INCLUDE_STOPPED=true
- WATCHTOWER_LABEL_ENABLE=true # Only update containers with specific label
- WATCHTOWER_LABEL_ENABLE=true
command: --interval ${WATCHTOWER_INTERVAL:-86400}
networks:
- homarr-network
labels:
- "com.centurylinklabs.watchtower.enable=true"
#------------------------------------------------------------------#
# (OPTIONAL) Cloudflare Tunnel - For external access without NPM #
#------------------------------------------------------------------#
# Uncomment this section to use Cloudflare Tunnel instead of NPM
#
# cloudflared:
# container_name: homarr-cloudflared
# image: cloudflare/cloudflared:latest
# restart: unless-stopped
# command: tunnel --no-autoupdate run --token ${CF_TUNNEL_TOKEN}
# networks:
# - homarr-network
# depends_on:
# - homarr
# - dash
networks:
homarr-network:
driver: bridge
npm-network:
external: true # Created by Nginx Proxy Manager
name: npm-network
# Uncomment if NPM is on SAME machine:
# npm-network:
# external: true