feat: add HOST environment variable for configurable bind address (#360)

* feat: add HOST environment variable for configurable bind address

Allow users to specify which host/IP address the servers should bind to
via the HOST environment variable. Defaults to 0.0.0.0 (all interfaces)
to maintain backward compatibility.

This enables users to restrict the server to localhost only (127.0.0.1)
for security purposes or bind to a specific network interface.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use correct proxy host when HOST is set to specific interface

When HOST is set to a specific interface (e.g., 192.168.1.100), the Vite
proxy needs to connect to that same host, not localhost. This fix:

- Adds proxyHost logic that uses localhost when HOST=0.0.0.0, otherwise
  uses the specific HOST value for proxy targets
- Adds DISPLAY_HOST to show a user-friendly URL in console output
  (0.0.0.0 isn't a connectable address)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Michael Fork <mjfork@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
This commit is contained in:
mjfork
2026-02-20 12:23:10 -06:00
committed by GitHub
parent 0207a1f3a3
commit cccd915c33
3 changed files with 20 additions and 7 deletions

View File

@@ -21,6 +21,10 @@ PORT=3001
#Frontend port
VITE_PORT=5173
# Host/IP to bind servers to (default: 0.0.0.0 for all interfaces)
# Use 127.0.0.1 to restrict to localhost only
HOST=0.0.0.0
# Uncomment the following line if you have a custom claude cli path other than the default "claude"
# CLAUDE_CLI_PATH=claude

View File

@@ -1886,6 +1886,9 @@ async function getFileTree(dirPath, maxDepth = 3, currentDepth = 0, showHidden =
}
const PORT = process.env.PORT || 3001;
const HOST = process.env.HOST || '0.0.0.0';
// Show localhost in URL when binding to all interfaces (0.0.0.0 isn't a connectable address)
const DISPLAY_HOST = HOST === '0.0.0.0' ? 'localhost' : HOST;
// Initialize database and start server
async function startServer() {
@@ -1905,7 +1908,7 @@ async function startServer() {
console.log(`${c.warn('[WARN]')} Note: Requests will be proxied to Vite dev server at ${c.dim('http://localhost:' + (process.env.VITE_PORT || 5173))}`);
}
server.listen(PORT, '0.0.0.0', async () => {
server.listen(PORT, HOST, async () => {
const appInstallPath = path.join(__dirname, '..');
console.log('');
@@ -1913,7 +1916,7 @@ async function startServer() {
console.log(` ${c.bright('Claude Code UI Server - Ready')}`);
console.log(c.dim('═'.repeat(63)));
console.log('');
console.log(`${c.info('[INFO]')} Server URL: ${c.bright('http://0.0.0.0:' + PORT)}`);
console.log(`${c.info('[INFO]')} Server URL: ${c.bright('http://' + DISPLAY_HOST + ':' + PORT)}`);
console.log(`${c.info('[INFO]')} Installed at: ${c.dim(appInstallPath)}`);
console.log(`${c.tip('[TIP]')} Run "cloudcli status" for full configuration details`);
console.log('');

View File

@@ -4,20 +4,26 @@ import react from '@vitejs/plugin-react'
export default defineConfig(({ command, mode }) => {
// Load env file based on `mode` in the current working directory.
const env = loadEnv(mode, process.cwd(), '')
const host = env.HOST || '0.0.0.0'
// When binding to all interfaces (0.0.0.0), proxy should connect to localhost
// Otherwise, proxy to the specific host the backend is bound to
const proxyHost = host === '0.0.0.0' ? 'localhost' : host
const port = env.PORT || 3001
return {
plugins: [react()],
server: {
host,
port: parseInt(env.VITE_PORT) || 5173,
proxy: {
'/api': `http://localhost:${env.PORT || 3001}`,
'/api': `http://${proxyHost}:${port}`,
'/ws': {
target: `ws://localhost:${env.PORT || 3001}`,
target: `ws://${proxyHost}:${port}`,
ws: true
},
'/shell': {
target: `ws://localhost:${env.PORT || 3001}`,
target: `ws://${proxyHost}:${port}`,
ws: true
}
}