Inspector 0.9.1: guide explains VPN apps and Portainer setup; dependency and token fixes

This commit is contained in:
Europium 63 committed 2026-10-28 00:30:40 -07:00
1 parent bd78835f4a
commit d3969d74f9
8 files changed
+206 -35

No files matched your search

+27
View File
@@ -7,6 +7,33 @@ Version numbers follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html
--- ---
## [0.9.1] — 2026-10-28
### Fixed
- **A dependency on a disabled container no longer blocks recovery forever.** If
`depends_on` named a container that is disabled in Inspector, the dependent app was
never restarted. Inspector now only waits for dependencies it is watching, and the
container page warns when the selected dependency is disabled.
- **`PORTAINER_API_TOKEN` now reaches the container.** The public `compose.yml` didn't
pass it in, so setting it as a Portainer stack variable had no effect. Existing
stacks need the line `- PORTAINER_API_TOKEN=${PORTAINER_API_TOKEN:-}` added under
`environment:` (Stacks → inspector → Editor).
- The "depends_on … is disabled or not found" warning was logged on every check
(since 0.8.0). It is now logged once, and again only when the container settings
change.
### Changed
- Guide: new sections **6. Apps behind a VPN container** (why depends_on matters, how to
spot a VPN-routed app, setup, what Inspector does) and **7. Portainer stack redeploy**
(why it's needed, what a redeploy does to the whole stack, requirements, where to find
every value, adding the token, the other settings, Test connection errors).
- Clearer form hints: `vpn_routed` only affects logging; `depends_on` works for any
dependency; where to find the endpoint ID.
---
## [0.9.0] — 2026-10-28 ## [0.9.0] — 2026-10-28
### Added ### Added
+1
View File
@@ -56,6 +56,7 @@ TZ=America/Los_Angeles
| `INSPECTOR_PORT` | Port on your server for the dashboard. Change it if `8080` is taken. | No (default `8080`) | | `INSPECTOR_PORT` | Port on your server for the dashboard. Change it if `8080` is taken. | No (default `8080`) |
| `INSPECTOR_TAG` | Version to run, e.g. `0.8.0`. See [Updating](#4-updating). | No (default `latest`) | | `INSPECTOR_TAG` | Version to run, e.g. `0.8.0`. See [Updating](#4-updating). | No (default `latest`) |
| `PUID` / `PGID` | User and group that own Inspector's files. Unraid users often use `99` / `100` so the files match other appdata. | No (default `1000` / `1000`) | | `PUID` / `PGID` | User and group that own Inspector's files. Unraid users often use `99` / `100` so the files match other appdata. | No (default `1000` / `1000`) |
| `PORTAINER_API_TOKEN` | A Portainer access token. Only needed if you use **Portainer stack redeploy** for VPN-routed apps; see the in-app guide (Help → Portainer). | No |
## 3. Deploy and sign in ## 3. Deploy and sign in
+3
View File
@@ -14,6 +14,8 @@
# INSPECTOR_TAG Image version to run (default "latest"; e.g. 0.8.0 to pin). # INSPECTOR_TAG Image version to run (default "latest"; e.g. 0.8.0 to pin).
# PUID / PGID User/group Inspector runs as (default 1000/1000). # PUID / PGID User/group Inspector runs as (default 1000/1000).
# Unraid users often prefer 99 / 100. # Unraid users often prefer 99 / 100.
# PORTAINER_API_TOKEN Portainer access token, only if you use stack redeploy
# (Settings -> Portainer in the dashboard).
# #
# No config file to create, no docker group ID to look up: Inspector creates # No config file to create, no docker group ID to look up: Inspector creates
# its config on first start and detects Docker socket permissions by itself. # its config on first start and detects Docker socket permissions by itself.
@@ -36,3 +38,4 @@ services:
- INSPECTOR_PASSWORD=${INSPECTOR_PASSWORD:-} - INSPECTOR_PASSWORD=${INSPECTOR_PASSWORD:-}
- PUID=${PUID:-1000} - PUID=${PUID:-1000}
- PGID=${PGID:-1000} - PGID=${PGID:-1000}
- PORTAINER_API_TOKEN=${PORTAINER_API_TOKEN:-}
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.9.0" __version__ = "0.9.1"
+155 -26
View File
@@ -78,10 +78,12 @@
<a href="#status">3. The Status page</a> <a href="#status">3. The Status page</a>
<a href="#notifications">4. Notifications</a> <a href="#notifications">4. Notifications</a>
<a href="#containers">5. Managing containers</a> <a href="#containers">5. Managing containers</a>
<a href="#events">6. Events history</a> <a href="#vpn">6. Apps behind a VPN</a>
<a href="#settings">7. Other settings</a> <a href="#portainer">7. Portainer stack redeploy</a>
<a href="#restart">8. "Requires restart" fields</a> <a href="#events">8. Events history</a>
<a href="#trouble">9. Troubleshooting</a> <a href="#settings">9. Other settings</a>
<a href="#restart">10. "Requires restart" fields</a>
<a href="#trouble">11. Troubleshooting</a>
</nav> </nav>
<main> <main>
@@ -175,7 +177,7 @@ Each card shows:</p>
under Apps). <b>Pushover</b>: enter your application API token and your user key.</li> under Apps). <b>Pushover</b>: enter your application API token and your user key.</li>
<li>Click <b>Send test</b>. You should get a message on your phone within seconds. If it fails, <li>Click <b>Send test</b>. You should get a message on your phone within seconds. If it fails,
the reason appears next to the button.</li> the reason appears next to the button.</li>
<li>Click <b>Save</b>, then restart Inspector once (see <a href="#restart">section 8</a>), <li>Click <b>Save</b>, then restart Inspector once (see <a href="#restart">section 10</a>),
because turning a channel on or off is a "requires restart" field.</li> because turning a channel on or off is a "requires restart" field.</li>
</ol> </ol>
<p>You'll get one alert when a container first fails, when Inspector restarts it, and when it <p>You'll get one alert when a container first fails, when Inspector restarts it, and when it
@@ -220,32 +222,159 @@ Inspector to act on it.</p>
<figure><img src="container-advanced.png" alt="Reachability, Dependencies and Recovery groups"> <figure><img src="container-advanced.png" alt="Reachability, Dependencies and Recovery groups">
<figcaption>Bottom of a container's page: an app behind a VPN container with an HTTP check and stack-redeploy recovery.</figcaption></figure> <figcaption>Bottom of a container's page: an app behind a VPN container with an HTTP check and stack-redeploy recovery.</figcaption></figure>
<h3>Apps behind a VPN container</h3> </section>
<p>If an app shares a VPN container's network (<code>network_mode: container:vpn</code> or similar), set these on the app's page:</p>
<section id="vpn">
<h2>6. Apps behind a VPN container</h2>
<h3>Why these apps need special handling</h3>
<p>A common setup routes download and indexer apps through a VPN container. Those apps don't get a
network of their own: their compose file says <code>network_mode: container:&lt;vpn&gt;</code> (or
<code>service:&lt;vpn&gt;</code>) and all their traffic goes through the VPN container. That causes
two problems for a watchdog:</p>
<ul>
<li><b>When the VPN breaks, every app behind it breaks at the same time.</b> Restarting the apps
does nothing while the tunnel is down. Without help, Inspector would restart each app over and
over, use up their hourly restart limits, and flood you with alerts, all for a problem in a
different container.</li>
<li><b>When the VPN container is recreated</b> (an image update, or someone redeploys its stack),
it gets a new container ID. The apps still point at the old one, so a normal restart fails with
errors like <i>"No such container"</i> or <i>"joining network namespace"</i>. The only fix is
to recreate the apps too, which is what a Portainer stack redeploy does
(<a href="#portainer">section 7</a>).</li>
</ul>
<h3>How to tell if an app is behind a VPN</h3>
<ul>
<li>In Portainer open <b>Stacks → your stack → Editor</b> and look for
<code>network_mode: container:…</code> or <code>network_mode: service:…</code> on the app.</li>
<li>Or open <b>Containers → the app</b>: under <b>Network</b> it shows the VPN container instead
of a normal network, and it has no ports of its own (they're published on the VPN container).</li>
</ul>
<h3>Setting it up</h3>
<ol class="steps"> <ol class="steps">
<li><b>Dependencies → depends_on</b>: pick the VPN container, and turn on <b>vpn_routed</b>. <li><b>Add the VPN container to Inspector and keep it enabled</b> (restart on UNHEALTHY and NOT
Inspector checks the VPN first and waits for it to recover before touching the app.</li> RUNNING is a good start). Inspector can only wait for containers it is watching: if the VPN
<li><b>Recovery → recovery_action</b>: choose <b>Restart, then redeploy stack if that fails</b> container is disabled, its apps are recovered normally, as if there were no dependency, and the
and enter the <b>stack name</b> exactly as Portainer shows it. When the VPN container gets container page shows a warning.</li>
recreated, a plain restart of the app fails; redeploying the stack reconnects it.</li> <li>On each app behind it, set <b>Dependencies → depends_on</b> to the VPN container.</li>
<li>Turn on <b>vpn_routed</b>. This only changes the log: Inspector writes down when it holds off
on the app because the VPN is down. The waiting itself comes from depends_on.</li>
<li>Add an <b>HTTP check</b> (<a href="#containers">section 5</a>) using your server's IP and the
port published on the VPN container, and tick <b>UNREACHABLE</b>. Docker often still reports
these apps as healthy when the tunnel is down; the HTTP check notices.</li>
<li>Under <b>Recovery</b>, choose <b>Restart, then redeploy stack if that fails</b> and enter the
stack name. This needs the Portainer connection from <a href="#portainer">section 7</a>.</li>
</ol> </ol>
<p>Stack redeploys need the Portainer connection in <b>Settings → Portainer</b>:</p> <h3>What Inspector then does</h3>
<p>Every check, it looks at the VPN container first. While the VPN is anything other than healthy
(or starting, or running without a health check), the apps that depend on it are not restarted;
Inspector fixes the VPN first. Once the VPN is healthy again, the apps are handled normally: a
restart first, and a stack redeploy if the restart fails or doesn't help.</p>
<p class="note"><b>depends_on isn't only for VPNs.</b> Use it for any "B needs A" pair, such as an
app and its database: Inspector won't restart the app while its database is down.</p>
</section>
<section id="portainer">
<h2>7. Portainer stack redeploy</h2>
<h3>Why Inspector needs Portainer</h3>
<p>Inspector talks to Docker directly, so it can restart or start a container. It can't
<i>recreate</i> one: that needs the container's compose definition, which lives in Portainer. A
stack redeploy asks Portainer to do exactly what its <b>Update the stack</b> button does. That's
how VPN-routed apps get reattached to a recreated VPN container. You only need this if you use one
of the two "redeploy" recovery actions.</p>
<p class="note warn"><b>A redeploy affects the whole stack.</b> Portainer pulls the latest images
and recreates <i>every</i> container in that stack, not just the failing app, so all of them blink
off for a moment. That's why <b>Restart, then redeploy stack if that fails</b> is the recommended
choice: most problems are fixed by the plain restart, and the redeploy is only used when that
doesn't work.</p>
<h3>Requirements</h3>
<ul>
<li>The app must belong to a stack that was <b>created in Portainer</b>. In <b>Stacks</b>, stacks
created elsewhere (for example with <code>docker compose</code> on the command line) are marked
<b>Limited</b>, and Portainer can't redeploy them.</li>
<li>An access token for a Portainer user who can manage that stack. An administrator's token is
the simplest.</li>
</ul>
<h3>Step 1: find the values</h3>
<table>
<tr><th>Setting</th><th>Where to find it</th></tr>
<tr><td>base_url</td><td>The address you open Portainer at, without anything after the port:
usually <code>http://&lt;server-ip&gt;:9000</code> or <code>https://&lt;server-ip&gt;:9443</code>.
Use the server's IP, not <code>localhost</code>: Inspector runs in its own container.</td></tr>
<tr><td>endpoint_id</td><td>On Portainer's <b>Home</b> page, click your environment (often
<b>local</b>). The browser address then ends like <code>#!/2/docker/dashboard</code>: the
number after <code>#!/</code> is the endpoint ID (here <code>2</code>).</td></tr>
<tr><td>stack name</td><td><b>Stacks</b> list, <b>Name</b> column, spelled exactly the same.
This goes on each app's container page, not on the Portainer page.</td></tr>
<tr><td>verify_ssl</td><td>Leave off for <code>http://</code> and for Portainer's built-in
self-signed certificate on 9443. Turn on only if Portainer has a real certificate.</td></tr>
<tr><td>API token</td><td>Click your username (top right) → <b>My account</b> →
<b>Access tokens</b> → <b>Add access token</b>. Name it <code>inspector</code> and copy the
token straight away: Portainer shows it only once.</td></tr>
</table>
<h3>Step 2: give Inspector the token</h3>
<p><b>Recommended: an environment variable.</b> The token then never lands in
<code>config.yml</code> or its backups.</p>
<ol class="steps"> <ol class="steps">
<li>In Portainer, open <b>My account → Access tokens</b> and create a token.</li> <li>In Portainer open <b>Stacks → inspector → Editor</b>.</li>
<li>Easiest and safest: add it to the Inspector stack as an environment variable (for example <li>Check that the compose file has this line under <code>environment:</code> (it's in the
<code>PORTAINER_API_TOKEN</code>) and redeploy Inspector. Or choose <b>Saved in config.yml</b> compose file from version 0.9.1 on; add it if your stack is older):
and paste it in.</li> <code>- PORTAINER_API_TOKEN=${PORTAINER_API_TOKEN:-}</code></li>
<li>In <b>Settings → Portainer</b>, add an environment with Portainer's URL and endpoint ID <li>Under <b>Environment variables</b> click <b>Add an environment variable</b>: name
(usually 1 or 2; it's the number in the URL when you open the environment in Portainer). <code>PORTAINER_API_TOKEN</code>, value the token.</li>
Click <b>Test connection</b>: it should list your stacks.</li> <li>Click <b>Update the stack</b>. Inspector restarts with the token available.</li>
<li>Turn Portainer on and save.</li> </ol>
<p><b>Alternative: save it in Inspector.</b> In the next step choose <b>Saved in config.yml</b>
and paste the token. It is masked in the dashboard, but anyone who can read Inspector's config
folder (or a backup of it) can read the token.</p>
<h3>Step 3: connect Inspector</h3>
<ol class="steps">
<li>Open <b>Settings → Portainer</b>. Under <b>Add environment</b>, give it a name (your own
label, e.g. <code>home</code>) and fill in base_url, endpoint_id and verify_ssl.</li>
<li><b>API token stored as</b>: <i>Environment variable</i> with the name
<code>PORTAINER_API_TOKEN</code>, or <i>Saved in config.yml</i> with the token.</li>
<li>Click <b>Test connection</b>. It should list the stacks on that endpoint; check that your
app's stack is there. Then <b>Save new environment</b>.</li>
<li>At the top of the page turn <b>enabled</b> on, pick the <b>default_environment</b>, and
<b>Save Portainer</b>.</li>
<li>On each app's container page, set the recovery action and stack name
(<a href="#vpn">section 6</a>). Leave <b>portainer_environment</b> on <i>Default</i> unless
you connected more than one Portainer.</li>
</ol> </ol>
<figure><img src="settings-portainer.png" alt="Portainer settings"> <figure><img src="settings-portainer.png" alt="Portainer settings">
<figcaption>Settings → Portainer with one environment; the token comes from an environment variable.</figcaption></figure> <figcaption>Settings → Portainer with one environment; the token comes from an environment variable.</figcaption></figure>
<h3>The other settings on the page</h3>
<table>
<tr><th>Setting</th><th>What it does</th></tr>
<tr><td>default_environment</td><td>Which connection apps use when they don't pick one. With a
single environment you can leave it on Automatic.</td></tr>
<tr><td>stack_redeploy_cooldown_seconds</td><td>Minimum time between two redeploys of the same
stack (default 300). Several apps often share a stack; this stops them triggering a redeploy
each.</td></tr>
<tr><td>post_redeploy_wait_seconds</td><td>How long Inspector waits after a redeploy for the
stack to come up before judging it again (default 90).</td></tr>
</table>
<h3>If Test connection fails</h3>
<table>
<tr><th>Message</th><th>Fix</th></tr>
<tr><td>environment variable … is not set</td><td>The compose line from step 2 is missing, or
the stack wasn't updated after adding the variable.</td></tr>
<tr><td>the API token was rejected</td><td>Token copied wrong, deleted, or from a user without
access. Create a new one.</td></tr>
<tr><td>no stacks found on endpoint N</td><td>Wrong endpoint ID; check the number in the
Portainer address again.</td></tr>
<tr><td>request failed …</td><td>Wrong address or port, <code>http</code> vs <code>https</code>
mixed up, or <code>localhost</code> used instead of the server IP. With https and a
self-signed certificate, turn verify_ssl off.</td></tr>
</table>
</section> </section>
<section id="events"> <section id="events">
<h2>6. Events history</h2> <h2>8. Events history</h2>
<p>The <b>Events</b> tab is a day-by-day timeline of failures, restarts, recoveries, mutes, and <p>The <b>Events</b> tab is a day-by-day timeline of failures, restarts, recoveries, mutes, and
maintenance. Use <b>Prev day</b> / <b>Next day</b> to look back.</p> maintenance. Use <b>Prev day</b> / <b>Next day</b> to look back.</p>
<figure><img src="events.png" alt="Events timeline"> <figure><img src="events.png" alt="Events timeline">
@@ -253,7 +382,7 @@ maintenance. Use <b>Prev day</b> / <b>Next day</b> to look back.</p>
</section> </section>
<section id="settings"> <section id="settings">
<h2>7. Other settings</h2> <h2>9. Other settings</h2>
<figure><img src="settings-inspector.png" alt="Inspector loop settings"> <figure><img src="settings-inspector.png" alt="Inspector loop settings">
<figcaption>Settings → Inspector loop.</figcaption></figure> <figcaption>Settings → Inspector loop.</figcaption></figure>
<table> <table>
@@ -266,14 +395,14 @@ maintenance. Use <b>Prev day</b> / <b>Next day</b> to look back.</p>
<tr><td>Maintenance</td><td>A daily quiet window (e.g. 02:00–05:00) so nightly backups or updates don't trigger restarts. Turn on <b>maintenance_window</b> on each container that should follow it.</td></tr> <tr><td>Maintenance</td><td>A daily quiet window (e.g. 02:00–05:00) so nightly backups or updates don't trigger restarts. Turn on <b>maintenance_window</b> on each container that should follow it.</td></tr>
<tr><td>Notification mute</td><td>Turns the per-container <b>Mute notifications</b> buttons on or off, and sets how long a mute lasts.</td></tr> <tr><td>Notification mute</td><td>Turns the per-container <b>Mute notifications</b> buttons on or off, and sets how long a mute lasts.</td></tr>
<tr><td>Uptime Kuma</td><td>Connection to your Uptime Kuma status page, used by container reachability checks.</td></tr> <tr><td>Uptime Kuma</td><td>Connection to your Uptime Kuma status page, used by container reachability checks.</td></tr>
<tr><td>Portainer</td><td>Connection to Portainer, used to redeploy stacks. See <a href="#containers">Apps behind a VPN container</a>.</td></tr> <tr><td>Portainer</td><td>Connection to Portainer, used to redeploy stacks. See <a href="#portainer">section 7</a>.</td></tr>
</table> </table>
<p>At the bottom of every settings page is a strip showing where the config file lives and <p>At the bottom of every settings page is a strip showing where the config file lives and
whether Inspector can write to it.</p> whether Inspector can write to it.</p>
</section> </section>
<section id="restart"> <section id="restart">
<h2>8. "Requires restart" fields</h2> <h2>10. "Requires restart" fields</h2>
<p>Most changes apply on the next check. Fields marked <p>Most changes apply on the next check. Fields marked
<span class="tag t-violet">REQUIRES RESTART</span> (like turning a notification channel or the <span class="tag t-violet">REQUIRES RESTART</span> (like turning a notification channel or the
dashboard on or off) only take effect after Inspector restarts:</p> dashboard on or off) only take effect after Inspector restarts:</p>
@@ -285,7 +414,7 @@ dashboard on or off) only take effect after Inspector restarts:</p>
</section> </section>
<section id="trouble"> <section id="trouble">
<h2>9. Troubleshooting</h2> <h2>11. Troubleshooting</h2>
<table> <table>
<tr><th>Problem</th><th>Fix</th></tr> <tr><th>Problem</th><th>Fix</th></tr>
<tr><td>Red <b>READ-ONLY</b> badge at the bottom of Settings</td> <tr><td>Red <b>READ-ONLY</b> badge at the bottom of Settings</td>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

