Skip to content

Commit cb7a899

Browse files
committed
Merge branch 'develop'
2 parents f1619b5 + fd0b161 commit cb7a899

24 files changed

Lines changed: 434 additions & 102 deletions

File tree

CHANGELOG.md

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,35 @@
33
Generated by `npm run set:version`.
44
The local changelog is rebuilt from the available `v*` release tags and the current `HEAD` range.
55
The script does not create tags locally.
6-
## v0.51.0 - 2026-04-29
6+
## v1.0.1 - 2026-04-30
77

88
- Release source: local versioning run
9+
- Base ref: `v0.51.0`
10+
- Range: `v0.51.0..HEAD`
11+
- Included commits: 4
12+
13+
### Features (1)
14+
15+
- [core] reintroduce bookstack service (`dcb2849`)
16+
17+
### Refactor (1)
18+
19+
- [core] remove trilium service (`71807e7`)
20+
21+
### Documentation (1)
22+
23+
- [readme] add index and service tags (`5dc5132`)
24+
25+
### CI / Maintenance (1)
26+
27+
- [release] v0.52.0 (`ee2ffa1`)
28+
29+
## v0.51.0 - 2026-04-29
30+
31+
- Release tag: `v0.51.0`
932
- Base ref: `v0.50.1`
10-
- Range: `v0.50.1..HEAD`
11-
- Included commits: 2
33+
- Range: `v0.50.1..v0.51.0`
34+
- Included commits: 3
1235

1336
### Features (1)
1437

@@ -18,6 +41,10 @@ The script does not create tags locally.
1841

1942
- [obsidian] remove wrapper basic auth (`83a4577`)
2043

44+
### CI / Maintenance (1)
45+
46+
- [release] v0.51.0 (`b06a2bd`)
47+
2148
## v0.50.1 - 2026-04-29
2249

2350
- Release tag: `v0.50.1`

README.md

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Atlas Lab
22

