File size: 18,234 Bytes
bcc50e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tabby Tavern UNIFIED — one compose, one network, the whole lab</title>
<meta name="description" content="Taproot + Basecamp + Tabby Tavern merged: 15 default Docker services, Qwen3.5-9B llama.cpp, Open WebUI, SillyTavern, MCPO, code-server, RAG, n8n. One network. RTX 4070 lab.">
<style>
  :root {
    --navy: #070707;
    --navy-2: #141413;
    --blue: #1F5FA8;
    --accent: #ff4c00;
    --light: #EEF3F8;
    --gray: #3E4C59;
    --green: #1E8E5A;
    --cream: #FFF7EC;
    --tag: #FFD9A8;
    --ink: #0B1F3A;
    --line: #d5e0ec;
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background: #f4f7fb;
    color: var(--gray);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
  }
  a { color: var(--blue); }
  code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.86em;
    background: #e8eef5;
    padding: 1px 6px;
    border-radius: 4px;
  }
  .banner {
    background: linear-gradient(165deg, #070707 0%, #141413 45%, #1a0c08 100%);
    color: white;
    text-align: center;
    padding: 52px 24px 44px;
  }
  .badge-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: 16px; }
  .badge {
    display: inline-block; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; padding: 5px 10px; border-radius: 999px;
    border: 1px solid rgba(255,76,0,0.45); color: var(--tag); background: rgba(255,76,0,0.08);
  }
  .banner h1 {
    font-size: clamp(1.55rem, 4.4vw, 2.6rem); font-weight: 800; letter-spacing: 0.02em;
    margin-bottom: 14px; line-height: 1.12;
  }
  .banner h1 em { color: var(--accent); font-style: normal; }
  .banner .tagline { font-size: 1.08rem; color: var(--tag); max-width: 760px; margin: 0 auto 14px; }
  .banner .contact { font-size: 0.9rem; color: var(--tag); opacity: 0.9; }
  .banner .links { margin-top: 18px; display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
  .banner .links a {
    color: #070707; text-decoration: none; background: var(--accent); font-weight: 800;
    font-size: 0.85rem; padding: 10px 16px; border-radius: 6px;
  }
  .banner .links a.ghost { background: transparent; border: 1px solid rgba(255,217,168,0.5); color: var(--tag); }
  .kicker-wrap { padding: 0 24px; }
  .kicker {
    background: white; border: 1.5px solid var(--accent); text-align: center;
    padding: 14px 20px; margin: -18px auto 0; max-width: 920px; border-radius: 8px;
    position: relative; z-index: 1; box-shadow: 0 8px 24px rgba(7,7,7,0.12);
  }
  .kicker p { font-size: 1.02rem; font-weight: 800; color: var(--navy); }
  .container { max-width: 920px; margin: 0 auto; padding: 28px 24px 24px; }
  .stats-bar {
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;
    background: #070707; color: white; border-radius: 10px; padding: 18px 12px; margin: 8px 0 28px;
  }
  @media (min-width: 700px) { .stats-bar { grid-template-columns: repeat(4, 1fr); } }
  .stat { text-align: center; }
  .stat .num { font-size: 1.7rem; font-weight: 800; color: var(--accent); }
  .stat .label { font-size: 0.7rem; color: var(--tag); text-transform: uppercase; letter-spacing: 0.08em; }
  .section { margin-bottom: 30px; }
  .section h2 { font-size: 1.22rem; font-weight: 800; color: var(--ink); margin-bottom: 4px; }
  .section h2::before { content: "\25B6"; color: var(--accent); margin-right: 8px; font-size: 0.8rem; }
  .section hr { border: none; border-top: 1.5px solid #ff4c00; margin-bottom: 12px; opacity: 0.35; }
  .section p { font-size: 0.95rem; margin-bottom: 10px; }
  .section ul { list-style: none; }
  .section ul li { font-size: 0.93rem; padding: 5px 0 5px 22px; position: relative; }
  .section ul li::before { content: "\2022"; position: absolute; left: 4px; color: var(--accent); font-weight: bold; }
  .section ul li b { color: var(--ink); }
  .cap-grid { display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 16px; }
  @media (min-width: 640px) { .cap-grid { grid-template-columns: 1fr 1fr; } }
  @media (min-width: 900px) { .cap-grid { grid-template-columns: 1fr 1fr 1fr; } }
  .cap-card {
    border: 1.5px solid var(--line); border-radius: 10px; padding: 14px; background: white; min-height: 128px;
  }
  .cap-card h3 { font-size: 0.76rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px; }
  .cap-card p { font-size: 0.84rem; margin: 0; line-height: 1.45; }
  .cap-card p b { color: var(--ink); }
  .port { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.72rem; color: var(--accent); font-weight: 700; margin-bottom: 6px; }
  .c1 { border-top: 3px solid var(--accent); } .c1 h3 { color: var(--accent); }
  .c2 { border-top: 3px solid var(--blue); } .c2 h3 { color: var(--blue); }
  .c3 { border-top: 3px solid var(--green); } .c3 h3 { color: var(--green); }
  .c4 { border-top: 3px solid #6C3FA8; } .c4 h3 { color: #6C3FA8; }
  .c5 { border-top: 3px solid #0E8E8E; } .c5 h3 { color: #0E8E8E; }
  .c6 { border-top: 3px solid #C0392B; } .c6 h3 { color: #C0392B; }
  pre.cmd {
    background: #070707; color: #FFD9A8; padding: 14px 16px; border-radius: 8px;
    overflow-x: auto; font-size: 0.82rem; line-height: 1.45; margin: 12px 0;
  }
  .note {
    background: var(--cream); border: 1px solid #f0d2a8; border-radius: 8px;
    padding: 12px 14px; font-size: 0.88rem; margin-top: 14px;
  }
  .note b { color: var(--ink); }
  .quote {
    font-style: italic; color: #4A5A6A; border-left: 3px solid var(--accent);
    padding-left: 16px; margin: 14px 0 0; font-size: 0.92rem;
  }
  .pricing-header {
    background: #070707; color: white; text-align: center; padding: 28px 24px; border-radius: 10px 10px 0 0;
  }
  .pricing-header h2 { font-size: 1.6rem; font-weight: 800; color: white; }
  .pricing-header h2::before { display: none; }
  .pricing-header p { color: var(--tag); font-size: 0.95rem; margin-top: 8px; }
  .tiers { display: grid; grid-template-columns: 1fr; gap: 16px; margin-top: 16px; }
  @media (min-width: 768px) { .tiers { grid-template-columns: repeat(3, 1fr); } }
  .tier-card { border: 2px solid; border-radius: 10px; padding: 20px 16px; text-align: center; background: white; }
  .tier-card.blue { border-color: var(--blue); background: var(--light); }
  .tier-card.accent { border-color: var(--accent); background: var(--cream); }
  .tier-card.green { border-color: var(--green); background: #EAF7F0; }
  .tier-card h3 { font-size: 1.0rem; font-weight: 800; color: var(--ink); margin-bottom: 6px; }
  .tier-card .price { font-size: 1.55rem; font-weight: 800; color: var(--accent); }
  .tier-card .price-sub { font-size: 0.78rem; margin-bottom: 8px; }
  .tier-card .who { font-style: italic; font-size: 0.82rem; margin-bottom: 12px; min-height: 42px; }
  .tier-card ul { list-style: none; text-align: left; }
  .tier-card ul li { font-size: 0.85rem; padding: 3px 0 3px 16px; position: relative; }
  .tier-card ul li::before { content: "\2022"; position: absolute; left: 2px; color: var(--ink); }
  .bottom-line {
    background: white; border-top: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
    padding: 18px 20px; margin: 24px 0 8px; border-radius: 4px;
  }
  .bottom-line p { font-size: 0.93rem; } .bottom-line b { color: var(--ink); }
  .footer { text-align: center; padding: 16px 24px 40px; font-size: 0.82rem; }
  .footer .refs { margin-top: 8px; opacity: 0.85; }
  @media (max-width: 639px) {
    .banner { padding: 36px 16px 32px; }
    .banner h1 { font-size: 1.32rem; letter-spacing: 0; }
    .kicker p { font-size: 0.84rem; }
    .container { padding: 22px 16px; }
    .cap-card { min-height: 0; }
  }
</style>
</head>
<body>

<div class="banner">
  <div class="badge-row">
    <span class="badge">v3.0 UNIFIED</span>
    <span class="badge">15 default services</span>
    <span class="badge">Qwen3.5-9B</span>
    <span class="badge">one network</span>
  </div>
  <h1>THREE LABS.<br>ONE COMPOSE.<br><em>THE WHOLE BOX IS YOURS.</em></h1>
  <p class="tagline">Taproot inference. Basecamp coding pack. Tabby Tavern chat, search, cards, and MCP. Hermes folded them onto one Docker network tonight. This is the stack that is actually running.</p>
  <p class="contact">Tabby Tavern UNIFIED &nbsp;|&nbsp; Jeremy Panasuk &nbsp;|&nbsp; jpanasuk@gmail.com &nbsp;|&nbsp; 715.970.0204</p>
  <div class="links">
    <a href="https://huggingface.co/jpanasuk/tabby-tavern-stack">Model card + compose</a>
    <a class="ghost" href="https://github.com/jpanasuk-netizen/tabby-tavern-stack">GitHub</a>
  </div>
</div>

<div class="kicker-wrap">
  <div class="kicker">
    <p>STOP RENTING TWELVE SAAS SEATS. BUY THE ROOM ONCE. RUN THE LAB FOREVER.</p>
  </div>
</div>

<div class="container">
  <div class="stats-bar">
    <div class="stat"><div class="num">15</div><div class="label">Default services live</div></div>
    <div class="stat"><div class="num">1</div><div class="label">Compose + network</div></div>
    <div class="stat"><div class="num">9B</div><div class="label">Qwen GGUF on CUDA</div></div>
    <div class="stat"><div class="num">4070</div><div class="label">12 GB lab card</div></div>
  </div>

  <div class="section">
    <h2>THE PAYDAY</h2>
    <hr>
    <p>Your team already pays for chat, search, a vector store, an IDE plugin, a workflow tool, and a second UI “just in case.” Every prompt leaves the building. Every seat is a recurring invoice. A 12 GB workstation can host the whole motion if someone will compose it, name the network, and refuse to run three GPU engines at once.</p>
    <p>That is this lab. Not a slide. A running Docker project named <code>tabby-tavern</code> on <code>tabby-tavern_ai-network</code>. Primary inference is <b>Qwen3.5-9B</b> through llama.cpp CUDA. Chat, RAG, search, MCP, browser VS Code, n8n, and character cards sit on the same bridge. TabbyAPI EXL3 and Ollama stay in an <b>alternate-inference</b> profile so the 4070 does not eat itself.</p>
  </div>

  <div class="section">
    <h2>WHAT GOT MERGED</h2>
    <hr>
    <ul>
      <li><b>Taproot</b> — Qwen llama.cpp server, 262k context flags, flash-attn, q4 KV, OpenAI-compatible <code>/v1</code>.</li>
      <li><b>Basecamp</b> — code-server, Continue, Qdrant, Chroma, n8n, Lobe, AnythingLLM, LibreChat, Mongo, Meilisearch, pgvector. Volumes kept.</li>
      <li><b>Tabby Tavern</b> — SillyTavern + character cards, SearXNG JSON, MCPO FastMCP, Open WebUI as the canonical chat UI.</li>
      <li><b>dockroot</b> — read-only Docker MCP, optional <code>diagnostics</code> profile. Socket stays internal.</li>
    </ul>
    <p>Old Taproot and qwen38-agent containers are stopped. Their YAML is folded in, not dangling as a second project.</p>
  </div>

  <div class="section">
    <h2>THE BLOWOUT CONFIG — DEFAULT 15</h2>
    <hr>
    <p>Verified up on the lab box after the merge. Host URLs from WSL. Inside Docker, use the service name — never localhost.</p>
    <div class="cap-grid">
      <div class="cap-card c1"><div class="port">:1234</div><h3>qwen · llama.cpp CUDA</h3><p><b>Qwen3.5-9B</b> GGUF. Alias <code>Qwen3.5-9B</code>. Containers call <code>http://qwen:8080/v1</code>. This is the primary engine.</p></div>
      <div class="cap-card c2"><div class="port">:3000</div><h3>Open WebUI</h3><p>Canonical chat UI. OpenAI API to Qwen. SearXNG RAG. One UI — not a second Taproot WebUI on 3001.</p></div>
      <div class="cap-card c3"><div class="port">:8000</div><h3>SillyTavern + cards</h3><p>Character frontend. PNG cards ship in <code>cards/</code>. Import Seraphina. 401 on root is auth doing its job.</p></div>
      <div class="cap-card c4"><div class="port">:8080</div><h3>SearXNG</h3><p>Private metasearch, JSON on. Open WebUI and MCPO search through it. No tracking SaaS.</p></div>
      <div class="cap-card c5"><div class="port">:8001</div><h3>MCPO</h3><p>MCP → OpenAPI. Stack tools plus tavern connectivity. Swagger at <code>/docs</code>.</p></div>
      <div class="cap-card c6"><div class="port">:8443</div><h3>code-server</h3><p>Browser VS Code. Continue + Tabby extensions. Wired to Qwen <code>/v1</code> for chat and autocomplete.</p></div>
      <div class="cap-card c2"><div class="port">:6333</div><h3>Qdrant</h3><p>Vector store for RAG. Health <code>/healthz</code> 200 on the live lab.</p></div>
      <div class="cap-card c3"><div class="port">:8005</div><h3>Chroma</h3><p>Lightweight embeddings DB. Basecamp volume preserved.</p></div>
      <div class="cap-card c4"><div class="port">:5678</div><h3>n8n</h3><p>Workflow automation on the same network as the model. 400+ integrations, local.</p></div>
      <div class="cap-card c5"><div class="port">:3210</div><h3>Lobe Chat</h3><p>Extra chat UI pointed at Qwen. Keep Open WebUI as the source of truth.</p></div>
      <div class="cap-card c1"><div class="port">:3002</div><h3>AnythingLLM</h3><p>RAG workspace. Bring docs to the same box that runs the model.</p></div>
      <div class="cap-card c6"><div class="port">:3080</div><h3>LibreChat + Mongo</h3><p>Multi-model frontend. Mongo on the bridge. JWT from your <code>.env</code>.</p></div>
      <div class="cap-card c2"><div class="port">:7700</div><h3>Meilisearch</h3><p>Full-text search. Health 200 after merge.</p></div>
      <div class="cap-card c3"><div class="port">:5432</div><h3>Postgres + pgvector</h3><p>Hermes memory backend. Healthy. Password is a placeholder in the public tree.</p></div>
      <div class="cap-card c4"><div class="port">:27017</div><h3>Mongo</h3><p>LibreChat data. Named volume kept from Basecamp.</p></div>
    </div>
    <pre class="cmd">cd tabby-tavern
cp .env.example .env          # generate real keys
docker compose up -d          # 15 default services, Qwen only on GPU
# optional:
docker compose --profile alternate-inference up -d tabbyapi ollama
docker compose --profile diagnostics up -d --build dockroot</pre>
    <div class="note">
      <b>VRAM is the law.</b> Default is Qwen only. TabbyAPI EXL3 (:5000) and Ollama (:11435) are real, tested, and gated. Two heavy engines on a 12 GB card can block CUDA instead of erroring. Start them when Qwen is down, or when you mean to fight for VRAM.
    </div>
  </div>

  <div class="section">
    <h2>THE CONNECTION RULE</h2>
    <hr>
    <ul>
      <li>Path is always <code>/v1</code> — <code>http://qwen:8080/v1</code> from another container.</li>
      <li>Host is the <b>service name</b>, not localhost. Localhost inside a container is that container.</li>
      <li>Model id is <code>Qwen3.5-9B</code>, not the word “qwen.”</li>
      <li>If auth is on, send the key. Do not “fix” a 401 by changing the host.</li>
    </ul>
  </div>

  <div class="section">
    <h2>WHO SHIPS IT</h2>
    <hr>
    <p>Jeremy Panasuk — enterprise data / platform background: Kohl's Informatica (PowerCenter Grid/HA, AIX→commodity Cisco/IBM, DQ/MDM POCs, ~$2M software); Dawn, MF Global, BNY, Micron, NFCU, Mercedes, Smith &amp; Nephew. Independent local-AI year from Aug 2024: this Docker lab, decode telemetry, multi-agent prototypes, Hermes on the same box.</p>
    <p class="quote">"You sent one of the best that Informatica has to offer in Jeremy." — MF Global Infrastructure</p>
  </div>
</div>

<div class="container" style="padding-top:0;">
  <div class="pricing-header">
    <h2>ENGAGEMENTS</h2>
    <p>Three ways to put UNIFIED on your metal. 30 days email support after deploy.</p>
  </div>
  <div class="tiers">
    <div class="tier-card blue">
      <h3>SINGLE-GPU INSTALL</h3>
      <div class="price">$12,500</div>
      <div class="price-sub">one-time</div>
      <div class="who">One RTX-class box. The 15-service default. Qwen on CUDA.</div>
      <ul>
        <li>Compose + network + .env keys that are yours</li>
        <li>Open WebUI, SillyTavern cards, SearXNG, MCPO</li>
        <li>code-server + Continue on Qwen</li>
        <li>WSL2 / Linux bring-up</li>
        <li>Half-day onboarding</li>
      </ul>
    </div>
    <div class="tier-card accent">
      <h3>PRODUCTION DEPLOYMENT</h3>
      <div class="price">$25,000</div>
      <div class="price-sub">one-time</div>
      <div class="who">Hardened lab: profiles, backups, localhost binds, RAG volumes.</div>
      <ul>
        <li>Everything in Single-GPU</li>
        <li>alternate-inference profile documented for EXL3/Ollama</li>
        <li>dockroot diagnostics, optional</li>
        <li>Reverse-proxy / bind-localhost guidance</li>
        <li>Full-day runbook</li>
      </ul>
    </div>
    <div class="tier-card green">
      <h3>MANAGED PRIVATE AI</h3>
      <div class="price">$3,500<span style="font-size:0.7em;">/mo</span></div>
      <div class="price-sub">ongoing</div>
      <div class="who">We keep UNIFIED current. You use the UIs.</div>
      <ul>
        <li>Everything in Production</li>
        <li>Model pack and llama.cpp flag retunes</li>
        <li>Quarterly VRAM / health report</li>
        <li>New compose services as the lab grows</li>
        <li>Priority phone / Slack, 4hr SLA</li>
      </ul>
    </div>
  </div>
  <div class="bottom-line">
    <p><b>THE CLOSE.</b> This is not a multi-tenant SaaS. It is a private lab, production-shaped, that Hermes just reconciled onto one compose file. If the requirement is “one network, one Qwen endpoint, chat + RAG + IDE + MCP + character cards on hardware we own,” UNIFIED is the tree that matches the running box.</p>
  </div>
</div>

<div class="footer">
  <p>Jeremy Panasuk &nbsp;&bull;&nbsp; jpanasuk@gmail.com &nbsp;&bull;&nbsp; 715.970.0204 &nbsp;&bull;&nbsp; <a href="https://huggingface.co/jpanasuk/tabby-tavern-stack">huggingface.co/jpanasuk/tabby-tavern-stack</a></p>
  <p class="refs"><a href="https://huggingface.co/spaces/jpanasuk/dockroot-mcp">dockroot-mcp</a> · <a href="https://huggingface.co/spaces/jpanasuk/local-ai-stack-connectivity">connection rule</a> · GitHub release trail on <a href="https://github.com/jpanasuk-netizen/tabby-tavern-stack">tabby-tavern-stack</a></p>
</div>
</body>
</html>