fadenstack 0.4.3__tar.gz → 0.4.4rc1__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 (153) hide show
  1. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/PKG-INFO +3 -3
  2. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/pyproject.toml +3 -3
  3. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/__init__.py +1 -1
  4. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/docker-compose.yaml +84 -2
  5. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/locations.conf +28 -0
  6. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/cli.py +2 -0
  7. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/admin.py +6 -1
  8. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/backup.py +12 -3
  9. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/deploy.py +103 -34
  10. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_up.py +2 -2
  11. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/rebuild.py +9 -1
  12. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/restore.py +43 -17
  13. fadenstack-0.4.4rc1/src/faden_cli/commands/secrets.py +145 -0
  14. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/upgrade.py +9 -1
  15. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/backup.py +364 -14
  16. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/compose.py +22 -1
  17. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/dev_modules.py +3 -0
  18. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/env_gen.py +106 -7
  19. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/local_node.py +180 -65
  20. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/maintenance.py +2 -2
  21. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/registry.py +8 -0
  22. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/release_feed.py +3 -1
  23. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/schedule.py +1 -1
  24. fadenstack-0.4.4rc1/src/faden_cli/core/secret_rotation.py +451 -0
  25. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/conftest.py +10 -0
  26. fadenstack-0.4.4rc1/tests/test_backup_retention.py +79 -0
  27. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_backup_schedule.py +2 -2
  28. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_backup_volumes.py +52 -0
  29. fadenstack-0.4.4rc1/tests/test_binary_notices.py +126 -0
  30. fadenstack-0.4.4rc1/tests/test_data_volumes_logs.py +350 -0
  31. fadenstack-0.4.4rc1/tests/test_deploy_summary.py +23 -0
  32. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_dev_up_terminal.py +2 -0
  33. fadenstack-0.4.4rc1/tests/test_generated_env_reaches_compose.py +58 -0
  34. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_installation.py +2 -2
  35. fadenstack-0.4.4rc1/tests/test_internal_token_env.py +86 -0
  36. fadenstack-0.4.4rc1/tests/test_local_node.py +151 -0
  37. fadenstack-0.4.4rc1/tests/test_rebuild.py +48 -0
  38. fadenstack-0.4.4rc1/tests/test_redis_limits.py +56 -0
  39. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_release_bundle.py +6 -0
  40. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_release_feed.py +7 -0
  41. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_required_env.py +51 -4
  42. fadenstack-0.4.4rc1/tests/test_restore_maintenance.py +96 -0
  43. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_runtime_images.py +2 -2
  44. fadenstack-0.4.4rc1/tests/test_secret_rotation.py +443 -0
  45. fadenstack-0.4.4rc1/tests/test_service_logins.py +63 -0
  46. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_tls.py +10 -10
  47. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_tls_renew.py +4 -4
  48. fadenstack-0.4.3/OFFICIAL.md +0 -9
  49. fadenstack-0.4.3/src/faden_cli/bundle/shared/OFFICIAL.md +0 -9
  50. fadenstack-0.4.3/tests/test_generated_env_reaches_compose.py +0 -32
  51. fadenstack-0.4.3/tests/test_internal_token_env.py +0 -34
  52. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/.gitignore +0 -0
  53. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/LICENSE +0 -0
  54. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/NOTICE +0 -0
  55. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/README.md +0 -0
  56. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/hatch_build.py +0 -0
  57. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/__main__.py +0 -0
  58. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/.gitignore +0 -0
  59. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/LICENSE +0 -0
  60. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/NOTICE +0 -0
  61. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/README.md +0 -0
  62. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/agent-binaries/.gitignore +0 -0
  63. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/alloy/config.alloy +0 -0
  64. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/clickhouse/config.d/system-logs.xml +0 -0
  65. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/docker-compose.gpu.yaml +0 -0
  66. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/grafana/dashboards/templates/vllm-runtime.json +0 -0
  67. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/grafana/provisioning/dashboards/dashboard.yml +0 -0
  68. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/grafana/provisioning/dashboards/json/faden-overview.json +0 -0
  69. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/grafana/provisioning/datasources/ds.yaml +0 -0
  70. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/grafana/provisioning/datasources/prometheus.yaml +0 -0
  71. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/initdb/01-init.sql +0 -0
  72. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/loki/local-config.yaml +0 -0
  73. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/maintenance.html +0 -0
  74. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/nginx-tls.conf +0 -0
  75. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/nginx.conf +0 -0
  76. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/rate-limits.conf +0 -0
  77. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/security-headers.conf +0 -0
  78. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/nginx/select-config.sh +0 -0
  79. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/prometheus/prometheus.yml +0 -0
  80. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/rabbitmq/definitions.json.example +0 -0
  81. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/bundle/shared/tls/README.md +0 -0
  82. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/__init__.py +0 -0
  83. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/config.py +0 -0
  84. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/__init__.py +0 -0
  85. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_doctor.py +0 -0
  86. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_down.py +0 -0
  87. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_group.py +0 -0
  88. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_init.py +0 -0
  89. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_pull.py +0 -0
  90. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/dev/dev_status.py +0 -0
  91. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/doctor.py +0 -0
  92. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/down.py +0 -0
  93. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/logs_cmd.py +0 -0
  94. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/maintenance.py +0 -0
  95. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/module.py +0 -0
  96. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/observe.py +0 -0
  97. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/ports.py +0 -0
  98. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/runtime_images.py +0 -0
  99. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/status.py +0 -0
  100. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/tls.py +0 -0
  101. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/tune.py +0 -0
  102. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/up.py +0 -0
  103. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/commands/version.py +0 -0
  104. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/__init__.py +0 -0
  105. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/api_client.py +0 -0
  106. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/bootstrap.py +0 -0
  107. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/bundle.py +0 -0
  108. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/clickhouse.py +0 -0
  109. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/console.py +0 -0
  110. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/detect.py +0 -0
  111. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/docker_env.py +0 -0
  112. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/edge.py +0 -0
  113. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/git.py +0 -0
  114. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/install.py +0 -0
  115. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/installation.py +0 -0
  116. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/private_files.py +0 -0
  117. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/rmq.py +0 -0
  118. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/runtime_images.py +0 -0
  119. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/settings.py +0 -0
  120. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/sysinfo.py +0 -0
  121. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/tls.py +0 -0
  122. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/tune.py +0 -0
  123. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/update_check.py +0 -0
  124. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/core/workspace.py +0 -0
  125. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/templates/env.j2 +0 -0
  126. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/tui/__init__.py +0 -0
  127. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/tui/widgets/__init__.py +0 -0
  128. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/src/faden_cli/tui/wizard/__init__.py +0 -0
  129. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_backup_tls.py +0 -0
  130. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_bootstrap_token.py +0 -0
  131. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_cli_output_encoding.py +0 -0
  132. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_dev_env_loopback.py +0 -0
  133. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_dev_modules.py +0 -0
  134. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_dev_up_port_holders.py +0 -0
  135. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_dev_up_reclaim.py +0 -0
  136. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_dev_up_service_hosts.py +0 -0
  137. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_docker_env.py +0 -0
  138. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_doctor_ports.py +0 -0
  139. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_edge.py +0 -0
  140. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_main.py +0 -0
  141. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_maintenance.py +0 -0
  142. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_module_env.py +0 -0
  143. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_postgres_logins.py +0 -0
  144. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_private_files.py +0 -0
  145. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_registry_gateway_env.py +0 -0
  146. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_shared_compose_ports.py +0 -0
  147. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_tune.py +0 -0
  148. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_tune_memory.py +0 -0
  149. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_update_check.py +0 -0
  150. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_update_feed.py +0 -0
  151. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_upgrade_housekeeping.py +0 -0
  152. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_upgrade_rabbitmq.py +0 -0
  153. {fadenstack-0.4.3 → fadenstack-0.4.4rc1}/tests/test_workspace_detection.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: fadenstack
