This site covers how to use each service after it's set up. For installation steps, see the setup guide. For source code and architecture, see the bundle README.
All Services at a Glance
Infrastructure Reference
ai-stack Docker network. Each service is reachable by its container name./shared and a bind-mount at /uploads.How to Read This Documentation
Each service tab follows the same structure:
- Quick Start โ login URL + first thing to do after logging in
- Common Tasks โ the 5-10 most useful workflows
- This Setup's Quirks โ anything specific to how it's configured here
- Resources โ official docs and references
.pocketcode.in cookie that protects every subdomain via Caddy's forward_auth. Auto-SSO goes further: the gateway also programmatically logs you into Sim.ai, Open WebUI, and n8n using stored credentials โ click any card and you're already inside. A watchdog refreshes those service sessions every 2 minutes and on tab focus, so if you accidentally click a service's own "Logout" or its session expires, you're silently re-logged-in within seconds.
forward_auth immediately blocks access to every *.pocketcode.in service โ visiting any of them redirects to the pocketcode login page. After re-logging in, every service is instantly accessible again (since their own sessions never died).
Quick Start
- Go to chat.pocketcode.in
- Sign in with your Open WebUI admin account (first signup = admin)
- Pick a model from the dropdown at the top center of the chat window
- Type a message โ press Enter
Pull a New Model
Models are pulled inside the Ollama container. You can do this from Open WebUI's admin panel OR via the web terminal:
docker exec ollama ollama pull llama3.2:3b docker exec ollama ollama pull qwen2.5:7b docker exec ollama ollama pull nomic-embed-text # for RAG embeddings
Or in Open WebUI: Settings โ Admin Panel โ Models โ Pull a model from Ollama.com. Type the model name (e.g. llama3.2:3b) and click pull.
Common Tasks
Upload a document for Q&A (RAG):
- Click the ๐ paperclip icon in the chat input
- Select a PDF, DOCX, MD, or TXT file
- Ask questions about it โ the model reads the document and answers
Build a permanent knowledge base:
- Profile (top right) โ Workspace โ Knowledge โ + Create Knowledge
- Name it (e.g. "Company Docs") โ upload multiple files
- Open WebUI chunks the docs, embeds them with
nomic-embed-text, stores in ChromaDB - In any chat, reference the collection with
#Company Docs
Create a custom model with a pinned system prompt:
- Workspace โ Models โ + Create a model
- Choose base model (e.g. llama3.2), add a system prompt, save
- Now appears in the chat model dropdown
Use as OpenAI-compatible API for other tools:
curl https://chat.pocketcode.in/api/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.2:3b",
"messages": [{"role":"user","content":"Hello"}]
}'
API key is in Settings โ Account โ API Keys. Click "Create new secret key".
Useful Settings
| Setting | Where | What it does |
|---|---|---|
| Default model | Settings โ General | Picked when you start a new chat |
| Embedding model | Admin โ Settings โ Documents | Set to nomic-embed-text for RAG |
| System prompt | Per-chat โ๏ธ icon | Pin instructions for that conversation |
| Temperature | Per-chat โ๏ธ โ Advanced | 0 = deterministic, 1 = creative |
| User signups | Admin โ Settings โ General | Enable/disable. Default is "pending approval" |
This Setup's Quirks
http://ollama:11434 (internal Docker DNS). Open WebUI sees all your Ollama models automatically.
Resources
Quick Start
- Go to sim.pocketcode.in
- Sign up (first time) or sign in
- Click + New Workflow
- Drag blocks from the left panel onto the canvas, connect them with lines
- Click Run in the top right to test
Block Types
| Block | What it does | Common use |
|---|---|---|
| Agent | LLM call with optional tools | Most workflows start here |
| Function | Run JavaScript code | Data transformation between steps |
| API | HTTP request to any URL | Call external services |
| Condition | If/else branching | Route based on agent output |
| Loop | Iterate over array | Process lists of items |
| Schedule | Cron trigger | Run workflow on schedule |
| Webhook | HTTP endpoint trigger | External app calls Sim.ai |
Connecting to Models
Inside any Agent block:
- Local Ollama: Provider = Ollama, base URL is auto-set to
http://ollama:11434 - Cloud models via OpenRouter: Provider = OpenAI, base URL =
http://openrouter-proxy:4000, API key = whatever you set in LiteLLM config (or leave blank if disabled) - Direct Claude API: Provider = Anthropic, paste your Anthropic API key
Build Your First Workflow โ Hello World
- Drag Agent block onto canvas
- Set model:
llama3.2:3b - Set system prompt: "You are a helpful assistant."
- Set user message: "What is 2+2?"
- Click Run โ see the output in the right panel
Add Tools to an Agent
Tools let agents take actions. Click an Agent block โ Tools tab โ add:
- HTTP request โ agent can call any URL
- JavaScript โ agent can execute code
- Knowledge base โ agent can query a Qdrant collection
- Memory โ agent can read/write to short-term memory
Common Tasks
Schedule a workflow to run daily:
- Add a Schedule block โ set cron (e.g.
0 9 * * *= daily 9am) - Connect it to your first Agent block
- Click Deploy in top right
- Workflow now runs automatically
Expose workflow as a webhook (for external apps):
- Add a Webhook block as the trigger
- Deploy โ copy the webhook URL
- Any service can POST JSON to it โ triggers the workflow
This Setup's Quirks
sim-db-1 (pgvector image) which also hosts databases for n8n, OpenClaw, and Open WebUI. Inspect via pgAdmin โ connect to host sim-db-1, port 5432.
sim-realtime.pocketcode.in serves the live-collaboration WebSocket. If /workspace goes blank, check the subdomain's cert is valid and your browser cache is clear.
Resources
Quick Start
- Go to n8n.pocketcode.in
- Sign in with your owner account (first signup = owner)
- Click + Add workflow
- Click + in the canvas โ search for a trigger (e.g. "Manual")
- Add more nodes โ connect โ click Execute Workflow
Node Categories
| Category | Examples | Use for |
|---|---|---|
| Triggers | Manual, Webhook, Schedule, Email, Slack | Starting events |
| AI | OpenAI, Anthropic, Ollama, OpenRouter | LLM calls |
| Apps | Slack, Discord, Gmail, GitHub, Notion | External service integration |
| Data | Postgres, HTTP Request, RSS, CSV | Read/write data |
| Logic | IF, Switch, Loop, Merge, Wait | Flow control |
| Code | Function, Code (JS/Python) | Custom transforms |
Build Your First Workflow โ Slack to Ollama
- Trigger: Slack Trigger (or Webhook for testing)
- Add Ollama Chat Model node โ base URL
http://ollama:11434, modelllama3.2:3b - Add AI Agent node โ pass the Slack message as user input
- Add Slack Send Message node โ post the AI response back
- Click Activate in top right
Common Tasks
Use Ollama directly in a workflow:
- Add Ollama Chat Model node
- Credentials โ New โ Base URL:
http://ollama:11434 - Pick model from dropdown
Use cloud models (Claude/GPT) via OpenRouter:
- Add OpenAI Chat Model node (yes, even for Claude โ OpenRouter is OpenAI-compatible)
- Credentials โ New โ Base URL:
http://openrouter-proxy:4000, API key: any value (or your LiteLLM master key) - Set model name to OpenRouter format (e.g.
anthropic/claude-3.5-sonnet)
Query the shared Postgres:
- Add Postgres node
- Credentials: Host =
sim-db-1, Port =5432, DB =n8n, User/Pass from your.env - Pick operation (Select, Insert, Update)
Receive webhooks from external apps:
- Use Webhook trigger node
- n8n shows you the test + production URLs
- For production (after Activate), URL is
https://n8n.pocketcode.in/webhook/<your-path>
This Setup's Quirks
n8n-data Docker volume holds the encryption key. All your stored credentials remain readable across container restarts. Back up this volume periodically.
~/ai-stack/n8n/run-n8n.sh โ should have WEBHOOK_URL=https://n8n.pocketcode.in/ so webhook URLs n8n generates point to the right place.
Resources
Quick Start
- Go to openclaw.pocketcode.in
- If first-time access, you may see a "Pair device" prompt โ see "Device Pairing" below
- Type a message in the chat input โ send
Device Pairing
OpenClaw uses a device pairing system. New browsers/devices need to be approved from the CLI:
docker exec -it openclaw node /app/openclaw.mjs devices list docker exec -it openclaw node /app/openclaw.mjs devices approve <UUID>
Common Tasks
Switch the active model:
- Settings (gear icon) โ Models
- Choose from local Ollama or configured cloud providers
Configure cloud model providers:
- Settings โ API Keys โ add Anthropic / OpenAI / OpenRouter keys
- Models become available in the chat selector
Start a new agent session:
- Click + New Session (sidebar)
- Pick a model + system prompt template (or custom)
- Sessions persist in the OpenClaw database
This Setup's Quirks
http://ollama:11434 via the ai-stack Docker network. Models pulled into Ollama appear automatically.
Resources
- OpenClaw docs (if available)
Quick Start
Claude Code is a CLI tool, not a web service. Access via the web terminal or SSH:
docker exec -it claude-code bash claude
First run prompts for an Anthropic API key. Paste yours from console.anthropic.com โ API Keys.
Basic Usage
claudeโ start interactive session in current directoryclaude "fix the bug in main.py"โ give a task directlyclaude --continueโ resume the last conversation/helpinside the session โ see all commands/clearโ clear the conversation/costโ see token usage and cost
Working with the Stack
The claude-code container mounts ~/ai-stack at /workspace. So you can:
docker exec -it claude-code bash cd /workspace/sim # Sim.ai config claude "review the docker-compose.prod.yml and suggest improvements"
Common Tasks
Code review a file:
claude "review /workspace/manage/start-all.sh and find any race conditions"
Generate a new service config:
claude "create a docker-compose.yml for a Redis instance on the ai-stack network with persistence"
Debug a failing container:
docker logs sim-simstudio-1 --tail 100 > /tmp/logs.txt claude "read /tmp/logs.txt and tell me why this container is restarting"
This Setup's Quirks
/cost regularly. Sonnet 4 is ~$3/M input + $15/M output tokens.
/workspace.
Resources
What This Is
A LiteLLM proxy that exposes an OpenAI-compatible API on port 4000. You configure cloud providers (OpenAI, Anthropic, OpenRouter.ai, etc.) once, and any tool that speaks OpenAI's API can use them.
From Inside the Stack
Containers on the ai-stack network reach the proxy at:
http://openrouter-proxy:4000
From Outside (via HTTPS)
https://openrouter.pocketcode.in
Configured Models
Check ~/ai-stack/openrouter-proxy/litellm-config.yaml on the server. Typical entries:
model_list:
- model_name: claude-sonnet-4
litellm_params:
model: anthropic/claude-sonnet-4-20250514
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
- model_name: llama-3.3-70b
litellm_params:
model: openrouter/meta-llama/llama-3.3-70b-instruct
api_key: os.environ/OPENROUTER_API_KEY
Common Tasks
Test from terminal:
curl https://openrouter.pocketcode.in/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4",
"messages": [{"role":"user","content":"Hello"}]
}'
Add a new model:
- Edit
~/ai-stack/openrouter-proxy/litellm-config.yamlโ add a new entry - Restart the container:
docker restart openrouter-proxy - The new
model_nameis now usable everywhere
Use from Python:
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.pocketcode.in/v1",
api_key="any-string" # disabled in default config
)
response = client.chat.completions.create(
model="claude-sonnet-4",
messages=[{"role": "user", "content": "Hello"}]
)
print(response.choices[0].message.content)
This Setup's Quirks
~/ai-stack/openrouter-proxy/.env: ANTHROPIC_API_KEY=, OPENAI_API_KEY=, OPENROUTER_API_KEY=. Reference them in the YAML as os.environ/VAR_NAME.
/spend endpoint for usage stats.
Resources
What This Is
The raw Ollama API. Most users interact with Ollama via Open WebUI (recommended for chat) or via the SDK in code. This page covers direct API usage.
Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/api/tags | GET | List installed models |
/api/generate | POST | Single-turn generation |
/api/chat | POST | Multi-turn chat |
/api/embeddings | POST | Get vector embeddings |
/api/pull | POST | Download a new model |
/api/show | POST | Get model details |
Common Calls
List installed models:
curl https://ollama.pocketcode.in/api/tags
Chat completion:
curl https://ollama.pocketcode.in/api/chat -d '{
"model": "llama3.2:3b",
"messages": [{"role":"user","content":"Hello"}],
"stream": false
}'
Generate embeddings (for RAG):
curl https://ollama.pocketcode.in/api/embeddings -d '{
"model": "nomic-embed-text",
"prompt": "The text to embed"
}'
Pull a new model (from terminal, not API recommended):
docker exec ollama ollama pull llama3.2:3b docker exec ollama ollama pull qwen2.5:7b docker exec ollama ollama pull nomic-embed-text
Model Recommendations (CPU mode)
| Model | Size | Speed on KVM 8 | Use for |
|---|---|---|---|
llama3.2:3b | 2.0 GB | 12-18 tok/s | Default chat, summaries |
llama3.2:1b | 1.3 GB | 30-40 tok/s | Fast tasks, classification |
qwen2.5:7b | 4.7 GB | 4-7 tok/s | Better reasoning |
qwen2.5-coder:7b | 4.7 GB | 4-7 tok/s | Code completion |
nomic-embed-text | 274 MB | Embedding only | RAG vector embeddings |
This Setup's Quirks
ollama-data Docker volume. Survives container restarts. Inspect with docker exec ollama du -sh /root/.ollama.
OLLAMA_NUM_PARALLEL=2 in the run script if multiple users share the instance.
Resources
What This Is
A vector database for semantic search and RAG. Store embeddings of text/images, query by similarity. Used by Sim.ai's knowledge tool and any custom workflow that needs vector search.
Web UI
qdrant.pocketcode.in/dashboard opens the Qdrant Web UI for browsing collections, inspecting points, running test queries.
Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/collections | GET | List all collections |
/collections/{name} | PUT | Create a collection |
/collections/{name}/points | PUT | Insert/update vectors |
/collections/{name}/points/search | POST | Similarity search |
Quick Workflow โ Create + Query Collection
Step 1 โ Create a collection (vectors of size 768, matching nomic-embed-text):
curl -X PUT https://qdrant.pocketcode.in/collections/my-docs \
-H "Content-Type: application/json" \
-d '{"vectors":{"size":768,"distance":"Cosine"}}'
Step 2 โ Get an embedding from Ollama and insert:
# Get embedding
EMB=$(curl -s https://ollama.pocketcode.in/api/embeddings \
-d '{"model":"nomic-embed-text","prompt":"The quick brown fox"}' \
| jq -c .embedding)
# Insert into Qdrant
curl -X PUT https://qdrant.pocketcode.in/collections/my-docs/points \
-H "Content-Type: application/json" \
-d "{\"points\":[{\"id\":1,\"vector\":$EMB,\"payload\":{\"text\":\"The quick brown fox\"}}]}"
Step 3 โ Search:
QUERY_EMB=$(curl -s https://ollama.pocketcode.in/api/embeddings \
-d '{"model":"nomic-embed-text","prompt":"fast animal"}' \
| jq -c .embedding)
curl -X POST https://qdrant.pocketcode.in/collections/my-docs/points/search \
-H "Content-Type: application/json" \
-d "{\"vector\":$QUERY_EMB,\"limit\":5,\"with_payload\":true}"
Common Tasks
List collections:
curl https://qdrant.pocketcode.in/collections
Delete a collection:
curl -X DELETE https://qdrant.pocketcode.in/collections/my-docs
This Setup's Quirks
nomic-embed-text outputs 768-dim vectors. If you switch to all-minilm use 384, OpenAI's text-embedding-3-small uses 1536. Set the right size when creating collections.
Resources
Quick Start
- Go to pgadmin.pocketcode.in
- Sign in with email/password from
PGADMIN_DEFAULT_EMAIL/PGADMIN_DEFAULT_PASSWORDenv vars - Add a new server connection (first-time only)
Connect to the Shared Postgres
In pgAdmin: right-click Servers โ Register โ Server. Then:
| Tab | Field | Value |
|---|---|---|
| General | Name | ai-stack-db (anything) |
| Connection | Host | sim-db-1 |
| Connection | Port | 5432 |
| Connection | Maintenance DB | postgres |
| Connection | Username | From your ~/ai-stack/sim/.env (POSTGRES_USER) |
| Connection | Password | From your ~/ai-stack/sim/.env (POSTGRES_PASSWORD) |
What Databases Are There?
| Database | Used by |
|---|---|
ailab | General-purpose (you can use freely) |
simstudio | Sim.ai workflows & users |
openclaw | OpenClaw sessions |
n8n | n8n workflows & credentials |
ollama_results | If you stash Ollama outputs (optional) |
Common Tasks
Run a query:
- Navigate to a database in the tree
- Right-click โ Query Tool
- Type SQL โ F5 to execute
Export a table to CSV:
- Right-click a table โ Import/Export Data
- Choose Export, set CSV format, browse for output location
Backup the whole stack DB:
docker exec sim-db-1 pg_dumpall -U postgres > ~/ai-stack/backups/all-$(date +%Y%m%d).sql
pgvector queries (Sim.ai uses this):
-- Find vectors closest to a target SELECT id, content, embedding <-> '[0.1, 0.2, ...]'::vector AS distance FROM documents ORDER BY distance LIMIT 5;
This Setup's Quirks
sim-db-1 container uses the pgvector/pgvector:pg17 image. CREATE EXTENSION vector; already done in each database.
Resources
What This Is
A full bash terminal running in your browser. The container has the host Docker socket mounted, so you can manage every container in your stack without SSH. Perfect for quick admin from your phone, tablet, or any browser.
Quick Start
- Go to terminal.pocketcode.in
- If not logged in โ bounces you to
pocketcode.into log in - Terminal loads โ you see
root@<container-id>:~#prompt - Type any command and press Enter
Keyboard Shortcuts
| Shortcut | What it does |
|---|---|
Ctrl+Shift+C | Copy selected text (browsers reserve plain Ctrl+C) |
Ctrl+Shift+V | Paste from clipboard |
| Right-click | Context menu with paste option |
Ctrl+C in terminal | Interrupt running process (e.g. stop a tail -f) |
Ctrl+D | Exit current shell (reconnects automatically) |
What You Can Do
Manage every container:
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
docker logs sim-simstudio-1 --tail 50
docker restart n8n
docker exec -it ollama bash
Edit any config file:
nano ~/ai-stack/caddy/Caddyfile nano ~/ai-stack/sim/.env docker exec caddy caddy reload --config /etc/caddy/Caddyfile
Use stack aliases (after sourcing .bashrc):
source ~/.bashrc ai-start # bring up all containers ai-stop # graceful shutdown ai-doctor # full diagnostic ai-status # quick container health snapshot ai-logs n8n # tail any service's logs ai-reboot # restart whole stack
Pull new Ollama models:
docker exec ollama ollama pull qwen2.5:7b docker exec ollama ollama list
Run Claude Code from here:
docker exec -it claude-code bash claude "review the start-all.sh script for race conditions"
Query the shared Postgres:
docker exec -it sim-db-1 psql -U postgres -d simstudio \dt -- list tables \q -- quit
This Setup's Quirks
bash in the terminal container, with these mounts:
/var/run/docker.sockโ talk to host Docker (manage all containers)/root/ai-stackโ edit any config file (changes affect host)/root/.bash_historyโ command history persists/root/.ssh:roโ read-only SSH keys (for outbound scp etc.)
apt install packages on the host. You're inside an Alpine-based image. For host-level changes (kernel modules, system packages, systemd services), use real SSH. 99% of stack management works fine here.
Resources
- ttyd on GitHub โ the web terminal we're using
- Docker CLI reference
Architecture
One PostgreSQL container โ sim-db-1 running pgvector/pgvector:pg17 โ hosts every database in the stack. Sim.ai brings it up (it's in the Sim.ai compose file), but pgAdmin, n8n, OpenClaw, and any custom workflow share the same instance. The container sits on two Docker networks simultaneously: sim_default (Sim.ai's own) and ai-stack (the rest of the stack), so anyone can reach it.
The Five Databases
| Database | Owner / Primary user | What's inside |
|---|---|---|
simstudio | Sim.ai | Workflows, agents, users, runs, knowledge base embeddings (pgvector) |
n8n | n8n | Workflows, credentials (encrypted), executions, webhooks |
openclaw | OpenClaw | Sessions, chat history, device pairings |
ailab | General-purpose | Free for your own use โ custom tables, prototypes, scratch |
ollama_results | Optional | If you stash inference outputs from cron jobs, n8n, etc. |
Connection Strings
| From | How to connect |
|---|---|
| Inside Docker (any service on ai-stack) | postgres://USER:PASS@sim-db-1:5432/<db> |
| pgAdmin in browser | Host = sim-db-1, Port = 5432 (Sim.ai's .env has the password) |
| Web terminal (CLI psql) | docker exec -it sim-db-1 psql -U postgres -d <db> |
pgvector Extension
Already installed in every database. Use it for semantic search inside Postgres without needing Qdrant for small datasets:
-- nomic-embed-text returns 768-dim vectors CREATE TABLE documents ( id BIGSERIAL PRIMARY KEY, content TEXT, embedding vector(768), created_at TIMESTAMPTZ DEFAULT now() ); -- Index for fast similarity search CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops); -- Find nearest neighbors SELECT id, content, embedding <=> '[0.1, 0.2, ...]'::vector AS distance FROM documents ORDER BY distance LIMIT 5;
Common Tasks
Get a psql shell:
docker exec -it sim-db-1 psql -U postgres -d ailab
List all databases:
docker exec sim-db-1 psql -U postgres -l
Backup a single database:
docker exec sim-db-1 pg_dump -U postgres -Fc -d n8n > ~/backups/n8n-$(date +%Y%m%d).pgcustom
Backup everything (pg_dumpall):
docker exec sim-db-1 pg_dumpall -U postgres > ~/backups/all-$(date +%Y%m%d).sql
Restore from backup:
cat ~/backups/all-20260516.sql | docker exec -i sim-db-1 psql -U postgres
Create a new database for your project:
-- via pgAdmin Query Tool or psql shell CREATE DATABASE my_project; \c my_project CREATE EXTENSION vector;
Connection Pool Limits
Default Postgres config allows ~100 concurrent connections. Sim.ai + n8n + OpenClaw typically use ~30. If you start running into "too many connections" errors, increase the limit:
docker exec sim-db-1 psql -U postgres -c "ALTER SYSTEM SET max_connections=200;" docker restart sim-db-1
This Setup's Quirks
docker compose down from ~/ai-stack/sim/, the database goes away. ai-stop handles this gracefully (stops dependent services first), but if you ever manually run compose commands, be aware.
sim_default AND ai-stack. After a Sim.ai recompose, it sometimes drops the ai-stack attachment โ ai-start reconnects it automatically. If you see "host sim-db-1 not found" errors from n8n or OpenClaw, run docker network connect ai-stack sim-db-1 manually.
n8n-data), not in Postgres. Back up that volume separately if you care about preserving stored credentials across rebuilds.
Resources
The Network Architecture
Every container in the stack is on the ai-stack Docker network. Docker provides automatic DNS resolution between containers using their container names. Sim.ai's compose stack has its own internal network sim_default, and sim-db-1 straddles both so services on either network can reach it.
Internal Hostnames
Inside any container on ai-stack, these hostnames resolve automatically:
| Hostname | Port | What it is | Common use |
|---|---|---|---|
ollama | 11434 | Ollama API | LLM inference |
open-webui | 8080 | Open WebUI | โ |
auth-gateway | 7000 | Gateway service | Caddy forward_auth |
sim-db-1 | 5432 | PostgreSQL | Any service's database |
sim-simstudio-1 | 3000 | Sim.ai web app | Caddy upstream |
sim-realtime-1 | 3002 | Sim.ai WebSocket | Workspace live collab |
sim-redis-1 | 6379 | Redis (Sim.ai) | Sim.ai queues, sessions |
openclaw | 8080 | OpenClaw | โ |
n8n | 5678 | n8n | โ |
openrouter-proxy | 4000 | LiteLLM proxy | Cloud model gateway |
qdrant | 6333 | Qdrant REST | Vector search |
pgadmin | 80 | pgAdmin | โ |
terminal | 7681 | Web terminal (ttyd) | โ |
caddy | 80, 443 | Reverse proxy | โ |
Why Use Internal Hostnames?
- Faster โ stays inside Docker, no DNS over the internet, no TLS handshake
- More reliable โ no dependence on external DNS or Caddy being up
- No auth wall โ gateway auth is at Caddy; internal calls skip it (intentional: they're already trusted within Docker)
- Container IPs change on restart, but the hostname always resolves to the current IP
Common Patterns
n8n calling Ollama: In n8n's Ollama Chat Model credentials, set Base URL to:
http://ollama:11434
n8n calling OpenRouter (cloud models) via the proxy:
Base URL: http://openrouter-proxy:4000 API Key: any-non-empty-string
Sim.ai calling Ollama: already wired via Sim.ai's OLLAMA_URL=http://ollama:11434 env var.
Custom script calling everything from a terminal:
curl http://ollama:11434/api/tags curl http://qdrant:6333/collections curl http://openrouter-proxy:4000/v1/models
Connecting from a brand-new container you create: Add it to the ai-stack network:
docker run -d --name my-app \ --network ai-stack \ -e DB_URL=postgres://postgres:PASS@sim-db-1:5432/ailab \ -e LLM_URL=http://ollama:11434 \ my-image:latest
Adding a Service to ai-stack
- Run with
--network ai-stackflag (ornetworks: [ai-stack]in compose) - Once started, it can reach every other container by name
- If it needs to be public via HTTPS, add a Caddyfile block per Tab 13
Auto-SSO Across Services
The gateway at pocketcode.in ships with optional auto-SSO: when you sign in at the apex, hidden iframes silently log you into Sim.ai, Open WebUI, and n8n using credentials stored in ~/ai-stack/auth-gateway/.env. Three things are happening:
| Phase | What runs | How it works |
|---|---|---|
| 1. Master login | Gateway sets pocketcode_session cookie scoped to .pocketcode.in | One cookie sent to every subdomain โ Caddy's forward_auth sees it and lets you through |
| 2. Bootstrap | home.html creates hidden iframes pointing at https://<svc>.pocketcode.in/_sso_init | Caddy proxies /_sso_init to the gateway; gateway POSTs to the service's login API internally, forwards Set-Cookie back through Caddy โ cookie scoped to <svc>.pocketcode.in |
| 3. Watchdog | iframes re-load every 2 min and on tab focus | If you got logged out of any service in the meantime, the next refresh logs you back in. No way to "stay out" of a service while the master session is alive. |
Which services auto-SSO works for
| Service | SSO? | Why / why not |
|---|---|---|
| Sim.ai | โ | BetterAuth's POST /api/auth/sign-in/email accepts JSON, returns a session cookie |
| Open WebUI | โ | POST /api/v1/auths/signin JSON + cookie-based auth |
| n8n | โ | POST /rest/login JSON + n8n-auth session cookie |
| OpenClaw | โ | Device pairing only, no credential-based login |
| pgAdmin | โ | Requires CSRF token (two-step login); skipped for simplicity. Sessions persist 30+ days though, so a one-time login. |
| Ollama / Qdrant / OpenRouter | โ | No login โ gated by Caddy's auth_gate directly |
The /_sso_init endpoint
Each SSO-enabled subdomain has this Caddyfile block:
sim.pocketcode.in {
import auth_gate
handle /_sso_init {
reverse_proxy auth-gateway:7000 {
rewrite /sso-init/sim
}
}
reverse_proxy sim-simstudio-1:3000
}
Browser loads /_sso_init in a hidden iframe โ Caddy proxies to gateway โ gateway logs into Sim.ai server-side โ response carries Set-Cookie for the user โ iframe posts a status message back to home.html.
What logging out does
- Logout at pocketcode.in: only the gateway cookie is cleared. Service-internal cookies remain valid. But Caddy now sees no gateway cookie โ every
*.pocketcode.inrequest gets 302'd to the login page. After re-login, every service is instantly accessible (their sessions never died). - Logout inside a service (e.g., clicking Sim.ai's own "Logout" button): that service's session cookie is cleared. The next watchdog tick at pocketcode.in (โค 2 min) re-runs
/_sso_initfor that service and restores the session. - Closing the pocketcode tab: Watchdog stops. Sessions naturally expire after their normal TTL. Re-opening pocketcode restarts the watchdog.
Troubleshooting
"Host not found" / "getaddrinfo ENOTFOUND":
- Verify the container is on
ai-stack:docker inspect <name> --format='{{json .NetworkSettings.Networks}}' - If missing, attach it:
docker network connect ai-stack <name> - For sim-db-1 specifically,
ai-startauto-reconnects it after Sim.ai recompose
"Connection refused" but container is up:
- The service may not be listening on
0.0.0.0internally. Inspect:docker exec <name> netstat -tlnp - Or it's still booting.
docker logs <name> --tail 20
n8n shows "Failed to load model catalog" briefly at start:
- Transient Docker DNS race after a recompose.
ai-doctorfilters it. Self-heals within ~10 seconds.
Resources
- Docker networking
- See Tab 9 (Inter-Service Comms) in the setup guide for initial wiring
Recipe 1: Slack-to-Ollama Chatbot (via n8n)
Listen for Slack messages, route through Ollama, respond.
- In n8n: Slack Trigger โ AI Agent (Ollama, model llama3.2:3b) โ Slack Send Message
- Use the message text as user input to the agent
- Pass the agent output back to Slack channel
Recipe 2: Document Q&A System (Open WebUI + Ollama)
- Pull embedding model:
docker exec ollama ollama pull nomic-embed-text - In Open WebUI: Settings โ Documents โ Embedding Model =
nomic-embed-text - Workspace โ Knowledge โ New Collection โ upload PDFs
- In chat, reference with
#collection-name
Recipe 3: Scheduled Web Scraping (n8n + OpenRouter)
- n8n: Schedule trigger (daily 9am) โ HTTP Request (fetch URL) โ AI Agent (summarize via OpenRouter Claude) โ Send Email/Slack
- Claude does the summarization since it's better at structured output
- Costs ~$0.01-0.05 per run depending on page size
Recipe 4: Custom RAG Pipeline (Ollama + Qdrant + Sim.ai)
- Create a Qdrant collection (size 768 for nomic-embed-text)
- In Sim.ai: build a workflow that takes a query, embeds via Ollama, searches Qdrant, passes top-K results + query to an Agent block
- Agent uses retrieved context + query to produce grounded answer
Recipe 5: Multi-Model Comparison (LiteLLM)
Compare outputs from local Ollama vs cloud Claude vs GPT side-by-side.
PROMPT="Explain quantum computing in 2 sentences"
# Local Ollama
curl -s http://localhost:11434/api/generate \
-d "{\"model\":\"llama3.2:3b\",\"prompt\":\"$PROMPT\",\"stream\":false}" \
| jq -r .response
# Cloud Claude via OpenRouter proxy
curl -s http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-d "{\"model\":\"claude-sonnet-4\",\"messages\":[{\"role\":\"user\",\"content\":\"$PROMPT\"}]}" \
| jq -r '.choices[0].message.content'
Recipe 6: Voice Pipeline (Open WebUI + Whisper)
Open WebUI supports voice input via Whisper. To enable:
- Settings โ Audio โ STT Engine: select "Local Whisper"
- Pick a Whisper model size (base / small / medium)
- Click ๐ค icon in chat input โ speak โ transcribed and sent
Recipe 7: Backup & Restore the Stack
Backup (run daily as a cron job or n8n workflow):
#!/bin/bash DATE=$(date +%Y%m%d-%H%M) mkdir -p ~/backups/$DATE # Postgres dump docker exec sim-db-1 pg_dumpall -U postgres > ~/backups/$DATE/postgres.sql # Critical volumes (n8n encryption key, Open WebUI chats, etc.) docker run --rm -v n8n-data:/data -v ~/backups/$DATE:/backup \ alpine tar czf /backup/n8n-data.tar.gz -C /data . docker run --rm -v open-webui-data:/data -v ~/backups/$DATE:/backup \ alpine tar czf /backup/open-webui-data.tar.gz -C /data . # Caddy data (certs) docker run --rm -v caddy_data:/data -v ~/backups/$DATE:/backup \ alpine tar czf /backup/caddy_data.tar.gz -C /data . # Compress everything tar czf ~/backups/$DATE.tar.gz -C ~/backups $DATE rm -rf ~/backups/$DATE
Recipe 8: Manage Stack from the Web Terminal
Everything in this guide can be done from terminal.pocketcode.in in your browser:
ai-start # bring up all containers ai-stop # shut down cleanly ai-doctor # diagnostic scan ai-logs SERVICE # tail any service's logs ai-status # quick health check
docker ps, docker exec, docker logs all work. Edit any config file under ~/ai-stack/.