feat: add configurable host binding for server and Vite dev server

- Add HOST environment variable (default: 0.0.0.0) to allow binding to specific network interfaces
- Update server to listen on configurable host instead of hardcoded localhost
- Update Vite dev server to respect HOST environment variable
- Enhanced server startup banner to display listening address
- Updated .env.example and CLAUDE.md documentation

Fixes #536

Co-authored-by: Web Dev Cody <webdevcody@users.noreply.github.com>
This commit is contained in:
claude[bot]
2026-01-17 01:34:06 +00:00
parent 03516ac09e
commit 09bb59d090
4 changed files with 17 additions and 7 deletions

View File

@@ -166,6 +166,7 @@ Use `resolveModelString()` from `@automaker/model-resolver` to convert model ali
## Environment Variables
- `ANTHROPIC_API_KEY` - Anthropic API key (or use Claude Code CLI auth)
- `HOST` - Host to bind server to (default: 0.0.0.0)
- `PORT` - Server port (default: 3008)
- `DATA_DIR` - Data storage directory (default: ./data)
- `ALLOWED_ROOT_DIRECTORY` - Restrict file operations to specific directory

View File

@@ -44,6 +44,11 @@ CORS_ORIGIN=http://localhost:3007
# OPTIONAL - Server
# ============================================
# Host to bind the server to (default: 0.0.0.0)
# Use 0.0.0.0 to listen on all interfaces (recommended for Docker/remote access)
# Use 127.0.0.1 or localhost to restrict to local connections only
HOST=0.0.0.0
# Port to run the server on
PORT=3008

View File

@@ -73,6 +73,7 @@ import { getDevServerService } from './services/dev-server-service.js';
dotenv.config();
const PORT = parseInt(process.env.PORT || '3008', 10);
const HOST = process.env.HOST || '0.0.0.0';
const DATA_DIR = process.env.DATA_DIR || './data';
const ENABLE_REQUEST_LOGGING = process.env.ENABLE_REQUEST_LOGGING !== 'false'; // Default to true
@@ -551,22 +552,24 @@ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage
});
// Start server with error handling for port conflicts
const startServer = (port: number) => {
server.listen(port, () => {
const startServer = (port: number, host: string) => {
server.listen(port, host, () => {
const terminalStatus = isTerminalEnabled()
? isTerminalPasswordRequired()
? 'enabled (password protected)'
: 'enabled'
: 'disabled';
const portStr = port.toString().padEnd(4);
const hostDisplay = host === '0.0.0.0' ? 'localhost' : host;
logger.info(`
╔═══════════════════════════════════════════════════════╗
║ Automaker Backend Server ║
╠═══════════════════════════════════════════════════════╣
HTTP API: http://localhost:${portStr}
WebSocket: ws://localhost:${portStr}/api/events
Terminal: ws://localhost:${portStr}/api/terminal/ws
Health: http://localhost:${portStr}/api/health
Listening: ${host}:${port}${' '.repeat(Math.max(0, 34 - host.length - port.toString().length))}
HTTP API: http://${hostDisplay}:${portStr}
WebSocket: ws://${hostDisplay}:${portStr}/api/events
Terminal: ws://${hostDisplay}:${portStr}/api/terminal/ws
║ Health: http://${hostDisplay}:${portStr}/api/health ║
║ Terminal: ${terminalStatus.padEnd(37)}
╚═══════════════════════════════════════════════════════╝
`);
@@ -600,7 +603,7 @@ const startServer = (port: number) => {
});
};
startServer(PORT);
startServer(PORT, HOST);
// Global error handlers to prevent crashes from uncaught errors
process.on('unhandledRejection', (reason: unknown, _promise: Promise<unknown>) => {

View File

@@ -65,6 +65,7 @@ export default defineConfig(({ command }) => {
},
},
server: {
host: process.env.HOST || '0.0.0.0',
port: parseInt(process.env.TEST_PORT || '3007', 10),
},
build: {