3-
![Version](https://img.shields.io/badge/version-0.51.0-blue.svg)
3+
![Version](https://img.shields.io/badge/version-1.0.1-blue.svg)
44
![License](https://img.shields.io/badge/license-MIT-22c55e.svg)
55
![Docker Compose](https://img.shields.io/badge/Docker%20Compose-v2-2496ED?logo=docker&logoColor=white)
66
![Gateway](https://img.shields.io/badge/Gateway-Caddy-1F2937?logo=caddy&logoColor=white)
@@ -12,15 +12,38 @@
1212

1313
Atlas Lab is a localhost-first self-hosted platform made of a Node.js/TypeScript CLI, a layered Docker Compose stack, and an operational React dashboard served by Caddy.
1414

15-
It provides a core collaboration layer with GitLab CE, TriliumNext, and Penpot, plus optional AI and development layers. Everything is reachable through dedicated HTTPS ports on `localhost`, with persistent state stored in Docker volumes.
15+
It provides a core collaboration layer with GitLab CE, BookStack, and Penpot, plus optional AI and development layers. Everything is reachable through dedicated HTTPS ports on `localhost`, with persistent state stored in Docker volumes.
16+
17+
---
18+
19+
## Index
20+
21+
- 🧭 [Overview](#overview)
22+
- 🏗️ [Architecture](#architecture)
23+
- 🔌 [Services, Ports, and URLs](#services-ports-and-urls)
24+
- 🕸️ [Docker Networks](#docker-networks)
25+
- 💾 [Persistence](#persistence)
26+
- 🧰 [Host Requirements](#host-requirements)
27+
- ⚙️ [Central Configuration](#central-configuration)
28+
- 🚀 [Quick Start](#quick-start)
29+
- 🧪 [CLI Workflows](#cli-workflows)
30+
- 🖥️ [Atlas Dashboard](#atlas-dashboard)
31+
- 📦 [Backup and Restore](#backup-and-restore)
32+
- 🔐 [Default Credentials](#default-credentials)
33+
- 🧩 [Adding Services](#adding-services)
34+
- 🗂️ [Repository Layout](#repository-layout)
35+
- 🩺 [Troubleshooting](#troubleshooting)
36+
- 🛡️ [Security Notes](#security-notes)
37+
- 📚 [Official References](#official-references)
38+
- 📄 [License](#license)
1639

1740
---
1841

1942
## Overview
2043

2144
### What It Gives You
2245

23-
- Always-on core layer with Atlas Dashboard, GitLab CE, TriliumNext, and Penpot.
46+
- Always-on core layer with Atlas Dashboard, GitLab CE, BookStack, and Penpot.
2447
- Optional AI LLM layer with Open WebUI, Ollama, and n8n.
2548
- Optional workbench layer with browser-based Node and Python environments plus shared PostgreSQL.
2649
- HTTPS-only browser ingress on `localhost`.
@@ -43,7 +66,7 @@ Atlas Lab is split into three explicit layers.
4366

4467
| Layer | Status | Includes | Purpose |
4568
| --- | --- | --- | --- |
46-
| `core` | always on | gateway, Atlas Dashboard, GitLab CE, TriliumNext, Penpot, and backing data services | baseline self-hosted platform |
69+
| `core` | always on | gateway, Atlas Dashboard, GitLab CE, BookStack, Penpot, and backing data services | baseline self-hosted platform |
4770
| `ai-llm` | optional | Open WebUI, Ollama, n8n, AI gateway | local AI workflows and automation |
4871
| `workbench` | optional | Node Forge, Python Grid, shared PostgreSQL, workbench gateway | browser-based development |
4972

@@ -58,6 +81,7 @@ The CLI:
5881
- starts Docker Compose
5982
- runs host preflight checks
6083
- validates Compose and repository assets
84+
- aligns the BookStack initial admin account
6185
- aligns the Penpot root profile
6286
- aligns the n8n owner account when the AI LLM layer is enabled
6387
- reconciles Ollama models when the AI LLM layer is enabled
@@ -77,9 +101,9 @@ All browser entry points are exposed over HTTPS on `localhost`.
77101
| Open WebUI | `ai-llm` | `https://localhost:8446/` | only with `--with-ai-llm` |
78102
| Ollama | `ai-llm` | `https://localhost:8447/` | HTTPS API with gateway auth |
79103
| Penpot | `core` | `https://localhost:8448/` | collaborative design workspace |
80-
| TriliumNext | `core` | `https://localhost:8449/` | server-side knowledge base |
81104
| Node Forge | `workbench` | `https://localhost:8450/` | Node / TypeScript workspace |
82105
| Python Grid | `workbench` | `https://localhost:8451/` | Python workspace |
106+
| BookStack | `core` | `https://localhost:8452/` | structured internal documentation |
83107
| n8n | `ai-llm` | `https://localhost:8453/` | workflow automation |
84108
| PostgreSQL | `workbench` | `localhost:15432` | host-side desktop access |
85109

@@ -96,7 +120,8 @@ Operational rules:
96120
| Network | Type | Purpose |
97121
| --- | --- | --- |
98122
| `edge-net` | exposed | published ingress ports |
99-
| `apps-net` | internal | GitLab CE, TriliumNext, and gateway-routed browser services |
123+
| `apps-net` | internal | GitLab CE, BookStack, and gateway-routed browser services |
124+
| `bookstack-net` | internal | BookStack and its MariaDB database |
100125
| `penpot-net` | internal | Penpot application services |
101126
| `ai-llm-net` | internal | Open WebUI, Ollama, and n8n |
102127
| `workbench-net` | internal | workbenches and PostgreSQL |
@@ -121,7 +146,8 @@ Core volumes:
121146
- `gitlab-config`
122147
- `gitlab-logs`
123148
- `gitlab-data`
124-
- `trilium-data`
149+
- `bookstack-config`
150+
- `bookstack-db`
125151
- `penpot-assets`
126152
- `penpot-postgres`
127153

@@ -173,9 +199,9 @@ Ports that should be free:
173199
- `8446`
174200
- `8447`
175201
- `8448`
176-
- `8449`
177202
- `8450`
178203
- `8451`
204+
- `8452`
179205
- `8453`
180206
- `15432` when `workbench` is enabled
181207

@@ -189,11 +215,12 @@ The main runtime configuration lives in:
189215

190216
Key variables include:
191217

192-
- `LAB_HTTPS_PORT`, `GITLAB_HTTPS_PORT`, `PENPOT_HTTPS_PORT`, `TRILIUM_HTTPS_PORT`
218+
- `LAB_HTTPS_PORT`, `GITLAB_HTTPS_PORT`, `PENPOT_HTTPS_PORT`, `BOOKSTACK_HTTPS_PORT`
193219
- `OPENWEBUI_HTTPS_PORT`, `OLLAMA_HTTPS_PORT`, `N8N_HTTPS_PORT`
194220
- `NODE_DEV_HTTPS_PORT`, `PYTHON_DEV_HTTPS_PORT`, `POSTGRES_DEV_HOST_PORT`
195221
- `GITLAB_EXTERNAL_URL`, `GITLAB_URL`
196222
- `GITLAB_ROOT_USERNAME`, `GITLAB_ROOT_PASSWORD`, `GITLAB_ROOT_EMAIL`
223+
- `BOOKSTACK_URL`, `BOOKSTACK_ROOT_EMAIL`, `BOOKSTACK_ROOT_PASSWORD`
197224
- `PENPOT_ROOT_EMAIL`, `PENPOT_ROOT_PASSWORD`
198225
- `N8N_ROOT_EMAIL`, `N8N_ROOT_PASSWORD`
199226
- `OLLAMA_CHAT_MODEL`, `OLLAMA_EMBEDDING_MODEL`, `OLLAMA_RUNTIME_MODELS`
@@ -332,7 +359,7 @@ npm run dev -- save-volumes --with-ai-llm --with-workbench
332359
npm run dev -- restore-volumes --input .\backups\volumes\atlas-lab-volumes.tar.gz
333360
```
334361

335-
Bootstrap is idempotent for GitLab CE, Penpot, and the optional AI LLM services.
362+
Bootstrap is idempotent for GitLab CE, BookStack initial setup, Penpot, and the optional AI LLM services.
336363

337364
---
338365

@@ -347,7 +374,7 @@ These credentials are intended for trusted local environments and are configurab
347374
| Open WebUI | `https://localhost:8446/` | `root@openwebui.local / RootOpenWebUI!2026` |
348375
| Ollama | `https://localhost:8447/` | gateway basic auth `root / RootOllama!2026` |
349376
| Penpot | `https://localhost:8448/` | `root@penpot.local / RootPenpot!2026` |
350-
| TriliumNext | `https://localhost:8449/` | first-run app setup |
377+
| BookStack | `https://localhost:8452/` | `root@bookstack.local / RootBookStack!2026` |
351378
| n8n | `https://localhost:8453/` | owner bootstrap `root@n8n.local / RootN8NApp!2026` |
352379
| PostgreSQL host-side | `localhost:15432` | `postgres / RootPostgresDev!2026` |
353380

@@ -361,6 +388,53 @@ For desktop PostgreSQL clients:
361388

362389
---
363390

391+
## Adding Services
392+
393+
Use the same layered flow when adding, removing, or moving services. The tag describes the runtime contract, and the emoji keeps the intent visible in notes, issues, and commits.
394+
395+
| Tag | Use when | Runtime contract |
396+
| --- | --- | --- |
397+
| 🏛️ `core` | The service is always on and browser-facing | Add it to `infra/docker/compose.yml`, publish it through `config/gateway/templates/Caddyfile.template`, expose it in `env/lab.env`, and include it in dashboard/runtime config when it should be visible to users. |
398+
| 🧠 `ai-llm` | The service belongs to optional AI workflows | Add it to `infra/docker/compose.ai-llm.yml`, route it through `gateway-ai-llm`, guard CLI checks behind `--with-ai-llm`, and add smoke/bootstrap only when that layer is enabled. |
399+
| 🧰 `workbench` | The service belongs to optional development environments | Add it to `infra/docker/compose.workbench.yml`, route browser surfaces through `gateway-workbench`, and add host TCP preflight/smoke checks only for ports exposed to the desktop. |
400+
| 🔒 `internal` | The service is a backing dependency only | Add Compose service, volumes, and internal networks, but skip Caddy, dashboard cards, and public smoke checks unless another service depends on them. |
401+
| 🛠️ `bootstrap` | The service needs deterministic initial state | Add or update a service under `src/services/integrations/`, call it from `src/services/orchestration/bootstrap.service.ts`, and validate required env in `src/config/lab-env.schema.ts`. |
402+
| 🩺 `smoke` | The service should be health-checked by `doctor --smoke` | Add required env to the smoke schema/types and add an HTTP, login, API, or TCP check in `src/services/diagnostics/doctor.service.ts`. |
403+
404+
### 🏛️ `core` Browser Service Flow
405+
406+
1. Add port, URL, image version, credentials, and secrets in `env/lab.env`.
407+
2. Add the service, volumes, `depends_on`, and networks in `infra/docker/compose.yml`.
408+
3. Add the HTTPS route in `config/gateway/templates/Caddyfile.template`.
409+
4. Add required template variables in `infra/docker/images/gateway/bootstrap-gateway.sh`.
410+
5. Add runtime payload fields in `config/gateway/templates/runtime/lab-config.json.template` when the dashboard needs them.
411+
6. Update dashboard schema, view-model builders, locale files, and network map nodes if the service should appear in the UI.
412+
7. Update host port preflight, smoke checks, tests, README tables, and content templates.
413+
414+
### 🧠 `ai-llm` Service Flow
415+
416+
1. Add the service in `infra/docker/compose.ai-llm.yml`.
417+
2. Publish browser/API routes through `gateway-ai-llm` only.
418+
3. Keep CLI behavior behind `--with-ai-llm`.
419+
4. Add bootstrap and smoke checks only when AI LLM env validation passes.
420+
5. Update dashboard optional-layer cards so disabled services remain visibly optional instead of pretending to be online.
421+
422+
### 🧰 `workbench` Service Flow
423+
424+
1. Add the service in `infra/docker/compose.workbench.yml`.
425+
2. Route browser workspaces through `gateway-workbench`.
426+
3. Add host port preflight only for ports published to the host, such as desktop database access.
427+
4. Add dashboard cards or briefings only for workflows users directly open or inspect.
428+
429+
### 🔒 `internal` Service Flow
430+
431+
1. Keep the service on an internal network.
432+
2. Add named volumes for persistent state.
433+
3. Add health checks when other services depend on readiness.
434+
4. Do not add public Caddy routes or dashboard cards unless the service becomes user-facing.
435+
436+
---
437+
364438
## Repository Layout
365439

366440
| Area | Purpose | Paths |
@@ -480,11 +554,10 @@ For stronger hardening:
480554
- Self-hosted user management: https://docs.n8n.io/hosting/configuration/user-management-self-hosted/
481555
- Docker install: https://docs.n8n.io/hosting/installation/docker/
482556

483-
### TriliumNext
557+
### BookStack
484558

485-
- Docker Hub image: https://hub.docker.com/r/triliumnext/trilium
486-
- Source repository: https://github.com/TriliumNext/Trilium
487-
- Docker installation: https://docs.triliumnotes.org/user-guide/setup/server/installation/docker
559+
- Official documentation: https://www.bookstackapp.com/docs/
560+
- LinuxServer image: https://docs.linuxserver.io/images/docker-bookstack/
488561

489562
### Open WebUI
490563

apps/atlas-dashboard/src/entities/dashboard/lib/dashboard-icon-map.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
GlobalOutlined,
1010
LockOutlined,
1111
NodeIndexOutlined,
12+
ReadOutlined,
1213
RobotOutlined,
1314
SafetyCertificateOutlined,
1415
ThunderboltOutlined
@@ -22,6 +23,7 @@ export type DashboardIconComponent = ComponentType<{
2223

2324
export const dashboardIconMap: Record<DashboardIconKey, DashboardIconComponent> = {
2425
ai: ApiOutlined,
26+
book: ReadOutlined,
2527
certificate: SafetyCertificateOutlined,
2628
forge: BranchesOutlined,
2729
host: GlobalOutlined,

apps/atlas-dashboard/src/entities/dashboard/model/builders/dashboard-core.builder.ts

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,29 +57,39 @@ export function createCoreServices(
5757
},
5858
{
5959
action: {
60-
href: config.services.trilium.url,
61-
label: t('dashboard.services.trilium.action')
60+
href: config.services.bookStack.url,
61+
label: t('dashboard.services.bookStack.action')
6262
},
6363
credentials: [
6464
{
6565
label: labels.endpoint,
66-
value: config.services.trilium.url
66+
value: config.services.bookStack.url
6767
},
6868
{
69-
label: labels.accessMode,
70-
value: t('values.directAppLogin')
69+
label: labels.rootName,
70+
value: config.services.bookStack.rootName
71+
},
72+
{
73+
label: labels.rootEmail,
74+
value: config.services.bookStack.rootEmail,
75+
concealed: true
7176
},
7277
{
73-
label: labels.usage,
74-
value: t('values.knowledgeVault')
78+
label: labels.password,
79+
value: config.services.bookStack.rootPassword,
80+
concealed: true
81+
},
82+
{
83+
label: labels.accessMode,
84+
value: t('values.directAppLogin')
7585
}
7686
],
77-
description: t('dashboard.services.trilium.description'),
78-
icon: 'host',
79-
id: 'trilium',
80-
note: t('dashboard.services.trilium.note'),
81-
status: t('values.knowledgeVault'),
82-
title: t('dashboard.services.trilium.title'),
87+
description: t('dashboard.services.bookStack.description'),
88+
icon: 'book',
89+
id: 'bookstack',
90+
note: t('dashboard.services.bookStack.note'),
91+
status: t('values.knowledgeBase'),
92+
title: t('dashboard.services.bookStack.title'),
8393
tone: 'core'
8494
},
8595
{

apps/atlas-dashboard/src/entities/dashboard/model/dashboard-view-model.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { BriefingReference } from '@/shared/types';
22

33
export type DashboardIconKey =
44
| 'ai'
5+
| 'book'
56
| 'certificate'
67
| 'forge'
78
| 'host'

apps/atlas-dashboard/src/entities/network-map/model/create-network-graph-view-model.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,16 @@ export function createNetworkGraphViewModel(
7878
}),
7979
createNode({
8080
active: true,
81-
description: t('dashboard.services.trilium.description'),
82-
id: 'trilium',
81+
description: t('dashboard.services.bookStack.description'),
82+
id: 'bookstack',
8383
kind: 'service',
8484
labels: [
85-
config.services.trilium.url,
86-
t('values.knowledgeVault'),
85+
config.services.bookStack.url,
86+
t('values.knowledgeBase'),
8787
t('networkMapDialog.labels.browser')
8888
],
89-
position: [-64, -20, 12],
90-
title: t('dashboard.services.trilium.title'),
89+
position: [-44, -42, 28],
90+
title: t('dashboard.services.bookStack.title'),
9191
tone: 'core'
9292
}),
9393
createNode({
@@ -239,7 +239,7 @@ export function createNetworkGraphViewModel(
239239
createLink('gateway', 'deck', 'core', true),
240240
createLink('gateway', 'core-layer', 'core', true),
241241
createLink('core-layer', 'gitlab', 'core', true),
242-
createLink('core-layer', 'trilium', 'core', true),
242+
createLink('core-layer', 'bookstack', 'core', true),
243243
createLink('core-layer', 'penpot', 'core', true),
244244
createLink('gateway', 'ai-layer', 'ai', aiActive),
245245
createLink('ai-layer', 'open-webui', 'ai', aiActive),

apps/atlas-dashboard/src/entities/runtime-config/model/lab-runtime-config.schema.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ const namedAccountSchema = z.object({
1010
url: nonEmptyString
1111
});
1212

13-
const urlOnlyServiceSchema = z.object({
14-
url: nonEmptyString
15-
});
16-
1713
export const labRuntimeConfigSchema = z.object({
1814
assets: z.object({
1915
certificateUrl: nonEmptyString
@@ -31,6 +27,7 @@ export const labRuntimeConfigSchema = z.object({
3127
publicUrl: nonEmptyString
3228
}),
3329
services: z.object({
30+
bookStack: namedAccountSchema,
3431
gitLab: z.object({
3532
externalUrl: nonEmptyString,
3633
rootEmail: nonEmptyString,
@@ -50,7 +47,6 @@ export const labRuntimeConfigSchema = z.object({
5047
url: nonEmptyString
5148
}),
5249
openWebUi: namedAccountSchema,
53-
trilium: urlOnlyServiceSchema,
5450
penpot: namedAccountSchema
5551
}),
5652
workbenches: z.object({

0 commit comments

Comments
 (0)