3
- Version: 0.4.3
3
+ Version: 0.4.4rc1
4
4
  Summary: CLI installer and management tool for the Fadenstack platform
5
- Project-URL: Homepage, https://fadenstack.github.io
5
+ Project-URL: Homepage, https://fadenstack.com
6
6
  Project-URL: Repository, https://github.com/fadenstack/fadenstack
7
- Project-URL: Documentation, https://fadenstack.github.io/docs
7
+ Project-URL: Documentation, https://help.fadenstack.com
8
8
  Project-URL: Issues, https://github.com/fadenstack/fadenstack/issues
9
9
  Author-email: Sachith Liyanagama <liyanagama@outlook.de>
10
10
  Maintainer-email: Sachith Liyanagama <liyanagama@outlook.de>
@@ -10,7 +10,7 @@ packages = ["src/faden_cli"]
10
10
 
11
11
  [project]
12
12
  name = "fadenstack"
13
- version = "0.4.3"
13
+ version = "0.4.4rc1"
14
14
  requires-python = ">=3.12,<4.0"
15
15
  description = "CLI installer and management tool for the Fadenstack platform"
16
16
  authors = [
@@ -49,9 +49,9 @@ dependencies = [
49
49
  ]
50
50
 
51
51
  [project.urls]
52
- Homepage = "https://fadenstack.github.io"
52
+ Homepage = "https://fadenstack.com"
53
53
  Repository = "https://github.com/fadenstack/fadenstack"
54
- Documentation = "https://fadenstack.github.io/docs"
54
+ Documentation = "https://help.fadenstack.com"
55
55
  Issues = "https://github.com/fadenstack/fadenstack/issues"
56
56
 
57
57
  [project.scripts]
@@ -13,4 +13,4 @@ Module activation via Docker Compose profiles.
13
13
  All secrets generated securely during init phase.
14
14
  """
15
15
 
16
- __version__ = "0.4.3"
16
+ __version__ = "0.4.4rc1"
@@ -11,6 +11,16 @@
11
11
  # unpacks the release into (~/fadenstack by default).
12
12
  name: fadenstack
13
13
 
14
+ # Docker's own log of every container (what `docker logs` and Alloy read) rotates:
15
+ # at most FADEN_LOG_MAX_FILE files of FADEN_LOG_MAX_SIZE each per container, the
16
+ # oldest dropped. Without it the json-file driver grows until the disk is full.
17
+ # Set in .env (faden deploy --log-max-size / --log-max-file; Help: Installing).
18
+ x-logging: &faden-logging
19
+ driver: json-file
20
+ options:
21
+ max-size: ${FADEN_LOG_MAX_SIZE:-50m}
22
+ max-file: "${FADEN_LOG_MAX_FILE:-5}"
23
+
14
24
  services:
15
25
  # -----------------------------
16
26
  # Platform base image (build-only, no runtime container)
@@ -28,6 +38,7 @@ services:
28
38
  nginx:
29
39
  image: nginx:1-alpine
30
40
  container_name: faden-nginx
41
+ logging: *faden-logging
31
42
  restart: unless-stopped
32
43
  ports:
33
44
  - "${FADEN_HTTP_PORT:-80}:80"
@@ -67,6 +78,7 @@ services:
67
78
  postgres:
68
79
  image: pgvector/pgvector:pg17
69
80
  container_name: faden-postgres
81
+ logging: *faden-logging
70
82
  restart: unless-stopped
71
83
  # Parallel index builds (pgvector HNSW) work in shared memory; Docker's
72
84
  # default 64 MB /dev/shm fails them ("could not resize shared memory
@@ -106,6 +118,7 @@ services:
106
118
  # CLICKHOUSE_IMAGE=clickhouse/clickhouse-server:<tag>
107
119
  image: ${CLICKHOUSE_IMAGE:-clickhouse/clickhouse-server:25.10}
108
120
  container_name: faden-clickhouse
121
+ logging: *faden-logging
109
122
  restart: unless-stopped
110
123
  user: "101:101"
111
124
  environment:
@@ -131,13 +144,24 @@ services:
131
144
  redis:
132
145
  image: redis:7.2
133
146
  container_name: faden-redis
147
+ logging: *faden-logging
134
148
  restart: unless-stopped
149
+ # Capped, so a runaway writer fills Redis rather than the host: at the cap Redis refuses writes
150
+ # (noeviction) and the writers carry on without them (a chat reply's shared log, device presence).
151
+ # It is not evicting because Langfuse's queues (BullMQ) and the chat replies' live events must not
152
+ # be dropped silently. Everything the gateway keeps here has a TTL; what it holds is a few tens
153
+ # of MB (110 MB for 9,500 replies kept 15 minutes in plain text, now 1 minute), so the 1gb default
154
+ # leaves a Langfuse backlog room. FADEN_REDIS_MAXMEMORY in .env changes it (Help, Installing).
135
155
  command: >
136
- --requirepass ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)} --maxmemory-policy noeviction
156
+ --requirepass ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)} --maxmemory ${FADEN_REDIS_MAXMEMORY:-1gb} --maxmemory-policy noeviction
157
+ environment:
158
+ # redis-cli reads the password from here: on its command line (-a) it showed in `ps`.
159
+ REDISCLI_AUTH: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
137
160
  ports:
138
161
  - "127.0.0.1:6379:6379"
139
162
  healthcheck:
140
- test: ["CMD", "redis-cli", "-a", "${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}", "ping"]
163
+ # NOAUTH and the like exit 0 as well, so the answer itself is checked.
164
+ test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
141
165
  interval: 3s
142
166
  timeout: 10s
143
167
  retries: 10
@@ -145,6 +169,7 @@ services:
145
169
  minio:
146
170
  image: cgr.dev/chainguard/minio:latest
147
171
  container_name: faden-minio
172
+ logging: *faden-logging
148
173
  restart: unless-stopped
149
174
  entrypoint: sh
150
175
  command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
@@ -169,6 +194,7 @@ services:
169
194
  langfuse-worker:
170
195
  image: docker.io/langfuse/langfuse-worker:3
171
196
  container_name: faden-worker
197
+ logging: *faden-logging
172
198
  restart: unless-stopped
173
199
  depends_on:
174
200
  postgres:
@@ -219,6 +245,7 @@ services:
219
245
  langfuse-web:
220
246
  image: docker.io/langfuse/langfuse:3
221
247
  container_name: faden-web
248
+ logging: *faden-logging
222
249
  restart: unless-stopped
223
250
  ports:
224
251
  # LLM observability UI (traces / evals / datasets), plain HTTP: on this
@@ -288,6 +315,7 @@ services:
288
315
  faden-rmq:
289
316
  image: rabbitmq:4.2.1-management-alpine
290
317
  container_name: faden-rmq
318
+ logging: *faden-logging
291
319
  restart: unless-stopped
292
320
  ports:
293
321
  - "127.0.0.1:5672:5672"
@@ -322,6 +350,7 @@ services:
322
350
  faden-gateway-migrator:
323
351
  image: ${REGISTRY:-ghcr.io/fadenstack}/gateway:${VERSION:-latest}
324
352
  container_name: faden-gateway-migrator
353
+ logging: *faden-logging
325
354
  restart: on-failure:5
326
355
  command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
327
356
  depends_on:
@@ -333,6 +362,11 @@ services:
333
362
  FADEN_GATEWAY_DB_USER: ${POSTGRES_USER:-postgres}
334
363
  FADEN_GATEWAY_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
335
364
  FADEN_GATEWAY_DB_BASE: faden_gateway
365
+ # The migration that seals the provider API keys (pr0vk3yg) uses the backend's master key; without it
366
+ # the migrator used the published development default.
367
+ FADEN_GATEWAY_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
368
+ # That migration refuses the published development key unless the install keeps it on purpose.
369
+ FADEN_GATEWAY_ALLOW_PUBLISHED_KEYS: ${FADEN_ALLOW_PUBLISHED_KEYS:-false}
336
370
 
337
371
  # -----------------------------
338
372
  # faden_gateway (OpenAI-compatible endpoint gateway)
@@ -346,6 +380,7 @@ services:
346
380
  args:
347
381
  BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
348
382
  container_name: faden-gateway
383
+ logging: *faden-logging
349
384
  restart: unless-stopped
350
385
  depends_on:
351
386
  postgres:
@@ -372,6 +407,9 @@ services:
372
407
  # These two env vars enable that path; no static JWT_SECRET env var is needed.
373
408
  FADEN_GATEWAY_BACKEND_DB_BASE: faden_backend
374
409
  FADEN_GATEWAY_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
410
+ # Set only while `faden secrets rotate` is unfinished: values sealed with the old key still open.
411
+ FADEN_GATEWAY_SETTINGS_MASTER_KEY_PREVIOUS: ${FADEN_BACKEND_SETTINGS_MASTER_KEY_PREVIOUS:-}
412
+ FADEN_GATEWAY_ENCRYPTION_KEY_PREVIOUS: ${FADEN_GATEWAY_ENCRYPTION_KEY_PREVIOUS:-}
375
413
  # An install that has stored data under the published development key may
376
414
  # keep it, with a warning at every start, until it is changed (Help:
377
415
  # Installing, Secrets in .env). Outside development the service refuses it otherwise.
@@ -405,6 +443,7 @@ services:
405
443
  # PII module integration (set via .env or COMPOSE_PROFILES)
406
444
  FADEN_GATEWAY_PII_ENABLED: ${FADEN_GATEWAY_PII_ENABLED:-false}
407
445
  FADEN_GATEWAY_PII_SERVICE_URL: ${FADEN_GATEWAY_PII_SERVICE_URL:-http://faden-pii:8000}
446
+ FADEN_GATEWAY_PII_SERVICE_TOKEN: ${FADEN_GATEWAY_PII_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
408
447
  # MCP tool registry integration (set via .env or COMPOSE_PROFILES)
409
448
  FADEN_GATEWAY_MCP_ENABLED: ${FADEN_GATEWAY_MCP_ENABLED:-false}
410
449
  FADEN_GATEWAY_MCP_SERVICE_URL: ${FADEN_GATEWAY_MCP_SERVICE_URL:-http://faden-mcp:8000}
@@ -431,6 +470,12 @@ services:
431
470
  FADEN_GATEWAY_DB_MAX_OVERFLOW: ${FADEN_GATEWAY_DB_MAX_OVERFLOW:-5}
432
471
  FADEN_GATEWAY_RABBIT_POOL_SIZE: ${FADEN_GATEWAY_RABBIT_POOL_SIZE:-2}
433
472
  FADEN_GATEWAY_RABBIT_CHANNEL_POOL_SIZE: ${FADEN_GATEWAY_RABBIT_CHANNEL_POOL_SIZE:-10}
473
+ volumes:
474
+ # Chat attachments (chat_file_store_root). In the container layer until this release: every upgrade
475
+ # and restore replaced the container and lost them. With FADEN_DATA_DIR set in .env the source is
476
+ # that directory plus /chat-files on the host (a company's own storage); empty, the named volume
477
+ # below. `faden upgrade` copies what the old container holds into it first.
478
+ - ${FADEN_DATA_DIR:-faden_chat_files}${FADEN_DATA_DIR:+/chat-files}:/data/faden/chat-files
434
479
  healthcheck:
435
480
  test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health', timeout=3).read()"]
436
481
  interval: 5s
@@ -443,6 +488,7 @@ services:
443
488
  faden-backend-migrator:
444
489
  image: ${REGISTRY:-ghcr.io/fadenstack}/backend:${VERSION:-latest}
445
490
  container_name: faden-backend-migrator
491
+ logging: *faden-logging
446
492
  restart: on-failure:5
447
493
  command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
448
494
  depends_on:
@@ -454,6 +500,11 @@ services:
454
500
  FADEN_BACKEND_DB_USER: ${POSTGRES_USER:-postgres}
455
501
  FADEN_BACKEND_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
456
502
  FADEN_BACKEND_DB_BASE: faden_backend
503
+ # The migration that seals the remote providers' API keys (pr0vk3ys) seals them with this key.
504
+ # Without it the migrator used the published development default, and the backend could not open them.
505
+ FADEN_BACKEND_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
506
+ # That migration refuses the published development key unless the install keeps it on purpose.
507
+ FADEN_BACKEND_ALLOW_PUBLISHED_KEYS: ${FADEN_ALLOW_PUBLISHED_KEYS:-false}
457
508
 
458
509
  faden-backend:
459
510
  image: ${REGISTRY:-ghcr.io/fadenstack}/backend:${VERSION:-latest}
@@ -467,6 +518,7 @@ services:
467
518
  args:
468
519
  BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
469
520
  container_name: faden-backend
521
+ logging: *faden-logging
470
522
  restart: unless-stopped
471
523
  depends_on:
472
524
  postgres:
@@ -504,6 +556,11 @@ services:
504
556
  FADEN_BACKEND_RABBIT_VHOST: /
505
557
  FADEN_BACKEND_GATEWAY_URL: ${FADEN_BACKEND_GATEWAY_URL:-http://faden-gateway:8000}
506
558
  FADEN_BACKEND_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
559
+ # Set only while `faden secrets rotate` is unfinished: values sealed with the old key still open.
560
+ FADEN_BACKEND_SETTINGS_MASTER_KEY_PREVIOUS: ${FADEN_BACKEND_SETTINGS_MASTER_KEY_PREVIOUS:-}
561
+ # What the machines' credential hashes are keyed with. Once the master key itself; a rotation
562
+ # changes the master key and must not change this, or every machine would have to enroll again.
563
+ FADEN_BACKEND_CREDENTIAL_PEPPER: ${FADEN_BACKEND_CREDENTIAL_PEPPER:?set it in .env, as faden upgrade does (it keeps the machines' credentials valid; Help, Rotating the keys)}
507
564
  # An install that has stored data under the published development key may
508
565
  # keep it, with a warning at every start, until it is changed (Help:
509
566
  # Installing, Secrets in .env). Outside development the service refuses it otherwise.
@@ -528,6 +585,7 @@ services:
528
585
  # Module enabled flags + service URLs (Docker-internal for health probes)
529
586
  FADEN_BACKEND_PII_ENABLED: ${FADEN_BACKEND_PII_ENABLED:-false}
530
587
  FADEN_BACKEND_PII_SERVICE_URL: ${FADEN_BACKEND_PII_SERVICE_URL:-http://faden-pii:8000/api}
588
+ FADEN_BACKEND_PII_SERVICE_TOKEN: ${FADEN_BACKEND_PII_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
531
589
  FADEN_BACKEND_INTERNAL_TOKEN: ${FADEN_BACKEND_INTERNAL_TOKEN:-}
532
590
  FADEN_BACKEND_MCP_ENABLED: ${FADEN_BACKEND_MCP_ENABLED:-false}
533
591
  FADEN_BACKEND_MCP_SERVICE_URL: ${FADEN_BACKEND_MCP_SERVICE_URL:-http://faden-mcp:8000}
@@ -588,6 +646,7 @@ services:
588
646
  faden-backend-worker:
589
647
  image: ${REGISTRY:-ghcr.io/fadenstack}/backend:${VERSION:-latest}
590
648
  container_name: faden-backend-worker
649
+ logging: *faden-logging
591
650
  restart: unless-stopped
592
651
  command:
593
652
  - taskiq
@@ -621,6 +680,11 @@ services:
621
680
  FADEN_BACKEND_RABBIT_VHOST: /
622
681
  FADEN_BACKEND_GATEWAY_URL: ${FADEN_BACKEND_GATEWAY_URL:-http://faden-gateway:8000}
623
682
  FADEN_BACKEND_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
683
+ # Set only while `faden secrets rotate` is unfinished: values sealed with the old key still open.
684
+ FADEN_BACKEND_SETTINGS_MASTER_KEY_PREVIOUS: ${FADEN_BACKEND_SETTINGS_MASTER_KEY_PREVIOUS:-}
685
+ # What the machines' credential hashes are keyed with. Once the master key itself; a rotation
686
+ # changes the master key and must not change this, or every machine would have to enroll again.
687
+ FADEN_BACKEND_CREDENTIAL_PEPPER: ${FADEN_BACKEND_CREDENTIAL_PEPPER:?set it in .env, as faden upgrade does (it keeps the machines' credentials valid; Help, Rotating the keys)}
624
688
  FADEN_BACKEND_LLM_GRAPH_DB_HOST: postgres
625
689
  FADEN_BACKEND_LLM_GRAPH_DB_USER: ${POSTGRES_USER:-postgres}
626
690
  FADEN_BACKEND_LLM_GRAPH_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
@@ -631,6 +695,7 @@ services:
631
695
  FADEN_BACKEND_MCP_ENABLED: ${FADEN_BACKEND_MCP_ENABLED:-false}
632
696
  FADEN_BACKEND_SKILLS_ENABLED: ${FADEN_BACKEND_SKILLS_ENABLED:-false}
633
697
  FADEN_BACKEND_PII_SERVICE_URL: ${FADEN_BACKEND_PII_SERVICE_URL:-http://faden-pii:8000/api}
698
+ FADEN_BACKEND_PII_SERVICE_TOKEN: ${FADEN_BACKEND_PII_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
634
699
  FADEN_BACKEND_INTERNAL_TOKEN: ${FADEN_BACKEND_INTERNAL_TOKEN:-}
635
700
  FADEN_BACKEND_MCP_SERVICE_URL: ${FADEN_BACKEND_MCP_SERVICE_URL:-http://faden-mcp:8000}
636
701
  FADEN_BACKEND_MCP_SERVICE_TOKEN: ${FADEN_BACKEND_MCP_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
@@ -666,6 +731,7 @@ services:
666
731
  additional_contexts:
667
732
  docs: ../docs
668
733
  container_name: faden-frontend
734
+ logging: *faden-logging
669
735
  restart: unless-stopped
670
736
  depends_on:
671
737
  faden-backend:
@@ -691,6 +757,7 @@ services:
691
757
  args:
692
758
  BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
693
759
  container_name: faden-pii
760
+ logging: *faden-logging
694
761
  restart: unless-stopped
695
762
  depends_on:
696
763
  faden-rmq:
@@ -702,6 +769,9 @@ services:
702
769
  FADEN_PII_ENVIRONMENT: ${FADEN_PII_ENVIRONMENT:-production}
703
770
  FADEN_PII_BACKEND_URL: http://faden-backend:8000
704
771
  FADEN_PII_BACKEND_TOKEN: ${FADEN_PII_BACKEND_TOKEN:-}
772
+ # What the gateway, the backend and MCP present on every call but health. Required: empty, the
773
+ # service would refuse them all.
774
+ FADEN_PII_SERVICE_TOKEN: ${FADEN_PII_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
705
775
  FADEN_PII_RABBIT_HOST: faden-rmq
706
776
  FADEN_PII_RABBIT_PORT: 5672
707
777
  FADEN_PII_RABBIT_USER: faden-pii
@@ -721,6 +791,7 @@ services:
721
791
  profiles: ["pii"]
722
792
  image: ${REGISTRY:-ghcr.io/fadenstack}/pii:${VERSION:-latest}
723
793
  container_name: faden-pii-worker
794
+ logging: *faden-logging
724
795
  restart: unless-stopped
725
796
  command:
726
797
  - taskiq
@@ -750,6 +821,7 @@ services:
750
821
  profiles: ["mcp"]
751
822
  image: ${REGISTRY:-ghcr.io/fadenstack}/mcp:${VERSION:-latest}
752
823
  container_name: faden-mcp-migrator
824
+ logging: *faden-logging
753
825
  restart: on-failure:5
754
826
  command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
755
827
  depends_on:
@@ -772,6 +844,7 @@ services:
772
844
  args:
773
845
  BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
774
846
  container_name: faden-mcp
847
+ logging: *faden-logging
775
848
  restart: unless-stopped
776
849
  depends_on:
777
850
  postgres:
@@ -795,8 +868,10 @@ services:
795
868
  FADEN_MCP_REDIS_PASS: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
796
869
  FADEN_MCP_REDIS_BASE: 3
797
870
  FADEN_MCP_PII_SERVICE_URL: ${FADEN_MCP_PII_SERVICE_URL:-http://faden-pii:8000}
871
+ FADEN_MCP_PII_SERVICE_TOKEN: ${FADEN_MCP_PII_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
798
872
  FADEN_MCP_SERVICE_TOKEN: ${FADEN_MCP_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
799
873
  FADEN_MCP_ENCRYPTION_KEY: ${FADEN_MCP_ENCRYPTION_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
874
+ FADEN_MCP_ENCRYPTION_KEY_PREVIOUS: ${FADEN_MCP_ENCRYPTION_KEY_PREVIOUS:-}
800
875
  # An install that has stored data under the published development key may
801
876
  # keep it, with a warning at every start, until it is changed (Help:
802
877
  # Installing, Secrets in .env). Outside development the service refuses it otherwise.
@@ -820,6 +895,7 @@ services:
820
895
  profiles: ["skills"]
821
896
  image: ${REGISTRY:-ghcr.io/fadenstack}/skills:${VERSION:-latest}
822
897
  container_name: faden-skills-migrator
898
+ logging: *faden-logging
823
899
  restart: on-failure:5
824
900
  command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
825
901
  depends_on:
@@ -842,6 +918,7 @@ services:
842
918
  args:
843
919
  BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
844
920
  container_name: faden-skills
921
+ logging: *faden-logging
845
922
  restart: unless-stopped
846
923
  depends_on:
847
924
  postgres:
@@ -885,6 +962,7 @@ services:
885
962
  # compose-private.
886
963
  image: prom/prometheus:v2.53.0
887
964
  container_name: faden-prometheus
965
+ logging: *faden-logging
888
966
  restart: unless-stopped
889
967
  ports:
890
968
  # Not 9090 on the host: MinIO's API is published there in this stack,
@@ -910,6 +988,7 @@ services:
910
988
  loki:
911
989
  image: grafana/loki:3.0.0
912
990
  container_name: faden-loki
991
+ logging: *faden-logging
913
992
  restart: unless-stopped
914
993
  # Loki has no authentication — it must never be reachable from the
915
994
  # network. Default to the loopback interface only; set LOKI_BIND
@@ -930,6 +1009,7 @@ services:
930
1009
  # back needs the backup the upgrade makes.
931
1010
  image: grafana/grafana:12.4.12@sha256:a3b504df900c24db125e5ec0646f3ac3428db38161302d69f05d0db70a330a90
932
1011
  container_name: faden-grafana
1012
+ logging: *faden-logging
933
1013
  restart: unless-stopped
934
1014
  ports:
935
1015
  # Dashboards, anonymous read-only (login form disabled), plain HTTP. The
@@ -970,6 +1050,7 @@ services:
970
1050
  # last. --disable-reporting: no usage reports to Grafana Labs.
971
1051
  image: grafana/alloy:v1.20.1@sha256:2aa2099af76c0098d4af7a4d6e48f86cb66dc1a000222ad927a1c67c6542d13f
972
1052
  container_name: faden-alloy
1053
+ logging: *faden-logging
973
1054
  restart: unless-stopped
974
1055
  ports:
975
1056
  - "127.0.0.1:12345:12345"
@@ -996,3 +1077,4 @@ volumes:
996
1077
  prom_data:
997
1078
  faden_models:
998
1079
  faden_rag_lite:
1080
+ faden_chat_files:
@@ -97,6 +97,7 @@ location = /api/health {
97
97
  proxy_set_header X-Real-IP $remote_addr;
98
98
  proxy_set_header X-Forwarded-For $remote_addr;
99
99
  proxy_set_header X-Forwarded-Proto $scheme;
100
+ proxy_set_header X-Forwarded-Host $http_host;
100
101
  }
101
102
 
102
103
  # ── Backend API (/api/*) ──────────────────────────────────────
@@ -119,6 +120,7 @@ location /api/ {
119
120
  proxy_set_header X-Real-IP $remote_addr;
120
121
  proxy_set_header X-Forwarded-For $remote_addr;
121
122
  proxy_set_header X-Forwarded-Proto $scheme;
123
+ proxy_set_header X-Forwarded-Host $http_host;
122
124
 
123
125
  # SSE streaming: disable buffering
124
126
  proxy_buffering off;
@@ -132,6 +134,25 @@ location /api/ {
132
134
  proxy_set_header Connection $connection_upgrade;
133
135
  }
134
136
 
137
+ # ── Backend API docs (/api/docs, /api/redoc, /api/openapi.json) ─
138
+ # The schema lists every route of the admin API, so it is for a signed-in
139
+ # console session only: the same check as /grafana/ (/_console_access/grafana
140
+ # below). A regex location wins over the /api/ prefix above.
141
+ location ~ ^/api/(docs|redoc|openapi\.json)$ {
142
+ if (-f /etc/nginx/faden/maintenance.flag) {
143
+ return 503;
144
+ }
145
+ error_page 502 503 = @faden_maintenance_api;
146
+ auth_request /_console_access/grafana;
147
+ set $backend http://faden-backend:8000;
148
+ proxy_pass $backend;
149
+ proxy_set_header Host $http_host;
150
+ proxy_set_header X-Real-IP $remote_addr;
151
+ proxy_set_header X-Forwarded-For $remote_addr;
152
+ proxy_set_header X-Forwarded-Proto $scheme;
153
+ proxy_set_header X-Forwarded-Host $http_host;
154
+ }
155
+
135
156
  # ── OpenAI-compatible API (/v1/*) ─────────────────────────────
136
157
  # External API clients (curl, SDKs) can hit /v1/* through the
137
158
  # same origin instead of needing a separate port.
@@ -146,6 +167,7 @@ location /v1/ {
146
167
  proxy_set_header X-Real-IP $remote_addr;
147
168
  proxy_set_header X-Forwarded-For $remote_addr;
148
169
  proxy_set_header X-Forwarded-Proto $scheme;
170
+ proxy_set_header X-Forwarded-Host $http_host;
149
171
 
150
172
  # SSE streaming
151
173
  proxy_buffering off;
@@ -171,6 +193,8 @@ location /gateway-static/ {
171
193
  # ── Gateway API docs (iframe-friendly path) ──────────────────
172
194
  # Proxies /gateway-docs/* → faden-gateway /api/*
173
195
  location /gateway-docs/ {
196
+ # Signed-in console sessions only, as for the backend's docs above.
197
+ auth_request /_console_access/grafana;
174
198
  set $gateway_docs http://faden-gateway:8000;
175
199
  rewrite ^/gateway-docs/(.*)$ /api/$1 break;
176
200
  proxy_pass $gateway_docs;
@@ -178,6 +202,7 @@ location /gateway-docs/ {
178
202
  proxy_set_header X-Real-IP $remote_addr;
179
203
  proxy_set_header X-Forwarded-For $remote_addr;
180
204
  proxy_set_header X-Forwarded-Proto $scheme;
205
+ proxy_set_header X-Forwarded-Host $http_host;
181
206
 
182
207
  # Rewrite absolute asset paths in Swagger/ReDoc HTML so they
183
208
  # load through /gateway-static/ and /gateway-docs/ instead of
@@ -206,6 +231,7 @@ location /grafana/ {
206
231
  proxy_set_header X-Real-IP $remote_addr;
207
232
  proxy_set_header X-Forwarded-For $remote_addr;
208
233
  proxy_set_header X-Forwarded-Proto $scheme;
234
+ proxy_set_header X-Forwarded-Host $http_host;
209
235
 
210
236
  # WebSocket support for Grafana Live
211
237
  proxy_http_version 1.1;
@@ -223,6 +249,7 @@ location = /_console_access/grafana {
223
249
  proxy_set_header Cookie $http_cookie;
224
250
  proxy_set_header Authorization $http_authorization;
225
251
  proxy_set_header X-Forwarded-Proto $scheme;
252
+ proxy_set_header X-Forwarded-Host $http_host;
226
253
  }
227
254
 
228
255
  # ── Frontend (everything else) ────────────────────────────────
@@ -238,6 +265,7 @@ location / {
238
265
  proxy_set_header X-Real-IP $remote_addr;
239
266
  proxy_set_header X-Forwarded-For $remote_addr;
240
267
  proxy_set_header X-Forwarded-Proto $scheme;
268
+ proxy_set_header X-Forwarded-Host $http_host;
241
269
 
242
270
  proxy_http_version 1.1;
243
271
  proxy_set_header Upgrade $http_upgrade;
@@ -98,6 +98,7 @@ def register_core_commands(group: click.Group | None = None) -> None:
98
98
  from faden_cli.commands.tls import tls_group
99
99
  from faden_cli.commands.ports import ports_cmd
100
100
  from faden_cli.commands.maintenance import maintenance_group
101
+ from faden_cli.commands.secrets import secrets_group
101
102
 
102
103
  target.add_command(version_cmd, "version")
103
104
  target.add_command(doctor_cmd, "doctor")
@@ -120,6 +121,7 @@ def register_core_commands(group: click.Group | None = None) -> None:
120
121
  target.add_command(tls_group, "tls")
121
122
  target.add_command(ports_cmd, "ports")
122
123
  target.add_command(maintenance_group, "maintenance")
124
+ target.add_command(secrets_group, "secrets")
123
125
 
124
126
 
125
127
  register_core_commands()
@@ -51,6 +51,8 @@ def reset_password_cmd(*, email: str, password: str | None, yes: bool) -> None:
51
51
 
52
52
  This bypasses the API and sets the password hash in PostgreSQL.
53
53
  The backend container must be running (needed for password hashing).
54
+ It changes the console sign-in only: Grafana, Langfuse and RabbitMQ
55
+ have passwords of their own in .env, which it leaves as they are.
54
56
  """
55
57
  # Validate email early to prevent any injection
56
58
  if not _EMAIL_RE.match(email):
@@ -110,8 +112,9 @@ def reset_password_cmd(*, email: str, password: str | None, yes: bool) -> None:
110
112
 
111
113
  # Both `hashed` (bcrypt output we generated) and `email` (validated
112
114
  # above by regex) are safe for SQL string interpolation here.
115
+ # The sign-ins end with the old password (sessions_valid_after): a reset is often meant to lock someone out.
113
116
  sql = (
114
- f"UPDATE \"user\" SET hashed_password = '{hashed}' "
117
+ f"UPDATE \"user\" SET hashed_password = '{hashed}', sessions_valid_after = now() "
115
118
  f"WHERE email = '{email}';"
116
119
  )
117
120
 
@@ -138,6 +141,8 @@ def reset_password_cmd(*, email: str, password: str | None, yes: bool) -> None:
138
141
  sys.exit(1)
139
142
 
140
143
  success(f"Password reset for '{email}'.")
144
+ # Only the console's password: Grafana, Langfuse and RabbitMQ have passwords of their own in .env.
145
+ info("Grafana, Langfuse and RabbitMQ sign-ins are not touched: their passwords are in .env.")
141
146
 
142
147
  # ── 3. Display credentials ────────────────────────────────
143
148
  from rich.panel import Panel
@@ -17,7 +17,7 @@ from pathlib import Path
17
17
 
18
18
  import click
19
19
 
20
- from faden_cli.core.backup import create_backup
20
+ from faden_cli.core.backup import BACKUP_KINDS, DEFAULT_KIND, create_backup
21
21
  from faden_cli.core.compose import build_context_from_config
22
22
  from faden_cli.core.console import console, error, info, success, warning
23
23
  from faden_cli.core.private_files import private_dir
@@ -44,7 +44,14 @@ from faden_cli.core.settings import load_config
44
44
  type=int,
45
45
  default=5,
46
46
  show_default=True,
47
- help="Keep only the N most recent backups.",
47
+ help="Keep only the N most recent backups of this kind (nightly, manual and upgrade backups count apart).",
48
+ )
49
+ @click.option(
50
+ "--kind",
51
+ type=click.Choice(BACKUP_KINDS),
52
+ default=DEFAULT_KIND,
53
+ hidden=True,
54
+ help="What the backup is, recorded in it; --retain only counts backups of the same kind. The nightly timer sets it.",
48
55
  )