+12 -5
View File
@@ -2177,7 +2177,7 @@ def _portainer_env_form(env_name: str, env, csrf_token: str, *, suggest_name: st
+ _settings_field("name", "env_name", env_name or suggest_name, + _settings_field("name", "env_name", env_name or suggest_name,
hint="Your own label, referenced by containers") hint="Your own label, referenced by containers")
+ _settings_field("endpoint_id", "endpoint_id", str(env.endpoint_id if env else 1), kind="number", + _settings_field("endpoint_id", "endpoint_id", str(env.endpoint_id if env else 1), kind="number",
hint="Portainer → Environments; the number in the URL (usually 1 or 2)") hint="Open the environment from Portainer's Home page; the number after #!/ in the address (often 1 or 2)")
+ "</div>" + "</div>"
+ _settings_field("base_url", "base_url", env.base_url if env else "", + _settings_field("base_url", "base_url", env.base_url if env else "",
hint="e.g. http://192.168.1.10:9000 or https://portainer.example.com") hint="e.g. http://192.168.1.10:9000 or https://portainer.example.com")
@@ -2190,7 +2190,7 @@ def _portainer_env_form(env_name: str, env, csrf_token: str, *, suggest_name: st
+ f'<div class="token-src" data-src="env"{" hidden" if inline else ""}>' + f'<div class="token-src" data-src="env"{" hidden" if inline else ""}>'
+ _settings_field("environment variable name", "api_token_env", + _settings_field("environment variable name", "api_token_env",
(env.api_token_env if env else "") or "PORTAINER_API_TOKEN", (env.api_token_env if env else "") or "PORTAINER_API_TOKEN",
hint="Set this variable on the Inspector container (Portainer → stack → Environment variables), then redeploy Inspector.") hint="Add it to the Inspector stack's environment variables; the compose file must pass it in. Step by step: Help → Portainer stack redeploy, step 2.")
+ "</div>" + "</div>"
+ f'<div class="token-src" data-src="inline"{"" if inline else " hidden"}>' + f'<div class="token-src" data-src="inline"{"" if inline else " hidden"}>'
+ _settings_secret_field("api_token", "api_token", bool(env and env.api_token)) + _settings_secret_field("api_token", "api_token", bool(env and env.api_token))
@@ -2451,18 +2451,25 @@ def _render_container_advanced(name: str, cfg, app: AppConfig) -> str:
) )
others = [c.name for c in app.containers if c.name != name] others = [c.name for c in app.containers if c.name != name]
disabled = {c.name for c in app.containers if not c.enabled}
dep_value = getattr(cfg, "depends_on", "") or "" dep_value = getattr(cfg, "depends_on", "") or ""
dep_options = [("", "— none —")] + [(n, n) for n in others] dep_options = [("", "— none —")] + [(n, n + (" (disabled)" if n in disabled else "")) for n in others]
if dep_value and dep_value not in others: if dep_value and dep_value not in others:
dep_options.append((dep_value, f"{dep_value} (not configured)")) dep_options.append((dep_value, f"{dep_value} (not configured)"))
dep_warn = ""
if dep_value in disabled:
dep_warn = _warn(f"{_escape(dep_value)} is disabled, so Inspector can't see its status and won't wait for it. "
"Enable it to make this dependency count.")
deps = ( deps = (
'<div class="form-group"><h4>Dependencies</h4>' '<div class="form-group"><h4>Dependencies</h4>'
'<p class="group-sub">Check this container after the one it relies on, and hold off recovering it ' '<p class="group-sub">Check this container after the one it relies on, and hold off recovering it '
"while that one is still failing.</p>" "while that one is still failing.</p>"
+ _settings_select("depends_on", "depends_on", dep_value, dep_options, + _settings_select("depends_on", "depends_on", dep_value, dep_options,
hint="e.g. the VPN container, for apps that use network_mode: container:<vpn>") hint="e.g. the VPN container, for apps that use network_mode: container:<vpn>. "
"Also works for any other dependency, like an app and its database.")
+ dep_warn
+ _settings_field("vpn_routed", "vpn_routed", "on" if getattr(cfg, "vpn_routed", False) else "", kind="switch", + _settings_field("vpn_routed", "vpn_routed", "on" if getattr(cfg, "vpn_routed", False) else "", kind="switch",
hint="Routes through the container above. Logs why recovery is deferred while it is down.") hint="Only affects logging: says in the log when recovery waits on the VPN container. The waiting itself comes from depends_on.")
+ "</div>" + "</div>"
) )
+7 -3
View File
@@ -293,8 +293,10 @@ def _check_one(
if ok: if ok:
dep = container_config.depends_on dep = container_config.depends_on
if dep: # Only wait on a dependency Inspector is watching. A disabled one has
dep_status = states[dep].current_status if dep in states else None # no state, and waiting on it would block recovery forever.
if dep and dep in states:
dep_status = states[dep].current_status
if dep_status not in (HEALTHY, STARTING, NO_HEALTH_CHECK): if dep_status not in (HEALTHY, STARTING, NO_HEALTH_CHECK):
if container_config.vpn_routed: if container_config.vpn_routed:
log.info( log.info(
@@ -454,8 +456,10 @@ def run_loop(config_ref: ConfigRef) -> int:
for gone in states.keys() - current_enabled.keys(): for gone in states.keys() - current_enabled.keys():
states.pop(gone, None) states.pop(gone, None)
log.info("Stopped watching container (removed or disabled): %s", gone) log.info("Stopped watching container (removed or disabled): %s", gone)
if current_enabled != enabled_configs:
# Only re-order (and re-log ordering warnings) when the config changed.
check_order = _topological_order(current_enabled)
enabled_configs = current_enabled enabled_configs = current_enabled
check_order = _topological_order(enabled_configs)
# Integration clients hold their config; rebuild them when the # Integration clients hold their config; rebuild them when the
# settings page changes Uptime Kuma / Portainer. # settings page changes Uptime Kuma / Portainer.