docs: rewrite README with structured overview and quick start guide

Replaces the minimal project description with a comprehensive README
including a component overview table, quick start instructions, common
Ansible operations, and links to detailed documentation. Aligns with
Red Panda Approval™ standards.
This commit is contained in:
2026-03-03 12:49:06 +00:00
parent c7be03a743
commit b4d60f2f38
219 changed files with 34586 additions and 2 deletions

View File

@@ -0,0 +1,423 @@
SERVER_PORT=3001
STORAGE_DIR="/app/server/storage"
UID='1000'
GID='1000'
# SIG_KEY='passphrase' # Please generate random string at least 32 chars long.
# SIG_SALT='salt' # Please generate random string at least 32 chars long.
# JWT_SECRET="my-random-string-for-seeding" # Only needed if AUTH_TOKEN is set. Please generate random string at least 12 chars long.
# JWT_EXPIRY="30d" # (optional) https://docs.anythingllm.com/configuration#custom-ttl-for-sessions
###########################################
######## LLM API SElECTION ################
###########################################
# LLM_PROVIDER='openai'
# OPEN_AI_KEY=
# OPEN_MODEL_PREF='gpt-4o'
# LLM_PROVIDER='gemini'
# GEMINI_API_KEY=
# GEMINI_LLM_MODEL_PREF='gemini-2.0-flash-lite'
# LLM_PROVIDER='azure'
# AZURE_OPENAI_ENDPOINT=
# AZURE_OPENAI_KEY=
# OPEN_MODEL_PREF='my-gpt35-deployment' # This is the "deployment" on Azure you want to use. Not the base model.
# EMBEDDING_MODEL_PREF='embedder-model' # This is the "deployment" on Azure you want to use for embeddings. Not the base model. Valid base model is text-embedding-ada-002
# LLM_PROVIDER='anthropic'
# ANTHROPIC_API_KEY=sk-ant-xxxx
# ANTHROPIC_MODEL_PREF='claude-2'
# ANTHROPIC_CACHE_CONTROL="5m" # Enable prompt caching (5m=5min cache, 1h=1hour cache). Reduces costs and improves speed by caching system prompts.
# LLM_PROVIDER='lmstudio'
# LMSTUDIO_BASE_PATH='http://your-server:1234/v1'
# LMSTUDIO_MODEL_PREF='Loaded from Chat UI' # this is a bug in LMStudio 0.2.17
# LMSTUDIO_MODEL_TOKEN_LIMIT=4096
# LMSTUDIO_AUTH_TOKEN='your-lmstudio-auth-token-here'
# LLM_PROVIDER='localai'
# LOCAL_AI_BASE_PATH='http://host.docker.internal:8080/v1'
# LOCAL_AI_MODEL_PREF='luna-ai-llama2'
# LOCAL_AI_MODEL_TOKEN_LIMIT=4096
# LOCAL_AI_API_KEY="sk-123abc"
# LLM_PROVIDER='ollama'
# OLLAMA_BASE_PATH='http://host.docker.internal:11434'
# OLLAMA_MODEL_PREF='llama2'
# OLLAMA_MODEL_TOKEN_LIMIT=4096
# OLLAMA_AUTH_TOKEN='your-ollama-auth-token-here (optional, only for ollama running behind auth - Bearer token)'
# OLLAMA_RESPONSE_TIMEOUT=7200000 (optional, max timeout in milliseconds for ollama response to conclude. Default is 5min before aborting)
# LLM_PROVIDER='togetherai'
# TOGETHER_AI_API_KEY='my-together-ai-key'
# TOGETHER_AI_MODEL_PREF='mistralai/Mixtral-8x7B-Instruct-v0.1'
# LLM_PROVIDER='mistral'
# MISTRAL_API_KEY='example-mistral-ai-api-key'
# MISTRAL_MODEL_PREF='mistral-tiny'
# LLM_PROVIDER='perplexity'
# PERPLEXITY_API_KEY='my-perplexity-key'
# PERPLEXITY_MODEL_PREF='codellama-34b-instruct'
# LLM_PROVIDER='openrouter'
# OPENROUTER_API_KEY='my-openrouter-key'
# OPENROUTER_MODEL_PREF='openrouter/auto'
# LLM_PROVIDER='huggingface'
# HUGGING_FACE_LLM_ENDPOINT=https://uuid-here.us-east-1.aws.endpoints.huggingface.cloud
# HUGGING_FACE_LLM_API_KEY=hf_xxxxxx
# HUGGING_FACE_LLM_TOKEN_LIMIT=8000
# LLM_PROVIDER='groq'
# GROQ_API_KEY=gsk_abcxyz
# GROQ_MODEL_PREF=llama3-8b-8192
# LLM_PROVIDER='koboldcpp'
# KOBOLD_CPP_BASE_PATH='http://127.0.0.1:5000/v1'
# KOBOLD_CPP_MODEL_PREF='koboldcpp/codellama-7b-instruct.Q4_K_S'
# KOBOLD_CPP_MODEL_TOKEN_LIMIT=4096
# LLM_PROVIDER='textgenwebui'
# TEXT_GEN_WEB_UI_BASE_PATH='http://127.0.0.1:5000/v1'
# TEXT_GEN_WEB_UI_TOKEN_LIMIT=4096
# TEXT_GEN_WEB_UI_API_KEY='sk-123abc'
# LLM_PROVIDER='generic-openai'
# GENERIC_OPEN_AI_BASE_PATH='http://proxy.url.openai.com/v1'
# GENERIC_OPEN_AI_MODEL_PREF='gpt-3.5-turbo'
# GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT=4096
# GENERIC_OPEN_AI_API_KEY=sk-123abc
# GENERIC_OPEN_AI_CUSTOM_HEADERS="X-Custom-Auth:my-secret-key,X-Custom-Header:my-value" (useful if using a proxy that requires authentication or other headers)
# LLM_PROVIDER='litellm'
# LITE_LLM_MODEL_PREF='gpt-3.5-turbo'
# LITE_LLM_MODEL_TOKEN_LIMIT=4096
# LITE_LLM_BASE_PATH='http://127.0.0.1:4000'
# LITE_LLM_API_KEY='sk-123abc'
# LLM_PROVIDER='novita'
# NOVITA_LLM_API_KEY='your-novita-api-key-here' check on https://novita.ai/settings/key-management
# NOVITA_LLM_MODEL_PREF='deepseek/deepseek-r1'
# LLM_PROVIDER='cometapi'
# COMETAPI_LLM_API_KEY='your-cometapi-api-key-here' # Get one at https://api.cometapi.com/console/token
# COMETAPI_LLM_MODEL_PREF='gpt-5-mini'
# COMETAPI_LLM_TIMEOUT_MS=500 # Optional; stream idle timeout in ms (min 500ms)
# LLM_PROVIDER='cohere'
# COHERE_API_KEY=
# COHERE_MODEL_PREF='command-r'
# LLM_PROVIDER='bedrock'
# AWS_BEDROCK_LLM_ACCESS_KEY_ID=
# AWS_BEDROCK_LLM_ACCESS_KEY=
# AWS_BEDROCK_LLM_REGION=us-west-2
# AWS_BEDROCK_LLM_MODEL_PREFERENCE=meta.llama3-1-8b-instruct-v1:0
# AWS_BEDROCK_LLM_MODEL_TOKEN_LIMIT=8191
# AWS_BEDROCK_LLM_CONNECTION_METHOD=iam
# AWS_BEDROCK_LLM_MAX_OUTPUT_TOKENS=4096
# AWS_BEDROCK_LLM_SESSION_TOKEN= # Only required if CONNECTION_METHOD is 'sessionToken'
# or even use Short and Long Term API keys
# AWS_BEDROCK_LLM_CONNECTION_METHOD="apiKey"
# AWS_BEDROCK_LLM_API_KEY=
# LLM_PROVIDER='fireworksai'
# FIREWORKS_AI_LLM_API_KEY='my-fireworks-ai-key'
# FIREWORKS_AI_LLM_MODEL_PREF='accounts/fireworks/models/llama-v3p1-8b-instruct'
# LLM_PROVIDER='apipie'
# APIPIE_LLM_API_KEY='sk-123abc'
# APIPIE_LLM_MODEL_PREF='openrouter/llama-3.1-8b-instruct'
# LLM_PROVIDER='xai'
# XAI_LLM_API_KEY='xai-your-api-key-here'
# XAI_LLM_MODEL_PREF='grok-beta'
# LLM_PROVIDER='zai'
# ZAI_API_KEY="your-zai-api-key-here"
# ZAI_MODEL_PREF="glm-4.5"
# LLM_PROVIDER='nvidia-nim'
# NVIDIA_NIM_LLM_BASE_PATH='http://127.0.0.1:8000'
# NVIDIA_NIM_LLM_MODEL_PREF='meta/llama-3.2-3b-instruct'
# LLM_PROVIDER='deepseek'
# DEEPSEEK_API_KEY='your-deepseek-api-key-here'
# DEEPSEEK_MODEL_PREF='deepseek-chat'
# LLM_PROVIDER='ppio'
# PPIO_API_KEY='your-ppio-api-key-here'
# PPIO_MODEL_PREF=deepseek/deepseek-v3/community
# LLM_PROVIDER='moonshotai'
# MOONSHOT_AI_API_KEY='your-moonshot-api-key-here'
# MOONSHOT_AI_MODEL_PREF='moonshot-v1-32k'
# LLM_PROVIDER='foundry'
# FOUNDRY_BASE_PATH='http://127.0.0.1:55776'
# FOUNDRY_MODEL_PREF='phi-3.5-mini'
# FOUNDRY_MODEL_TOKEN_LIMIT=4096
# LLM_PROVIDER='giteeai'
# GITEE_AI_API_KEY=
# GITEE_AI_MODEL_PREF=
# GITEE_AI_MODEL_TOKEN_LIMIT=
# LLM_PROVIDER='docker-model-runner'
# DOCKER_MODEL_RUNNER_BASE_PATH='http://127.0.0.1:12434'
# DOCKER_MODEL_RUNNER_LLM_MODEL_PREF='phi-3.5-mini'
# DOCKER_MODEL_RUNNER_LLM_MODEL_TOKEN_LIMIT=4096
# LLM_PROVIDER='privatemode'
# PRIVATEMODE_LLM_BASE_PATH='http://127.0.0.1:8080'
# PRIVATEMODE_LLM_MODEL_PREF='gemma-3-27b'
# LLM_PROVIDER='sambanova'
# SAMBANOVA_LLM_API_KEY='xxx-xxx-xxx'
# SAMBANOVA_LLM_MODEL_PREF='gpt-oss-120b'
###########################################
######## Embedding API SElECTION ##########
###########################################
# This will be the assumed default embedding seleciton and model
# EMBEDDING_ENGINE='native'
# EMBEDDING_MODEL_PREF='Xenova/all-MiniLM-L6-v2'
# Only used if you are using an LLM that does not natively support embedding (openai or Azure)
# EMBEDDING_ENGINE='openai'
# OPEN_AI_KEY=sk-xxxx
# EMBEDDING_MODEL_PREF='text-embedding-ada-002'
# EMBEDDING_ENGINE='azure'
# AZURE_OPENAI_ENDPOINT=
# AZURE_OPENAI_KEY=
# EMBEDDING_MODEL_PREF='my-embedder-model' # This is the "deployment" on Azure you want to use for embeddings. Not the base model. Valid base model is text-embedding-ada-002
# EMBEDDING_ENGINE='localai'
# EMBEDDING_BASE_PATH='http://localhost:8080/v1'
# EMBEDDING_MODEL_PREF='text-embedding-ada-002'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=1000 # The max chunk size in chars a string to embed can be
# EMBEDDING_ENGINE='ollama'
# EMBEDDING_BASE_PATH='http://host.docker.internal:11434'
# EMBEDDING_MODEL_PREF='nomic-embed-text:latest'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
# EMBEDDING_ENGINE='lmstudio'
# EMBEDDING_BASE_PATH='https://host.docker.internal:1234/v1'
# EMBEDDING_MODEL_PREF='nomic-ai/nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.Q4_0.gguf'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
# EMBEDDING_ENGINE='cohere'
# COHERE_API_KEY=
# EMBEDDING_MODEL_PREF='embed-english-v3.0'
# EMBEDDING_ENGINE='voyageai'
# VOYAGEAI_API_KEY=
# EMBEDDING_MODEL_PREF='voyage-large-2-instruct'
# EMBEDDING_ENGINE='litellm'
# EMBEDDING_MODEL_PREF='text-embedding-ada-002'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
# LITE_LLM_BASE_PATH='http://127.0.0.1:4000'
# LITE_LLM_API_KEY='sk-123abc'
# EMBEDDING_ENGINE='generic-openai'
# EMBEDDING_MODEL_PREF='text-embedding-ada-002'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
# EMBEDDING_BASE_PATH='http://127.0.0.1:4000'
# GENERIC_OPEN_AI_EMBEDDING_API_KEY='sk-123abc'
# GENERIC_OPEN_AI_EMBEDDING_MAX_CONCURRENT_CHUNKS=500
# GENERIC_OPEN_AI_EMBEDDING_API_DELAY_MS=1000
# EMBEDDING_ENGINE='gemini'
# GEMINI_EMBEDDING_API_KEY=
# EMBEDDING_MODEL_PREF='text-embedding-004'
# EMBEDDING_ENGINE='openrouter'
# EMBEDDING_MODEL_PREF='baai/bge-m3'
# OPENROUTER_API_KEY=''
###########################################
######## Vector Database Selection ########
###########################################
# Enable all below if you are using vector database: LanceDB.
# VECTOR_DB="lancedb"
# Enable all below if you are using vector database: Weaviate.
# VECTOR_DB="pgvector"
# PGVECTOR_CONNECTION_STRING="postgresql://dbuser:dbuserpass@localhost:5432/yourdb"
# PGVECTOR_TABLE_NAME="anythingllm_vectors" # optional, but can be defined
# Enable all below if you are using vector database: Chroma.
# VECTOR_DB="chroma"
# CHROMA_ENDPOINT='http://host.docker.internal:8000'
# CHROMA_API_HEADER="X-Api-Key"
# CHROMA_API_KEY="sk-123abc"
# Enable all below if you are using vector database: Chroma Cloud.
# VECTOR_DB="chromacloud"
# CHROMACLOUD_API_KEY="ck-your-api-key"
# CHROMACLOUD_TENANT=
# CHROMACLOUD_DATABASE=
# Enable all below if you are using vector database: Pinecone.
# VECTOR_DB="pinecone"
# PINECONE_API_KEY=
# PINECONE_INDEX=
# Enable all below if you are using vector database: Weaviate.
# VECTOR_DB="weaviate"
# WEAVIATE_ENDPOINT="http://localhost:8080"
# WEAVIATE_API_KEY=
# Enable all below if you are using vector database: Qdrant.
# VECTOR_DB="qdrant"
# QDRANT_ENDPOINT="http://localhost:6333"
# QDRANT_API_KEY=
# Enable all below if you are using vector database: Milvus.
# VECTOR_DB="milvus"
# MILVUS_ADDRESS="http://localhost:19530"
# MILVUS_USERNAME=
# MILVUS_PASSWORD=
# Enable all below if you are using vector database: Zilliz Cloud.
# VECTOR_DB="zilliz"
# ZILLIZ_ENDPOINT="https://sample.api.gcp-us-west1.zillizcloud.com"
# ZILLIZ_API_TOKEN=api-token-here
# Enable all below if you are using vector database: Astra DB.
# VECTOR_DB="astra"
# ASTRA_DB_APPLICATION_TOKEN=
# ASTRA_DB_ENDPOINT=
###########################################
######## Audio Model Selection ############
###########################################
# (default) use built-in whisper-small model.
# WHISPER_PROVIDER="local"
# use openai hosted whisper model.
# WHISPER_PROVIDER="openai"
# OPEN_AI_KEY=sk-xxxxxxxx
###########################################
######## TTS/STT Model Selection ##########
###########################################
# TTS_PROVIDER="native"
# TTS_PROVIDER="openai"
# TTS_OPEN_AI_KEY=sk-example
# TTS_OPEN_AI_VOICE_MODEL=nova
# TTS_PROVIDER="generic-openai"
# TTS_OPEN_AI_COMPATIBLE_KEY=sk-example
# TTS_OPEN_AI_COMPATIBLE_MODEL=tts-1
# TTS_OPEN_AI_COMPATIBLE_VOICE_MODEL=nova
# TTS_OPEN_AI_COMPATIBLE_ENDPOINT="https://api.openai.com/v1"
# TTS_PROVIDER="elevenlabs"
# TTS_ELEVEN_LABS_KEY=
# TTS_ELEVEN_LABS_VOICE_MODEL=21m00Tcm4TlvDq8ikWAM # Rachel
# CLOUD DEPLOYMENT VARIRABLES ONLY
# AUTH_TOKEN="hunter2" # This is the password to your application if remote hosting.
# DISABLE_TELEMETRY="false"
###########################################
######## PASSWORD COMPLEXITY ##############
###########################################
# Enforce a password schema for your organization users.
# Documentation on how to use https://github.com/kamronbatman/joi-password-complexity
# Default is only 8 char minimum
# PASSWORDMINCHAR=8
# PASSWORDMAXCHAR=250
# PASSWORDLOWERCASE=1
# PASSWORDUPPERCASE=1
# PASSWORDNUMERIC=1
# PASSWORDSYMBOL=1
# PASSWORDREQUIREMENTS=4
###########################################
######## ENABLE HTTPS SERVER ##############
###########################################
# By enabling this and providing the path/filename for the key and cert,
# the server will use HTTPS instead of HTTP.
#ENABLE_HTTPS="true"
#HTTPS_CERT_PATH="sslcert/cert.pem"
#HTTPS_KEY_PATH="sslcert/key.pem"
###########################################
######## AGENT SERVICE KEYS ###############
###########################################
#------ SEARCH ENGINES -------
#=============================
#------ Google Search -------- https://programmablesearchengine.google.com/controlpanel/create
# AGENT_GSE_KEY=
# AGENT_GSE_CTX=
#------ SearchApi.io ----------- https://www.searchapi.io/
# AGENT_SEARCHAPI_API_KEY=
# AGENT_SEARCHAPI_ENGINE=google
#------ SerpApi ----------- https://serpapi.com/
# AGENT_SERPAPI_API_KEY=
# AGENT_SERPAPI_ENGINE=google
#------ Serper.dev ----------- https://serper.dev/
# AGENT_SERPER_DEV_KEY=
#------ Bing Search ----------- https://portal.azure.com/
# AGENT_BING_SEARCH_API_KEY=
#------ Serply.io ----------- https://serply.io/
# AGENT_SERPLY_API_KEY=
#------ SearXNG ----------- https://github.com/searxng/searxng
# AGENT_SEARXNG_API_URL=
#------ Tavily ----------- https://www.tavily.com/
# AGENT_TAVILY_API_KEY=
#------ Exa Search ----------- https://www.exa.ai/
# AGENT_EXA_API_KEY=
###########################################
######## Other Configurations ############
###########################################
# Disable viewing chat history from the UI and frontend APIs.
# See https://docs.anythingllm.com/configuration#disable-view-chat-history for more information.
# DISABLE_VIEW_CHAT_HISTORY=1
# Enable simple SSO passthrough to pre-authenticate users from a third party service.
# See https://docs.anythingllm.com/configuration#simple-sso-passthrough for more information.
# SIMPLE_SSO_ENABLED=1
# SIMPLE_SSO_NO_LOGIN=1
# SIMPLE_SSO_NO_LOGIN_REDIRECT=https://your-custom-login-url.com (optional)
# Allow scraping of any IP address in collector - must be string "true" to be enabled
# See https://docs.anythingllm.com/configuration#local-ip-address-scraping for more information.
# COLLECTOR_ALLOW_ANY_IP="true"
# Specify the target languages for when using OCR to parse images and PDFs.
# This is a comma separated list of language codes as a string. Unsupported languages will be ignored.
# Default is English. See https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html for a list of valid language codes.
# TARGET_OCR_LANG=eng,deu,ita,spa,fra,por,rus,nld,tur,hun,pol,ita,spa,fra,por,rus,nld,tur,hun,pol
# Runtime flags for built-in pupeeteer Chromium instance
# This is only required on Linux machines running AnythingLLM via Docker
# and do not want to use the --cap-add=SYS_ADMIN docker argument
# ANYTHINGLLM_CHROMIUM_ARGS="--no-sandbox,--disable-setuid-sandbox"
# Disable Swagger API documentation endpoint.
# Set to "true" to disable the /api/docs endpoint (recommended for production deployments).
# DISABLE_SWAGGER_DOCS="true"
# Disable MCP cooldown timer for agent calls
# this can lead to infinite recursive calls of the same function
# for some model/provider combinations
# MCP_NO_COOLDOWN="true

