Skip to content

Commit

Permalink
feat: auto generate ssl certs
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbbreuer committed Nov 15, 2024
1 parent c095ad1 commit 7f50167
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 328 deletions.
1 change: 1 addition & 0 deletions .vscode/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ proxied
socio
Solana
stacksjs
tlsx
typecheck
unplugin
unref
Expand Down
85 changes: 61 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<p align="center"><img src="https://github.com/stacksjs/reverse-proxy/blob/main/.github/art/cover.jpg?raw=true" alt="Social Card of this repo"></p>
<p align="center"><img src="https://github.com/stacksjs/rpx/blob/main/.github/art/cover.jpg?raw=true" alt="Social Card of this repo"></p>

[![npm version][npm-version-src]][npm-version-href]
[![GitHub Actions][github-actions-src]][github-actions-href]
Expand All @@ -12,25 +12,23 @@
## Features

- Simple Reverse Proxy
- Simple, lightweight Reverse Proxy
- Custom Domains _(with wildcard support)_
- Dependency-Free
- Zero-Config Setup
<!-- - SSL Support _(HTTPS by default)_ -->
<!-- - Auto HTTP-to-HTTPS Redirection -->
<!-- - `/etc/hosts` Management _(auto-updating)_ -->
- SSL Support _(HTTPS by default)_
- Auto HTTP-to-HTTPS Redirection

## Install

```bash
bun install -d @stacksjs/reverse-proxy
bun install -d @stacksjs/rpx
```

<!-- _Alternatively, you can install:_
```bash
brew install reverse-proxy # wip
pkgx install reverse-proxy # wip
brew install rpx # wip
pkgx install rpx # wip
``` -->

## Get Started
Expand All @@ -41,13 +39,28 @@ There are two ways of using this reverse proxy: _as a library or as a CLI._

Given the npm package is installed:

```js
import { startProxy } from '@stacksjs/reverse-proxy'
```ts
import type { TlsConfig } from '@stacksjs/rpx'
import { startProxy } from '@stacksjs/rpx'

export interface ReverseProxyConfig {
from: string // domain to proxy from, defaults to localhost:3000
to: string // domain to proxy to, defaults to stacks.localhost
https: TlsConfig // use https, defaults to true, also redirects http to https
verbose: boolean // log verbose output, defaults to false
}

startProxy({
const config: ReverseProxyOptions = {
from: 'localhost:3000',
to: 'my-project.localhost' // or try 'my-project.test'
})
to: 'my-project.localhost',
https: {
keyPath: './key.pem',
certPath: './cert.pem',
caCertPath: './ca.pem',
},
}

