Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .env.lan.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Example .env for LAN deployment on mcdonaldhomelab.com
# Copy this to .env on your LAN server machine

# ========================================
# REQUIRED: Database Connection (same as dev)
# ========================================
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your-service-role-key-here

# ========================================
# LAN Server Configuration
# ========================================
# Network binding - bind to all interfaces for LAN access
BIND_IP=0.0.0.0

# Domain configuration for mcdonaldhomelab.com
HOST=archon.mcdonaldhomelab.com

# CORS - allow access from the domain
CORS_ORIGINS=https://archon.mcdonaldhomelab.com

# API base URL for internal service communication
API_BASE_URL=https://archon.mcdonaldhomelab.com/api

# ========================================
# Optional: API Keys (can be set via UI)
# ========================================
OPENAI_API_KEY=your-openai-key-optional

# ========================================
# Optional: Logging and Monitoring
# ========================================
LOGFIRE_TOKEN=your-logfire-token-optional
LOG_LEVEL=INFO

# ========================================
# Port Configuration (defaults usually fine)
# ========================================
ARCHON_SERVER_PORT=8181
ARCHON_MCP_PORT=8051
ARCHON_AGENTS_PORT=8052
ARCHON_UI_PORT=3737

# ========================================
# MCP Configuration for LAN deployment
# ========================================
VITE_MCP_HOST=archon.mcdonaldhomelab.com
VITE_MCP_PROTOCOL=https
VITE_MCP_USE_PROXY=true
VITE_MCP_PORT=8051

# ========================================
# Optional: Enable Agents Service
# ========================================
AGENTS_ENABLED=false
64 changes: 64 additions & 0 deletions .env.unified.lan
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# LAN/Production Configuration
# Copy to .env for LAN deployment

# ========================================
# REQUIRED: Database Connection
# ========================================
SUPABASE_URL=https://ywqhytytvsugasmbpdfa.supabase.co
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl3cWh5dHl0dnN1Z2FzbWJwZGZhIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc1NjQyMjIxNiwiZXhwIjoyMDcxOTk4MjE2fQ.3DnxBT2hVtQgDdrxq5L2YgElZBV2-vkhUFKnJ7txQGQ

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Hardcoded Supabase service role key committed. Rotate immediately and purge history.

A real JWT service role key is present. This grants DB-wide privileges. Immediate action required:

  • Revoke/rotate the Supabase service role key now (Dashboard → Project Settings → API → Regenerate).
  • Force-push removal: purge from git history (filter-repo), invalidate caches.
  • Do not commit real secrets. Use an example file with placeholders.

Apply this minimal diff to remove the secret from the repo:

-SUPABASE_URL=https://ywqhytytvsugasmbpdfa.supabase.co
-SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl3cWh5dHl0dnN1Z2FzbWJwZGZhIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc1NjQyMjIxNiwiZXhwIjoyMDcxOTk4MjE2fQ.3DnxBT2hVtQgDdrxq5L2YgElZBV2-vkhUFKnJ7txQGQ
+SUPABASE_URL=https://your-project.supabase.co
+SUPABASE_SERVICE_KEY=your-service-role-key-here

Additionally, move this file to .env.unified.lan.example and add .env.unified.lan to .gitignore:

+ # .gitignore
+.env.unified.lan

I can provide a sanitized commit plan and a filter-repo script if helpful.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
SUPABASE_URL=https://ywqhytytvsugasmbpdfa.supabase.co
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl3cWh5dHl0dnN1Z2FzbWJwZGZhIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc1NjQyMjIxNiwiZXhwIjoyMDcxOTk4MjE2fQ.3DnxBT2hVtQgDdrxq5L2YgElZBV2-vkhUFKnJ7txQGQ
# .env.unified.lan (update to placeholders)
-SUPABASE_URL=https://ywqhytytvsugasmbpdfa.supabase.co
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your-service-role-key-here
Suggested change
SUPABASE_URL=https://ywqhytytvsugasmbpdfa.supabase.co
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl3cWh5dHl0dnN1Z2FzbWJwZGZhIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc1NjQyMjIxNiwiZXhwIjoyMDcxOTk4MjE2fQ.3DnxBT2hVtQgDdrxq5L2YgElZBV2-vkhUFKnJ7txQGQ
# .gitignore
.env.unified.lan
🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 8-8: [UnorderedKey] The SUPABASE_SERVICE_KEY key should go before the SUPABASE_URL key

