Skip to content

Commit 4e1679f

Browse files
committed
Add startup error about 443 perms
1 parent a964a3a commit 4e1679f

1 file changed

Lines changed: 54 additions & 0 deletions

File tree

vite.config.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import tailwindcss from '@tailwindcss/vite';
44
import boxen from 'boxen';
55
import chalk from 'chalk';
66
import dns from 'node:dns/promises';
7+
import net from 'node:net';
78
import os from 'node:os';
89
import { env } from 'node:process';
910
import license from 'rollup-plugin-license';
@@ -149,9 +150,62 @@ async function getServerConfig(mode: string, useLocalRedirect: boolean) {
149150
// Ensure we have the host entry redirecting to localhost
150151
await ensureFqdnRedirect('127.0.0.1', host);
151152

153+
// Check if we can bind to port 443 before Vite tries and fails with an unhelpful error
154+
await ensurePortBindable(host, 443);
155+
152156
return { host, port: 443, proxy: {} };
153157
}
154158

159+
async function ensurePortBindable(host: string, port: number): Promise<void> {
160+
return new Promise((resolve) => {
161+
const server = net.createServer();
162+
server.once('error', (err: NodeJS.ErrnoException) => {
163+
if (err.code === 'EACCES') {
164+
const platform = os.platform();
165+
let fix: string;
166+
167+
if (platform === 'linux') {
168+
fix = [
169+
`Node.js needs permission to serve HTTPS on port ${port}.\n`,
170+
'Option 1 (Recommended): Set up a reverse proxy',
171+
' Use Nginx or Caddy to proxy traffic to your Node server.',
172+
' This is more secure and follows best practices.\n',
173+
'Option 2 (Quick fix): Grant Node.js permission to bind to privileged ports',
174+
chalk.blue.bold(` sudo setcap 'cap_net_bind_service=+ep' $(which node)\n`),
175+
chalk.yellow.bold(' ⚠️ Security note: This allows Node to bind to ANY port below 1024.'),
176+
chalk.yellow.bold(' Only use this in trusted development environments.'),
177+
].join('\n');
178+
} else if (platform === 'darwin') {
179+
fix = [
180+
`Node.js needs permission to serve HTTPS on port ${port}.\n`,
181+
'Fix: Run the dev server with sudo, or set up a reverse proxy.',
182+
].join('\n');
183+
} else {
184+
fix = `Node.js does not have permission to bind to port ${port}.\nTry running with elevated privileges or use a reverse proxy.`;
185+
}
186+
187+
console.log(
188+
boxen(fix, {
189+
padding: 1,
190+
margin: 1,
191+
borderStyle: 'round',
192+
borderColor: 'yellow',
193+
title: `Port ${port} Permission Denied`,
194+
titleAlignment: 'center',
195+
})
196+
);
197+
process.exit(1);
198+
}
199+
// For other errors (e.g. EADDRINUSE), let Vite handle them
200+
resolve();
201+
});
202+
server.once('listening', () => {
203+
server.close(() => resolve());
204+
});
205+
server.listen(port, host);
206+
});
207+
}
208+
155209
export default defineConfig(async ({ command, mode, isPreview }) => {
156210
const isLocalServe = command === 'serve' || isPreview === true;
157211
const isProduction = mode === 'production' && (isTruthy(env.DOCKER) || isTruthy(env.CF_PAGES));

0 commit comments

Comments
 (0)