cognitivesystems 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. cognitivesystems-0.0.2/.gitignore +49 -0
  2. cognitivesystems-0.0.2/PKG-INFO +229 -0
  3. cognitivesystems-0.0.2/README.md +199 -0
  4. cognitivesystems-0.0.2/frontend/.gitignore +11 -0
  5. cognitivesystems-0.0.2/frontend/e2e/auth.setup.ts +15 -0
  6. cognitivesystems-0.0.2/frontend/e2e/dashboard.spec.ts +47 -0
  7. cognitivesystems-0.0.2/frontend/e2e/docker.spec.ts +41 -0
  8. cognitivesystems-0.0.2/frontend/e2e/fixtures.ts +7 -0
  9. cognitivesystems-0.0.2/frontend/e2e/services.spec.ts +14 -0
  10. cognitivesystems-0.0.2/frontend/eslint.config.js +19 -0
  11. cognitivesystems-0.0.2/frontend/index.html +12 -0
  12. cognitivesystems-0.0.2/frontend/package-lock.json +5377 -0
  13. cognitivesystems-0.0.2/frontend/package.json +42 -0
  14. cognitivesystems-0.0.2/frontend/playwright.config.ts +37 -0
  15. cognitivesystems-0.0.2/frontend/src/App.test.tsx +125 -0
  16. cognitivesystems-0.0.2/frontend/src/App.tsx +45 -0
  17. cognitivesystems-0.0.2/frontend/src/api/client.ts +57 -0
  18. cognitivesystems-0.0.2/frontend/src/api/hooks.ts +50 -0
  19. cognitivesystems-0.0.2/frontend/src/app.css +203 -0
  20. cognitivesystems-0.0.2/frontend/src/components/JobLog.tsx +27 -0
  21. cognitivesystems-0.0.2/frontend/src/context/auth.tsx +72 -0
  22. cognitivesystems-0.0.2/frontend/src/context/notify.tsx +68 -0
  23. cognitivesystems-0.0.2/frontend/src/context/theme.tsx +29 -0
  24. cognitivesystems-0.0.2/frontend/src/layout/Shell.tsx +52 -0
  25. cognitivesystems-0.0.2/frontend/src/main.tsx +24 -0
  26. cognitivesystems-0.0.2/frontend/src/pages/Config.tsx +171 -0
  27. cognitivesystems-0.0.2/frontend/src/pages/Custom.tsx +102 -0
  28. cognitivesystems-0.0.2/frontend/src/pages/Docker.tsx +335 -0
  29. cognitivesystems-0.0.2/frontend/src/pages/Jobs.tsx +62 -0
  30. cognitivesystems-0.0.2/frontend/src/pages/Login.tsx +109 -0
  31. cognitivesystems-0.0.2/frontend/src/pages/Networks.tsx +99 -0
  32. cognitivesystems-0.0.2/frontend/src/pages/Overview.tsx +41 -0
  33. cognitivesystems-0.0.2/frontend/src/pages/Services.tsx +253 -0
  34. cognitivesystems-0.0.2/frontend/src/pages/System.tsx +85 -0
  35. cognitivesystems-0.0.2/frontend/src/pages.test.tsx +113 -0
  36. cognitivesystems-0.0.2/frontend/src/test/setup.ts +1 -0
  37. cognitivesystems-0.0.2/frontend/src/types.ts +155 -0
  38. cognitivesystems-0.0.2/frontend/src/ui.tsx +89 -0
  39. cognitivesystems-0.0.2/frontend/tsconfig.json +23 -0
  40. cognitivesystems-0.0.2/frontend/vite.config.ts +24 -0
  41. cognitivesystems-0.0.2/hatch_build.py +65 -0
  42. cognitivesystems-0.0.2/profiles/README.md +72 -0
  43. cognitivesystems-0.0.2/profiles/homeserver.yml +46 -0
  44. cognitivesystems-0.0.2/profiles/localdev.yml +41 -0
  45. cognitivesystems-0.0.2/pyproject.toml +96 -0
  46. cognitivesystems-0.0.2/services/adguard/service.yml +19 -0
  47. cognitivesystems-0.0.2/services/autobrr/service.yml +18 -0
  48. cognitivesystems-0.0.2/services/bazarr/service.yml +21 -0
  49. cognitivesystems-0.0.2/services/betterdesk/service.yml +106 -0
  50. cognitivesystems-0.0.2/services/byparr/service.yml +25 -0
  51. cognitivesystems-0.0.2/services/chrome/service.yml +29 -0
  52. cognitivesystems-0.0.2/services/code-server/service.yml +23 -0
  53. cognitivesystems-0.0.2/services/crontabui/service.yml +22 -0
  54. cognitivesystems-0.0.2/services/crossseed/service.yml +26 -0
  55. cognitivesystems-0.0.2/services/firefox/service.yml +29 -0
  56. cognitivesystems-0.0.2/services/flaresolverr/service.yml +23 -0
  57. cognitivesystems-0.0.2/services/heimdall/service.yml +21 -0
  58. cognitivesystems-0.0.2/services/install_order.yml +8 -0
  59. cognitivesystems-0.0.2/services/jackett/service.yml +20 -0
  60. cognitivesystems-0.0.2/services/maintainerr/service.yml +19 -0
  61. cognitivesystems-0.0.2/services/mariadb/service.yml +26 -0
  62. cognitivesystems-0.0.2/services/mongodb/service.yml +19 -0
  63. cognitivesystems-0.0.2/services/mqtt-broker/service.yml +22 -0
  64. cognitivesystems-0.0.2/services/mysql/service.yml +19 -0
  65. cognitivesystems-0.0.2/services/ollama/service.yml +19 -0
  66. cognitivesystems-0.0.2/services/openwebui/service.yml +24 -0
  67. cognitivesystems-0.0.2/services/paperless/service.yml +74 -0
  68. cognitivesystems-0.0.2/services/plex/service.yml +28 -0
  69. cognitivesystems-0.0.2/services/portainer/service.yml +25 -0
  70. cognitivesystems-0.0.2/services/profilarr/service.yml +18 -0
  71. cognitivesystems-0.0.2/services/prowlarr/service.yml +20 -0
  72. cognitivesystems-0.0.2/services/qbittorrent/service.yml +28 -0
  73. cognitivesystems-0.0.2/services/qbittorrent/sidecars/ext_webhooks.sh +59 -0
  74. cognitivesystems-0.0.2/services/radarr/service.yml +21 -0
  75. cognitivesystems-0.0.2/services/rarrnomore/service.yml +22 -0
  76. cognitivesystems-0.0.2/services/seerr/service.yml +18 -0
  77. cognitivesystems-0.0.2/services/sftpgo/service.yml +33 -0
  78. cognitivesystems-0.0.2/services/snappymail/service.yml +18 -0
  79. cognitivesystems-0.0.2/services/sonarr/service.yml +21 -0
  80. cognitivesystems-0.0.2/services/stalwart/service.yml +50 -0
  81. cognitivesystems-0.0.2/services/stash/service.yml +28 -0
  82. cognitivesystems-0.0.2/services/tautulli/service.yml +21 -0
  83. cognitivesystems-0.0.2/services/threadfin/service.yml +20 -0
  84. cognitivesystems-0.0.2/services/traefik/service.yml +116 -0
  85. cognitivesystems-0.0.2/services/traefik/sidecars/dynamic_config/tls.yml +6 -0
  86. cognitivesystems-0.0.2/services/uploadarr/service.yml +22 -0
  87. cognitivesystems-0.0.2/services/vaultwarden/service.yml +24 -0
  88. cognitivesystems-0.0.2/services/watchtower/service.yml +23 -0
  89. cognitivesystems-0.0.2/services/wg-easy/service.yml +31 -0
  90. cognitivesystems-0.0.2/services/whisparr/service.yml +21 -0
  91. cognitivesystems-0.0.2/services/wizarr/service.yml +18 -0
  92. cognitivesystems-0.0.2/src/cognitivesystems/__init__.py +8 -0
  93. cognitivesystems-0.0.2/src/cognitivesystems/__main__.py +7 -0
  94. cognitivesystems-0.0.2/src/cognitivesystems/bootstrap.py +10 -0
  95. cognitivesystems-0.0.2/src/cognitivesystems/catalog.py +65 -0
  96. cognitivesystems-0.0.2/src/cognitivesystems/cli.py +540 -0
  97. cognitivesystems-0.0.2/src/cognitivesystems/config.py +104 -0
  98. cognitivesystems-0.0.2/src/cognitivesystems/core/__init__.py +8 -0
  99. cognitivesystems-0.0.2/src/cognitivesystems/core/capabilities.py +149 -0
  100. cognitivesystems-0.0.2/src/cognitivesystems/core/dockerctl.py +627 -0
  101. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/__init__.py +14 -0
  102. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/config.py +350 -0
  103. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/custom.py +279 -0
  104. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/docker.py +356 -0
  105. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/jobs.py +60 -0
  106. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/network.py +257 -0
  107. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/overview.py +48 -0
  108. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/services.py +475 -0
  109. cognitivesystems-0.0.2/src/cognitivesystems/core/ops/system.py +149 -0
  110. cognitivesystems-0.0.2/src/cognitivesystems/core/registry.py +42 -0
  111. cognitivesystems-0.0.2/src/cognitivesystems/core/runner.py +364 -0
  112. cognitivesystems-0.0.2/src/cognitivesystems/credentials.py +502 -0
  113. cognitivesystems-0.0.2/src/cognitivesystems/deploy.py +453 -0
  114. cognitivesystems-0.0.2/src/cognitivesystems/hooks.py +335 -0
  115. cognitivesystems-0.0.2/src/cognitivesystems/hydrate.py +64 -0
  116. cognitivesystems-0.0.2/src/cognitivesystems/render.py +1058 -0
  117. cognitivesystems-0.0.2/src/cognitivesystems/state.py +393 -0
  118. cognitivesystems-0.0.2/src/cognitivesystems/system.py +351 -0
  119. cognitivesystems-0.0.2/src/cognitivesystems/tui/__init__.py +13 -0
  120. cognitivesystems-0.0.2/src/cognitivesystems/tui/app.py +405 -0
  121. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/__init__.py +13 -0
  122. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/config.py +97 -0
  123. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/custom.py +102 -0
  124. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/docker.py +154 -0
  125. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/jobs.py +72 -0
  126. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/network.py +130 -0
  127. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/overview.py +76 -0
  128. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/registries.py +107 -0
  129. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/secrets.py +123 -0
  130. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/services.py +228 -0
  131. cognitivesystems-0.0.2/src/cognitivesystems/tui/screens/system.py +135 -0
  132. cognitivesystems-0.0.2/src/cognitivesystems/web/__init__.py +7 -0
  133. cognitivesystems-0.0.2/src/cognitivesystems/web/app.py +128 -0
  134. cognitivesystems-0.0.2/src/cognitivesystems/web/auth.py +167 -0
  135. cognitivesystems-0.0.2/src/cognitivesystems/web/deps.py +187 -0
  136. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/__init__.py +12 -0
  137. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/config.py +319 -0
  138. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/custom.py +263 -0
  139. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/docker.py +501 -0
  140. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/jobs.py +100 -0
  141. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/networks.py +236 -0
  142. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/overview.py +31 -0
  143. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/services.py +342 -0
  144. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/settings.py +70 -0
  145. cognitivesystems-0.0.2/src/cognitivesystems/web/routers/system.py +202 -0
  146. cognitivesystems-0.0.2/src/cognitivesystems/web/schemas.py +54 -0
  147. cognitivesystems-0.0.2/src/cognitivesystems/web/security.py +235 -0
  148. cognitivesystems-0.0.2/src/cognitivesystems/web/server.py +72 -0
  149. cognitivesystems-0.0.2/src/cognitivesystems/web/settings.py +60 -0
  150. cognitivesystems-0.0.2/src/cognitivesystems/web/static/index.html +32 -0
  151. cognitivesystems-0.0.2/tests/README.md +45 -0
  152. cognitivesystems-0.0.2/tools/bootstrap-opencode.cmd +23 -0
  153. cognitivesystems-0.0.2/tools/bootstrap-opencode.ps1 +81 -0
  154. cognitivesystems-0.0.2/tools/check-operator-env-gates.sh +28 -0
  155. cognitivesystems-0.0.2/tools/e2e_server.py +87 -0
  156. cognitivesystems-0.0.2/tools/fix_tests_zero_env.py +28 -0
  157. cognitivesystems-0.0.2/tools/install-githooks.cmd +8 -0
  158. cognitivesystems-0.0.2/tools/rename_catalog_roots.py +31 -0
