diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ad3566..80b835e 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
### Added
diff --git a/INSTALL.md b/INSTALL.md
index 36a40a7..97ec467 100755
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -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_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`) |
+| `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
diff --git a/compose.yml b/compose.yml
index 487e495..dac2070 100755
--- a/compose.yml
+++ b/compose.yml
@@ -14,6 +14,8 @@
# 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).
# 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
# its config on first start and detects Docker socket permissions by itself.
@@ -36,3 +38,4 @@ services:
- INSPECTOR_PASSWORD=${INSPECTOR_PASSWORD:-}
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
+ - PORTAINER_API_TOKEN=${PORTAINER_API_TOKEN:-}
diff --git a/src/inspector/__init__.py b/src/inspector/__init__.py
index 3e2f46a..d69d16e 100755
--- a/src/inspector/__init__.py
+++ b/src/inspector/__init__.py
@@ -1 +1 @@
-__version__ = "0.9.0"
+__version__ = "0.9.1"
diff --git a/src/inspector/assets/guide/guide.html b/src/inspector/assets/guide/guide.html
index e46ee8e..c7e8ccd 100755
--- a/src/inspector/assets/guide/guide.html
+++ b/src/inspector/assets/guide/guide.html
@@ -78,10 +78,12 @@
3. The Status page
4. Notifications
5. Managing containers
- 6. Events history
- 7. Other settings
- 8. "Requires restart" fields
- 9. Troubleshooting
+ 6. Apps behind a VPN
+ 7. Portainer stack redeploy
+ 8. Events history
+ 9. Other settings
+ 10. "Requires restart" fields
+ 11. Troubleshooting
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.
If an app shares a VPN container's network (network_mode: container:vpn or similar), set these on the app's page:
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 network_mode: container:<vpn> (or
+service:<vpn>) and all their traffic goes through the VPN container. That causes
+two problems for a watchdog:
network_mode: container:… or network_mode: service:… on the app.Stack redeploys need the Portainer connection in Settings → Portainer:
+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.
+depends_on isn't only for VPNs. 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.
+Inspector talks to Docker directly, so it can restart or start a container. It can't +recreate one: that needs the container's compose definition, which lives in Portainer. A +stack redeploy asks Portainer to do exactly what its Update the stack 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.
+A redeploy affects the whole stack. Portainer pulls the latest images +and recreates every container in that stack, not just the failing app, so all of them blink +off for a moment. That's why Restart, then redeploy stack if that fails is the recommended +choice: most problems are fixed by the plain restart, and the redeploy is only used when that +doesn't work.
+docker compose on the command line) are marked
+ Limited, and Portainer can't redeploy them.| Setting | Where to find it |
|---|---|
| base_url | The address you open Portainer at, without anything after the port:
+ usually http://<server-ip>:9000 or https://<server-ip>:9443.
+ Use the server's IP, not localhost: Inspector runs in its own container. |
| endpoint_id | On Portainer's Home page, click your environment (often
+ local). The browser address then ends like #!/2/docker/dashboard: the
+ number after #!/ is the endpoint ID (here 2). |
| stack name | Stacks list, Name column, spelled exactly the same. + This goes on each app's container page, not on the Portainer page. |
| verify_ssl | Leave off for http:// and for Portainer's built-in
+ self-signed certificate on 9443. Turn on only if Portainer has a real certificate. |
| API token | Click your username (top right) → My account →
+ Access tokens → Add access token. Name it inspector and copy the
+ token straight away: Portainer shows it only once. |
Recommended: an environment variable. The token then never lands in
+config.yml or its backups.
PORTAINER_API_TOKEN) and redeploy Inspector. Or choose Saved in config.yml
- and paste it in.environment: (it's in the
+ compose file from version 0.9.1 on; add it if your stack is older):
+ - PORTAINER_API_TOKEN=${PORTAINER_API_TOKEN:-}PORTAINER_API_TOKEN, value the token.Alternative: save it in Inspector. In the next step choose Saved in config.yml +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.
+ +home) and fill in base_url, endpoint_id and verify_ssl.PORTAINER_API_TOKEN, or Saved in config.yml with the token.
| Setting | What it does |
|---|---|
| default_environment | Which connection apps use when they don't pick one. With a + single environment you can leave it on Automatic. |
| stack_redeploy_cooldown_seconds | Minimum time between two redeploys of the same + stack (default 300). Several apps often share a stack; this stops them triggering a redeploy + each. |
| post_redeploy_wait_seconds | How long Inspector waits after a redeploy for the + stack to come up before judging it again (default 90). |
| Message | Fix |
|---|---|
| environment variable … is not set | The compose line from step 2 is missing, or + the stack wasn't updated after adding the variable. |
| the API token was rejected | Token copied wrong, deleted, or from a user without + access. Create a new one. |
| no stacks found on endpoint N | Wrong endpoint ID; check the number in the + Portainer address again. |
| request failed … | Wrong address or port, http vs https
+ mixed up, or localhost used instead of the server IP. With https and a
+ self-signed certificate, turn verify_ssl off. |
The Events tab is a day-by-day timeline of failures, restarts, recoveries, mutes, and maintenance. Use Prev day / Next day to look back.
@@ -253,7 +382,7 @@ maintenance. Use Prev day / Next day to look back.
| Maintenance | A daily quiet window (e.g. 02:00–05:00) so nightly backups or updates don't trigger restarts. Turn on maintenance_window on each container that should follow it. |
| Notification mute | Turns the per-container Mute notifications buttons on or off, and sets how long a mute lasts. |
| Uptime Kuma | Connection to your Uptime Kuma status page, used by container reachability checks. |
| Portainer | Connection to Portainer, used to redeploy stacks. See Apps behind a VPN container. |
| Portainer | Connection to Portainer, used to redeploy stacks. See section 7. |
At the bottom of every settings page is a strip showing where the config file lives and whether Inspector can write to it.
Most changes apply on the next check. Fields marked REQUIRES RESTART (like turning a notification channel or the dashboard on or off) only take effect after Inspector restarts:
@@ -285,7 +414,7 @@ dashboard on or off) only take effect after Inspector restarts:| Problem | Fix |
|---|---|
| Red READ-ONLY badge at the bottom of Settings | diff --git a/src/inspector/assets/guide/settings-portainer.png b/src/inspector/assets/guide/settings-portainer.png index edfc67e..3d6f302 100755 Binary files a/src/inspector/assets/guide/settings-portainer.png and b/src/inspector/assets/guide/settings-portainer.png differ diff --git a/src/inspector/dashboard.py b/src/inspector/dashboard.py index acc0bde..f132182 100755 --- a/src/inspector/dashboard.py +++ b/src/inspector/dashboard.py @@ -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, hint="Your own label, referenced by containers") + _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)") + "" + _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") @@ -2190,7 +2190,7 @@ def _portainer_env_form(env_name: str, env, csrf_token: str, *, suggest_name: st + f'