(UnorderedKey)

🪛 Gitleaks (8.27.2)

[high] 8-8: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
In .env.unified.lan around lines 7 to 9 there is a committed real Supabase
service_role key; remove the secret from the file, replace it with a placeholder
(e.g. SUPABASE_SERVICE_KEY=REPLACE_ME), move the sanitized file to
.env.unified.lan.example and add .env.unified.lan to .gitignore, then
immediately rotate/revoke the exposed key in the Supabase dashboard (Project
Settings → API → Regenerate) and purge the leaked secret from repository history
using a tool like git filter-repo (or BFG) and force-push the rewritten history,
and finally notify stakeholders and invalidate any caches or CI secrets that may
have used the key.

# ========================================
# Deployment Mode: LAN/PRODUCTION
# ========================================
DEPLOYMENT_MODE=lan
BUILD_TARGET=production
NODE_ENV=production

# ========================================
# Network Configuration - UPDATE YOUR DOMAIN
# ========================================
HOST=archon.mcdonaldhomelab.com
BIND_IP=0.0.0.0
CORS_ORIGINS=https://archon.mcdonaldhomelab.com
API_BASE_URL=https://archon.mcdonaldhomelab.com/api
VITE_API_URL=https://archon.mcdonaldhomelab.com

# ========================================
# MCP Configuration for LAN
# ========================================
VITE_MCP_HOST=archon.mcdonaldhomelab.com
VITE_MCP_PROTOCOL=https
VITE_MCP_USE_PROXY=true
VITE_MCP_PORT=8051

# ========================================
# Service Ports (internal)
# ========================================
ARCHON_SERVER_PORT=8181
ARCHON_MCP_PORT=8051
ARCHON_AGENTS_PORT=8052
ARCHON_UI_PORT=3737
VITE_ARCHON_SERVER_PORT=

Comment on lines +41 to +42

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Unset VITE_ARCHON_SERVER_PORT: verify consumers.

An empty value can override defaults in some loaders. Either remove the key or set an explicit value.

Run to check usages:


🏁 Script executed:

#!/bin/bash
rg -nP --type=ts --type=py -C2 '\bVITE_ARCHON_SERVER_PORT\b|ARCHON_SERVER_PORT'

Length of output: 12015


Remove or set explicit VITE_ARCHON_SERVER_PORT in .env.unified.lan. Blank entries become empty strings in import.meta.env and will override built-in defaults in api.ts/vite.config.ts; delete the key if it’s unused or assign a concrete port (e.g. 8181).

🤖 Prompt for AI Agents
In .env.unified.lan around lines 41-42 the VITE_ARCHON_SERVER_PORT key is set to
an empty value which will become an empty string in import.meta.env and override
built-in defaults; either remove the VITE_ARCHON_SERVER_PORT line entirely if
unused, or assign a concrete port number (for example
VITE_ARCHON_SERVER_PORT=8181) so the app reads the intended port rather than an
empty string.

# ========================================
# Production Settings
# ========================================
DOCKER_SOCKET=/var/run/docker.sock
PROD=true
# Use prod profile for production without volume mounts
COMPOSE_PROFILES=prod

# ========================================
# Network Configuration (LAN/Traefik)
# ========================================
# Use external Traefik proxy network
PROXY_EXTERNAL=true
PROXY_NETWORK=proxy