@@ -0,0 +1,49 @@
1
+ # Root credentials file — copy from .env.example, never commit real values
2
+ .env
3
+
4
+ # Test render artefacts — tests render under $CS_TMP (defaults to /tmp/cs-*,
5
+ # outside the repo). Nothing test-related is written into the tree.
6
+
7
+ # Python build / packaging artefacts (byte-compile, ruff cache, wheel builds)
8
+ __pycache__/
9
+ *.pyc
10
+ .ruff_cache/
11
+ .pytest_cache/
12
+ .coverage
13
+ build/
14
+ dist/
15
+ *.egg-info/
16
+ .venv/
17
+ venv/
18
+ # CLI render output (cognitivesystems render --out default)
19
+ render-out/
20
+
21
+ # Built dashboard SPA copied into the package at publish time (the committed
22
+ # placeholder web/static/index.html is replaced by the real Vite build in CI).
23
+ src/cognitivesystems/web/static/assets/
24
+
25
+ # Dev-only files (DEVELOPMENT.md, docs/development/, CLAUDE.md, .mcp.json,
26
+ # .claude/, tasks/, ...) are tracked on dev and stripped from main by the
27
+ # Release workflow — see .github/dev-only-paths. Only machine-local AI state
28
+ # stays untracked:
29
+ AGENT-HANDOFF.md
30
+ AGENTS.md
31
+ CLAUDE.md
32
+ .cursor/
33
+ .claude/
34
+ .mcp.json
35
+ .cursorrules
36
+ .aider*
37
+ .windsurf/
38
+ .copilot/
39
+ .continuedev/
40
+ .codeium/
41
+ opencode.json
42
+ .opencode/
43
+ .claude/settings.local.json
44
+
45
+ # Editor
46
+ *.swp
47
+ *.log
48
+ .vscode/
49
+ .idea/
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: cognitivesystems
3
+ Version: 0.0.2
4
+ Summary: Catalog-driven Docker homeserver deployer: per-service compose renderer + terminal UI.
5
+ Project-URL: Homepage, https://github.com/automationnexus/CognitiveSystems
6
+ Project-URL: Source, https://github.com/automationnexus/CognitiveSystems
7
+ Author: Tahasanul Abraham
8
+ License-Expression: MIT
9
+ Keywords: compose,deploy,docker,homeserver,self-hosted
10
+ Classifier: Environment :: Console
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: System :: Installation/Setup
14
+ Requires-Python: >=3.9
15
+ Requires-Dist: pyyaml>=6
16
+ Requires-Dist: textual>=0.60
17
+ Provides-Extra: dev
18
+ Requires-Dist: httpx>=0.26; extra == 'dev'
19
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
20
+ Requires-Dist: pytest>=8; extra == 'dev'
21
+ Requires-Dist: ruff>=0.5; extra == 'dev'
22
+ Provides-Extra: web
23
+ Requires-Dist: docker<8,>=7; extra == 'web'
24
+ Requires-Dist: fastapi>=0.115; extra == 'web'
25
+ Requires-Dist: itsdangerous>=2.2; extra == 'web'
26
+ Requires-Dist: pydantic>=2; extra == 'web'
27
+ Requires-Dist: python-multipart>=0.0.9; extra == 'web'
28
+ Requires-Dist: uvicorn[standard]>=0.30; extra == 'web'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # CognitiveSystems Deployment
32
+
33
+ A pip-installable deployment app for the CognitiveSystems Docker stack.
34
+ One package, 42 services — no per-service `git clone` at deploy time.
35
+
36
+ `cognitivesystems` renders a `docker-compose.yml` + `.env` for each service from
37
+ per-service definitions (`services/<name>/service.yml`) plus an **install profile**
38
+ that supplies the values specific to your machine (paths, network, ports, timezone),
39
+ then drives `docker compose`. Drive it from the **web dashboard**, the **terminal UI**,
40
+ or the CLI. Rendering works on any OS; **deploying needs Linux + Docker** (run it on the
41
+ server, or in WSL).
42
+
43
+ ---
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ pip install cognitivesystems # from PyPI
49
+ # or, from a clone (for development):
50
+ git clone https://github.com/automationnexus/CognitiveSystems.git
51
+ cd CognitiveSystems && pip install -e .
52
+ ```
53
+
54
+ Requires **Python 3.9+**; deploying additionally needs **Docker + compose v2** on a
55
+ Linux host (the app checks and tells you what's missing).
56
+
57
+ ---
58
+
59
+ ## Quick start
60
+
61
+ ```bash
62
+ pip install "cognitivesystems[web]" # include the web dashboard (optional extra)
63
+ sudo cognitivesystems # launch the dashboard (or the TUI); deploy actions need root
64
+ ```
65
+
66
+ With the `[web]` extra, `cognitivesystems` opens the **web dashboard** on `127.0.0.1:8800` — a
67
+ browser GUI that does everything the TUI does. Disable the dashboard with `dashboard.enabled: false` in
68
+ `state.json` to get the **terminal UI** instead (or run `cognitivesystems tui`). See [docs/dashboard.md](docs/dashboard.md).
69
+
70
+ The TUI lists every service (`✓` = installed) with a live deploy-log pane. Keys:
71
+ **`i`** install · **`u`** update · **`x`** uninstall · **`c`** configure · **`s`** service ·
72
+ **`g`** config · **`k`** secrets · **`d`** docker · **`n`** network · **`a`** apps · **`h`** host ·
73
+ **`r`** refresh · **`q`** quit (arrows/mouse to select). Great over SSH on the server.
74
+
75
+ Or use the CLI:
76
+
77
+ ```bash
78
+ # 1. pick an install profile (system-specific paths/network/ports/timezone)
79
+ cognitivesystems init --profile homeserver # NFS-backed homeserver (default)
80
+ cognitivesystems init --profile localdev # laptop / VM
81
+
82
+ # 2. set credentials (prompt; Enter = auto-generate a strong value). No defaults ship.
83
+ cognitivesystems configure # mode/domain + admin password, LE email,
84
+ # Cloudflare DNS token, per-service overrides
85
+
86
+ # 3. install services (Linux + Docker; needs root for docker/chown)
87
+ sudo cognitivesystems install traefik portainer plex uploadarr \
88
+ --mode public --domain example.com --auto-update --wildcard
89
+
90
+ # 4. update / list / uninstall
91
+ sudo cognitivesystems update # all installed
92
+ sudo cognitivesystems update traefik plex # specific services
93
+ cognitivesystems list # catalog (* = installed)
94
+ sudo cognitivesystems uninstall plex # remove service + working dir
95
+ sudo cognitivesystems uninstall plex --purge # also delete the data dir
96
+ ```
97
+
98
+ `homeserver` expects two NFS mounts to exist first — `/home/data` and
99
+ `/mnt/homeserver`. See [docs/services.md](docs/services.md#install-profiles) for the
100
+ mount layout and `localdev` caveats. Re-run `init --profile <name>` to switch profiles.
101
+
102
+ ### Reinstall an existing service
103
+
104
+ ```bash
105
+ sudo cognitivesystems install plex --force # uninstall then install (keeps data dir)
106
+ sudo cognitivesystems install plex --force --purge # same, but also drops the data dir
107
+ ```
108
+
109
+ Without `--force`, installing an already-installed service is a no-op.
110
+
111
+ ### Render only (any OS)
112
+
113
+ ```bash
114
+ cognitivesystems render plex --out ./out # write docker-compose.yml + .env, no deploy
115
+ ```
116
+
117
+ ### OS administration (Linux)
118
+
119
+ ```bash
120
+ sudo cognitivesystems system ssh-keygen --bits=8192 --install-to=admin,operator
121
+ sudo cognitivesystems system change-password --target=root --password='…' --enable-root-ssh
122
+ sudo cognitivesystems system media-user create
123
+ ```
124
+
125
+ See [docs/system-admin.md](docs/system-admin.md).
126
+
127
+ ---
128
+
129
+ ## Repository layout
130
+
131
+ ```
132
+ .
133
+ ├── pyproject.toml # package metadata (hatchling); entry point `cognitivesystems`
134
+ ├── frontend/ # React + Vite dashboard SPA (built into the wheel at package time)
135
+ ├── src/cognitivesystems/ # the app
136
+ │ ├── cli.py # CLI: list / render / init / install / update / uninstall / system / tui / web
137
+ │ ├── render.py # renderer: catalog + state -> docker-compose.yml + .env
138
+ │ ├── catalog.py state.py config.py deploy.py hooks.py system.py
139
+ │ ├── core/ # shared capability registry, job runner, Docker client, per-area ops
140
+ │ ├── tui/ # Textual terminal UI (app + per-area screens)
141
+ │ ├── web/ # FastAPI dashboard backend (serves the built SPA + JSON/WS API)
142
+ │ └── data/ # catalog bundled into the wheel (services + profiles)
143
+ ├── services/
144
+ │ ├── install_order.yml # infra precedence (db/proxy come up first)
145
+ │ └── <name>/
146
+ │ ├── service.yml # one service definition per folder
147
+ │ └── sidecars/ # optional static files (e.g. the qbittorrent webhook script)
148
+ ├── profiles/ # install profiles: homeserver.yml, localdev.yml
149
+ ├── tests/ # pytest (render parity, GUI⇄TUI parity, variants, profiles, …)
150
+ └── docs/ # install-guide, migration-guide, dashboard, services, networking, configuration, system-admin
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Deployment modes
156
+
157
+ | Mode | Flag | TLS | Use case |
158
+ |---|---|---|---|
159
+ | Public | `--mode public` | Let's Encrypt TLS-ALPN-01, one cert per subdomain | Internet-facing server |
160
+ | Public + Wildcard | `--mode public --wildcard` | Cloudflare DNS-01, single `*.<domain>` cert | Internet-facing, one cert for all |
161
+ | Private | `--mode private` | None | LAN access via IP or hostname |
162
+ | Local | `--mode local` | None | Single machine, `localhost` only |
163
+
164
+ `--wildcard` needs `--cf-token` (a scoped Cloudflare DNS-edit API token). Healthchecks
165
+ are not configured by the installer; use each image's built-in `HEALTHCHECK` if needed.
166
+
167
+ ---
168
+
169
+ ## Automatic install ordering
170
+
171
+ You never order services manually — infra installs first, in a fixed order:
172
+ `traefik → mariadb → mysql → mongodb → mqtt-broker`. Everything else follows.
173
+
174
+ ---
175
+
176
+ ## State & profile
177
+
178
+ Persisted under `/home/installation_cognitivesystems/state.json` (override with
179
+ `CS_STATE_DIR`):
180
+
181
+ - **Runtime config** — mode, domain, passwords, installed services. Saved as you install.
182
+ - **`.site`** — the system-specific values from your chosen install profile.
183
+
184
+ Re-running `update` re-renders every installed service from saved state. To change
185
+ domain / passwords / TLS mode: edit `state.json`, then `update`. To change profile
186
+ values (paths, ports, network): edit `profiles/<name>.yml` and re-run `init`.
187
+ See [docs/configuration.md](docs/configuration.md) for the schema.
188
+
189
+ ### Host file layout after install (homeserver defaults)
190
+
191
+ ```
192
+ ~/cognitivesystems/state/state.json # default state file (--state to override)
193
+ /home/<service>/{docker-compose.yml,.env} # per-service working dir (install_root)
194
+ /home/data/<ServiceDisplayName>/ # persistent app data (config_root)
195
+ ```
196
+
197
+ Data directories are never removed by `uninstall`; pass `--purge` to delete them too.
198
+ Paths resolve from `state.json` `.site.paths` after `init --profile <name>`.
199
+
200
+ ---
201
+
202
+ ## Services
203
+
204
+ 42 services. Full details: [docs/services.md](docs/services.md) · Port model: [docs/networking-and-ports.md](docs/networking-and-ports.md)
205
+
206
+ | Category | Services |
207
+ |---|---|
208
+ | Core infra | Traefik, Portainer, WatchTower, WG-Easy, CrontabUI |
209
+ | Databases | MariaDB, MySQL, MongoDB, MQTT-Broker |
210
+ | Media | Plex, Radarr, Sonarr, Prowlarr, Jackett, Bazarr, Tautulli, Stash, Whisparr, Threadfin, Seerr |
211
+ | Download | Qbittorrent, CrossSeed, Autobrr, Rarrnomore, FlareSolverr, Byparr |
212
+ | Files / Comms | SFTPGo, SnappyMail, Stalwart, Vaultwarden, Paperless |
213
+ | Dev / Tools | Code-Server, OpenWebUI, Profilarr, Maintainerr, Heimdall, Wizarr, AdGuard, BetterDesk, Firefox, Chrome |
214
+ | Custom | Uploadarr |
215
+
216
+ ---
217
+
218
+ ## Contributing
219
+
220
+ Development happens on the `dev` branch, which carries the developer documentation
221
+ (architecture, catalog reference, how to add a service, the test framework):
222
+
223
+ → [DEVELOPMENT.md on the `dev` branch](https://github.com/automationnexus/CognitiveSystems/blob/dev/DEVELOPMENT.md)
224
+
225
+ <!-- dev-ci-verify -->
226
+
227
+ <!-- nightly-e2e-verify -->
228
+
229
+ <!-- final-nightly-verify -->
@@ -0,0 +1,199 @@
1
+ # CognitiveSystems Deployment
2
+
3
+ A pip-installable deployment app for the CognitiveSystems Docker stack.
4
+ One package, 42 services — no per-service `git clone` at deploy time.
5
+
6
+ `cognitivesystems` renders a `docker-compose.yml` + `.env` for each service from
7
+ per-service definitions (`services/<name>/service.yml`) plus an **install profile**
8
+ that supplies the values specific to your machine (paths, network, ports, timezone),
9
+ then drives `docker compose`. Drive it from the **web dashboard**, the **terminal UI**,
10
+ or the CLI. Rendering works on any OS; **deploying needs Linux + Docker** (run it on the
11
+ server, or in WSL).
12
+
13
+ ---
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install cognitivesystems # from PyPI
19
+ # or, from a clone (for development):
20
+ git clone https://github.com/automationnexus/CognitiveSystems.git
21
+ cd CognitiveSystems && pip install -e .
22
+ ```
23
+
24
+ Requires **Python 3.9+**; deploying additionally needs **Docker + compose v2** on a
25
+ Linux host (the app checks and tells you what's missing).
26
+
27
+ ---
28
+
29
+ ## Quick start
30
+
31
+ ```bash
32
+ pip install "cognitivesystems[web]" # include the web dashboard (optional extra)
33
+ sudo cognitivesystems # launch the dashboard (or the TUI); deploy actions need root
34
+ ```
35
+
36
+ With the `[web]` extra, `cognitivesystems` opens the **web dashboard** on `127.0.0.1:8800` — a
37
+ browser GUI that does everything the TUI does. Disable the dashboard with `dashboard.enabled: false` in
38
+ `state.json` to get the **terminal UI** instead (or run `cognitivesystems tui`). See [docs/dashboard.md](docs/dashboard.md).
39
+
40
+ The TUI lists every service (`✓` = installed) with a live deploy-log pane. Keys:
41
+ **`i`** install · **`u`** update · **`x`** uninstall · **`c`** configure · **`s`** service ·
42
+ **`g`** config · **`k`** secrets · **`d`** docker · **`n`** network · **`a`** apps · **`h`** host ·
43
+ **`r`** refresh · **`q`** quit (arrows/mouse to select). Great over SSH on the server.
44
+
45
+ Or use the CLI:
46
+
47
+ ```bash
48
+ # 1. pick an install profile (system-specific paths/network/ports/timezone)
49
+ cognitivesystems init --profile homeserver # NFS-backed homeserver (default)
50
+ cognitivesystems init --profile localdev # laptop / VM
51
+
52
+ # 2. set credentials (prompt; Enter = auto-generate a strong value). No defaults ship.
53
+ cognitivesystems configure # mode/domain + admin password, LE email,
54
+ # Cloudflare DNS token, per-service overrides
55
+
56
+ # 3. install services (Linux + Docker; needs root for docker/chown)
57
+ sudo cognitivesystems install traefik portainer plex uploadarr \
58
+ --mode public --domain example.com --auto-update --wildcard
59
+
60
+ # 4. update / list / uninstall
61
+ sudo cognitivesystems update # all installed
62
+ sudo cognitivesystems update traefik plex # specific services
63
+ cognitivesystems list # catalog (* = installed)
64
+ sudo cognitivesystems uninstall plex # remove service + working dir
65
+ sudo cognitivesystems uninstall plex --purge # also delete the data dir
66
+ ```
67
+
68
+ `homeserver` expects two NFS mounts to exist first — `/home/data` and
69
+ `/mnt/homeserver`. See [docs/services.md](docs/services.md#install-profiles) for the
70
+ mount layout and `localdev` caveats. Re-run `init --profile <name>` to switch profiles.
71
+
72
+ ### Reinstall an existing service
73
+
74
+ ```bash
75
+ sudo cognitivesystems install plex --force # uninstall then install (keeps data dir)
76
+ sudo cognitivesystems install plex --force --purge # same, but also drops the data dir
77
+ ```
78
+
79
+ Without `--force`, installing an already-installed service is a no-op.
80
+
81
+ ### Render only (any OS)
82
+
83
+ ```bash
84
+ cognitivesystems render plex --out ./out # write docker-compose.yml + .env, no deploy
85
+ ```
86
+
87
+ ### OS administration (Linux)
88
+
89
+ ```bash
90
+ sudo cognitivesystems system ssh-keygen --bits=8192 --install-to=admin,operator
91
+ sudo cognitivesystems system change-password --target=root --password='…' --enable-root-ssh
92
+ sudo cognitivesystems system media-user create
93
+ ```
94
+
95
+ See [docs/system-admin.md](docs/system-admin.md).
96
+
97
+ ---
98
+
99
+ ## Repository layout
100
+
101
+ ```
102
+ .
103
+ ├── pyproject.toml # package metadata (hatchling); entry point `cognitivesystems`
104
+ ├── frontend/ # React + Vite dashboard SPA (built into the wheel at package time)
105
+ ├── src/cognitivesystems/ # the app
106
+ │ ├── cli.py # CLI: list / render / init / install / update / uninstall / system / tui / web
107
+ │ ├── render.py # renderer: catalog + state -> docker-compose.yml + .env
108
+ │ ├── catalog.py state.py config.py deploy.py hooks.py system.py
109
+ │ ├── core/ # shared capability registry, job runner, Docker client, per-area ops
110
+ │ ├── tui/ # Textual terminal UI (app + per-area screens)
111
+ │ ├── web/ # FastAPI dashboard backend (serves the built SPA + JSON/WS API)
112
+ │ └── data/ # catalog bundled into the wheel (services + profiles)
113
+ ├── services/
114
+ │ ├── install_order.yml # infra precedence (db/proxy come up first)
115
+ │ └── <name>/
116
+ │ ├── service.yml # one service definition per folder
117
+ │ └── sidecars/ # optional static files (e.g. the qbittorrent webhook script)
118
+ ├── profiles/ # install profiles: homeserver.yml, localdev.yml
119
+ ├── tests/ # pytest (render parity, GUI⇄TUI parity, variants, profiles, …)
120
+ └── docs/ # install-guide, migration-guide, dashboard, services, networking, configuration, system-admin
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Deployment modes
126
+
127
+ | Mode | Flag | TLS | Use case |
128
+ |---|---|---|---|
129
+ | Public | `--mode public` | Let's Encrypt TLS-ALPN-01, one cert per subdomain | Internet-facing server |
130
+ | Public + Wildcard | `--mode public --wildcard` | Cloudflare DNS-01, single `*.<domain>` cert | Internet-facing, one cert for all |
131
+ | Private | `--mode private` | None | LAN access via IP or hostname |
132
+ | Local | `--mode local` | None | Single machine, `localhost` only |
133
+
134
+ `--wildcard` needs `--cf-token` (a scoped Cloudflare DNS-edit API token). Healthchecks
135
+ are not configured by the installer; use each image's built-in `HEALTHCHECK` if needed.
136
+
137
+ ---
138
+
139
+ ## Automatic install ordering
140
+
141
+ You never order services manually — infra installs first, in a fixed order:
142
+ `traefik → mariadb → mysql → mongodb → mqtt-broker`. Everything else follows.
143
+
144
+ ---
145
+
146
+ ## State & profile
147
+
148
+ Persisted under `/home/installation_cognitivesystems/state.json` (override with
149
+ `CS_STATE_DIR`):
150
+
151
+ - **Runtime config** — mode, domain, passwords, installed services. Saved as you install.
152
+ - **`.site`** — the system-specific values from your chosen install profile.
153
+
154
+ Re-running `update` re-renders every installed service from saved state. To change
155
+ domain / passwords / TLS mode: edit `state.json`, then `update`. To change profile
156
+ values (paths, ports, network): edit `profiles/<name>.yml` and re-run `init`.
157
+ See [docs/configuration.md](docs/configuration.md) for the schema.
158
+
159
+ ### Host file layout after install (homeserver defaults)
160
+
161
+ ```
162
+ ~/cognitivesystems/state/state.json # default state file (--state to override)
163
+ /home/<service>/{docker-compose.yml,.env} # per-service working dir (install_root)
164
+ /home/data/<ServiceDisplayName>/ # persistent app data (config_root)
165
+ ```
166
+
167
+ Data directories are never removed by `uninstall`; pass `--purge` to delete them too.
168
+ Paths resolve from `state.json` `.site.paths` after `init --profile <name>`.
169
+
170
+ ---
171
+
172
+ ## Services
173
+
174
+ 42 services. Full details: [docs/services.md](docs/services.md) · Port model: [docs/networking-and-ports.md](docs/networking-and-ports.md)
175
+
176
+ | Category | Services |
177
+ |---|---|
178
+ | Core infra | Traefik, Portainer, WatchTower, WG-Easy, CrontabUI |
179
+ | Databases | MariaDB, MySQL, MongoDB, MQTT-Broker |
180
+ | Media | Plex, Radarr, Sonarr, Prowlarr, Jackett, Bazarr, Tautulli, Stash, Whisparr, Threadfin, Seerr |
181
+ | Download | Qbittorrent, CrossSeed, Autobrr, Rarrnomore, FlareSolverr, Byparr |
182
+ | Files / Comms | SFTPGo, SnappyMail, Stalwart, Vaultwarden, Paperless |
183
+ | Dev / Tools | Code-Server, OpenWebUI, Profilarr, Maintainerr, Heimdall, Wizarr, AdGuard, BetterDesk, Firefox, Chrome |
184
+ | Custom | Uploadarr |
185
+
186
+ ---
187
+
188
+ ## Contributing
189
+
190
+ Development happens on the `dev` branch, which carries the developer documentation
191
+ (architecture, catalog reference, how to add a service, the test framework):
192
+
193
+ → [DEVELOPMENT.md on the `dev` branch](https://github.com/automationnexus/CognitiveSystems/blob/dev/DEVELOPMENT.md)
194
+
195
+ <!-- dev-ci-verify -->
196
+
197
+ <!-- nightly-e2e-verify -->
198
+
199
+ <!-- final-nightly-verify -->
@@ -0,0 +1,11 @@
1
+ node_modules
2
+ dist
3
+ coverage
4
+ *.local
5
+ .vite
6
+
7
+ # Playwright e2e artefacts
8
+ e2e/.auth
9
+ test-results
10
+ playwright-report
11
+ playwright/.cache
@@ -0,0 +1,15 @@
1
+ import { expect, test as setup } from '@playwright/test'
2
+ import { ADMIN, AUTH_FILE } from './fixtures'
3
+
4
+ // First-run against a fresh state (no admin password): the sign-in screen shows the one-time
5
+ // "create admin password" form. Setting it must land on the dashboard. This also primes the
6
+ // password for every other spec (it persists in the server's state).
7
+ setup('first-run creates the admin password', async ({ page }) => {
8
+ await page.goto('/')
9
+ await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible()
10
+ await page.getByLabel('New password').fill(ADMIN.pass)
11
+ await page.getByLabel('Confirm password').fill(ADMIN.pass)
12
+ await page.getByRole('button', { name: /create & sign in/i }).click()
13
+ await expect(page.getByRole('heading', { name: 'Overview' })).toBeVisible()
14
+ await page.context().storageState({ path: AUTH_FILE }) // reused by every other spec
15
+ })
@@ -0,0 +1,47 @@
1
+ import { expect, test } from '@playwright/test'
2
+
3
+ const PAGES: ReadonlyArray<readonly [string, string]> = [
4
+ ['Services', 'Services'],
5
+ ['Config', 'Configuration'],
6
+ ['Docker', 'Docker'],
7
+ ['Networks', 'Managed networks'],
8
+ ['Apps', 'Custom apps'],
9
+ ['Host', 'Host administration'],
10
+ ['Jobs', 'Jobs'],
11
+ ]
12
+
13
+ test('navigates every page without a runtime error', async ({ page }) => {
14
+ const errors: string[] = []
15
+ page.on('pageerror', (e) => errors.push(String(e)))
16
+ await page.goto('/')
17
+ await expect(page.getByRole('heading', { name: 'Overview' })).toBeVisible()
18
+ for (const [nav, heading] of PAGES) {
19
+ await page.getByRole('link', { name: nav, exact: true }).click()
20
+ await expect(page.getByRole('heading', { level: 1, name: heading })).toBeVisible()
21
+ }
22
+ await page.getByRole('link', { name: 'Overview', exact: true }).click()
23
+ await expect(page.getByRole('heading', { name: 'Overview' })).toBeVisible()
24
+ expect(errors, errors.join('\n')).toEqual([])
25
+ })
26
+
27
+ test('theme toggle flips data-theme', async ({ page }) => {
28
+ await page.goto('/')
29
+ await expect(page.getByRole('heading', { name: 'Overview' })).toBeVisible()
30
+ const before = await page.evaluate(() => document.documentElement.dataset.theme)
31
+ await page.getByRole('button', { name: /light|dark/i }).click()
32
+ const after = await page.evaluate(() => document.documentElement.dataset.theme)
33
+ expect(after).not.toBe(before)
34
+ })
35
+
36
+ test('logout returns to the sign-in screen', async ({ page }) => {
37
+ await page.goto('/')
38
+ await page.getByRole('button', { name: /logout/i }).click()
39
+ await expect(page.getByRole('heading', { name: 'Sign in' })).toBeVisible()
40
+ })
41
+
42
+ test('responsive: the nav still works at mobile width', async ({ page }) => {
43
+ await page.setViewportSize({ width: 390, height: 800 })
44
+ await page.goto('/')
45
+ await page.getByRole('link', { name: 'Docker', exact: true }).click()
46
+ await expect(page.getByRole('heading', { name: 'Docker' })).toBeVisible()
47
+ })
@@ -0,0 +1,41 @@
1
+ import { expect, test } from '@playwright/test'
2
+
3
+ async function gotoDocker(page: import('@playwright/test').Page) {
4
+ await page.goto('/')
5
+ await page.getByRole('link', { name: 'Docker', exact: true }).click()
6
+ await expect(page.getByRole('heading', { name: 'Docker' })).toBeVisible()
7
+ }
8
+
9
+ test('containers tab streams logs and exec over websockets', async ({ page }) => {
10
+ await gotoDocker(page)
11
+ await expect(page.getByText('nginx-demo')).toBeVisible()
12
+
13
+ // logs websocket → "fake log line"
14
+ await page.getByRole('button', { name: 'logs' }).click()
15
+ await expect(page.getByText('fake log line')).toBeVisible({ timeout: 10000 })
16
+ await page.getByRole('button', { name: '✕' }).click()
17
+
18
+ // exec websocket (CSRF-gated) echoes the command output
19
+ await page.getByRole('button', { name: 'exec' }).click()
20
+ await page.getByPlaceholder(/command/).fill('ls -la')
21
+ await page.getByRole('button', { name: 'Run' }).click()
22
+ await expect(page.getByText(/ran:/)).toBeVisible({ timeout: 10000 })
23
+ await page.getByRole('button', { name: '✕' }).click()
24
+ })
25
+
26
+ test('images and volumes tabs show seeded data', async ({ page }) => {
27
+ await gotoDocker(page)
28
+ await page.getByRole('button', { name: 'images' }).click()
29
+ await expect(page.getByText('nginx:alpine')).toBeVisible()
30
+ await page.getByRole('button', { name: 'volumes' }).click()
31
+ await expect(page.getByText('demo-vol')).toBeVisible()
32
+ })
33
+
34
+ test('confirm modal cancels a destructive action (no window.confirm)', async ({ page }) => {
35
+ await gotoDocker(page)
36
+ // "remove" opens the glass confirm dialog; cancelling keeps the container
37
+ await page.getByRole('button', { name: 'remove', exact: true }).first().click()
38
+ await expect(page.getByRole('dialog')).toContainText(/Remove container/)
39
+ await page.getByRole('button', { name: 'Cancel' }).click()
40
+ await expect(page.getByText('nginx-demo')).toBeVisible()
41
+ })
@@ -0,0 +1,7 @@
1
+ // >= 8 chars to satisfy the first-run min-length check.
2
+ export const ADMIN = { user: 'admin', pass: 'e2e-password-123' }
3
+
4
+ // auth.setup.ts signs in once and saves the session here; the chromium project reuses it
5
+ // (storageState), so specs start authenticated — one login total, which also keeps the backend
6
+ // login rate-limiter (5/60s per IP) from tripping across parallel specs.
7
+ export const AUTH_FILE = 'e2e/.auth/state.json'
@@ -0,0 +1,14 @@
1
+ import { expect, test } from '@playwright/test'
2
+
3
+ test('install streams a job log to completion', async ({ page }) => {
4
+ await page.goto('/')
5
+ await page.getByRole('link', { name: 'Services', exact: true }).click()
6
+ await expect(page.getByRole('heading', { name: 'Services' })).toBeVisible()
7
+
8
+ // open a service's Manage modal and kick off an install — the fake runner emits two lines
9
+ // and exits 0, so the JobLog websocket streams to a "done (rc=0)" end frame.
10
+ await page.getByRole('button', { name: 'Manage' }).first().click()
11
+ await expect(page.getByRole('dialog')).toBeVisible()
12
+ await page.getByRole('button', { name: 'Install', exact: true }).click()
13
+ await expect(page.getByText(/rc=0/)).toBeVisible({ timeout: 15000 })
14
+ })
@@ -0,0 +1,19 @@
1
+ import js from '@eslint/js'
2
+ import reactHooks from 'eslint-plugin-react-hooks'
3
+ import reactRefresh from 'eslint-plugin-react-refresh'
4
+ import globals from 'globals'
5
+ import tseslint from 'typescript-eslint'
6
+
7
+ export default tseslint.config(
8
+ { ignores: ['dist', 'coverage', 'node_modules'] },
9
+ {
10
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
11
+ files: ['**/*.{ts,tsx}'],
12
+ languageOptions: { ecmaVersion: 2022, globals: globals.browser },
13
+ plugins: { 'react-hooks': reactHooks, 'react-refresh': reactRefresh },
14
+ rules: {
15
+ ...reactHooks.configs.recommended.rules,
16
+ 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
17
+ },
18
+ },
19
+ )
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en" data-theme="dark">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>CognitiveSystems Dashboard</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>