49
56
  @click.option(
50
57
  "--db-only",
@@ -60,6 +67,7 @@ def backup_cmd(
60
67
  output_dir: str,
61
68
  include_volumes: bool,
62
69
  retain: int,
70
+ kind: str,
63
71
  db_only: bool,
64
72
  yes: bool,
65
73
  ) -> None:
@@ -88,6 +96,7 @@ def backup_cmd(
88
96
  include_volumes=include_volumes,
89
97
  db_only=db_only,
90
98
  retain=retain,
99
+ kind=kind,
91
100
  )
92
101
 
93
102
  if not result.ok:
@@ -113,7 +122,7 @@ def backup_cmd(
113
122
 
114
123
  @backup_cmd.command("schedule")
115
124
  @click.option("--at", "at", default="03:00", show_default=True, help="Time of day, HH:MM (server time).")
116
- @click.option("--retain", type=int, default=7, show_default=True, help="Keep the N most recent backups.")
125
+ @click.option("--retain", type=int, default=7, show_default=True, help="Keep the N most recent nightly backups.")
117
126
  @click.option("--off", is_flag=True, default=False, help="Stop the nightly backup.")
118
127
  def schedule_cmd(*, at: str, retain: int, off: bool) -> None:
119
128
  """Back up every night, keeping the most recent few.