startProxy(config)
```

### CLI
Expand All @@ -64,16 +77,40 @@ reverse-proxy --version
The Reverse Proxy can be configured using a `reverse-proxy.config.ts` _(or `reverse-proxy.config.js`)_ file and it will be automatically loaded when running the `reverse-proxy` command.

```ts
// reverse-proxy.config.ts (or reverse-proxy.config.js)
export default {
'localhost:3000': 'stacks.localhost'
// reverse-proxy.config.{ts,js}
import type { ReverseProxyOptions } from './src/types'
import os from 'node:os'
import path from 'node:path'

const config: ReverseProxyOptions = {
from: 'localhost:5173',
to: 'stacks.localhost',
https: {
domain: 'stacks.localhost',
hostCertCN: 'stacks.localhost',
caCertPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.ca.crt`),
certPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt`),
keyPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt.key`),
altNameIPs: ['127.0.0.1'],
altNameURIs: ['localhost'],
organizationName: 'stacksjs.org',
countryName: 'US',
stateName: 'California',
localityName: 'Playa Vista',
commonName: 'stacks.localhost',
validityDays: 180,
verbose: false,
},
verbose: false,
}

export default config
```

_Then run:_

```bash
reverse-proxy start
./rpx start
```

To learn more, head over to the [documentation](https://reverse-proxy.sh/).
Expand Down Expand Up @@ -127,10 +164,10 @@ The MIT License (MIT). Please see [LICENSE](https://github.com/stacksjs/stacks/t
Made with 💙

<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/@stacksjs/reverse-proxy?style=flat-square
[npm-version-href]: https://npmjs.com/package/@stacksjs/reverse-proxy
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/reverse-proxy/ci.yml?style=flat-square&branch=main
[github-actions-href]: https://github.com/stacksjs/reverse-proxy/actions?query=workflow%3Aci
[npm-version-src]: https://img.shields.io/npm/v/@stacksjs/rpx?style=flat-square
[npm-version-href]: https://npmjs.com/package/@stacksjs/rpx
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/rpx/ci.yml?style=flat-square&branch=main
[github-actions-href]: https://github.com/stacksjs/rpx/actions?query=workflow%3Aci

<!-- [codecov-src]: https://img.shields.io/codecov/c/gh/stacksjs/reverse-proxy/main?style=flat-square
[codecov-href]: https://codecov.io/gh/stacksjs/reverse-proxy -->
<!-- [codecov-src]: https://img.shields.io/codecov/c/gh/stacksjs/rpx/main?style=flat-square
[codecov-href]: https://codecov.io/gh/stacksjs/rpx -->
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"name": "@stacksjs/reverse-proxy",
"name": "@stacksjs/rpx",
"type": "module",
"version": "0.1.0",
"description": "A modern reverse proxy.",
"author": "Chris Breuer <chris@stacksjs.org>",
"license": "MIT",
"homepage": "https://github.com/stacksjs/reverse-proxy#readme",
"homepage": "https://github.com/stacksjs/rpx#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/stacksjs/reverse-proxy.git"
"url": "git+https://github.com/stacksjs/rpx.git"
},
"bugs": {
"url": "https://github.com/stacksjs/reverse-proxy/issues"
"url": "https://github.com/stacksjs/rpx/issues"
},
"keywords": [
"reverse proxy",
Expand Down Expand Up @@ -61,7 +61,7 @@
"preview:docs": "vitepress preview docs"
},
"dependencies": {
"@stacksjs/tlsx": "^0.3.3"
"@stacksjs/tlsx": "^0.5.6"
},
"devDependencies": {
"@stacksjs/cli": "^0.68.2",
Expand Down
20 changes: 16 additions & 4 deletions reverse-proxy.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@ import path from 'node:path'
const config: ReverseProxyOptions = {
from: 'localhost:5173',
to: 'stacks.localhost',
keyPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt.key`),
certPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt`),
caCertPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.ca.crt`),
httpsRedirect: false,
https: {
domain: 'stacks.localhost',
hostCertCN: 'stacks.localhost',
caCertPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.ca.crt`),
certPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt`),
keyPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt.key`),
altNameIPs: ['127.0.0.1'],
altNameURIs: ['localhost'],
organizationName: 'stacksjs.org',
countryName: 'US',
stateName: 'California',
localityName: 'Playa Vista',
commonName: 'stacks.localhost',
validityDays: 180,
verbose: false,
},
verbose: false,
}

Expand Down
19 changes: 18 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { ReverseProxyConfig } from './types'
import os from 'node:os'
import path from 'node:path'
import { loadConfig } from 'bun-config'

// eslint-disable-next-line antfu/no-top-level-await
Expand All @@ -7,7 +9,22 @@ export const config: ReverseProxyConfig = await loadConfig({
defaultConfig: {
from: 'localhost:5173',
to: 'stacks.localhost',
httpsRedirect: false,
https: {
domain: 'stacks.localhost',
hostCertCN: 'stacks.localhost',
caCertPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.ca.crt`),
certPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt`),
keyPath: path.join(os.homedir(), '.stacks', 'ssl', `stacks.localhost.crt.key`),
altNameIPs: ['127.0.0.1'],
altNameURIs: ['localhost'],
organizationName: 'stacksjs.org',
countryName: 'US',
stateName: 'California',
localityName: 'Playa Vista',
commonName: 'stacks.localhost',
validityDays: 180,
verbose: false,
},
verbose: true,
},
})
31 changes: 31 additions & 0 deletions src/https.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { log } from '@stacksjs/cli'
import { addCertToSystemTrustStoreAndSaveCert, createRootCA, generateCert } from '@stacksjs/tlsx'
import { config } from './config'

export async function generateCertificate(domain?: string): Promise<void> {
domain = domain ?? config.https.altNameURIs[0]

log.info(`Generating a self-signed SSL certificate for: ${domain}`)

const caCert = await createRootCA(config.https)
const hostCert = await generateCert({
hostCertCN: config.https.commonName ?? domain,
domain,
altNameIPs: config.https.altNameIPs,
altNameURIs: config.https.altNameURIs,
countryName: config.https.countryName,
stateName: config.https.stateName,
localityName: config.https.localityName,
organizationName: config.https.organizationName,
validityDays: config.https.validityDays,
rootCAObject: {
certificate: caCert.certificate,
privateKey: caCert.privateKey,
},
verbose: config.https.verbose || config.verbose,
})

await addCertToSystemTrustStoreAndSaveCert(hostCert, caCert.certificate, config.https)

log.success('Certificate generated')
}
Loading

0 comments on commit 7f50167

Please sign in to comment.