feat: add Docker health-state HTTP endpoint for Swarm Health Watchdog

- Python HTTP server on 0.0.0.0:18809
- GET /health -> all monitored containers (JSON)
- GET /health/<name> -> single container
- Monitors: brave-search, kokoro-tts, litellm, litellm-db, n8n-agent, searxng, whisper-server
- Returns status, health, restart count via docker inspect
- systemd user service for auto-start

Task: t_461f71fe
This commit is contained in:
William Valentin
2026-05-13 14:29:25 -07:00
parent aea9042cce
commit 9fdd29f7b7
1272 changed files with 863206 additions and 16973 deletions
@@ -27,34 +27,28 @@
"openai-codex:default": {
"type": "oauth",
"provider": "openai-codex",
"access": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MzQ0ZTY1LWJiYzktNDRkMS1hOWQwLWY5NTdiMDc5YmQwZSIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MSJdLCJjbGllbnRfaWQiOiJhcHBfRU1vYW1FRVo3M2YwQ2tYYVhwN2hyYW5uIiwiZXhwIjoxNzc0Mjk2MTg1LCJodHRwczovL2FwaS5vcGVuYWkuY29tL2F1dGgiOnsiY2hhdGdwdF9hY2NvdW50X2lkIjoiYzA2MmNmNmItYmIxOS00ZDA4LWE2ZTMtYTRlNGYxNzdlN2UxIiwiY2hhdGdwdF9hY2NvdW50X3VzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFa19fYzA2MmNmNmItYmIxOS00ZDA4LWE2ZTMtYTRlNGYxNzdlN2UxIiwiY2hhdGdwdF9jb21wdXRlX3Jlc2lkZW5jeSI6Im5vX2NvbnN0cmFpbnQiLCJjaGF0Z3B0X3BsYW5fdHlwZSI6InBsdXMiLCJjaGF0Z3B0X3VzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFayIsInVzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFayJ9LCJodHRwczovL2FwaS5vcGVuYWkuY29tL21mYSI6eyJyZXF1aXJlZCI6InllcyJ9LCJodHRwczovL2FwaS5vcGVuYWkuY29tL3Byb2ZpbGUiOnsiZW1haWwiOiJ3aWxsaWFtLnZhbGVudGluLmluZm9AZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWV9LCJpYXQiOjE3NzM0MzIxODQsImlzcyI6Imh0dHBzOi8vYXV0aC5vcGVuYWkuY29tIiwianRpIjoiY2FhZDQ2ZmEtNGIxMy00ZTI5LTg2N2QtZjI4ZWVhZGFiNGVjIiwibmJmIjoxNzczNDMyMTg0LCJwd2RfYXV0aF90aW1lIjoxNzcyNTA0OTE1NzM1LCJzY3AiOlsib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIiwib2ZmbGluZV9hY2Nlc3MiXSwic2Vzc2lvbl9pZCI6ImF1dGhzZXNzX1RJVkZNWkRJcjNWWEk5NWhUa3BQUXczQyIsInNsIjp0cnVlLCJzdWIiOiJnb29nbGUtb2F1dGgyfDEwNjMzNzY4NjU4MzU5MjgwODAxNyJ9.SELfl6WbyaSSZn03yKR95dFvgrLeAPqiCieGxWOqY2PJQQb_cxmjY3yGJqTEVofGF-pyeDZVWx3HAB20Ng-9KbKQKFMdNTxuURb3uoRRuoit4cbg2kwH7lL07nQXKkY8nkusJLsLNQCZYGziW8WMAdypwEvm2ODWWav0ygl3PLJWjRj5OZ1Mcc_mRj6koYahgmWWoMo7oyDOn5tHpZKIxaSPRVBMvEee7JH3FP8zauPrlfmh6uIVhaY4ANwJqOM9bBbiFTv6unaQXx57uDaLo9XZOPa-vMeDWQYNvGs8XcKng3AE8-CMlQV1G_TRiWYZTFH9k5O3YGBO0t-h0jWNG658ccVcLoYB2PQ_3BmTTSpU2lQ6VosCDvg6SMA-GtI_kEOwV5XmsHpoDL6VyD--6EMxUyrYZ2W8sC4b6k-H58Bu-p4MO_Qc00nMhimBz_JP9vlfF9Dg1rypW9KA9gPZUgJR_dDG3bPofMQFAyGGrLHoXUqCYWJn0dLzW5wrmbNz1gOI3WNJjVUCmKzaEY3w2bpci90WGxIixrnVAoaP5XQQyw4x_urYbEdXlzuEERlFtkZIxRUMQAp9OwSaU76KnCrXVNsBUQdXNN_mdNKr1riebh4hzsgAnCkj1hazrT1hkWGD8eMrUFcLymu5OIYcdzxq-nroUhX6566L7mWozHk",
"refresh": "rt_lGvf7w6JR1AvXL0Dc7xCGcZf7P0P4kkcFW_VmTSccVA.56jMY8jGDblmVXZ9egKC57skTCl4clEGo2_cDyBzIRQ",
"expires": 1774296185000,
"access": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MzQ0ZTY1LWJiYzktNDRkMS1hOWQwLWY5NTdiMDc5YmQwZSIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MSJdLCJjbGllbnRfaWQiOiJhcHBfRU1vYW1FRVo3M2YwQ2tYYVhwN2hyYW5uIiwiZXhwIjoxNzc1NDA0ODI1LCJodHRwczovL2FwaS5vcGVuYWkuY29tL2F1dGgiOnsiY2hhdGdwdF9hY2NvdW50X2lkIjoiYzA2MmNmNmItYmIxOS00ZDA4LWE2ZTMtYTRlNGYxNzdlN2UxIiwiY2hhdGdwdF9hY2NvdW50X3VzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFa19fYzA2MmNmNmItYmIxOS00ZDA4LWE2ZTMtYTRlNGYxNzdlN2UxIiwiY2hhdGdwdF9jb21wdXRlX3Jlc2lkZW5jeSI6Im5vX2NvbnN0cmFpbnQiLCJjaGF0Z3B0X3BsYW5fdHlwZSI6InBsdXMiLCJjaGF0Z3B0X3VzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFayIsImxvY2FsaG9zdCI6dHJ1ZSwidXNlcl9pZCI6InVzZXItVVh2bTQxVEpRblNCbGRkSFh4NnpIbEVrIn0sImh0dHBzOi8vYXBpLm9wZW5haS5jb20vbWZhIjp7InJlcXVpcmVkIjoieWVzIn0sImh0dHBzOi8vYXBpLm9wZW5haS5jb20vcHJvZmlsZSI6eyJlbWFpbCI6IndpbGxpYW0udmFsZW50aW4uaW5mb0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0sImlhdCI6MTc3NDU0MDgyNCwiaXNzIjoiaHR0cHM6Ly9hdXRoLm9wZW5haS5jb20iLCJqdGkiOiJjZjY0NmUwOS1hNTIyLTQ3OWQtYTVkNy04YmE2MjEwNmRjMmMiLCJuYmYiOjE3NzQ1NDA4MjQsInB3ZF9hdXRoX3RpbWUiOjE3NzQ1NDA4MTc3MzksInNjcCI6WyJvcGVuaWQiLCJwcm9maWxlIiwiZW1haWwiLCJvZmZsaW5lX2FjY2VzcyJdLCJzZXNzaW9uX2lkIjoiYXV0aHNlc3NfcU8zaFJjVENYMDQxS3BPSGt1aUtOVHFQIiwic2wiOnRydWUsInN1YiI6Imdvb2dsZS1vYXV0aDJ8MTA2MzM3Njg2NTgzNTkyODA4MDE3In0.7YWYM64rXEyAYPN_7BiTHt7U5Ly_E0EF1LFKP3sJTu7df4vmEMP5kwA5vIpkaaZyddsqbRhXsai4x_mo410UGl56shcoAulR46qJlFvF6Fae0iPQZ_pQyxghnomUrvE_gDKV5VShuvAB11r04RiYdATHYLajwKsaxvl19s1aXanX2yyLYus0dTdX-cLEatD5OSkIR_8k6yNJF3TyMDCidVdR4Eqkm8arZC3jAc_F_3gsb20cNxp7z7ybza017cL_EOwkrby0jW4l_ab0jXNIXU5j11OaIjd3ZUtxnQU2At3rhplZNRgtgWVn84VlXKQFkZnW-zG8eiZj9WaaPdm4utOqq38mNfDaR9NxLZ-yQ1GYKHqn86eFQunxjXYMszHKA7FsElrGnRwiDMbFFpA2bXFVa6zUs2CcM_MA2riHQLYCU0zglQL9s7xgwgn1ZqdRYZTRjNtR2PIoNzrdqAhy5TIfPtFb27seH5KUyct0Mqc9ZREs6VnG3OTBLUdD8qJYCvHfdBtBjJTc0cXnFOXCO-BekfE5xazceJYdQgjO1tljY5b0DsVSbJjXuIOE6wA2AgiBecrO6uxX2w2DNRgm1yMDQmepibnPwg0UasAvMSigTuOOQtgxVz8Y9gqf-z4H67a7CIh5Op8z_rYOfewVjUZ5Ok7l9hvgDXm8O2RlsfE",
"refresh": "rt_6c2ESjxgMd6f8j1RFreVYsmxwFyUaBfvo_ZCihN_s40.AF5LoBIKU-zs-0Hinnz1Dp4FBBrxIwQ2txZBdj6aeic",
"expires": 1775404825013
},
"zai:default": {
"type": "api_key",
"provider": "zai",
"key": "b951f79792e6475e8bb5c97aa07385f1.qmEUjOfC6CMdSBfO"
},
"anthropic:default": {
"type": "token",
"provider": "anthropic",
"token": "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"
},
"openai-codex:william.valentin.info@gmail.com": {
"type": "oauth",
"provider": "openai-codex",
"access": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MzQ0ZTY1LWJiYzktNDRkMS1hOWQwLWY5NTdiMDc5YmQwZSIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MSJdLCJjbGllbnRfaWQiOiJhcHBfRU1vYW1FRVo3M2YwQ2tYYVhwN2hyYW5uIiwiZXhwIjoxNzc2ODMwMjY2LCJodHRwczovL2FwaS5vcGVuYWkuY29tL2F1dGgiOnsiY2hhdGdwdF9hY2NvdW50X2lkIjoiYzA2MmNmNmItYmIxOS00ZDA4LWE2ZTMtYTRlNGYxNzdlN2UxIiwiY2hhdGdwdF9hY2NvdW50X3VzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFa19fYzA2MmNmNmItYmIxOS00ZDA4LWE2ZTMtYTRlNGYxNzdlN2UxIiwiY2hhdGdwdF9jb21wdXRlX3Jlc2lkZW5jeSI6Im5vX2NvbnN0cmFpbnQiLCJjaGF0Z3B0X3BsYW5fdHlwZSI6InBsdXMiLCJjaGF0Z3B0X3VzZXJfaWQiOiJ1c2VyLVVYdm00MVRKUW5TQmxkZEhYeDZ6SGxFayIsImxvY2FsaG9zdCI6dHJ1ZSwidXNlcl9pZCI6InVzZXItVVh2bTQxVEpRblNCbGRkSFh4NnpIbEVrIn0sImh0dHBzOi8vYXBpLm9wZW5haS5jb20vbWZhIjp7InJlcXVpcmVkIjoieWVzIn0sImh0dHBzOi8vYXBpLm9wZW5haS5jb20vcHJvZmlsZSI6eyJlbWFpbCI6IndpbGxpYW0udmFsZW50aW4uaW5mb0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0sImlhdCI6MTc3NTk2NjI2NSwiaXNzIjoiaHR0cHM6Ly9hdXRoLm9wZW5haS5jb20iLCJqdGkiOiI4MDZjMjM1MC0xNTU1LTQyN2ItYTJkOC03NjUzOGJiY2NiNjQiLCJuYmYiOjE3NzU5NjYyNjUsInB3ZF9hdXRoX3RpbWUiOjE3NzQ5Nzc1OTY2NjEsInNjcCI6WyJvcGVuaWQiLCJwcm9maWxlIiwiZW1haWwiLCJvZmZsaW5lX2FjY2VzcyJdLCJzZXNzaW9uX2lkIjoiYXV0aHNlc3NfdXk1dEZNQWFKaWhIWU12NFhPUnFWWjBSIiwic2wiOnRydWUsInN1YiI6Imdvb2dsZS1vYXV0aDJ8MTA2MzM3Njg2NTgzNTkyODA4MDE3In0.g0rhDvfKOhTgYJhBuRzkNuKJJ2WirDmS5MswGUXBgQZgaJ_eCWvI9Fmfp1wdPQNEKQsgp_pBgx4jsdF4GiiyhoLZlh2zsmFCxj1uEWgnBCpSsDcA8rQPJQGQe4rfSNj9v5sgwGeTRDyhWF-jL2syqTn0pOj_gWz59p4CVAuFTf_JvNac7lcM6KXnq7FYmSrR7D7r-7uZzZN-vvom20AY1oK88ce4CSS0Q5UMCXngt5iNa6kf_u5lJdJyGf5HkPmb1kTLCXz1n6QxUG8pO1yl1aY6Ad4jeYVJ0-9A8ZD3tXASGiKH7MJOuzzTIeUlru96P3rNWMnZ_-oJXO8qMMciF3yAxLJs3cKvnh_bjTo-2tCkasfpCIZQUMA5C5Fi97J_Ild2gYHBKPhrXc6o9LrZiqoITExVHMJIQjzMZEq_IlJoM9g_L8-hBrkbNpWNRH0O_EK0Xwr_8aZZmDb1qynB_7DdzIH059MdSzVfBlL0RYMgtcwfO0nffsB9Ivn4RtI9ZVJXvavz_ao8qpoOO2gASj9hmmgWL1dyv1vo7QqQe2xk0zKKCvrFAcRObGtuCSJF-VXRU31pZ7njFp91LUpzjUUbZGvZviOZmeHi1i44GNW8goxhGX4RCLgbElohW5MhSuu1qf6rfXrCJeRpohTqzO8m_c3Xs1yLdmCPsdmj6hE",
"refresh": "rt_6jVFmYwnAVKh7J3cizAvQaeiVuXTMrCO0lP8_cxyOn0.C4fm48Z-LjSxhGcHAk6b9cxsXwXpDf8q3hHBMSbBXBs",
"expires": 1776830265957,
"email": "william.valentin.info@gmail.com",
"accountId": "c062cf6b-bb19-4d08-a6e3-a4e4f177e7e1"
}
},
"lastGood": {
"litellm": "litellm:default",
"openai-codex": "openai-codex:default",
"github-copilot": "github-copilot:github"
},
"usageStats": {
"litellm:default": {
"lastUsed": 1774855505361,
"errorCount": 0,
"lastFailureAt": 1774054888659
},
"github-copilot:github": {
"errorCount": 0,
"lastUsed": 1774539324287
},
"anthropic:manual": {
"errorCount": 0,
"lastUsed": 1773951080133
},
"openai-codex:default": {
"lastUsed": 1773258773792,
"errorCount": 0
}
}
}
@@ -0,0 +1,42 @@
{
"version": 1,
"lastGood": {
"litellm": "litellm:default",
"openai-codex": "openai-codex:william.valentin.info@gmail.com",
"anthropic": "anthropic:manual",
"github-copilot": "github-copilot:github",
"zai": "zai:default"
},
"usageStats": {
"litellm:default": {
"lastUsed": 1774981524176,
"errorCount": 0,
"lastFailureAt": 1774054888659
},
"github-copilot:github": {
"errorCount": 0,
"lastUsed": 1774539324287
},
"anthropic:manual": {
"errorCount": 0,
"lastUsed": 1773951080133
},
"openai-codex:default": {
"lastUsed": 1776297614983,
"errorCount": 0
},
"anthropic:default": {
"errorCount": 0,
"lastFailureAt": 1774583413860
},
"zai:default": {
"errorCount": 0,
"lastUsed": 1774977296466,
"lastFailureAt": 1774982308436
},
"openai-codex:william.valentin.info@gmail.com": {
"errorCount": 0,
"lastUsed": 1776303019964
}
}
}
File diff suppressed because it is too large Load Diff