View File

@@ -0,0 +1,29 @@
[Unit]
Description=AnythingLLM Document Collector
Documentation=https://docs.anythingllm.com
After=network.target anythingllm-server.service
BindsTo=anythingllm-server.service
[Service]
Type=simple
User={{ anythingllm_user }}
Group={{ anythingllm_group }}
WorkingDirectory={{ anythingllm_directory }}/app/collector
EnvironmentFile={{ anythingllm_directory }}/app/server/.env
Environment=NODE_ENV=production
ExecStart=/usr/bin/node index.js
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=anythingllm-collector
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths={{ anythingllm_directory }}
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,29 @@
[Unit]
Description=AnythingLLM Server
Documentation=https://docs.anythingllm.com
After=network.target postgresql.service
Wants=anythingllm-collector.service
[Service]
Type=simple
User={{ anythingllm_user }}
Group={{ anythingllm_group }}
WorkingDirectory={{ anythingllm_directory }}/app/server
Environment=NODE_ENV=production
Environment=SERVER_PORT={{ anythingllm_port }}
ExecStart=/usr/bin/node index.js
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=anythingllm-server
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths={{ anythingllm_directory }}
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,60 @@
{
"mcpServers": {
"upstash-context7": {
"command": "npx",
"args": [
"-y",
"@upstash/context7-mcp"
]
},
"angelia": {
"type": "streamable",
"url": "{{angelia_mcp_url}}",
"headers": {
"Authorization": "Bearer {{angelia_mcp_auth}}"
}
},
"argos": {
"type": "streamable",
"url": "{{argos_mcp_url}}"
},
"caliban": {
"type": "streamable",
"url": "{{caliban_mcp_url}}"
},
"gitea": {
"type": "streamable",
"url": "{{gitea_mcp_url}}"
},
"github": {
"type": "streamable",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer {{github_personal_access_token}}"
}
},
"grafana": {
"type": "streamable",
"url": "{{grafana_mcp_url}}"
},
"huggingface": {
"type": "streamable",
"url": "https://huggingface.co/mcp",
"headers": {
"Authorization": "Bearer {{huggingface_mcp_token}}"
}
},
"korax": {
"type": "streamable",
"url": "{{korax_mcp_url}}"
},
"neo4j": {
"type": "streamable",
"url": "{{neo4j_mcp_url}}"
},
"nike": {
"type": "streamable",
"url": "{{nike_mcp_url}}"
}
}
}

