vite-plugin-caddy-multiple-tls 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -13
- package/dist/index.d.ts +4 -1
- package/dist/index.js +38 -13
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -1,28 +1,132 @@
|
|
|
1
1
|
# vite-plugin-caddy-multiple-tls
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
derived domains like `<repo>.<branch>.localhost`.
|
|
3
|
+
## Usage
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
```js
|
|
6
|
+
// vite.config.js
|
|
7
|
+
import { defineConfig } from 'vite';
|
|
8
|
+
import caddyTls from 'vite-plugin-caddy-multiple-tls';
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const config = defineConfig({
|
|
11
|
+
plugins: [
|
|
12
|
+
caddyTls(),
|
|
13
|
+
]
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export default config;
|
|
10
17
|
```
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
Will give this in the terminal, allow you to connect to your app on HTTPS with a self-signed and trusted cert.
|
|
20
|
+
```
|
|
21
|
+
> vite
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
🔒 Caddy is proxying your traffic on https
|
|
25
|
+
|
|
26
|
+
🔗 Access your local server
|
|
27
|
+
🌍 https://my-repo.my-branch.localhost
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
By default, the plugin derives `<repo>.<branch>.localhost` from git.
|
|
32
|
+
If repo or branch can't be detected, pass `repo`/`branch` or use `domain`.
|
|
33
|
+
|
|
34
|
+
If you want a fixed host without repo/branch in the URL, pass a single domain:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
// vite.config.js
|
|
38
|
+
import { defineConfig } from 'vite';
|
|
39
|
+
import caddyTls from 'vite-plugin-caddy-multiple-tls';
|
|
40
|
+
|
|
41
|
+
const config = defineConfig({
|
|
42
|
+
plugins: [
|
|
43
|
+
caddyTls({
|
|
44
|
+
domain: 'app.localhost',
|
|
45
|
+
})
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export default config;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
To derive a domain like `<repo>.<branch>.<baseDomain>` automatically from git (repo name first, then branch):
|
|
13
53
|
|
|
14
54
|
```js
|
|
55
|
+
// vite.config.js
|
|
15
56
|
import { defineConfig } from 'vite';
|
|
16
57
|
import caddyTls from 'vite-plugin-caddy-multiple-tls';
|
|
17
58
|
|
|
18
|
-
|
|
19
|
-
plugins: [
|
|
59
|
+
const config = defineConfig({
|
|
60
|
+
plugins: [
|
|
61
|
+
caddyTls({
|
|
62
|
+
baseDomain: 'local.conekto.eu',
|
|
63
|
+
})
|
|
64
|
+
]
|
|
20
65
|
});
|
|
66
|
+
|
|
67
|
+
export default config;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
You can override auto-detection with `repo` or `branch` if needed.
|
|
71
|
+
|
|
72
|
+
For a zero-config experience, use `baseDomain: 'localhost'` (the default) so the derived domain works without editing `/etc/hosts`.
|
|
73
|
+
|
|
74
|
+
`internalTls` defaults to `true` when you pass `baseDomain` or `domain`. You can override it if needed.
|
|
75
|
+
|
|
76
|
+
For non-`.localhost` domains (like `local.example.test`), keep `internalTls: true` to force Caddy to use its internal CA for certificates.
|
|
77
|
+
|
|
78
|
+
> [!IMPORTANT]
|
|
79
|
+
> **Hosts file limitation:** If you use a custom domain, you must **manually** add each generated subdomain to your `/etc/hosts` file (e.g., `127.0.0.1 repo.branch.local.example.test`). System hosts files **do not support wildcards** (e.g., `*.local.example.test`), so you lose the benefit of automatic domain resolution that `localhost` provides.
|
|
80
|
+
|
|
81
|
+
## Recommended base domain: `.localhost`
|
|
82
|
+
Why `localhost` is the best option for local development:
|
|
83
|
+
- Reserved by RFC 6761 (never on the public internet).
|
|
84
|
+
- Automatic resolution on macOS: `*.localhost` maps to `127.0.0.1` and `::1` without DNS or `/etc/hosts`.
|
|
85
|
+
- Subdomain support: `api.localhost`, `foo.bar.localhost`, etc.
|
|
86
|
+
- Secure context in browsers for HTTPS, service workers, and cookies.
|
|
87
|
+
- Works well with Caddy and other local reverse proxies.
|
|
88
|
+
|
|
89
|
+
Example usage:
|
|
90
|
+
```
|
|
91
|
+
app.localhost
|
|
92
|
+
api.app.localhost
|
|
21
93
|
```
|
|
22
94
|
|
|
23
|
-
|
|
95
|
+
> [!NOTE]
|
|
96
|
+
> **Linux users:** Unlike macOS, most Linux distributions don't automatically resolve `*.localhost` subdomains. The plugin will detect Linux and show you the exact command to run:
|
|
97
|
+
> ```
|
|
98
|
+
> 🐧 Linux users: if the domain doesn't resolve, run:
|
|
99
|
+
> echo "127.0.0.1 my-repo.my-branch.localhost" | sudo tee -a /etc/hosts
|
|
100
|
+
> ```
|
|
101
|
+
>
|
|
102
|
+
> If you want to avoid `/etc/hosts` edits on Linux, set `loopbackDomain` to a public loopback domain:
|
|
103
|
+
> ```ts
|
|
104
|
+
> caddyTls({
|
|
105
|
+
> loopbackDomain: 'localtest.me',
|
|
106
|
+
> })
|
|
107
|
+
> ```
|
|
108
|
+
> Supported values: `localtest.me`, `lvh.me`, `nip.io` (maps to `127.0.0.1.nip.io`). These rely on public DNS, so they can fail offline or on restricted networks.
|
|
109
|
+
>
|
|
110
|
+
> Why these work: they use wildcard DNS so any subdomain resolves to `127.0.0.1`, meaning the request loops back to your machine after DNS.
|
|
111
|
+
> - `localtest.me` and `lvh.me`: static wildcard -> always `127.0.0.1` (great for subdomain testing).
|
|
112
|
+
> - `nip.io`: dynamic parsing of the IP in the hostname (e.g. `app.192.168.1.50.nip.io`) so you can target LAN devices.
|
|
113
|
+
> Why use them: subdomains behave like real domains, no `/etc/hosts` edits, and closer parity for cookies/CORS rules.
|
|
114
|
+
>
|
|
115
|
+
> When using loopback domains, ensure your Vite config allows the Host header, e.g. `server: { allowedHosts: true }`.
|
|
116
|
+
>
|
|
117
|
+
> For a permanent fix that handles all `*.localhost` domains automatically, install dnsmasq:
|
|
118
|
+
> ```bash
|
|
119
|
+
> sudo apt install dnsmasq
|
|
120
|
+
> echo "address=/.localhost/127.0.0.1" | sudo tee /etc/dnsmasq.d/localhost.conf
|
|
121
|
+
> sudo systemctl restart dnsmasq
|
|
122
|
+
> ```
|
|
123
|
+
|
|
124
|
+
## Development
|
|
125
|
+
This repo uses npm workspaces. Install from the root with `npm install`, then run workspace scripts like `npm run build --workspace packages/plugin` or `npm run dev --workspace playground`.
|
|
126
|
+
|
|
127
|
+
## Contributing
|
|
128
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) to see how to get started.
|
|
129
|
+
|
|
130
|
+
## License
|
|
24
131
|
|
|
25
|
-
|
|
26
|
-
- `baseDomain`: base domain to build `<repo>.<branch>.<baseDomain>` (defaults to `localhost`)
|
|
27
|
-
- `repo`, `branch`: override repo/branch names used for derived domains
|
|
28
|
-
- `internalTls`: use Caddy internal CA for provided domains
|
|
132
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ interface ViteCaddyTlsPluginOptions {
|
|
|
5
5
|
domain?: string;
|
|
6
6
|
/** Base domain to build <repo>.<branch>.<baseDomain> (defaults to localhost) */
|
|
7
7
|
baseDomain?: string;
|
|
8
|
+
/** Optional loopback domain to avoid /etc/hosts edits */
|
|
9
|
+
loopbackDomain?: LoopbackDomain;
|
|
8
10
|
/** Override repo name used in derived domains */
|
|
9
11
|
repo?: string;
|
|
10
12
|
/** Override branch name used in derived domains */
|
|
@@ -15,6 +17,7 @@ interface ViteCaddyTlsPluginOptions {
|
|
|
15
17
|
/** Use Caddy's internal CA for the provided domains (defaults to true when baseDomain or domain is set) */
|
|
16
18
|
internalTls?: boolean;
|
|
17
19
|
}
|
|
20
|
+
type LoopbackDomain = 'localtest.me' | 'lvh.me' | 'nip.io';
|
|
18
21
|
/**
|
|
19
22
|
* Vite plugin to run Caddy server to proxy traffic on https for local development
|
|
20
23
|
*
|
|
@@ -27,6 +30,6 @@ interface ViteCaddyTlsPluginOptions {
|
|
|
27
30
|
* ```
|
|
28
31
|
* @returns {Plugin} - a Vite plugin
|
|
29
32
|
*/
|
|
30
|
-
declare function viteCaddyTlsPlugin({ domain, baseDomain, repo, branch, cors, serverName, internalTls, }?: ViteCaddyTlsPluginOptions): PluginOption;
|
|
33
|
+
declare function viteCaddyTlsPlugin({ domain, baseDomain, loopbackDomain, repo, branch, cors, serverName, internalTls, }?: ViteCaddyTlsPluginOptions): PluginOption;
|
|
31
34
|
|
|
32
35
|
export { type ViteCaddyTlsPluginOptions, viteCaddyTlsPlugin as default };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import chalk from "chalk";
|
|
3
2
|
import { execSync as execSync2 } from "child_process";
|
|
4
3
|
import path from "path";
|
|
5
4
|
|
|
@@ -271,6 +270,11 @@ async function removeTlsPolicy(id) {
|
|
|
271
270
|
}
|
|
272
271
|
|
|
273
272
|
// src/index.ts
|
|
273
|
+
var LOOPBACK_DOMAINS = {
|
|
274
|
+
"localtest.me": "localtest.me",
|
|
275
|
+
"lvh.me": "lvh.me",
|
|
276
|
+
"nip.io": "127.0.0.1.nip.io"
|
|
277
|
+
};
|
|
274
278
|
function execGit(command) {
|
|
275
279
|
return execSync2(command, { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
276
280
|
}
|
|
@@ -298,11 +302,20 @@ function getGitRepoInfo() {
|
|
|
298
302
|
function normalizeBaseDomain(baseDomain) {
|
|
299
303
|
return baseDomain.trim().replace(/^\.+|\.+$/g, "").toLowerCase();
|
|
300
304
|
}
|
|
305
|
+
function resolveBaseDomain(options) {
|
|
306
|
+
if (options.baseDomain !== void 0) {
|
|
307
|
+
return normalizeBaseDomain(options.baseDomain);
|
|
308
|
+
}
|
|
309
|
+
if (options.loopbackDomain) {
|
|
310
|
+
return normalizeBaseDomain(LOOPBACK_DOMAINS[options.loopbackDomain]);
|
|
311
|
+
}
|
|
312
|
+
return "localhost";
|
|
313
|
+
}
|
|
301
314
|
function sanitizeDomainLabel(value) {
|
|
302
315
|
return value.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
303
316
|
}
|
|
304
317
|
function buildDerivedDomain(options) {
|
|
305
|
-
const baseDomain =
|
|
318
|
+
const baseDomain = resolveBaseDomain(options);
|
|
306
319
|
if (!baseDomain) return null;
|
|
307
320
|
let repo = options.repo;
|
|
308
321
|
let branch = options.branch;
|
|
@@ -331,6 +344,7 @@ function resolveDomain(options) {
|
|
|
331
344
|
function viteCaddyTlsPlugin({
|
|
332
345
|
domain,
|
|
333
346
|
baseDomain,
|
|
347
|
+
loopbackDomain,
|
|
334
348
|
repo,
|
|
335
349
|
branch,
|
|
336
350
|
cors,
|
|
@@ -341,17 +355,21 @@ function viteCaddyTlsPlugin({
|
|
|
341
355
|
name: "vite:caddy-tls",
|
|
342
356
|
configureServer({ httpServer, config }) {
|
|
343
357
|
const fallbackPort = config.server.port || 5173;
|
|
344
|
-
const resolvedDomain = resolveDomain({
|
|
358
|
+
const resolvedDomain = resolveDomain({
|
|
359
|
+
domain,
|
|
360
|
+
baseDomain,
|
|
361
|
+
loopbackDomain,
|
|
362
|
+
repo,
|
|
363
|
+
branch
|
|
364
|
+
});
|
|
345
365
|
const domainArray = resolvedDomain ? [resolvedDomain] : [];
|
|
346
366
|
const routeId = `vite-proxy-${Date.now()}-${Math.floor(Math.random() * 1e3)}`;
|
|
347
|
-
const shouldUseInternalTls = internalTls ?? (baseDomain !== void 0 || domain !== void 0);
|
|
367
|
+
const shouldUseInternalTls = internalTls ?? (baseDomain !== void 0 || loopbackDomain !== void 0 || domain !== void 0);
|
|
348
368
|
const tlsPolicyId = shouldUseInternalTls ? `${routeId}-tls` : null;
|
|
349
369
|
let cleanupStarted = false;
|
|
350
370
|
if (domainArray.length === 0) {
|
|
351
371
|
console.error(
|
|
352
|
-
|
|
353
|
-
"No domain resolved. Provide domain, or run inside a git repo, or pass repo/branch."
|
|
354
|
-
)
|
|
372
|
+
"No domain resolved. Provide domain, or run inside a git repo, or pass repo/branch."
|
|
355
373
|
);
|
|
356
374
|
return;
|
|
357
375
|
}
|
|
@@ -400,14 +418,14 @@ function viteCaddyTlsPlugin({
|
|
|
400
418
|
if (!running) {
|
|
401
419
|
running = await startCaddy();
|
|
402
420
|
if (!running) {
|
|
403
|
-
console.error(
|
|
421
|
+
console.error("Failed to start Caddy server.");
|
|
404
422
|
return;
|
|
405
423
|
}
|
|
406
424
|
}
|
|
407
425
|
try {
|
|
408
426
|
await ensureBaseConfig(serverName);
|
|
409
427
|
} catch (e) {
|
|
410
|
-
console.error(
|
|
428
|
+
console.error("Failed to configure Caddy base settings.", e);
|
|
411
429
|
return;
|
|
412
430
|
}
|
|
413
431
|
const port = getServerPort();
|
|
@@ -416,7 +434,7 @@ function viteCaddyTlsPlugin({
|
|
|
416
434
|
await addTlsPolicy(tlsPolicyId, domainArray);
|
|
417
435
|
tlsPolicyAdded = true;
|
|
418
436
|
} catch (e) {
|
|
419
|
-
console.error(
|
|
437
|
+
console.error("Failed to add TLS policy to Caddy.", e);
|
|
420
438
|
return;
|
|
421
439
|
}
|
|
422
440
|
}
|
|
@@ -426,18 +444,25 @@ function viteCaddyTlsPlugin({
|
|
|
426
444
|
if (tlsPolicyAdded && tlsPolicyId) {
|
|
427
445
|
await removeTlsPolicy(tlsPolicyId);
|
|
428
446
|
}
|
|
429
|
-
console.error(
|
|
447
|
+
console.error("Failed to add route to Caddy.", e);
|
|
430
448
|
return;
|
|
431
449
|
}
|
|
432
450
|
console.log();
|
|
433
|
-
console.log(
|
|
451
|
+
console.log("\u{1F512} Caddy is proxying your traffic on https");
|
|
434
452
|
console.log();
|
|
435
453
|
console.log(
|
|
436
454
|
`\u{1F517} Access your local ${domainArray.length > 1 ? "servers" : "server"} `
|
|
437
455
|
);
|
|
438
456
|
domainArray.forEach((domain2) => {
|
|
439
|
-
console.log(
|
|
457
|
+
console.log(`\u{1F30D} https://${domain2}`);
|
|
440
458
|
});
|
|
459
|
+
if (process.platform === "linux" && !loopbackDomain) {
|
|
460
|
+
console.log();
|
|
461
|
+
console.log("\u{1F427} Linux users: if the domain doesn't resolve, run:");
|
|
462
|
+
domainArray.forEach((domain2) => {
|
|
463
|
+
console.log(` echo "127.0.0.1 ${domain2}" | sudo tee -a /etc/hosts`);
|
|
464
|
+
});
|
|
465
|
+
}
|
|
441
466
|
console.log();
|
|
442
467
|
registerProcessCleanup();
|
|
443
468
|
httpServer?.once("close", onServerClose);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-caddy-multiple-tls",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Vite plugin that uses Caddy to provide local HTTPS with derived domains.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"dev": "tsup --watch src/**/* src/index.ts --format esm --dts-resolve",
|
|
32
|
-
"
|
|
32
|
+
"sync-readme": "bash scripts/sync-readme.sh",
|
|
33
|
+
"build": "npm run sync-readme && tsup src/index.ts --format esm --dts",
|
|
33
34
|
"prepublishOnly": "npm run build",
|
|
34
35
|
"test": "vitest run",
|
|
35
36
|
"test:watch": "vitest"
|
|
@@ -55,8 +56,5 @@
|
|
|
55
56
|
"tsup": "^8.5.1",
|
|
56
57
|
"vite": "^7.3.0",
|
|
57
58
|
"vitest": "^4.0.16"
|
|
58
|
-
},
|
|
59
|
-
"dependencies": {
|
|
60
|
-
"chalk": "^5.6.2"
|
|
61
59
|
}
|
|
62
60
|
}
|