@connectai/selfhost
Advanced tools
@@ -198,17 +198,2 @@ # ConnectAI self-host stack — IMAGE-BASED variant (no source clone). | ||
| # Local, offline inference (text + 1024-dim embeddings). To use a hosted model | ||
| # instead, remove this service and set the BYO path in deploy/selfhost/.env. | ||
| # ConnectAI's billed gateway is forbidden in self-host mode. | ||
| ollama: | ||
| image: ollama/ollama:latest | ||
| restart: unless-stopped | ||
| volumes: | ||
| - ollama-data:/root/.ollama | ||
| # The bundled Ollama is reached by the api/loop-svc over the compose network at | ||
| # http://ollama:11434, so it needs no host port. Publishing 11434 to the host | ||
| # collides with a native `ollama serve` (common on a dev box). Uncomment + | ||
| # remap to a free host port only if you want to reach this Ollama from the host. | ||
| # ports: | ||
| # - "11435:11434" | ||
| volumes: | ||
@@ -218,2 +203,1 @@ db-data: | ||
| infisical-redis-data: | ||
| ollama-data: |
@@ -127,3 +127,3 @@ #!/usr/bin/env bash | ||
| # --- 4. full stack ----------------------------------------------------------- | ||
| log "Bringing up the full stack (db, api, loop-svc, console, ollama)." | ||
| log "Bringing up the full stack (db, api, loop-svc, console)." | ||
| "${COMPOSE[@]}" up -d | ||
@@ -174,3 +174,3 @@ | ||
| 2. Open ${SETUP_URL} and paste the token. | ||
| 3. Create the first administrator, confirm inference, and connect a source. | ||
| 3. Create the first administrator, confirm the configured inference endpoint, and connect a source. | ||
@@ -177,0 +177,0 @@ Full walkthrough + troubleshooting: SELF_HOSTING.md |
+2
-3
| // Boot orchestration for `connectai run`. Delegates the actual stack bring-up to | ||
| // the bundled up.sh (the hardened, idempotent boot ENGINE) rather than | ||
| // re-implementing compose orchestration, then pulls models (soft-fail) and prints | ||
| // the next step. CON-131 scope items 5-7. | ||
| // re-implementing compose orchestration, then prints the next step. | ||
| import { spawn } from 'node:child_process' | ||
@@ -47,3 +46,3 @@ import path from 'node:path' | ||
| ui.raw(` Images: ghcr.io/connectai-os/connectai-{app,console}:${imageTag}`) | ||
| ui.raw(` Models: ${DEFAULT_CHAT_MODEL} + ${EMBED_MODEL}`) | ||
| ui.raw(` Default endpoint models: ${DEFAULT_CHAT_MODEL} + ${EMBED_MODEL}`) | ||
| ui.raw('') | ||
@@ -50,0 +49,0 @@ ui.raw(' NEXT STEP: copy the one-time setup token, then open the setup URL.') |
+5
-23
@@ -5,4 +5,2 @@ // `@connectai/selfhost` CLI entry. Dependency-free arg parsing + command dispatch. | ||
| // Flags: --dir <path> working dir (default ~/.connectai-selfhost) | ||
| // --model <name> override the chat model to pull (run only) | ||
| // --no-pull skip model pull (run only) | ||
| // --yes / -y non-interactive (already the default; accepted for CI) | ||
@@ -15,3 +13,3 @@ // --tag <tag> override the GHCR image tag (sets CONNECTAI_IMAGE_TAG) | ||
| import { fileURLToPath } from 'node:url' | ||
| import { DEFAULT_DIR, DEFAULT_CHAT_MODEL, DEFAULT_IMAGE_TAG, LEGACY_DEFAULT_DIR } from './constants.js' | ||
| import { DEFAULT_DIR, DEFAULT_IMAGE_TAG, LEGACY_DEFAULT_DIR } from './constants.js' | ||
| import { ui } from './ui.js' | ||
@@ -22,3 +20,2 @@ import { runPreflight } from './preflight.js' | ||
| import { runUpScript, printNextStep } from './boot.js' | ||
| import { pullModels } from './models.js' | ||
| import { down, getBootstrapStatus, logs, printSetupToken } from './compose.js' | ||
@@ -32,3 +29,3 @@ | ||
| export function parseArgs(argv) { | ||
| const flags = { dir: DEFAULT_DIR, model: DEFAULT_CHAT_MODEL, pull: true, yes: false, tag: undefined } | ||
| const flags = { dir: DEFAULT_DIR, yes: false, tag: undefined } | ||
| const rest = [] | ||
@@ -48,11 +45,5 @@ let command | ||
| break | ||
| case '--model': | ||
| flags.model = argv[++i] ?? DEFAULT_CHAT_MODEL | ||
| break | ||
| case '--tag': | ||
| flags.tag = argv[++i] | ||
| break | ||
| case '--no-pull': | ||
| flags.pull = false | ||
| break | ||
| case '--yes': | ||
@@ -181,10 +172,3 @@ case '-y': | ||
| // 5. Model pull (soft-fail). | ||
| if (flags.pull) { | ||
| await pullModels(flags.dir, { chatModel: flags.model }) | ||
| } else { | ||
| ui.step('Skipping model pull (--no-pull). Pull a model later from the wizard.') | ||
| } | ||
| // 6. Output. | ||
| // 5. Output. | ||
| printNextStep(flags.dir) | ||
@@ -242,3 +226,3 @@ return 0 | ||
| run (default) pre-flight, materialize assets, write .env, boot the | ||
| stack, pull local models, print the console URL + next step | ||
| stack and print the console URL + next step | ||
| down stop the stack (add -v to also remove volumes / wipe the brain) | ||
@@ -253,4 +237,2 @@ logs tail stack logs (e.g. \`logs api\`) | ||
| --dir <path> working directory (default: ~/.connectai-selfhost) | ||
| --model <name> chat model to pull (default: ${DEFAULT_CHAT_MODEL}) | ||
| --no-pull skip the model pull | ||
| --tag <tag> GHCR image tag to run (default: ${DEFAULT_IMAGE_TAG}) | ||
@@ -263,3 +245,3 @@ --yes, -y non-interactive (already the default; accepted for CI) | ||
| npx @connectai/selfhost run | ||
| npx @connectai/selfhost run --dir /opt/connectai --no-pull | ||
| npx @connectai/selfhost run --dir /opt/connectai | ||
| npx @connectai/selfhost token | ||
@@ -266,0 +248,0 @@ npx @connectai/selfhost down -v |
+2
-2
| { | ||
| "name": "@connectai/selfhost", | ||
| "version": "0.1.8", | ||
| "description": "One-command self-host installer for ConnectAI. Takes a clean machine (only Docker + Node) to a running, health-checked company-brain in one command, with no source clone and no local image build: `npx @connectai/selfhost run`. Bundles the image-based docker-compose stack + boot scripts, generates a strong .env (CSPRNG ENCRYPTION_SECRET + POSTGRES_PASSWORD), boots the stack, and soft-pulls the local inference models.", | ||
| "version": "0.1.9", | ||
| "description": "One-command self-host installer for ConnectAI. Takes a clean machine (only Docker + Node) to a running, health-checked company-brain in one command, with no source clone and no local image build: `npx @connectai/selfhost run`. Bundles the image-based docker-compose stack + boot scripts, generates a strong .env (CSPRNG ENCRYPTION_SECRET + POSTGRES_PASSWORD), and boots the stack.", | ||
| "type": "module", | ||
@@ -6,0 +6,0 @@ "bin": { |
+5
-8
@@ -15,3 +15,3 @@ # @connectai/selfhost | ||
| The CLI pulls prebuilt images, writes a hardened `.env`, boots the stack, pulls the local inference models, and prints the console URL + your single next step. | ||
| The CLI pulls prebuilt images, writes a hardened `.env`, boots the stack, and prints the console URL + your single next step. The installed stack is endpoint-first: use your `INFERENCE_*` values to point at an OpenAI-compatible provider, with host-local Ollama as the default starter endpoint. | ||
@@ -41,5 +41,4 @@ ## Quick start | ||
| 3. **Generate `.env`**: copies the example, then fills the secrets with a CSPRNG (`crypto.randomBytes`): `INFISICAL_*`, **`ENCRYPTION_SECRET`** (32 bytes / 64 hex), and a strong **`POSTGRES_PASSWORD`** (with `DATABASE_URL` updated to match). Written `chmod 600`. **Idempotent**: it never overwrites a value you already set, and a second run is a no-op. Secrets are local-only: never logged, never transmitted. | ||
| 4. **Boot**: delegates to the bundled `up.sh`, which `docker compose pull`s the prebuilt images, brings up Infisical, provisions the vault identity, brings up the full stack, and waits for the API `/health` + the console. By default the installer runs the first-party GHCR images at the pinned, pullable tag **`v0.1.7`**: the merged backend image `ghcr.io/connectai-os/connectai-app:v0.1.7` (used by both api + worker roles) plus `ghcr.io/connectai-os/connectai-console:v0.1.7`. You can override the release with `--tag` / `CONNECTAI_IMAGE_TAG`. It also pulls the pinned support images from the compose bundle: `infisical/infisical:v0.159.28`, `pgvector/pgvector:pg16`, `postgres:16-alpine`, `redis:7-alpine`, and `ollama/ollama:latest`. | ||
| 5. **Pull models** (`qwen2.5:1.5b` chat + `mxbai-embed-large` embed) into the bundled Ollama. **Soft-fail**: a pull error warns and points at the wizard, it never fails the install. | ||
| 6. **Print** the console URL, the setup-token command, and the next step. | ||
| 4. **Boot**: delegates to the bundled `up.sh`, which `docker compose pull`s the prebuilt images, brings up Infisical, provisions the vault identity, brings up the full stack, and waits for the API `/health` + the console. By default the installer runs the first-party GHCR images at the pinned, pullable tag **`v0.1.7`**: the merged backend image `ghcr.io/connectai-os/connectai-app:v0.1.7` (used by both api + worker roles) plus `ghcr.io/connectai-os/connectai-console:v0.1.7`. You can override the release with `--tag` / `CONNECTAI_IMAGE_TAG`. It also pulls the pinned support images from the compose bundle: `infisical/infisical:v0.159.28`, `pgvector/pgvector:pg16`, `postgres:16-alpine`, and `redis:7-alpine`. | ||
| 5. **Print** the console URL, the setup-token command, and the next step. | ||
@@ -50,3 +49,3 @@ ## Command examples | ||
| npx @connectai/selfhost run | ||
| npx @connectai/selfhost run --dir /opt/connectai --no-pull | ||
| npx @connectai/selfhost run --dir /opt/connectai | ||
| npx @connectai/selfhost logs api | ||
@@ -72,4 +71,2 @@ npx @connectai/selfhost token | ||
| | `--dir <path>` | working directory (default `~/.connectai-selfhost`) | | ||
| | `--model <name>` | chat model to pull (default `qwen2.5:1.5b`) | | ||
| | `--no-pull` | skip the model pull | | ||
| | `--tag <tag>` | GHCR image tag to run (default: `v0.1.7`; also `CONNECTAI_IMAGE_TAG`) | | ||
@@ -92,3 +89,3 @@ | `--yes`, `-y` | non-interactive (already the default; accepted for CI) | | ||
| - The packaged installer defaults to the verified `v0.1.7` release tag. If you override it, keep the same tag across your operator docs and rollout notes. | ||
| - The first run downloads several GB (images + models) and can take a few minutes; re-runs are fast and idempotent. | ||
| - The first run downloads several GB of images and can take a few minutes; re-runs are fast and idempotent. | ||
| - This is a thin front door over the same hardened `up.sh` boot engine used by a source checkout; it does not re-implement orchestration. | ||
@@ -95,0 +92,0 @@ |
| // Pull the local inference models into the bundled Ollama. SOFT-FAIL by contract | ||
| // (CON-131 scope item 6): a pull failure WARNS and points at the wizard, it never | ||
| // fails the install. The stack is already healthy at this point; models only affect | ||
| // first-query latency. | ||
| import { spawn } from 'node:child_process' | ||
| import { composeArgs, composeEnv } from './compose.js' | ||
| import { DEFAULT_CHAT_MODEL, EMBED_MODEL } from './constants.js' | ||
| import { ui } from './ui.js' | ||
| export function pullOne(dir, model, { spawnImpl = spawn, composeEnvImpl = composeEnv } = {}) { | ||
| return new Promise((resolve) => { | ||
| // `docker compose exec -T ollama ollama pull <model>` streams progress to the | ||
| // inherited stdout. -T disables TTY allocation (safe in non-interactive runs). | ||
| const child = spawnImpl('docker', [...composeArgs(dir), 'exec', '-T', 'ollama', 'ollama', 'pull', model], { | ||
| stdio: 'inherit', | ||
| env: composeEnvImpl(dir), | ||
| }) | ||
| child.on('error', () => resolve(false)) | ||
| child.on('exit', (code) => resolve(code === 0)) | ||
| }) | ||
| } | ||
| // Pull the chat model (override via --model) + the embedding model. Returns a | ||
| // summary; the caller decides messaging. Always resolves (never rejects). | ||
| export async function pullModels(dir, { chatModel = DEFAULT_CHAT_MODEL } = {}) { | ||
| const targets = [chatModel, EMBED_MODEL] | ||
| const results = [] | ||
| for (const model of targets) { | ||
| ui.step(`Pulling model ${ui.bold(model)} into the bundled Ollama (this can take a while).`) | ||
| const ok = await pullOne(dir, model) | ||
| results.push({ model, ok }) | ||
| if (ok) ui.ok(`pulled ${model}`) | ||
| else ui.warn(`could not pull ${model}; you can pull it later from the setup wizard.`) | ||
| } | ||
| return results | ||
| } |
Sorry, the diff of this file is not supported yet
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
83057
-3.86%16
-5.88%745
-6.52%91
-3.19%