Skip to content

Commit d439e95

Browse files
dennys246claude
andcommitted
fix(tunnel): prefer /etc/cloudflared/ over ~/.cloudflared/ for config detection
The systemd cloudflared service reads from /etc/cloudflared/config.yml, not ~/.cloudflared/. Flipped detection priority in leader_mode.py and daemon_spawner.py to check /etc/ first. Updated troubleshooting docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1446c8a commit d439e95

3 files changed

Lines changed: 16 additions & 13 deletions

File tree

docs/troubleshooting/remote_update.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ maxim peer restart
7575

7676
**Causes (in order of likelihood):**
7777
1. **Tunnel points at port 8100** (llama-cpp-server) instead of 8099 (LeaderProxy)
78-
- Check on leader: `grep service ~/.cloudflared/config.yml`
78+
- Check on leader: `grep service /etc/cloudflared/config.yml`
7979
- Should say `service: http://localhost:8099`
8080
- Fix: edit config, restart cloudflared
8181
2. **cloudflared not restarted** after config change
8282
- `sudo systemctl restart cloudflared` (Linux/systemd)
83-
- `pkill -f cloudflared && cloudflared --config ~/.cloudflared/config.yml tunnel run &` (WSL2/manual)
83+
- `pkill -f cloudflared && cloudflared --config /etc/cloudflared/config.yml tunnel run &` (WSL2/manual)
8484
3. **LeaderProxy didn't start** — port 8099 held by stale process
8585
- Check on leader: `ss -ltnp | grep 8099`
8686
- Restart maxim
@@ -95,7 +95,7 @@ maxim peer restart
9595

9696
**Fix:** Leaders in leader mode auto-enable this. If it's still disabled:
9797
- Leader may not be detected as leader. Check: `maxim doctor` → Role section
98-
- Need either `MAXIM_ROLE=leader` env var or `~/.cloudflared/config.yml` present
98+
- Need either `MAXIM_ROLE=leader` env var or `/etc/cloudflared/config.yml` present
9999
- Explicitly: `MAXIM_ALLOW_REMOTE_UPDATE=1 maxim`
100100

101101
### HTTP 409 — Dirty working tree

src/maxim/runtime/leader_mode.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
88
Signals, in priority order:
99
1. MAXIM_ROLE env var (explicit) → "leader" | "client" | "solo"
10-
2. ~/.cloudflared/config.yml exists → leader (implicit)
11-
3. default → "solo"
10+
2. /etc/cloudflared/config.yml exists → leader (implicit, systemd)
11+
3. ~/.cloudflared/config.yml exists → leader (implicit, user-space)
12+
4. default → "solo"
1213
1314
The leader distinction only changes bind semantics and peer advertising —
1415
the process itself is still a normal Maxim instance with its own CLI + loop.
@@ -46,11 +47,13 @@ def _env_role() -> str | None:
4647
def _cloudflared_config_exists() -> Path | None:
4748
"""Return the path to cloudflared's config.yml if present.
4849
49-
Checks ~/.cloudflared/config.yml and /etc/cloudflared/config.yml.
50+
Prefers /etc/cloudflared/ (systemd service, production) over
51+
~/.cloudflared/ (user-space, development). The systemd service
52+
reads from /etc/, so that's the authoritative location.
5053
"""
5154
candidates = [
52-
Path.home() / ".cloudflared" / "config.yml",
5355
Path("/etc/cloudflared/config.yml"),
56+
Path.home() / ".cloudflared" / "config.yml",
5457
]
5558
for path in candidates:
5659
try:

src/maxim/tunnel/daemon_spawner.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ def cloudflared_already_running() -> bool:
4949
def resolve_config_path() -> Path | None:
5050
"""Return the cloudflared config path to pass to --config.
5151
52-
Prefers the user-space config (~/.cloudflared/config.yml, the path
53-
`maxim tunnel setup` writes) over the system-wide one, so the daemon
54-
uses the same credentials file referenced by the user's config.
55-
Falls through to /etc/cloudflared/config.yml if only that exists.
52+
Prefers /etc/cloudflared/config.yml (system-wide, used by the
53+
systemd service) over ~/.cloudflared/config.yml (user-space).
54+
The systemd service is the authoritative tunnel process — its
55+
config must match what we expect.
5656
"""
57-
if USER_CONFIG_PATH.is_file():
58-
return USER_CONFIG_PATH
5957
if SYSTEM_CONFIG_PATH.is_file():
6058
return SYSTEM_CONFIG_PATH
59+
if USER_CONFIG_PATH.is_file():
60+
return USER_CONFIG_PATH
6161
return None
6262

6363

0 commit comments

Comments
 (0)