# ========================================
# Optional Features
# ========================================
AGENTS_ENABLED=false
OPENAI_API_KEY=
LOGFIRE_TOKEN=
LOG_LEVEL=INFO
9 changes: 9 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ LOGFIRE_TOKEN=your-logfire-token # For observability
LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR
```

### Important: Environment vs Database Settings

**Critical**: The following settings MUST come from environment variables, NOT the database:
- `HOST` - Server hostname/domain
- `PORT` - Server port bindings
- `BIND_IP` - Network binding interface

These are deployment-specific and should never be loaded from the database settings table. The credential service has been updated to exclude these from database loading to prevent override issues in different deployment environments.

## File Organization

### Frontend Structure
Expand Down
90 changes: 90 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,96 @@ docker system prune -f
- **Backend**: Check that volumes are mounted correctly in `docker-compose.yml`
- **File permissions**: On some systems, mounted volumes may have permission issues

## 🌐 LAN/Production Deployment

### Overview

Deploy Archon on your local network for access from multiple devices or for production use with HTTPS support.

### Prerequisites

- Domain name (can be local like `archon.homelab.local`)
- Reverse proxy (Traefik, Nginx, or Caddy) for HTTPS
- Docker and Docker Compose

### Configuration Files

1. **`.env.unified.lan`** - LAN-specific environment variables:
```bash
DEPLOYMENT_MODE=lan
BUILD_TARGET=production
HOST=archon.yourdomain.com # Your domain
BIND_IP=0.0.0.0 # Allow external access
VITE_MCP_PROTOCOL=https
VITE_MCP_USE_PROXY=true
COMPOSE_PROFILES=prod
```

2. **`docker-compose.unified.yml`** - Unified deployment with profiles for dev/prod

### Deployment Steps

```bash
# 1. Copy the LAN environment template
cp .env.unified.lan .env

# 2. Edit .env with your domain
nano .env # Update HOST to your domain

# 3. Build and deploy all services
docker-compose -f docker-compose.unified.yml --profile prod build --no-cache
docker-compose -f docker-compose.unified.yml --profile prod up -d

# 4. Check status
docker-compose -f docker-compose.unified.yml ps
```

### Key Fixes Applied for LAN Deployment

During development, we identified and fixed several critical issues for LAN deployment:

1. **Service Discovery Fix** (`python/src/server/config/service_discovery.py`)
- Fixed hard-coded localhost in Docker Compose environment
- Added support for `VITE_MCP_USE_PROXY` to use external URLs
- Properly respects HOST environment variable

2. **Credential Service Fix** (`python/src/server/services/credential_service.py`)
- Removed HOST and PORT from database-loaded credentials
- Prevents database settings from overriding environment variables
- Ensures deployment-specific config comes from environment only

3. **MCP Configuration Fix** (`python/src/server/api_routes/mcp_api.py`)
- Updated `/api/mcp/config` endpoint to use service discovery
- Returns correct external URLs based on deployment mode

4. **Frontend Multi-Stage Build** (`archon-ui-main/Dockerfile`)
- Added production stage for optimized builds
- Proper build args for Vite environment variables
- Static file serving for production

5. **Docker Compose Updates** (`docker-compose.unified.yml`)
- Added `VITE_MCP_USE_PROXY` environment variable
- Proper profile configuration for dev/prod separation
- Docker socket access for container monitoring

### Common LAN Deployment Issues

#### MCP Dashboard Shows "localhost"
- **Cause**: Database settings overriding environment variables
- **Fix**: Applied in credential service - HOST/PORT no longer loaded from database

#### Docker Status Shows "unavailable"
- **Cause**: Docker socket not accessible in production
- **Fix**: Set `DOCKER_SOCKET=/var/run/docker.sock` in `.env.unified.lan`

#### Frontend Build Fails
- **Cause**: Missing production stage in Dockerfile
- **Fix**: Added multi-stage Dockerfile with development and production targets

#### 406 Not Acceptable on MCP Endpoint
- **Expected**: The `/mcp` endpoint requires SSE headers
- **Note**: Frontend shouldn't call this directly - it's for MCP clients only

## 📈 Progress

<p align="center">
Expand Down
141 changes: 141 additions & 0 deletions UNIFIED-DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Unified Docker Deployment

This repository now uses a **single unified docker-compose.yml** file that works for both local development and LAN/production deployments through environment variables.

## Quick Start

### Local Development
```bash
# Copy local environment template
cp .env.unified.local .env

