Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f459c7023 |
@@ -55,7 +55,7 @@
|
||||
"name": "mesh-registry",
|
||||
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
|
||||
"ports": [
|
||||
"5000"
|
||||
"5000:5000"
|
||||
],
|
||||
"volumes": [
|
||||
"/var/lib/mesh-registry:/var/lib/registry"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// The Letta API client — letta's own code, living in the module (novox/hq ADR 0039). Its tools
|
||||
// import it; nothing outside letta does.
|
||||
//
|
||||
// Letta authenticates with a single server password, presented as a Bearer token. That password is
|
||||
// a mesh own-secret, minted once and handed to both the server (LETTA_SERVER_PASSWORD) and this
|
||||
// client (MESH_LETTA_PASSWORD) — so the module's tools are live without anything configured by hand.
|
||||
// The runtime config file may still override the URL or password.
|
||||
// Letta authenticates with a single server password. That password is a mesh own-secret handed to
|
||||
// both the server (LETTA_SERVER_PASSWORD) and this client, through the runtime config file the mesh
|
||||
// mounts (its `password` key) — so the module's tools are live without anything configured by hand.
|
||||
// Where a server already has clients, the password is accepted rather than minted.
|
||||
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
@@ -58,6 +58,10 @@ export class LettaClient {
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// The server's --secure mode checks X-BARE-PASSWORD ("password <it>") and answers a Bearer
|
||||
// token alone with 401 (letta/server/rest_api/app.py, 0.6.x). Both are sent: Bearer is what
|
||||
// later servers read.
|
||||
"X-BARE-PASSWORD": `password ${this.password}`,
|
||||
Authorization: `Bearer ${this.password}`,
|
||||
...(options.headers as Record<string, string> | undefined),
|
||||
},
|
||||
|
||||
+21
-25
@@ -5,21 +5,28 @@
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database"
|
||||
"postgres-database",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "letta"
|
||||
},
|
||||
"route": {
|
||||
"label": "letta",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "/var/lib/letta/database.json"
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "/var/lib/letta/database.secret"
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"own-secrets": {
|
||||
"server-password": "/var/lib/letta/server-password.secret",
|
||||
"server-password": "${dir:state}/server-password.secret",
|
||||
"openai-api-key": "${dir:state}/openai-api-key.secret",
|
||||
"broker": "/var/lib/mesh/letta/broker"
|
||||
},
|
||||
"listens": [
|
||||
@@ -28,7 +35,7 @@
|
||||
"port": 8283,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the Letta agent server REST API and web UI; a public name is a route grant later"
|
||||
"why": "the Letta agent server REST API and web UI, password-protected (--secure); a public name is the route's"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
@@ -41,15 +48,15 @@
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/letta",
|
||||
"mode": "0700"
|
||||
"mode": "0700",
|
||||
"place": "."
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "/var/lib/letta/server.env",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"content": "LETTA_PG_URI=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\nLETTA_SERVER_PASSWORD=${secret:server-password}\nSECURE=true\nTZ=Europe/Brussels\n"
|
||||
"content": "LETTA_PG_URI=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\nLETTA_SERVER_PASSWORD=${secret:server-password}\nOPENAI_API_KEY=${secret:openai-api-key}\nSECURE=true\nTZ=Europe/Brussels\n"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
@@ -60,31 +67,24 @@
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "letta",
|
||||
"image": "letta/letta@sha256:1d2e0692514287c5ed1a483e14e16ed945f8632d315539f5e66373bb7d7c471b",
|
||||
"image": "letta/letta@sha256:bfd1e49ce45b9a208c941e832c1d1d194017ff210a3784b0ca6c323aed767a29",
|
||||
"network": "letta",
|
||||
"env-file": [
|
||||
"/var/lib/letta/server.env"
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"8283"
|
||||
],
|
||||
"secrets-in-environment": "the letta image is env-driven and its file-source support could not be verified; the mesh runtime can take its password from config.json (client.ts) \u2014 not yet converted"
|
||||
"secrets-in-environment": "letta 0.6.x reads its settings from the environment only (pydantic settings, no secrets_dir or _FILE twin), and its startup.sh starts an embedded PostgreSQL unless LETTA_PG_URI is set - so the database password travels inside that URI (startup.sh also echoes it to the log); LETTA_SERVER_PASSWORD and OPENAI_API_KEY have no file source either"
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "/var/lib/mesh/letta/config.json",
|
||||
"mode": "0600",
|
||||
"content": "{}\n",
|
||||
"content": "{\n \"password\": \"${secret:server-password}\"\n}\n",
|
||||
"merge": "json"
|
||||
},
|
||||
{
|
||||
"id": "runtime-env",
|
||||
"type": "file",
|
||||
"path": "/var/lib/letta/runtime.env",
|
||||
"mode": "0600",
|
||||
"content": "MESH_LETTA_PASSWORD=${secret:server-password}\n"
|
||||
},
|
||||
{
|
||||
"id": "runtime",
|
||||
"type": "container",
|
||||
@@ -99,14 +99,10 @@
|
||||
"MESH_LETTA_URL": "http://letta:8283",
|
||||
"MESH_LETTA_CONFIG_FILE": "/run/config/config.json"
|
||||
},
|
||||
"env-file": [
|
||||
"/var/lib/letta/runtime.env"
|
||||
],
|
||||
"restart-on": [
|
||||
"runtime-config"
|
||||
],
|
||||
"artifact": "runtime",
|
||||
"secrets-in-environment": "the letta image is env-driven and its file-source support could not be verified; the mesh runtime can take its password from config.json (client.ts) \u2014 not yet converted"
|
||||
"artifact": "runtime"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
|
||||
@@ -117,14 +117,14 @@
|
||||
},
|
||||
{
|
||||
"name": "web",
|
||||
"port": 80,
|
||||
"port": 7080,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the web front over http; only the ACME HTTP-01 passthrough is routed here \u2014 everything else 301s to https and would loop a proxy"
|
||||
},
|
||||
{
|
||||
"name": "web-tls",
|
||||
"port": 443,
|
||||
"port": 7443,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the web front over its own TLS (admin, webmail, API); the public name mail.novox.be is a route grant reaching it here"
|
||||
@@ -168,7 +168,7 @@
|
||||
"type": "file",
|
||||
"path": "${dir:state}/mailu.env",
|
||||
"mode": "0644",
|
||||
"content": "ADMIN_ADDRESS=mailu-admin\nANTISPAM_ADDRESS=mailu-antispam\nANTIVIRUS_ADDRESS=mailu-antivirus\nIMAP_ADDRESS=mailu-imap\nSMTP_ADDRESS=mailu-smtp\nFRONT_ADDRESS=mailu-front\nWEBMAIL_ADDRESS=mailu-webmail\nWEBDAV_ADDRESS=mailu-webdav\nREDIS_ADDRESS=mailu-redis\nPORTS=25,80,443,465,993,995,4190,110,143,587\nDOMAIN=novox.be\nHOSTNAMES=mail.novox.be\nPOSTMASTER=admin\nSITENAME=Novox\nWEBSITE=https://novox.be\nTLS_FLAVOR=letsencrypt\nSUBNET=192.168.203.0/24\nCOMPOSE_PROJECT_NAME=mailu\nANTIVIRUS=clamav\nWEBMAIL=roundcube\nWEBDAV=radicale\nFETCHMAIL_ENABLED=True\nFETCHMAIL_DELAY=600\nADMIN=true\nWEB_ADMIN=/admin\nWEB_WEBMAIL=/webmail\nWEBROOT_REDIRECT=/webmail\nAPI=true\nWEB_API=/api\nAUTH_RATELIMIT_IP=6000/hour\nAUTH_RATELIMIT_USER=1000/day\nCREDENTIAL_ROUNDS=12\nPASSWORD_SCHEME=PBKDF2\nDISABLE_STATISTICS=True\nMESSAGE_SIZE_LIMIT=50000000\nMESSAGE_RATELIMIT=200/day\nRECIPIENT_DELIMITER=+\nPOSTFIX_MYNETWORKS=127.0.0.0/8 [::1]/128\nRELAYNETS=\nRELAYHOST=\nREJECT_UNLISTED_RECIPIENT=\nDB_FLAVOR=postgresql\nINITIAL_ADMIN_ACCOUNT=admin\nINITIAL_ADMIN_DOMAIN=novox.be\nINITIAL_ADMIN_MODE=ifmissing\nSMTP_PORT=25\nSMTPS_PORT=465\nSUBMISSION_PORT=587\nPOP3_PORT=110\nPOP3S_PORT=995\nIMAP_PORT=143\nIMAPS_PORT=993\nHTTP_PORT=${port:80}\nHTTPS_PORT=${port:443}\nAUTOMX_PORT=4243\nAMX_SMTP_ADDRESS=mail.novox.be\nAMX_SMTP_PORT=587\nAMX_IMAP_ADDRESS=mail.novox.be\nAMX_IMAP_PORT=143\nAMX_MAIL_DOMAINS=novox.be\nDMARC_RUA=admin\nDMARC_RUF=admin\nLETSENCRYPT_SHORTCHAIN=True\nTZ=Etc/UTC\nLOG_LEVEL=INFO\nWELCOME=false\nREAL_IP_HEADER=X-Real-IP\nREAL_IP_FROM=142.132.152.141\nCOMPRESSION=\nCOMPRESS_LEVEL=\nCOMPRESSION_LEVEL=\nBIND_ADDRESS4=127.0.0.1\nBIND_ADDRESS6=::1\nMAILU_VERSION=1.9\nDOCKER_ORG=mailu\nDOCKER_PREFIX=\nWELCOME_SUBJECT=Welcome to your new email account\nWELCOME_BODY=Welcome to your new email account, if you can read this, then it is configured properly!\n"
|
||||
"content": "ADMIN_ADDRESS=mailu-admin\nANTISPAM_ADDRESS=mailu-antispam\nANTIVIRUS_ADDRESS=mailu-antivirus\nIMAP_ADDRESS=mailu-imap\nSMTP_ADDRESS=mailu-smtp\nFRONT_ADDRESS=mailu-front\nWEBMAIL_ADDRESS=mailu-webmail\nWEBDAV_ADDRESS=mailu-webdav\nREDIS_ADDRESS=mailu-redis\nPORTS=25,80,443,465,993,995,4190,110,143,587\nDOMAIN=novox.be\nHOSTNAMES=mail.novox.be\nPOSTMASTER=admin\nSITENAME=Novox\nWEBSITE=https://novox.be\nTLS_FLAVOR=letsencrypt\nSUBNET=192.168.203.0/24\nCOMPOSE_PROJECT_NAME=mailu\nANTIVIRUS=clamav\nWEBMAIL=roundcube\nWEBDAV=radicale\nFETCHMAIL_ENABLED=True\nFETCHMAIL_DELAY=600\nADMIN=true\nWEB_ADMIN=/admin\nWEB_WEBMAIL=/webmail\nWEBROOT_REDIRECT=/webmail\nAPI=true\nWEB_API=/api\nAUTH_RATELIMIT_IP=6000/hour\nAUTH_RATELIMIT_USER=1000/day\nCREDENTIAL_ROUNDS=12\nPASSWORD_SCHEME=PBKDF2\nDISABLE_STATISTICS=True\nMESSAGE_SIZE_LIMIT=50000000\nMESSAGE_RATELIMIT=200/day\nRECIPIENT_DELIMITER=+\nPOSTFIX_MYNETWORKS=127.0.0.0/8 [::1]/128\nRELAYNETS=\nRELAYHOST=\nREJECT_UNLISTED_RECIPIENT=\nDB_FLAVOR=postgresql\nINITIAL_ADMIN_ACCOUNT=admin\nINITIAL_ADMIN_DOMAIN=novox.be\nINITIAL_ADMIN_MODE=ifmissing\nSMTP_PORT=25\nSMTPS_PORT=465\nSUBMISSION_PORT=587\nPOP3_PORT=110\nPOP3S_PORT=995\nIMAP_PORT=143\nIMAPS_PORT=993\nHTTP_PORT=7080\nHTTPS_PORT=7443\nAUTOMX_PORT=4243\nAMX_SMTP_ADDRESS=mail.novox.be\nAMX_SMTP_PORT=587\nAMX_IMAP_ADDRESS=mail.novox.be\nAMX_IMAP_PORT=143\nAMX_MAIL_DOMAINS=novox.be\nDMARC_RUA=admin\nDMARC_RUF=admin\nLETSENCRYPT_SHORTCHAIN=True\nTZ=Etc/UTC\nLOG_LEVEL=INFO\nWELCOME=false\nREAL_IP_HEADER=X-Real-IP\nREAL_IP_FROM=142.132.152.141\nCOMPRESSION=\nCOMPRESS_LEVEL=\nCOMPRESSION_LEVEL=\nBIND_ADDRESS4=127.0.0.1\nBIND_ADDRESS6=::1\nMAILU_VERSION=1.9\nDOCKER_ORG=mailu\nDOCKER_PREFIX=\nWELCOME_SUBJECT=Welcome to your new email account\nWELCOME_BODY=Welcome to your new email account, if you can read this, then it is configured properly!\n"
|
||||
},
|
||||
{
|
||||
"id": "secret-env",
|
||||
@@ -456,8 +456,8 @@
|
||||
"587",
|
||||
"993",
|
||||
"995",
|
||||
"80",
|
||||
"443"
|
||||
"7080:80",
|
||||
"7443:443"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-certs}:/certs",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 80,
|
||||
"port": 9070,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the document server over http; the public name office.novox.be is a route grant, and route-proxy reaches it on this published port"
|
||||
@@ -93,7 +93,7 @@
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"80"
|
||||
"9070:80"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:logs}:/var/log/onlyoffice",
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 9000,
|
||||
"port": 9090,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the dashboard over http; routed, so the proxy reaches it here"
|
||||
"why": "the dashboard over http; portainer.novox.be is a route grant and the proxy reaches it here \u2014 the machine side of 9090:9000, the predecessor's number"
|
||||
},
|
||||
{
|
||||
"name": "web-tls",
|
||||
@@ -39,8 +39,8 @@
|
||||
"name": "portainer",
|
||||
"image": "portainer/portainer-ce@sha256:4d616db18cfeb5dd41a69c0958bc825c84483ea9cde1106eb82a5d26f3bd8b0e",
|
||||
"ports": [
|
||||
"9000",
|
||||
"9443"
|
||||
"9090:9000",
|
||||
"9443:9443"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/data",
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
"PGDATA": "/var/lib/postgresql/data/pgdata"
|
||||
},
|
||||
"ports": [
|
||||
"5432"
|
||||
"5432:5432"
|
||||
],
|
||||
"volumes": [
|
||||
"/var/lib/mesh-store:/var/lib/postgresql/data",
|
||||
|
||||
Reference in New Issue
Block a user