README.md 11.1 KB
Newer Older
1
# Auto Encrypt Localhost
Aral Balkan's avatar
Aral Balkan committed
2

3
Automatically provisions and installs locally-trusted TLS certificates for Node.js® https servers (including Express.js, etc.) using [mkcert](https://github.com/FiloSottile/mkcert/).
Aral Balkan's avatar
Aral Balkan committed
4
5
6

## How it works

Aral Balkan's avatar
Aral Balkan committed
7
At npm package installation time, Auto Encrypt Localhost installs mkcert.
8

Aral Balkan's avatar
Aral Balkan committed
9
10
11
At runtime, Auto Encrypt Localhost uses mkcert to create a local certificate authority and add it to the various trust stores. It then uses it to create locally-trusted TLS certificates that are automatically used by your server.

You can reach your server via the local loopback addresses (localhost, 127.0.0.1) on the device itself and also from other devices on the local area network by using your device’s external IPv4 address(es).
12

13
14
15
16
## System requirements

Tested and supported on:

Aral Balkan's avatar
Aral Balkan committed
17
  - Linux (tested with elementary OS 5.x/Hera)
18
  - macOS (tested on Big Sur)
Aral Balkan's avatar
Aral Balkan committed
19
  - Windows 10 (tested with Windows Terminal and PowerShell)
20

Aral Balkan's avatar
Aral Balkan committed
21
22
(WSL is not supported for certificates at localhost unless you’re running your browser under WSL also).

23
## Installation
24
25
26
27
28

```sh
npm i @small-tech/auto-encrypt-localhost
```

Aral Balkan's avatar
Aral Balkan committed
29
Note that during installation, Auto Encrypt Localhost will download and install the correct mkcert binary for your system.
30

31
## Usage
32

Aral Balkan's avatar
Aral Balkan committed
33
34
35
36
37
### Instructions

1. Import the module:

    ```js
Aral Balkan's avatar
Aral Balkan committed
38
    import AutoEncryptLocalhost from '@small-tech/auto-encrypt-localhost'
Aral Balkan's avatar
Aral Balkan committed
39
40
41
42
43
44
45
46
47
48
49
    ```

2. Prefix your server creation code with a reference to the Auto Encrypt Localhost class:

    ```js
    // const server = https.createServer(…) becomes
    const server = AutoEncryptLocalhost.https.createServer(…)
    ```

### Example

50
51
(You can find this example in the _example/_ folder in the source code. Run it by typing `node example`.)

52
53
54
```js
// Create an https server using locally-trusted certificates.

Aral Balkan's avatar
Aral Balkan committed
55
import AutoEncryptLocalhost from '@small-tech/auto-encrypt-localhost'
56

Aral Balkan's avatar
Aral Balkan committed
57
const server = AutoEncryptLocalhost.https.createServer((request, response) => {
58
59
60
  response.end('Hello, world!')
})

Aral Balkan's avatar
Aral Balkan committed
61
server.listen(443, () => {
62
63
64
65
  console.log('Web server is running at https://localhost')
})
```

Aral Balkan's avatar
Aral Balkan committed
66
67
68
On first run, Auto Encrypt Localhost will use mkcert to create your local certificate authority and install it in the system root store and generate locally-trusted certificates. These actions require elevated privileges and you will be prompted for your password unless you have passwordless sudo set up for your system.

Once your server is up and running, you can reach it via https://localhost, https://127.0.0.1, and via its external IPv4 address(es) on your local area network. To find the list of IP addresses that your local server is reachable from, you can run the following code in the Node interpreter:
69
70
71
72
73
74
75
76

```js
Object.entries(os.networkInterfaces())
  .map(iface =>
    iface[1].filter(addresses =>
      addresses.family === 'IPv4')
      .map(addresses => addresses.address)).flat()
```
77

Aral Balkan's avatar
Aral Balkan committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
### Plain Node.js example

If you just want to use the TLS certificates generated at installation time without using the Auto Encrypt Localhost library itself at runtime, you should install Auto Encrypt Localhost into your `dev-dependencies`. Post install, you can find your certificates in the _~/.small-tech.org/auto-encrypt-localhost_ folder.

Here’s a somewhat equivalent example to the one above but using Node’s regular `https` module instead of Auto Encrypt Localhost at runtime:

```js
import os from 'os'
import fs from 'fs'
import path from 'path'
import https from 'https'

const certificatesPath = path.join(os.homedir(), '.small-tech.org', 'auto-encrypt-localhost')
const keyFilePath = path.join(certificatesPath, 'localhost-key.pem')
const certFilePath = path.join(certificatesPath, 'localhost.pem')

const options = {
  key: fs.readFileSync(keyFilePath, 'utf-8'),
  cert: fs.readFileSync(certFilePath, 'utf-8')
}

const server = https.createServer(options, (request, response) => {
  response.end('Hello, world!')
})

server.listen(443, () => {
  console.log('Web server is running at https://localhost')
})
```

Aral Balkan's avatar
Aral Balkan committed
108
_Note that if you don’t use Auto Encrypt Localhost at runtime, you won’t get some of the benefits that it provides, like automatically adding the certificate authority to Node’s trust store (for hitting your server using Node.js without certificate errors), the `/.ca` convenience route, and HTTP to HTTPS forwarding, etc._
Aral Balkan's avatar
Aral Balkan committed
109
110
111
112
113
114
115
116
117
118
119

### On Linux

To access your server on port 443, make sure you’ve disabled privileged ports:

```
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=0
```

(On Linux, ports 80 and 443 require special privileges. Please see [A note on Linux and the security farce that is “privileged ports”](#a-note-on-linux-and-the-security-farce-that-is-priviliged-ports). If you just need a Node web server that handles all that and more for you – or to see how to implement privilege escalation seamlessly in your own servers – see [Site.js](https://sitejs.org)).

120
121
### Multiple servers

Aral Balkan's avatar
Aral Balkan committed
122
You are not limited to running your server on port 443. You can listen on any port you like and you can have multiple servers with the following caveat: the HTTP server that redirects HTTP calls to HTTPS and serves your local root certificate authority public key (see below) will only be created for the first server and then only if port 80 is free.
Aral Balkan's avatar
Aral Balkan committed
123

124
### Accessing your local machine from other devices on your local area network
Aral Balkan's avatar
Aral Balkan committed
125
126
127
128
129

You can access local servers via their IPv4 address over a local area network.

This is useful when you want to test your site with different devices without having to expose your server over the Internet using a service like ngrok. For example, if your machine’s IPv4 address on the local area network is 192.168.2.42, you can just enter that IP to access it from, say, your iPhone.

130
131
To access your local machine from a different device on your local area network, you must transfer the public key of your generated local root certificate authority to that device and install and trust it.

Aral Balkan's avatar
Aral Balkan committed
132
For example, if you’re on an iPhone, hit the `/.ca` route in your browser:
133

134
135
136
137
```
http://192.168.2.42/.ca
```

Aral Balkan's avatar
Aral Balkan committed
138
139
140
The browser will download the local root certificate authority’s public key and prompt you to install profile on your iPhone. You then have to go to Settings → Profile Downloaded → Tap Install when the Install Profile pop-up appears showing you the mkcert certificate you downloaded. Then, go to Settings → General → About → Certificate Trust Settings → Turn on the switch next to the mkcert certificate you downloaded. You should now be able to hit `https://192.168.2.42` and see your site from your iPhone.

You can also transfer your key manually. You can find the key at `~/.small-tech/auto-encrypt-localhost/rootCA.pem` after you’ve created at least one server. For more details on transferring your key to other devices, please refer to [the relevant section in the mkcert documentation](https://github.com/FiloSottile/mkcert#mobile-devices).
141

Aral Balkan's avatar
Aral Balkan committed
142
## Developer documentation
143

Aral Balkan's avatar
Aral Balkan committed
144
If you want to help improve Auto Encrypt Localhost or better understand how it is structured and operates, please see the [developer documentation](developer-documentation.md).
145

Aral Balkan's avatar
Aral Balkan committed
146
## Like this? Fund us!
147

Aral Balkan's avatar
Aral Balkan committed
148
[Small Technology Foundation](https://small-tech.org) is a tiny, independent not-for-profit.
149

Aral Balkan's avatar
Aral Balkan committed
150
We exist in part thanks to patronage by people like you. If you share [our vision](https://small-tech.org/about/#small-technology) and want to support our work, please [become a patron or donate to us](https://small-tech.org/fund-us) today and help us continue to exist.
151

Aral Balkan's avatar
Aral Balkan committed
152
## Audience
153

Aral Balkan's avatar
Aral Balkan committed
154
This is [small technology](https://small-tech.org/about/#small-technology).
155

Aral Balkan's avatar
Aral Balkan committed
156
If you’re evaluating this for a “startup” or an enterprise, let us save you some time: this is not the right tool for you. This tool is for individual developers to build personal web sites and apps for themselves and for others in a non-colonial manner that respects the human rights of the people who use them.
157

158
159
160
161
## Caveats

### Windows

162
Locally-trusted certificates do not work under Firefox. Please use Edge or Chrome on this platform. This is [a mkcert limitation](https://github.com/FiloSottile/mkcert#supported-root-stores).
163

Aral Balkan's avatar
Aral Balkan committed
164
165
166
167
## Related projects

From lower-level to higher-level:

168
169
### Auto Encrypt

Aral Balkan's avatar
Aral Balkan committed
170
  - Source: https://github.com/small-tech/auto-encrypt
171
  - Package: [@small-tech/auto-encrypt](https://www.npmjs.com/package/@small-tech/auto-encrypt)
Aral Balkan's avatar
Aral Balkan committed
172

Aral Balkan's avatar
Aral Balkan committed
173
Adds automatic provisioning and renewal of [Let’s Encrypt](https://letsencrypt.org) TLS certificates with [OCSP Stapling](https://letsencrypt.org/docs/integration-guide/#implement-ocsp-stapling) to [Node.js](https://nodejs.org) [https](https://nodejs.org/dist/latest-v12.x/docs/api/https.html) servers (including [Express.js](https://expressjs.com/), etc.)
Aral Balkan's avatar
Aral Balkan committed
174

175
176
### HTTPS

Aral Balkan's avatar
Aral Balkan committed
177
  - Source: https://github.com/small-tech/https
178
179
  - Package: [@small-tech/https](https://www.npmjs.com/package/@small-tech/https)

Aral Balkan's avatar
Aral Balkan committed
180
A drop-in replacement for the [standard Node.js HTTPS module](https://nodejs.org/dist/latest-v12.x/docs/api/https.html) with automatic development-time (localhost) certificates via Auto Encrypt Localhost and automatic production certificates via Auto Encrypt.
Aral Balkan's avatar
Aral Balkan committed
181

182
### Site.js
Aral Balkan's avatar
Aral Balkan committed
183

184
  - Web site: https://sitejs.org
Aral Balkan's avatar
Aral Balkan committed
185
186
187
188
189
190
191
  - Source: https://github.com/small-tech/site.js

A tool for developing, testing, and deploying a secure static or dynamic personal web site or app with zero configuration.

### Place (work-in-progress)

Small Web Protocol Reference Server.
Aral Balkan's avatar
Aral Balkan committed
192

Aral Balkan's avatar
Aral Balkan committed
193
  - Source: https://github.com/small-tech/place
Aral Balkan's avatar
Aral Balkan committed
194

Aral Balkan's avatar
Aral Balkan committed
195
196
197
198
## A note on Linux and the security farce that is “privileged ports”

Linux has an outdated feature dating from the mainframe days that requires a process that wants to bind to ports < 1024 to have elevated privileges. While this was a security feature in the days of dumb terminals, today it is a security anti-feature. (macOS has dropped this requirement as of macOS Mojave.)

Aral Balkan's avatar
Aral Balkan committed
199
200
201
202
203
204
205
On modern Linux systems, you can disable privileged ports like this:

```sh
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=0
```

Or, if you want to cling to ancient historic relics like a conservative to a racist statue, ensure your Node process has the right to bind to so-called “privileged” ports by issuing the following command before use:
Aral Balkan's avatar
Aral Balkan committed
206
207
208
209
210
211
212

```sh
sudo setcap cap_net_bind_service=+ep $(which node)
```

If you are wrapping your Node app into an executable binary using a module like [Nexe](https://github.com/nexe/nexe), you will have to ensure that every build of your app has that capability set. For an example of how we do this in [Site.js](https://sitejs.org), [see this listing](https://source.ind.ie/site.js/app/blob/master/bin/lib/ensure.js#L124).

213
214
## Help wanted

215
216
217
* Linux: _certutil_ (nss) auto-installation has not been tested with yum.
* macOS: _certutil_ (nss) auto-installation has not been tested with MacPorts.

218
219
220
221
222
223
224
225
## Like this? Fund us!

[Small Technology Foundation](https://small-tech.org) is a tiny, independent not-for-profit.

We exist in part thanks to patronage by people like you. If you share [our vision](https://small-tech.org/about/#small-technology) and want to support our work, please [become a patron or donate to us](https://small-tech.org/fund-us) today and help us continue to exist.

## Copyright

Aral Balkan's avatar
Aral Balkan committed
226
Copyright &copy; 2019-2021 [Aral Balkan](https://ar.al), [Small Technology Foundation](https://small-tech.org).
227
228
229
230

## License

Auto Encrypt Localhost is released under [AGPL 3.0 or later](./LICENSE).