# Edit .env with your Supabase credentials
nano .env

# Start services
docker-compose -f docker-compose.unified.yml up -d
```

Access at: `http://localhost:3737`

### LAN/Production Deployment
```bash
# Copy LAN environment template
cp .env.unified.lan .env

# Edit .env with your Supabase credentials and domain
nano .env

# Start services (with Traefik proxy)
docker-compose -f docker-compose.unified.yml up -d
```

Access at: `https://archon.yourdomain.com`

## Key Differences Between Modes

| Setting | Local Development | LAN/Production |
|---------|------------------|----------------|
| **BUILD_TARGET** | `development` | `production` |
| **BIND_IP** | `127.0.0.1` | `0.0.0.0` |
| **HOST** | `localhost` | `archon.yourdomain.com` |
| **CORS_ORIGINS** | `http://localhost:3737` | `https://archon.yourdomain.com` |
| **VITE_MCP_USE_PROXY** | `false` | `true` |
| **Volume Mounts** | Enabled | Disabled |
| **Docker Socket** | Mounted | Not mounted |
| **External Proxy** | Not used | Traefik proxy network |

## Environment Variables

### Core Settings
- `DEPLOYMENT_MODE`: `local` or `lan`
- `BUILD_TARGET`: `development` or `production`
- `NODE_ENV`: `development` or `production`

### Network Configuration
- `HOST`: Domain or localhost
- `BIND_IP`: IP to bind ports to (127.0.0.1 for local, 0.0.0.0 for LAN)
- `CORS_ORIGINS`: Allowed CORS origins
- `API_BASE_URL`: Base URL for API

### MCP Configuration
- `VITE_MCP_HOST`: MCP server hostname
- `VITE_MCP_PROTOCOL`: `http` or `https`
- `VITE_MCP_USE_PROXY`: `true` for LAN (routes through /mcp)
- `VITE_MCP_PORT`: MCP server port

## Migration from Separate Files

If you're currently using separate docker-compose files:

1. **Backup current configuration**:
```bash
cp .env .env.backup
cp docker-compose.yml docker-compose.yml.backup
cp docker-compose-lan.yml docker-compose-lan.yml.backup
```

2. **Choose your deployment mode**:
- For local: `cp .env.unified.local .env`
- For LAN: `cp .env.unified.lan .env`

3. **Update .env with your credentials**:
- Copy `SUPABASE_URL` and `SUPABASE_SERVICE_KEY` from backup
- Update domain settings if using LAN mode

4. **Switch to unified compose**:
```bash
docker-compose down
docker-compose -f docker-compose.unified.yml up -d
```

## Using with Traefik

For LAN deployment with Traefik:

1. **Ensure proxy network exists**:
```bash
docker network create proxy
```

2. **Set in .env**:
```bash
PROXY_NETWORK=proxy
```

3. **Configure Traefik labels** (optional - add to docker-compose.unified.yml):
```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.archon.rule=Host(`archon.yourdomain.com`)"
```

## Benefits of Unified Approach

1. **Single source of truth**: One docker-compose file to maintain
2. **Environment-based configuration**: Everything controlled via .env
3. **Easier testing**: Switch between modes by changing .env
4. **Reduced complexity**: No need to remember different compose files
5. **Version control friendly**: Same file structure for all deployments

## Troubleshooting

### Services not accessible externally
- Check `BIND_IP` is set to `0.0.0.0` for LAN
- Verify firewall rules allow the ports

### MCP connection issues
- Ensure `VITE_MCP_USE_PROXY` matches your deployment mode
- Check browser console for the loaded configuration

### Traefik proxy not working
- Verify proxy network exists: `docker network ls`
- Check `PROXY_NETWORK` in .env matches your Traefik network name

## Third-Party MCP Clients

External MCP clients can connect to:
- **Local**: `http://localhost:8051/mcp`
- **LAN**: `https://archon.yourdomain.com/mcp`

The configuration automatically handles routing based on `VITE_MCP_USE_PROXY` setting.
Loading