View File

@@ -0,0 +1,276 @@
---
- name: Deploy AnythingLLM (Native Node.js)
hosts: ubuntu
become: true
vars:
nodejs_version: "22"
ansible_common_remote_group: "{{ anythingllm_group }}"
allow_world_readable_tmpfiles: true
tasks:
- name: Check if host has anythingllm service
ansible.builtin.set_fact:
has_anythingllm_service: "{{'anythingllm' in services}}"
- name: Skip hosts without anythingllm service
ansible.builtin.meta: end_host
when: not has_anythingllm_service
- name: Install build dependencies
ansible.builtin.apt:
name:
- curl
- tar
- build-essential
- python3
- libpq-dev
state: present
update_cache: true
- name: Add NodeSource GPG key
ansible.builtin.apt_key:
url: https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key
state: present
- name: Add NodeSource repository
ansible.builtin.apt_repository:
repo: "deb https://deb.nodesource.com/node_{{ nodejs_version }}.x nodistro main"
state: present
filename: nodesource
- name: Install Node.js
ansible.builtin.apt:
name: nodejs
state: present
update_cache: true
- name: Install Yarn globally
ansible.builtin.npm:
name: yarn
global: true
state: present
- name: Create anythingllm group
ansible.builtin.group:
name: "{{ anythingllm_group }}"
- name: Create anythingllm user
ansible.builtin.user:
name: "{{ anythingllm_user }}"
comment: "AnythingLLM service account"
group: "{{ anythingllm_group }}"
home: "{{ anythingllm_directory }}"
system: true
shell: /bin/bash
- name: Add remote_user to anythingllm group
ansible.builtin.user:
name: "{{ remote_user }}"
groups: "{{ anythingllm_group }}"
append: true
- name: Create anythingllm directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: directory
mode: '0750'
- name: Create app directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}/app"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: directory
mode: '0750'
- name: Transfer and unarchive AnythingLLM release
ansible.builtin.unarchive:
src: "~/rel/anythingllm_{{ anythingllm_rel }}.tar"
dest: "{{ anythingllm_directory }}/app"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
mode: '0750'
register: app_unarchive
notify:
- Restart AnythingLLM Server
- Restart AnythingLLM Collector
- name: Run yarn setup
become_user: "{{ anythingllm_user }}"
ansible.builtin.command:
cmd: yarn setup
chdir: "{{ anythingllm_directory }}/app"
when: app_unarchive.changed
register: yarn_setup
- name: Create storage directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}/storage"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: directory
mode: '0750'
- name: Create plugins directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}/storage/plugins"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: directory
mode: '0750'
- name: Template MCP servers configuration
ansible.builtin.template:
src: anythingllm_mcp_servers.json.j2
dest: "{{ anythingllm_directory }}/storage/plugins/anythingllm_mcp_servers.json"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
mode: '0600'
notify:
- Restart AnythingLLM Server
- Restart AnythingLLM Collector
- name: Create hotdir directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}/hotdir"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: directory
mode: '0750'
- name: Create collector symlink directory
ansible.builtin.file:
path: /srv/collector
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: directory
mode: '0755'
- name: Create hotdir symlink for AnythingLLM path resolution
ansible.builtin.file:
src: "{{ anythingllm_directory }}/hotdir"
dest: /srv/collector/hotdir
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: link
- name: Remove collector's default hotdir directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}/app/collector/hotdir"
state: absent
- name: Create hotdir symlink for collector
ansible.builtin.file:
src: "{{ anythingllm_directory }}/hotdir"
dest: "{{ anythingllm_directory }}/app/collector/hotdir"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
state: link
- name: Template server environment file
ansible.builtin.template:
src: env.j2
dest: "{{ anythingllm_directory }}/app/server/.env"
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
mode: '0600'
notify:
- Restart AnythingLLM Server
- Restart AnythingLLM Collector
- name: Configure frontend API base
ansible.builtin.lineinfile:
path: "{{ anythingllm_directory }}/app/frontend/.env"
regexp: "^VITE_API_BASE="
line: "VITE_API_BASE='/api'"
create: true
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
mode: '0644'
register: frontend_env
- name: Build frontend
become_user: "{{ anythingllm_user }}"
ansible.builtin.command:
cmd: yarn build
chdir: "{{ anythingllm_directory }}/app/frontend"
when: app_unarchive.changed or frontend_env.changed
register: frontend_build
- name: Remove old server/public directory
ansible.builtin.file:
path: "{{ anythingllm_directory }}/app/server/public"
state: absent
when: frontend_build.changed
- name: Copy frontend build to server/public
become_user: "{{ anythingllm_user }}"
ansible.builtin.copy:
src: "{{ anythingllm_directory }}/app/frontend/dist/"
dest: "{{ anythingllm_directory }}/app/server/public/"
remote_src: true
owner: "{{ anythingllm_user }}"
group: "{{ anythingllm_group }}"
when: frontend_build.changed
- name: Generate Prisma client
become_user: "{{ anythingllm_user }}"
ansible.builtin.command:
cmd: npx prisma generate --schema=./prisma/schema.prisma
chdir: "{{ anythingllm_directory }}/app/server"
when: app_unarchive.changed or yarn_setup.changed
- name: Run Prisma migrations
become_user: "{{ anythingllm_user }}"
ansible.builtin.command:
cmd: npx prisma migrate deploy --schema=./prisma/schema.prisma
chdir: "{{ anythingllm_directory }}/app/server"
when: app_unarchive.changed or yarn_setup.changed
- name: Create AnythingLLM server systemd service
ansible.builtin.template:
src: anythingllm-server.service.j2
dest: /etc/systemd/system/anythingllm-server.service
mode: '0644'
notify:
- Reload systemd
- Restart AnythingLLM Server
- name: Create AnythingLLM collector systemd service
ansible.builtin.template:
src: anythingllm-collector.service.j2
dest: /etc/systemd/system/anythingllm-collector.service
mode: '0644'
notify:
- Reload systemd
- Restart AnythingLLM Collector
- name: Enable and start AnythingLLM server
ansible.builtin.systemd:
name: anythingllm-server
enabled: true
state: started
daemon_reload: true
- name: Enable and start AnythingLLM collector
ansible.builtin.systemd:
name: anythingllm-collector
enabled: true
state: started
daemon_reload: true
handlers:
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
- name: Restart AnythingLLM Server
ansible.builtin.systemd:
name: anythingllm-server
state: restarted
- name: Restart AnythingLLM Collector
ansible.builtin.systemd:
name: anythingllm-collector
state: restarted

