lynkr 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CITATIONS.bib +6 -0
- package/DEPLOYMENT.md +1001 -0
- package/README.md +215 -71
- package/docs/index.md +55 -2
- package/monitor-agents.sh +31 -0
- package/package.json +7 -3
- package/src/agents/context-manager.js +220 -0
- package/src/agents/definitions/loader.js +563 -0
- package/src/agents/executor.js +412 -0
- package/src/agents/index.js +157 -0
- package/src/agents/parallel-coordinator.js +68 -0
- package/src/agents/reflector.js +321 -0
- package/src/agents/skillbook.js +331 -0
- package/src/agents/store.js +244 -0
- package/src/api/router.js +55 -0
- package/src/clients/databricks.js +214 -17
- package/src/clients/routing.js +15 -7
- package/src/clients/standard-tools.js +341 -0
- package/src/config/index.js +41 -5
- package/src/orchestrator/index.js +254 -37
- package/src/server.js +2 -0
- package/src/tools/agent-task.js +96 -0
- package/test/azure-openai-config.test.js +203 -0
- package/test/azure-openai-error-resilience.test.js +238 -0
- package/test/azure-openai-format-conversion.test.js +354 -0
- package/test/azure-openai-integration.test.js +281 -0
- package/test/azure-openai-routing.test.js +148 -0
- package/test/azure-openai-streaming.test.js +171 -0
- package/test/format-conversion.test.js +578 -0
- package/test/hybrid-routing-integration.test.js +18 -11
- package/test/openrouter-error-resilience.test.js +418 -0
- package/test/passthrough-mode.test.js +385 -0
- package/test/routing.test.js +9 -3
- package/test/web-tools.test.js +3 -0
- package/test-agents-simple.js +43 -0
- package/test-cli-connection.sh +33 -0
- package/test-learning-unit.js +126 -0
- package/test-learning.js +112 -0
- package/test-parallel-agents.sh +124 -0
- package/test-parallel-direct.js +155 -0
- package/test-subagents.sh +117 -0
package/DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,1001 @@
|
|
|
1
|
+
# Lynkr Deployment Guide
|
|
2
|
+
|
|
3
|
+
This guide covers production deployment options for Lynkr, including Docker, Kubernetes, systemd, and cloud platforms.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Quick Start](#quick-start)
|
|
8
|
+
- [Docker Deployment](#docker-deployment)
|
|
9
|
+
- [Kubernetes Deployment](#kubernetes-deployment)
|
|
10
|
+
- [Systemd Service](#systemd-service)
|
|
11
|
+
- [Production Considerations](#production-considerations)
|
|
12
|
+
- [Monitoring & Observability](#monitoring--observability)
|
|
13
|
+
- [Security Hardening](#security-hardening)
|
|
14
|
+
- [Scaling Strategies](#scaling-strategies)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
The fastest way to deploy Lynkr in production:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 1. Clone and configure
|
|
24
|
+
git clone https://github.com/vishalveerareddy123/Lynkr.git
|
|
25
|
+
cd Lynkr
|
|
26
|
+
cp .env.example .env
|
|
27
|
+
# Edit .env with your credentials
|
|
28
|
+
|
|
29
|
+
# 2. Deploy with Docker Compose (recommended for most users)
|
|
30
|
+
docker compose up -d
|
|
31
|
+
|
|
32
|
+
# 3. Verify health
|
|
33
|
+
curl http://localhost:8080/health
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Docker Deployment
|
|
39
|
+
|
|
40
|
+
### Docker Compose (Recommended)
|
|
41
|
+
|
|
42
|
+
The included `docker-compose.yml` provides a complete setup with Ollama integration.
|
|
43
|
+
|
|
44
|
+
#### 1. Basic Setup
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Copy and configure environment
|
|
48
|
+
cp .env.example .env
|
|
49
|
+
nano .env # Configure your providers
|
|
50
|
+
|
|
51
|
+
# Start services
|
|
52
|
+
docker compose up -d
|
|
53
|
+
|
|
54
|
+
# View logs
|
|
55
|
+
docker compose logs -f lynkr
|
|
56
|
+
|
|
57
|
+
# Stop services
|
|
58
|
+
docker compose down
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### 2. Environment Configuration
|
|
62
|
+
|
|
63
|
+
Key variables to configure in `.env`:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Primary provider
|
|
67
|
+
MODEL_PROVIDER=ollama # Options: ollama, databricks, azure-anthropic, openrouter
|
|
68
|
+
|
|
69
|
+
# Tool execution mode
|
|
70
|
+
TOOL_EXECUTION_MODE=server # Options: server, client (passthrough)
|
|
71
|
+
|
|
72
|
+
# Ollama configuration
|
|
73
|
+
OLLAMA_MODEL=qwen2.5-coder:latest
|
|
74
|
+
OLLAMA_MAX_TOOLS_FOR_ROUTING=3
|
|
75
|
+
|
|
76
|
+
# OpenRouter (optional)
|
|
77
|
+
OPENROUTER_API_KEY=your-key-here
|
|
78
|
+
OPENROUTER_MODEL=amazon/nova-2-lite-v1:free
|
|
79
|
+
|
|
80
|
+
# Databricks (fallback)
|
|
81
|
+
DATABRICKS_API_BASE=https://your-workspace.cloud.databricks.com
|
|
82
|
+
DATABRICKS_API_KEY=your-pat-token
|
|
83
|
+
|
|
84
|
+
# Fallback settings
|
|
85
|
+
FALLBACK_ENABLED=true
|
|
86
|
+
FALLBACK_PROVIDER=databricks
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### 3. Production Docker Compose
|
|
90
|
+
|
|
91
|
+
For production, update `docker-compose.yml`:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
services:
|
|
95
|
+
lynkr:
|
|
96
|
+
image: ghcr.io/vishalveerareddy123/lynkr:latest
|
|
97
|
+
container_name: lynkr-prod
|
|
98
|
+
restart: always
|
|
99
|
+
ports:
|
|
100
|
+
- "8080:8080"
|
|
101
|
+
environment:
|
|
102
|
+
LOG_LEVEL: info # Use info for production
|
|
103
|
+
NODE_ENV: production
|
|
104
|
+
volumes:
|
|
105
|
+
- lynkr-data:/app/data # Named volume for persistence
|
|
106
|
+
- /path/to/workspace:/workspace
|
|
107
|
+
deploy:
|
|
108
|
+
resources:
|
|
109
|
+
limits:
|
|
110
|
+
cpus: '2'
|
|
111
|
+
memory: 4G
|
|
112
|
+
reservations:
|
|
113
|
+
cpus: '1'
|
|
114
|
+
memory: 2G
|
|
115
|
+
healthcheck:
|
|
116
|
+
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
|
|
117
|
+
interval: 30s
|
|
118
|
+
timeout: 10s
|
|
119
|
+
retries: 3
|
|
120
|
+
start_period: 40s
|
|
121
|
+
|
|
122
|
+
volumes:
|
|
123
|
+
lynkr-data:
|
|
124
|
+
driver: local
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Standalone Docker
|
|
128
|
+
|
|
129
|
+
#### Build Image
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
docker build -t lynkr:latest .
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Run Container
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
docker run -d \
|
|
139
|
+
--name lynkr \
|
|
140
|
+
--restart unless-stopped \
|
|
141
|
+
-p 8080:8080 \
|
|
142
|
+
-v $(pwd)/data:/app/data \
|
|
143
|
+
-v $(pwd):/workspace \
|
|
144
|
+
--env-file .env \
|
|
145
|
+
lynkr:latest
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### With Specific Provider
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
docker run -d \
|
|
152
|
+
--name lynkr-databricks \
|
|
153
|
+
-p 8080:8080 \
|
|
154
|
+
-v $(pwd)/data:/app/data \
|
|
155
|
+
-e MODEL_PROVIDER=databricks \
|
|
156
|
+
-e DATABRICKS_API_BASE=https://your-workspace.cloud.databricks.com \
|
|
157
|
+
-e DATABRICKS_API_KEY=your-pat-token \
|
|
158
|
+
-e WORKSPACE_ROOT=/workspace \
|
|
159
|
+
-e PORT=8080 \
|
|
160
|
+
-e LOG_LEVEL=info \
|
|
161
|
+
lynkr:latest
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Kubernetes Deployment
|
|
167
|
+
|
|
168
|
+
### Prerequisites
|
|
169
|
+
|
|
170
|
+
- Kubernetes cluster (1.19+)
|
|
171
|
+
- `kubectl` configured
|
|
172
|
+
- Secrets management (external-secrets, sealed-secrets, or Vault)
|
|
173
|
+
|
|
174
|
+
### 1. Create Namespace
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
# namespace.yaml
|
|
178
|
+
apiVersion: v1
|
|
179
|
+
kind: Namespace
|
|
180
|
+
metadata:
|
|
181
|
+
name: lynkr
|
|
182
|
+
labels:
|
|
183
|
+
name: lynkr
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
kubectl apply -f namespace.yaml
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 2. Create Secrets
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Create secret from .env file
|
|
194
|
+
kubectl create secret generic lynkr-secrets \
|
|
195
|
+
--from-env-file=.env \
|
|
196
|
+
--namespace=lynkr
|
|
197
|
+
|
|
198
|
+
# Or create manually
|
|
199
|
+
kubectl create secret generic lynkr-secrets \
|
|
200
|
+
--from-literal=DATABRICKS_API_KEY=your-key \
|
|
201
|
+
--from-literal=DATABRICKS_API_BASE=https://your-workspace.cloud.databricks.com \
|
|
202
|
+
--from-literal=OPENROUTER_API_KEY=your-key \
|
|
203
|
+
--namespace=lynkr
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 3. ConfigMap for Non-Sensitive Configuration
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
# configmap.yaml
|
|
210
|
+
apiVersion: v1
|
|
211
|
+
kind: ConfigMap
|
|
212
|
+
metadata:
|
|
213
|
+
name: lynkr-config
|
|
214
|
+
namespace: lynkr
|
|
215
|
+
data:
|
|
216
|
+
MODEL_PROVIDER: "openrouter"
|
|
217
|
+
TOOL_EXECUTION_MODE: "server"
|
|
218
|
+
LOG_LEVEL: "info"
|
|
219
|
+
PORT: "8080"
|
|
220
|
+
OLLAMA_MODEL: "qwen2.5-coder:latest"
|
|
221
|
+
OLLAMA_MAX_TOOLS_FOR_ROUTING: "3"
|
|
222
|
+
OPENROUTER_MAX_TOOLS_FOR_ROUTING: "15"
|
|
223
|
+
FALLBACK_ENABLED: "true"
|
|
224
|
+
FALLBACK_PROVIDER: "databricks"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 4. Deployment Manifest
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
# deployment.yaml
|
|
231
|
+
apiVersion: apps/v1
|
|
232
|
+
kind: Deployment
|
|
233
|
+
metadata:
|
|
234
|
+
name: lynkr
|
|
235
|
+
namespace: lynkr
|
|
236
|
+
labels:
|
|
237
|
+
app: lynkr
|
|
238
|
+
spec:
|
|
239
|
+
replicas: 3
|
|
240
|
+
strategy:
|
|
241
|
+
type: RollingUpdate
|
|
242
|
+
rollingUpdate:
|
|
243
|
+
maxSurge: 1
|
|
244
|
+
maxUnavailable: 0
|
|
245
|
+
selector:
|
|
246
|
+
matchLabels:
|
|
247
|
+
app: lynkr
|
|
248
|
+
template:
|
|
249
|
+
metadata:
|
|
250
|
+
labels:
|
|
251
|
+
app: lynkr
|
|
252
|
+
annotations:
|
|
253
|
+
prometheus.io/scrape: "true"
|
|
254
|
+
prometheus.io/port: "8080"
|
|
255
|
+
prometheus.io/path: "/metrics/prometheus"
|
|
256
|
+
spec:
|
|
257
|
+
containers:
|
|
258
|
+
- name: lynkr
|
|
259
|
+
image: ghcr.io/vishalveerareddy123/lynkr:latest
|
|
260
|
+
imagePullPolicy: Always
|
|
261
|
+
ports:
|
|
262
|
+
- containerPort: 8080
|
|
263
|
+
name: http
|
|
264
|
+
protocol: TCP
|
|
265
|
+
env:
|
|
266
|
+
# Load from ConfigMap
|
|
267
|
+
- name: MODEL_PROVIDER
|
|
268
|
+
valueFrom:
|
|
269
|
+
configMapKeyRef:
|
|
270
|
+
name: lynkr-config
|
|
271
|
+
key: MODEL_PROVIDER
|
|
272
|
+
- name: TOOL_EXECUTION_MODE
|
|
273
|
+
valueFrom:
|
|
274
|
+
configMapKeyRef:
|
|
275
|
+
name: lynkr-config
|
|
276
|
+
key: TOOL_EXECUTION_MODE
|
|
277
|
+
- name: LOG_LEVEL
|
|
278
|
+
valueFrom:
|
|
279
|
+
configMapKeyRef:
|
|
280
|
+
name: lynkr-config
|
|
281
|
+
key: LOG_LEVEL
|
|
282
|
+
- name: FALLBACK_ENABLED
|
|
283
|
+
valueFrom:
|
|
284
|
+
configMapKeyRef:
|
|
285
|
+
name: lynkr-config
|
|
286
|
+
key: FALLBACK_ENABLED
|
|
287
|
+
# Load from Secrets
|
|
288
|
+
- name: DATABRICKS_API_KEY
|
|
289
|
+
valueFrom:
|
|
290
|
+
secretKeyRef:
|
|
291
|
+
name: lynkr-secrets
|
|
292
|
+
key: DATABRICKS_API_KEY
|
|
293
|
+
- name: DATABRICKS_API_BASE
|
|
294
|
+
valueFrom:
|
|
295
|
+
secretKeyRef:
|
|
296
|
+
name: lynkr-secrets
|
|
297
|
+
key: DATABRICKS_API_BASE
|
|
298
|
+
- name: OPENROUTER_API_KEY
|
|
299
|
+
valueFrom:
|
|
300
|
+
secretKeyRef:
|
|
301
|
+
name: lynkr-secrets
|
|
302
|
+
key: OPENROUTER_API_KEY
|
|
303
|
+
optional: true
|
|
304
|
+
resources:
|
|
305
|
+
requests:
|
|
306
|
+
cpu: 500m
|
|
307
|
+
memory: 1Gi
|
|
308
|
+
limits:
|
|
309
|
+
cpu: 2000m
|
|
310
|
+
memory: 4Gi
|
|
311
|
+
livenessProbe:
|
|
312
|
+
httpGet:
|
|
313
|
+
path: /health/live
|
|
314
|
+
port: 8080
|
|
315
|
+
initialDelaySeconds: 30
|
|
316
|
+
periodSeconds: 10
|
|
317
|
+
timeoutSeconds: 5
|
|
318
|
+
failureThreshold: 3
|
|
319
|
+
readinessProbe:
|
|
320
|
+
httpGet:
|
|
321
|
+
path: /health/ready
|
|
322
|
+
port: 8080
|
|
323
|
+
initialDelaySeconds: 10
|
|
324
|
+
periodSeconds: 5
|
|
325
|
+
timeoutSeconds: 3
|
|
326
|
+
failureThreshold: 3
|
|
327
|
+
volumeMounts:
|
|
328
|
+
- name: data
|
|
329
|
+
mountPath: /app/data
|
|
330
|
+
volumes:
|
|
331
|
+
- name: data
|
|
332
|
+
persistentVolumeClaim:
|
|
333
|
+
claimName: lynkr-pvc
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### 5. Persistent Volume Claim
|
|
337
|
+
|
|
338
|
+
```yaml
|
|
339
|
+
# pvc.yaml
|
|
340
|
+
apiVersion: v1
|
|
341
|
+
kind: PersistentVolumeClaim
|
|
342
|
+
metadata:
|
|
343
|
+
name: lynkr-pvc
|
|
344
|
+
namespace: lynkr
|
|
345
|
+
spec:
|
|
346
|
+
accessModes:
|
|
347
|
+
- ReadWriteOnce
|
|
348
|
+
resources:
|
|
349
|
+
requests:
|
|
350
|
+
storage: 10Gi
|
|
351
|
+
storageClassName: standard # Adjust based on your cluster
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### 6. Service
|
|
355
|
+
|
|
356
|
+
```yaml
|
|
357
|
+
# service.yaml
|
|
358
|
+
apiVersion: v1
|
|
359
|
+
kind: Service
|
|
360
|
+
metadata:
|
|
361
|
+
name: lynkr
|
|
362
|
+
namespace: lynkr
|
|
363
|
+
labels:
|
|
364
|
+
app: lynkr
|
|
365
|
+
spec:
|
|
366
|
+
type: ClusterIP
|
|
367
|
+
ports:
|
|
368
|
+
- port: 8080
|
|
369
|
+
targetPort: 8080
|
|
370
|
+
protocol: TCP
|
|
371
|
+
name: http
|
|
372
|
+
selector:
|
|
373
|
+
app: lynkr
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### 7. Ingress (Optional)
|
|
377
|
+
|
|
378
|
+
```yaml
|
|
379
|
+
# ingress.yaml
|
|
380
|
+
apiVersion: networking.k8s.io/v1
|
|
381
|
+
kind: Ingress
|
|
382
|
+
metadata:
|
|
383
|
+
name: lynkr
|
|
384
|
+
namespace: lynkr
|
|
385
|
+
annotations:
|
|
386
|
+
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
387
|
+
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
388
|
+
spec:
|
|
389
|
+
ingressClassName: nginx
|
|
390
|
+
tls:
|
|
391
|
+
- hosts:
|
|
392
|
+
- lynkr.yourdomain.com
|
|
393
|
+
secretName: lynkr-tls
|
|
394
|
+
rules:
|
|
395
|
+
- host: lynkr.yourdomain.com
|
|
396
|
+
http:
|
|
397
|
+
paths:
|
|
398
|
+
- path: /
|
|
399
|
+
pathType: Prefix
|
|
400
|
+
backend:
|
|
401
|
+
service:
|
|
402
|
+
name: lynkr
|
|
403
|
+
port:
|
|
404
|
+
number: 8080
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### 8. Deploy to Kubernetes
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
# Apply all manifests
|
|
411
|
+
kubectl apply -f namespace.yaml
|
|
412
|
+
kubectl apply -f configmap.yaml
|
|
413
|
+
kubectl apply -f pvc.yaml
|
|
414
|
+
kubectl apply -f deployment.yaml
|
|
415
|
+
kubectl apply -f service.yaml
|
|
416
|
+
kubectl apply -f ingress.yaml # Optional
|
|
417
|
+
|
|
418
|
+
# Verify deployment
|
|
419
|
+
kubectl get pods -n lynkr
|
|
420
|
+
kubectl logs -f deployment/lynkr -n lynkr
|
|
421
|
+
|
|
422
|
+
# Check service
|
|
423
|
+
kubectl get svc -n lynkr
|
|
424
|
+
|
|
425
|
+
# Test health endpoint
|
|
426
|
+
kubectl port-forward svc/lynkr 8080:8080 -n lynkr
|
|
427
|
+
curl http://localhost:8080/health
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### 9. Horizontal Pod Autoscaling
|
|
431
|
+
|
|
432
|
+
```yaml
|
|
433
|
+
# hpa.yaml
|
|
434
|
+
apiVersion: autoscaling/v2
|
|
435
|
+
kind: HorizontalPodAutoscaler
|
|
436
|
+
metadata:
|
|
437
|
+
name: lynkr-hpa
|
|
438
|
+
namespace: lynkr
|
|
439
|
+
spec:
|
|
440
|
+
scaleTargetRef:
|
|
441
|
+
apiVersion: apps/v1
|
|
442
|
+
kind: Deployment
|
|
443
|
+
name: lynkr
|
|
444
|
+
minReplicas: 2
|
|
445
|
+
maxReplicas: 10
|
|
446
|
+
metrics:
|
|
447
|
+
- type: Resource
|
|
448
|
+
resource:
|
|
449
|
+
name: cpu
|
|
450
|
+
target:
|
|
451
|
+
type: Utilization
|
|
452
|
+
averageUtilization: 70
|
|
453
|
+
- type: Resource
|
|
454
|
+
resource:
|
|
455
|
+
name: memory
|
|
456
|
+
target:
|
|
457
|
+
type: Utilization
|
|
458
|
+
averageUtilization: 80
|
|
459
|
+
behavior:
|
|
460
|
+
scaleDown:
|
|
461
|
+
stabilizationWindowSeconds: 300
|
|
462
|
+
policies:
|
|
463
|
+
- type: Percent
|
|
464
|
+
value: 50
|
|
465
|
+
periodSeconds: 60
|
|
466
|
+
scaleUp:
|
|
467
|
+
stabilizationWindowSeconds: 0
|
|
468
|
+
policies:
|
|
469
|
+
- type: Percent
|
|
470
|
+
value: 100
|
|
471
|
+
periodSeconds: 30
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## Systemd Service
|
|
477
|
+
|
|
478
|
+
For deployment on Linux VMs without container orchestration.
|
|
479
|
+
|
|
480
|
+
### 1. Installation
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
# Clone repository
|
|
484
|
+
cd /opt
|
|
485
|
+
sudo git clone https://github.com/vishalveerareddy123/Lynkr.git
|
|
486
|
+
cd Lynkr
|
|
487
|
+
|
|
488
|
+
# Install dependencies
|
|
489
|
+
npm ci --omit=dev
|
|
490
|
+
|
|
491
|
+
# Configure
|
|
492
|
+
sudo cp .env.example .env
|
|
493
|
+
sudo nano .env
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### 2. Create Systemd Service
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
sudo nano /etc/systemd/system/lynkr.service
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
```ini
|
|
503
|
+
[Unit]
|
|
504
|
+
Description=Lynkr - Claude Code Proxy
|
|
505
|
+
After=network.target
|
|
506
|
+
Wants=network-online.target
|
|
507
|
+
|
|
508
|
+
[Service]
|
|
509
|
+
Type=simple
|
|
510
|
+
User=lynkr
|
|
511
|
+
Group=lynkr
|
|
512
|
+
WorkingDirectory=/opt/Lynkr
|
|
513
|
+
EnvironmentFile=/opt/Lynkr/.env
|
|
514
|
+
ExecStart=/usr/bin/node /opt/Lynkr/index.js
|
|
515
|
+
Restart=always
|
|
516
|
+
RestartSec=10
|
|
517
|
+
StandardOutput=journal
|
|
518
|
+
StandardError=journal
|
|
519
|
+
SyslogIdentifier=lynkr
|
|
520
|
+
|
|
521
|
+
# Security hardening
|
|
522
|
+
NoNewPrivileges=true
|
|
523
|
+
PrivateTmp=true
|
|
524
|
+
ProtectSystem=strict
|
|
525
|
+
ProtectHome=true
|
|
526
|
+
ReadWritePaths=/opt/Lynkr/data
|
|
527
|
+
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
|
528
|
+
|
|
529
|
+
# Resource limits
|
|
530
|
+
LimitNOFILE=65536
|
|
531
|
+
MemoryLimit=4G
|
|
532
|
+
CPUQuota=200%
|
|
533
|
+
|
|
534
|
+
[Install]
|
|
535
|
+
WantedBy=multi-user.target
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### 3. Create User and Set Permissions
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
# Create dedicated user
|
|
542
|
+
sudo useradd -r -s /bin/false lynkr
|
|
543
|
+
|
|
544
|
+
# Set ownership
|
|
545
|
+
sudo chown -R lynkr:lynkr /opt/Lynkr
|
|
546
|
+
|
|
547
|
+
# Create data directory
|
|
548
|
+
sudo mkdir -p /opt/Lynkr/data
|
|
549
|
+
sudo chown lynkr:lynkr /opt/Lynkr/data
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### 4. Enable and Start Service
|
|
553
|
+
|
|
554
|
+
```bash
|
|
555
|
+
# Reload systemd
|
|
556
|
+
sudo systemctl daemon-reload
|
|
557
|
+
|
|
558
|
+
# Enable on boot
|
|
559
|
+
sudo systemctl enable lynkr
|
|
560
|
+
|
|
561
|
+
# Start service
|
|
562
|
+
sudo systemctl start lynkr
|
|
563
|
+
|
|
564
|
+
# Check status
|
|
565
|
+
sudo systemctl status lynkr
|
|
566
|
+
|
|
567
|
+
# View logs
|
|
568
|
+
sudo journalctl -u lynkr -f
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### 5. Log Rotation
|
|
572
|
+
|
|
573
|
+
```bash
|
|
574
|
+
sudo nano /etc/logrotate.d/lynkr
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
```
|
|
578
|
+
/var/log/lynkr/*.log {
|
|
579
|
+
daily
|
|
580
|
+
missingok
|
|
581
|
+
rotate 14
|
|
582
|
+
compress
|
|
583
|
+
delaycompress
|
|
584
|
+
notifempty
|
|
585
|
+
create 0640 lynkr lynkr
|
|
586
|
+
sharedscripts
|
|
587
|
+
postrotate
|
|
588
|
+
systemctl reload lynkr > /dev/null 2>&1 || true
|
|
589
|
+
endscript
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
## Production Considerations
|
|
597
|
+
|
|
598
|
+
### 1. High Availability
|
|
599
|
+
|
|
600
|
+
- **Multiple replicas**: Run at least 3 instances for redundancy
|
|
601
|
+
- **Load balancing**: Use cloud load balancers or nginx
|
|
602
|
+
- **Health checks**: Configure liveness and readiness probes
|
|
603
|
+
- **Circuit breakers**: Built-in protection against cascading failures
|
|
604
|
+
|
|
605
|
+
### 2. Data Persistence
|
|
606
|
+
|
|
607
|
+
```yaml
|
|
608
|
+
# For Kubernetes - use StatefulSet for sticky sessions
|
|
609
|
+
apiVersion: apps/v1
|
|
610
|
+
kind: StatefulSet
|
|
611
|
+
metadata:
|
|
612
|
+
name: lynkr
|
|
613
|
+
spec:
|
|
614
|
+
serviceName: "lynkr"
|
|
615
|
+
replicas: 3
|
|
616
|
+
volumeClaimTemplates:
|
|
617
|
+
- metadata:
|
|
618
|
+
name: data
|
|
619
|
+
spec:
|
|
620
|
+
accessModes: ["ReadWriteOnce"]
|
|
621
|
+
resources:
|
|
622
|
+
requests:
|
|
623
|
+
storage: 10Gi
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### 3. Database Backup
|
|
627
|
+
|
|
628
|
+
```bash
|
|
629
|
+
# Backup SQLite databases
|
|
630
|
+
*/30 * * * * /usr/local/bin/backup-lynkr.sh
|
|
631
|
+
|
|
632
|
+
# backup-lynkr.sh
|
|
633
|
+
#!/bin/bash
|
|
634
|
+
BACKUP_DIR=/backups/lynkr/$(date +%Y%m%d)
|
|
635
|
+
mkdir -p $BACKUP_DIR
|
|
636
|
+
cp /app/data/*.db $BACKUP_DIR/
|
|
637
|
+
aws s3 sync $BACKUP_DIR s3://lynkr-backups/$(date +%Y%m%d)/
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
### 4. TLS/SSL
|
|
641
|
+
|
|
642
|
+
```yaml
|
|
643
|
+
# Ingress with cert-manager
|
|
644
|
+
apiVersion: networking.k8s.io/v1
|
|
645
|
+
kind: Ingress
|
|
646
|
+
metadata:
|
|
647
|
+
name: lynkr
|
|
648
|
+
annotations:
|
|
649
|
+
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
650
|
+
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
|
651
|
+
spec:
|
|
652
|
+
tls:
|
|
653
|
+
- hosts:
|
|
654
|
+
- lynkr.example.com
|
|
655
|
+
secretName: lynkr-tls
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
### 5. Rate Limiting
|
|
659
|
+
|
|
660
|
+
Lynkr includes built-in rate limiting. Configure via environment:
|
|
661
|
+
|
|
662
|
+
```bash
|
|
663
|
+
RATE_LIMIT_ENABLED=true
|
|
664
|
+
RATE_LIMIT_MAX=100 # requests per window
|
|
665
|
+
RATE_LIMIT_WINDOW_MS=60000 # 1 minute
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
## Monitoring & Observability
|
|
671
|
+
|
|
672
|
+
### Prometheus Integration
|
|
673
|
+
|
|
674
|
+
```yaml
|
|
675
|
+
# ServiceMonitor for Prometheus Operator
|
|
676
|
+
apiVersion: monitoring.coreos.com/v1
|
|
677
|
+
kind: ServiceMonitor
|
|
678
|
+
metadata:
|
|
679
|
+
name: lynkr
|
|
680
|
+
namespace: lynkr
|
|
681
|
+
spec:
|
|
682
|
+
selector:
|
|
683
|
+
matchLabels:
|
|
684
|
+
app: lynkr
|
|
685
|
+
endpoints:
|
|
686
|
+
- port: http
|
|
687
|
+
path: /metrics/prometheus
|
|
688
|
+
interval: 30s
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### Grafana Dashboard
|
|
692
|
+
|
|
693
|
+
Import the included Grafana dashboard:
|
|
694
|
+
|
|
695
|
+
```bash
|
|
696
|
+
# dashboards/grafana-lynkr.json
|
|
697
|
+
kubectl create configmap lynkr-dashboard \
|
|
698
|
+
--from-file=dashboards/grafana-lynkr.json \
|
|
699
|
+
-n monitoring
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### CloudWatch (AWS)
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
# Install CloudWatch agent
|
|
706
|
+
aws logs create-log-group --log-group-name /lynkr/application
|
|
707
|
+
|
|
708
|
+
# Configure in task definition
|
|
709
|
+
"logConfiguration": {
|
|
710
|
+
"logDriver": "awslogs",
|
|
711
|
+
"options": {
|
|
712
|
+
"awslogs-group": "/lynkr/application",
|
|
713
|
+
"awslogs-region": "us-east-1",
|
|
714
|
+
"awslogs-stream-prefix": "lynkr"
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Key Metrics to Monitor
|
|
720
|
+
|
|
721
|
+
- **Request rate**: `/metrics/prometheus` - `http_requests_total`
|
|
722
|
+
- **Latency**: `http_request_duration_seconds` (p50, p95, p99)
|
|
723
|
+
- **Error rate**: `http_requests_failed_total`
|
|
724
|
+
- **Circuit breaker state**: `/metrics/circuit-breakers`
|
|
725
|
+
- **Load shedding**: `load_shedding_requests_rejected_total`
|
|
726
|
+
- **Token usage**: `tokens_used_total{type="input|output"}`
|
|
727
|
+
- **Provider routing**: `provider_requests_total{provider="ollama|databricks|openrouter"}`
|
|
728
|
+
|
|
729
|
+
---
|
|
730
|
+
|
|
731
|
+
## Security Hardening
|
|
732
|
+
|
|
733
|
+
### 1. Secrets Management
|
|
734
|
+
|
|
735
|
+
**Never commit secrets to git**
|
|
736
|
+
|
|
737
|
+
Use environment variables or secrets management:
|
|
738
|
+
|
|
739
|
+
```bash
|
|
740
|
+
# Kubernetes Secrets (with external-secrets)
|
|
741
|
+
apiVersion: external-secrets.io/v1beta1
|
|
742
|
+
kind: ExternalSecret
|
|
743
|
+
metadata:
|
|
744
|
+
name: lynkr-secrets
|
|
745
|
+
spec:
|
|
746
|
+
secretStoreRef:
|
|
747
|
+
name: aws-secretsmanager
|
|
748
|
+
kind: SecretStore
|
|
749
|
+
target:
|
|
750
|
+
name: lynkr-secrets
|
|
751
|
+
data:
|
|
752
|
+
- secretKey: DATABRICKS_API_KEY
|
|
753
|
+
remoteRef:
|
|
754
|
+
key: lynkr/databricks
|
|
755
|
+
property: api_key
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
### 2. Network Policies
|
|
759
|
+
|
|
760
|
+
```yaml
|
|
761
|
+
# network-policy.yaml
|
|
762
|
+
apiVersion: networking.k8s.io/v1
|
|
763
|
+
kind: NetworkPolicy
|
|
764
|
+
metadata:
|
|
765
|
+
name: lynkr-network-policy
|
|
766
|
+
namespace: lynkr
|
|
767
|
+
spec:
|
|
768
|
+
podSelector:
|
|
769
|
+
matchLabels:
|
|
770
|
+
app: lynkr
|
|
771
|
+
policyTypes:
|
|
772
|
+
- Ingress
|
|
773
|
+
- Egress
|
|
774
|
+
ingress:
|
|
775
|
+
- from:
|
|
776
|
+
- namespaceSelector:
|
|
777
|
+
matchLabels:
|
|
778
|
+
name: ingress-nginx
|
|
779
|
+
ports:
|
|
780
|
+
- protocol: TCP
|
|
781
|
+
port: 8080
|
|
782
|
+
egress:
|
|
783
|
+
- to:
|
|
784
|
+
- namespaceSelector: {}
|
|
785
|
+
ports:
|
|
786
|
+
- protocol: TCP
|
|
787
|
+
port: 443 # HTTPS to external APIs
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
### 3. Pod Security Standards
|
|
791
|
+
|
|
792
|
+
```yaml
|
|
793
|
+
apiVersion: v1
|
|
794
|
+
kind: Pod
|
|
795
|
+
metadata:
|
|
796
|
+
name: lynkr
|
|
797
|
+
spec:
|
|
798
|
+
securityContext:
|
|
799
|
+
runAsNonRoot: true
|
|
800
|
+
runAsUser: 1000
|
|
801
|
+
fsGroup: 1000
|
|
802
|
+
seccompProfile:
|
|
803
|
+
type: RuntimeDefault
|
|
804
|
+
containers:
|
|
805
|
+
- name: lynkr
|
|
806
|
+
securityContext:
|
|
807
|
+
allowPrivilegeEscalation: false
|
|
808
|
+
readOnlyRootFilesystem: true
|
|
809
|
+
capabilities:
|
|
810
|
+
drop:
|
|
811
|
+
- ALL
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
### 4. API Authentication
|
|
815
|
+
|
|
816
|
+
Add authentication middleware:
|
|
817
|
+
|
|
818
|
+
```javascript
|
|
819
|
+
// Add to src/server.js
|
|
820
|
+
const authenticateRequest = (req, res, next) => {
|
|
821
|
+
const apiKey = req.headers['x-api-key'];
|
|
822
|
+
if (apiKey !== process.env.API_KEY) {
|
|
823
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
824
|
+
}
|
|
825
|
+
next();
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
app.use('/v1/messages', authenticateRequest);
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
---
|
|
832
|
+
|
|
833
|
+
## Scaling Strategies
|
|
834
|
+
|
|
835
|
+
### Horizontal Scaling
|
|
836
|
+
|
|
837
|
+
**Kubernetes HPA** (see above) - auto-scale based on:
|
|
838
|
+
- CPU utilization
|
|
839
|
+
- Memory utilization
|
|
840
|
+
- Custom metrics (request rate, queue depth)
|
|
841
|
+
|
|
842
|
+
### Vertical Scaling
|
|
843
|
+
|
|
844
|
+
Adjust resource limits based on load:
|
|
845
|
+
|
|
846
|
+
```yaml
|
|
847
|
+
resources:
|
|
848
|
+
requests:
|
|
849
|
+
cpu: 1000m # Start with 1 CPU
|
|
850
|
+
memory: 2Gi
|
|
851
|
+
limits:
|
|
852
|
+
cpu: 4000m # Allow burst to 4 CPUs
|
|
853
|
+
memory: 8Gi
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
### Load Shedding
|
|
857
|
+
|
|
858
|
+
Built-in load shedding activates automatically:
|
|
859
|
+
|
|
860
|
+
```bash
|
|
861
|
+
# Configure thresholds
|
|
862
|
+
LOAD_SHEDDING_ENABLED=true
|
|
863
|
+
LOAD_SHEDDING_HEAP_THRESHOLD=0.90 # Reject when >90% heap used
|
|
864
|
+
LOAD_SHEDDING_CPU_THRESHOLD=0.85 # Reject when >85% CPU
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
### Caching Strategy
|
|
868
|
+
|
|
869
|
+
```bash
|
|
870
|
+
# Prompt caching configuration
|
|
871
|
+
PROMPT_CACHE_ENABLED=true
|
|
872
|
+
PROMPT_CACHE_MAX_SIZE=1000 # Max entries
|
|
873
|
+
PROMPT_CACHE_TTL_MS=3600000 # 1 hour
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
### Multi-Region Deployment
|
|
877
|
+
|
|
878
|
+
Deploy to multiple regions with DNS-based load balancing:
|
|
879
|
+
|
|
880
|
+
```yaml
|
|
881
|
+
# Route53 configuration (AWS)
|
|
882
|
+
Type: A
|
|
883
|
+
Name: lynkr.example.com
|
|
884
|
+
Value:
|
|
885
|
+
- us-east-1-alb.example.com
|
|
886
|
+
- eu-west-1-alb.example.com
|
|
887
|
+
Routing Policy: Latency-based
|
|
888
|
+
Health Check: Enabled
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
## Troubleshooting
|
|
894
|
+
|
|
895
|
+
### Common Issues
|
|
896
|
+
|
|
897
|
+
#### 1. Container Won't Start
|
|
898
|
+
|
|
899
|
+
```bash
|
|
900
|
+
# Check logs
|
|
901
|
+
docker logs lynkr
|
|
902
|
+
kubectl logs -f deployment/lynkr -n lynkr
|
|
903
|
+
|
|
904
|
+
# Common causes:
|
|
905
|
+
# - Missing required environment variables
|
|
906
|
+
# - Invalid credentials
|
|
907
|
+
# - Port already in use
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
#### 2. Health Checks Failing
|
|
911
|
+
|
|
912
|
+
```bash
|
|
913
|
+
# Test health endpoints
|
|
914
|
+
curl http://localhost:8080/health/live
|
|
915
|
+
curl http://localhost:8080/health/ready
|
|
916
|
+
|
|
917
|
+
# Check readiness conditions
|
|
918
|
+
kubectl describe pod -n lynkr
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
#### 3. High Memory Usage
|
|
922
|
+
|
|
923
|
+
```bash
|
|
924
|
+
# Monitor memory
|
|
925
|
+
kubectl top pod -n lynkr
|
|
926
|
+
|
|
927
|
+
# Adjust heap size
|
|
928
|
+
NODE_OPTIONS="--max-old-space-size=4096" # 4GB heap
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
#### 4. Circuit Breaker Open
|
|
932
|
+
|
|
933
|
+
```bash
|
|
934
|
+
# Check circuit breaker state
|
|
935
|
+
curl http://localhost:8080/metrics/circuit-breakers
|
|
936
|
+
|
|
937
|
+
# Reset manually (if needed)
|
|
938
|
+
# Circuit breakers auto-recover after cooldown period
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
### Debug Mode
|
|
942
|
+
|
|
943
|
+
```bash
|
|
944
|
+
# Enable debug logging
|
|
945
|
+
LOG_LEVEL=debug
|
|
946
|
+
|
|
947
|
+
# View detailed logs
|
|
948
|
+
kubectl logs -f deployment/lynkr -n lynkr --tail=100
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
---
|
|
952
|
+
|
|
953
|
+
## Maintenance
|
|
954
|
+
|
|
955
|
+
### Rolling Updates
|
|
956
|
+
|
|
957
|
+
```bash
|
|
958
|
+
# Kubernetes
|
|
959
|
+
kubectl set image deployment/lynkr lynkr=ghcr.io/vishalveerareddy123/lynkr:v2.0.0 -n lynkr
|
|
960
|
+
kubectl rollout status deployment/lynkr -n lynkr
|
|
961
|
+
|
|
962
|
+
# Rollback if needed
|
|
963
|
+
kubectl rollout undo deployment/lynkr -n lynkr
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
### Backup & Restore
|
|
967
|
+
|
|
968
|
+
```bash
|
|
969
|
+
# Backup
|
|
970
|
+
kubectl exec -n lynkr deployment/lynkr -- tar -czf /tmp/backup.tar.gz /app/data
|
|
971
|
+
kubectl cp lynkr/lynkr-pod:/tmp/backup.tar.gz ./backup.tar.gz
|
|
972
|
+
|
|
973
|
+
# Restore
|
|
974
|
+
kubectl cp ./backup.tar.gz lynkr/lynkr-pod:/tmp/backup.tar.gz
|
|
975
|
+
kubectl exec -n lynkr deployment/lynkr -- tar -xzf /tmp/backup.tar.gz -C /
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
### Database Optimization
|
|
979
|
+
|
|
980
|
+
```bash
|
|
981
|
+
# SQLite vacuum (compress and optimize)
|
|
982
|
+
sqlite3 /app/data/sessions.db 'VACUUM;'
|
|
983
|
+
sqlite3 /app/data/sessions.db 'ANALYZE;'
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
---
|
|
987
|
+
|
|
988
|
+
## Support
|
|
989
|
+
|
|
990
|
+
For deployment issues:
|
|
991
|
+
|
|
992
|
+
1. Check the [GitHub Issues](https://github.com/vishalveerareddy123/Lynkr/issues)
|
|
993
|
+
2. Review [README.md](README.md) for configuration details
|
|
994
|
+
3. Join the community discussions
|
|
995
|
+
4. Contact support for enterprise deployments
|
|
996
|
+
|
|
997
|
+
---
|
|
998
|
+
|
|
999
|
+
## License
|
|
1000
|
+
|
|
1001
|
+
MIT License - see [LICENSE](LICENSE) for details.
|