View File

@@ -0,0 +1,393 @@
networks:
frontend:
driver: bridge
backend:
driver: bridge
monitoring:
driver: bridge
volumes:
anythingllm_data:
driver: local
postgres_data:
driver: local
prometheus_data:
driver: local
loki_data:
driver: local
grafana_data:
driver: local
services:
# ============================================
# PostgreSQL with pgvector Extension
# ============================================
postgres:
image: pgvector/pgvector:pg17
container_name: anythingllm-postgres
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-anythingllm}
POSTGRES_USER: ${POSTGRES_USER:-anythingllm}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
POSTGRES_INITDB_ARGS: "-E UTF8"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init-pgvector.sql:/docker-entrypoint-initdb.d/init-pgvector.sql:ro
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-anythingllm}"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=postgres"
# ============================================
# AnythingLLM Application
# ============================================
anythingllm:
image: mintplexlabs/anythingllm:latest
container_name: anythingllm
restart: unless-stopped
cap_add:
- SYS_ADMIN
environment:
# Server Configuration
SERVER_PORT: 3001
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
SIG_KEY: ${SIG_KEY:?SIG_KEY is required}
SIG_SALT: ${SIG_SALT:?SIG_SALT is required}
STORAGE_DIR: /app/server/storage
# PostgreSQL Configuration
VECTOR_DB: "pgvector"
PGVECTOR_CONNECTION_STRING: "postgresql://${POSTGRES_USER:-anythingllm}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-anythingllm}"
# LLM Provider - Generic OpenAI (for llama-cpp)
LLM_PROVIDER: "generic-openai"
GENERIC_OPEN_AI_BASE_PATH: ${LLAMACPP_BASE_URL:?LLAMACPP_BASE_URL is required}
GENERIC_OPEN_AI_MODEL_PREF: ${LLAMACPP_MODEL:-llama-3-8b}
GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT: ${LLAMACPP_TOKEN_LIMIT:-8192}
GENERIC_OPEN_AI_API_KEY: ${LLAMACPP_API_KEY:-not-needed}
# AWS Bedrock Configuration (optional - uncomment if using)
# LLM_PROVIDER: "bedrock"
# AWS_BEDROCK_LLM_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
# AWS_BEDROCK_LLM_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
# AWS_BEDROCK_LLM_REGION: ${AWS_REGION:-us-east-1}
# AWS_BEDROCK_LLM_MODEL_PREFERENCE: ${BEDROCK_MODEL:-anthropic.claude-3-sonnet-20240229-v1:0}
# AWS_BEDROCK_LLM_MODEL_TOKEN_LIMIT: 200000
# Embedding Configuration
EMBEDDING_ENGINE: ${EMBEDDING_ENGINE}
EMBEDDING_MODEL_PREF: ${EMBEDDING_MODEL_PREF}
EMBEDDING_MODEL_MAX_CHUNK_LENGTH: ${EMBEDDING_MODEL_MAX_CHUNK_LENGTH}
EMBEDDING_BASE_PATH: ${EMBEDDING_BASE_PATH}
GENERIC_OPEN_AI_EMBEDDING_API_KEY: ${GENERIC_OPEN_AI_EMBEDDING_API_KEY}
GENERIC_OPEN_AI_EMBEDDING_MAX_CONCURRENT_CHUNKS: ${GENERIC_OPEN_AI_EMBEDDING_MAX_CONCURRENT_CHUNKS}
GENERIC_OPEN_AI_EMBEDDING_API_DELAY_MS: ${GENERIC_OPEN_AI_EMBEDDING_API_DELAY_MS}
# Whisper Configuration
WHISPER_PROVIDER: "local"
# TTS Configuration
TTS_PROVIDER: "native"
# Security
DISABLE_TELEMETRY: "true"
# Logging (JSON format for Loki)
NODE_ENV: production
# Optional: Enable HTTP logging
# ENABLE_HTTP_LOGGER: "true"
# ENABLE_HTTP_LOGGER_TIMESTAMPS: "true"
volumes:
- anythingllm_data:/app/server/storage
- anythingllm_data:/app/collector/hotdir
- anythingllm_data:/app/collector/outputs
networks:
- frontend
- backend
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3001/api/ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 2G
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
labels: "service=anythingllm"
# ============================================
# HAProxy - Reverse Proxy & Load Balancer
# ============================================
haproxy:
image: haproxy:2.9-alpine
container_name: anythingllm-haproxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8404:8404" # HAProxy stats
volumes:
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./haproxy/certs:/etc/haproxy/certs:ro
- ./haproxy/errors:/etc/haproxy/errors:ro
networks:
- frontend
- monitoring
depends_on:
- anythingllm
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8404/stats"]
interval: 10s
timeout: 5s
retries: 3
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=haproxy"
# ============================================
# Prometheus - Metrics Collection
# ============================================
prometheus:
image: prom/prometheus:latest
container_name: anythingllm-prometheus
restart: unless-stopped
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
- '--web.enable-lifecycle'
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro
- prometheus_data:/prometheus
networks:
- monitoring
- backend
ports:
- "9090:9090"
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=prometheus"
# ============================================
# Postgres Exporter - Database Metrics
# ============================================
postgres-exporter:
image: prometheuscommunity/postgres-exporter:latest
container_name: anythingllm-postgres-exporter
restart: unless-stopped
environment:
DATA_SOURCE_NAME: "postgresql://${POSTGRES_USER:-anythingllm}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-anythingllm}?sslmode=disable"
networks:
- backend
- monitoring
depends_on:
postgres:
condition: service_healthy
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 128M
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
labels: "service=postgres-exporter"
# ============================================
# cAdvisor - Container Metrics
# ============================================
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: anythingllm-cadvisor
restart: unless-stopped
privileged: true
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
networks:
- monitoring
ports:
- "8080:8080"
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
labels: "service=cadvisor"
# ============================================
# Loki - Log Aggregation
# ============================================
loki:
image: grafana/loki:latest
container_name: anythingllm-loki
restart: unless-stopped
command: -config.file=/etc/loki/loki-config.yml
volumes:
- ./loki/loki-config.yml:/etc/loki/loki-config.yml:ro
- loki_data:/loki
networks:
- monitoring
ports:
- "3100:3100"
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3100/ready"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=loki"
# ============================================
# Grafana Alloy - Log Collection
# ============================================
alloy:
image: grafana/alloy:latest
container_name: anythingllm-alloy
restart: unless-stopped
command:
- run
- /etc/alloy/config.alloy
- --server.http.listen-addr=0.0.0.0:12345
- --storage.path=/var/lib/alloy/data
volumes:
- ./alloy/config.alloy:/etc/alloy/config.alloy:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
networks:
- monitoring
ports:
- "12345:12345"
depends_on:
- loki
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=alloy"
# ============================================
# Grafana - Visualization Dashboard
# ============================================
grafana:
image: grafana/grafana:latest
container_name: anythingllm-grafana
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:?GRAFANA_ADMIN_PASSWORD is required}
GF_INSTALL_PLUGINS: grafana-clock-panel,grafana-simple-json-datasource
GF_SERVER_ROOT_URL: ${GRAFANA_ROOT_URL:-http://localhost:3000}
GF_USERS_ALLOW_SIGN_UP: "false"
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
networks:
- monitoring
- frontend
ports:
- "3000:3000"
depends_on:
- prometheus
- loki
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=grafana"

View File

@@ -0,0 +1,79 @@
# AnythingLLM Server Environment Configuration
# Managed by Ansible - Red Panda Approved
# Generated for {{ inventory_hostname }}
# ============================================
# Server Configuration
# ============================================
SERVER_PORT={{ anythingllm_port }}
STORAGE_DIR={{ anythingllm_directory }}/storage
# ============================================
# Security
# ============================================
JWT_SECRET={{ anythingllm_jwt_secret }}
SIG_KEY={{ anythingllm_sig_key }}
SIG_SALT={{ anythingllm_sig_salt }}
# ============================================
# PostgreSQL + pgvector (Portia)
# ============================================
VECTOR_DB=pgvector
PGVECTOR_CONNECTION_STRING=postgresql://{{ anythingllm_db_user }}:{{ anythingllm_db_password }}@{{ anythingllm_db_host }}:{{ anythingllm_db_port }}/{{ anythingllm_db_name }}
# ============================================
# LLM Provider - AWS Bedrock
# ============================================
# LLM_PROVIDER='bedrock'
# AWS_BEDROCK_LLM_ACCESS_KEY_ID=
# AWS_BEDROCK_LLM_ACCESS_KEY=
# AWS_BEDROCK_LLM_REGION=us-west-2
# AWS_BEDROCK_LLM_MODEL_PREFERENCE=meta.llama3-1-8b-instruct-v1:0
# AWS_BEDROCK_LLM_MODEL_TOKEN_LIMIT=8191
# AWS_BEDROCK_LLM_CONNECTION_METHOD=iam
# AWS_BEDROCK_LLM_MAX_OUTPUT_TOKENS=4096
# AWS_BEDROCK_LLM_SESSION_TOKEN= # Only required if CONNECTION_METHOD is 'sessionToken'
# or even use Short and Long Term API keys
# AWS_BEDROCK_LLM_CONNECTION_METHOD="apiKey"
# AWS_BEDROCK_LLM_API_KEY=
# ============================================
# LLM Provider - Generic OpenAI (llama-cpp)
# ============================================
LLM_PROVIDER=generic-openai
GENERIC_OPEN_AI_BASE_PATH={{ anythingllm_llm_base_url }}
GENERIC_OPEN_AI_MODEL_PREF={{ anythingllm_llm_model }}
GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT={{ anythingllm_llm_token_limit }}
GENERIC_OPEN_AI_API_KEY={{ anythingllm_llm_api_key }}
# ============================================
# Embedding Configuration
# ============================================
EMBEDDING_ENGINE={{ anythingllm_embedding_engine }}
EMBEDDING_MODEL_PREF={{ anythingllm_embedding_model }}
# ============================================
# TTS Configuration (FastKokoro)
# ============================================
TTS_PROVIDER={{ anythingllm_tts_provider }}
{% if anythingllm_tts_provider == 'openai' %}
TTS_OPEN_AI_KEY={{ anythingllm_tts_api_key }}
TTS_OPEN_AI_ENDPOINT={{ anythingllm_tts_endpoint }}
TTS_OPEN_AI_MODEL={{ anythingllm_tts_model }}
TTS_OPEN_AI_VOICE={{ anythingllm_tts_voice }}
{% endif %}
# ============================================
# Whisper Configuration
# ============================================
WHISPER_PROVIDER=local
# use openai hosted whisper model.
# WHISPER_PROVIDER="openai"
# OPEN_AI_KEY=sk-xxxxxxxx
# ============================================
# Telemetry & Environment
# ============================================
DISABLE_TELEMETRY=true
NODE_ENV=production

View File

@@ -0,0 +1,29 @@
---
- name: Stage AnythingLLM release tarball
hosts: localhost
gather_facts: false
vars:
anythingllm_repo_dir: "{{github_dir}}/anything-llm"
archive_path: "{{rel_dir}}/anythingllm_{{anythingllm_rel}}.tar"
tasks:
- name: Ensure release directory exists
file:
path: "{{rel_dir}}"
state: directory
mode: '755'
- name: Fetch all remote branches and tags
ansible.builtin.command: git fetch --all
args:
chdir: "{{anythingllm_repo_dir}}"
- name: Pull latest changes
ansible.builtin.command: git pull
args:
chdir: "{{anythingllm_repo_dir}}"
- name: Create AnythingLLM archive for specified release
ansible.builtin.command: git archive -o "{{archive_path}}" "{{anythingllm_rel}}"
args:
chdir: "{{anythingllm_repo_dir}}"