npm http-server with SSL
Asked Answered
C

5

122

I'm using the npm package "http-server" (https://www.npmjs.com/package/http-server) to set up a simple webserver, but I cannot get it to use SSL. My command in package.json is

http-server -p 8000 -o -S

with a cert.pem and key.pem in my root directory (for now). The "-o" option opens a browser to the default page, but the page is served using HTTP and not even accessible through HTTPS. I don't get any errors or warnings. I've also tried adding the "-C" and "-K" options without luck. Has any one had any success with this package?

Crampton answered 1/2, 2016 at 9:50 Comment(2)
@Abhijeet That link is unavailable.Thies
@RabbiShukiGur sorry I don't own the resource. But thanks to web.archive.org It's still availableConvocation
C
2

Just for future reference, my problem was solved by updating the package to the latest version in package.json. I copy-pasted an old example file without updating the version numbers.

Crampton answered 8/2, 2016 at 7:34 Comment(0)
S
232

First, make sure that you have key.pem and cert.pem files. You can generate them using this command:

openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem

You will be prompted with a few questions after entering the command. Use 127.0.0.1 as value for "Common name" if you want to be able to install the certificate in your OS's root certificate store or browser so that it is trusted.

This generates a cert-key pair and it will be valid for roughly 10 years (3650 days to be exact).

Then you need to run the server with -S for enabling SSL and -C for your certificate file:

$ http-server -S -C cert.pem -o
Starting up http-server, serving ./ through https
Available on:
  https:127.0.0.1:8080
  https:192.168.1.101:8080
  https:192.168.1.104:8080
Hit CTRL-C to stop the server
Steatite answered 5/2, 2016 at 18:37 Comment(11)
It appears my package just needed an update. After trying everything, I saw I was running an old version...Crampton
How can I get this to use the same key and pem files from my local machine regardless of which app or sample code I'm running?Accuracy
BTW if you ever need a certificate from a CA I recommend using letsencrypt.org. It solved our issues here. Cheers!Demarcusdemaria
Suggesting for anyone who cannot get a recent version of Chrome on OSX to work....... version 65 works with this answer: https://mcmap.net/q/182522/-subject-alternative-name-missing-amp-err_ssl_version_or_cipher_mismatchKike
With Chrome 66 I have to enable Allow invalid certificates for resources loaded from localhost in chrome://flags as it says its untrustedSilverman
Solution is great thanks! @Steatite do you know if there is an option to serve SPA? It doesn't work for me.Jez
-new can also be omitted if -newkey is used.Flit
When trying to run http-server I get: Error: Could not find private key key.pem however the key.pem is sitting in the same folder as the cert.pemCarbine
What if I want to use my keys file?Dimitry
@Carbine - you will need to pass another option -K certs/key.pemWintergreen
Is it not a problem that the private key is now hosted on the server and can be downloaded by anyone?Ketron
R
56

I installed mkcert:

brew install mkcert
brew install nss # if you use Firefox
mkcert -install

Then, in your project directory:

mkcert 0.0.0.0 localhost 127.0.0.1 ::1

Finally, I renamed generated files:

  • 0.0.0.0+3-key.pem -> key.pem
  • 0.0.0.0+3.pem -> cert.pem

And ran the following command:

http-server -S -C cert.pem -o

Then I got:

enter image description here

I referenced this blog: https://qiita.com/walkers/items/b90a97a99bbb27f6550f (written in Japanese)

Reposit answered 20/5, 2020 at 5:9 Comment(2)
I was having trouble with the top voted solution but this worked great!Ran
renaming the file to key.pem and cert.pem fixed my issueDhole
C
2

Just for future reference, my problem was solved by updating the package to the latest version in package.json. I copy-pasted an old example file without updating the version numbers.

Crampton answered 8/2, 2016 at 7:34 Comment(0)
F
1

EDIT: Since writing this answer there is a new tool mkcert that does this for you. See https://mcmap.net/q/180695/-npm-http-server-with-ssl instead. My original answer below for historical interest.

Firefox didn't accept self-signed certs, so a bit more effort was required. First create a CA:

openssl req -batch -new -newkey ec:(openssl ecparam -name prime256v1|psub) -nodes -keyout ca-key.pem -x509 -out ca.pem -days 3650 -subj "/CN=A localhost CA"

Add ca.pem (A localhost CA) to trusted certs of your OS and/or Firefox (other browsers use system CAs). Keep the ca* files in a secure location for future use, so you never have to do this again.

Then, for any site that you are running, and whenever you wish to change settings, create cert.pem and key.pem with:

openssl req -batch -new -newkey ec:(openssl ecparam -name prime256v1|psub) -nodes -keyout key.pem -subj /CN=localhost | openssl x509 -req -CAkey ca-key.pem -CA ca.pem -CAcreateserial -out cert.pem -days 365 -extfile (echo subjectAltName=DNS:localhost|psub)

The above should work on most systems. If not, you might want to create temporary files ecparam.tmp and ext.tmp. Commands functionally equivalent to the two oneliners:

# Output Elliptic Curve parameters to a temporary file
openssl ecparam -name prime256v1 -out ecparam.tmp

# Create CA
openssl req -batch -new -newkey ec:ecparam.tmp -nodes -keyout ca-key.pem \
  -x509 -out ca.pem -days 3650 -subj "/CN=A localhost CA"

# Create a CSR for localhost, then sign it by CA
echo subjectAltName=DNS:localhost > ext.tmp
openssl req -batch -new -newkey ec:ecparam.tmp -nodes -keyout key.pem \
  -subj /CN=localhost | openssl x509 -req -CAkey ca-key.pem -CA ca.pem \
  -CAcreateserial -out cert.pem -days 365 -extfile ext.tmp
Foxtail answered 25/5, 2019 at 16:50 Comment(4)
When I run the first command I get an error. openssl req -batch -new -newkey ec:<(openssl ecparam -name prime256v1) -nodes -keyout ca-key.pem -x509 -out ca.pem -days 3650 -subj "/CN=A localhost CA" req: Unrecognized flag ---BEGIN EC PARAMETERS----- req: Use -help for summary. Yolk
Code updated with psub which should be better compatible with various shells.Foxtail
NET::ERR_CERT_COMMON_NAME_INVALID chrome 81 not accepting this certBiz
Are you accessing by "localhost", rather than by IP address? For IP or other addresses to work, you'll need to add more lines to ext.tmp, like subjectAltName=IP:127.0.0.1. The use of extfile can be entirely avoided with latest OpenSSL versions by using the -addext argument security.stackexchange.com/questions/74345/…Foxtail
M
0

1. Summary

I use Node.js package @Subash/mkcert, based on Forge.

It’s not the same as @FiloSottile/mkcert.

2. Advantages

  1. @Subash/mkcert is a free cross-platform package. I use it successfully on Ubuntu (see my example Travis CI build for Ubuntu 22.04.3 LTS Jammy Jellyfish) and on Windows (see my example AppVeyor CI build for Windows Server 2019) with the tools described in items 3.2—3.4 of this answer.

  2. Simple installation via bun/npm/pnpm/Yarn — package managers, some one of which are already used by http-server users. The user doesn’t have to install anything additional, as in @FiloSottile/mkcert.

  3. Simple usage:

    # [INFO] @Subash/mkcert installation
    npm install --global mkcert
    
    # [INFO] Create a certificate authority
    mkcert create-ca
    
    # [INFO] Create a certificate
    mkcert create-cert
    
    # [INFO] Run http-server in background with HTTPS
    # [INFO] Linux command
    nohup http-server --cert cert.crt --key cert.key --tls &
    # [INFO] Windows command
    powershell -Command "Start-Process cmd -ArgumentList '/c http-server --cert cert.crt --key cert.key --tls'"
    
  4. User of @Subash/mkcert can configure the certificate’s validity period using the --validity option. The developer of @FiloSottile/mkcert refused to add the same option.

3. Limitations

Programs/applications/tools/utilities that check the validity of a certificate don’t accept certificates from @Subash/mkcert. I’m having similar problems with self-signed certificates generated by OpenSSL and @FiloSottile/mkcert. Examples of problems:

  1. Browsers. The user must manually bypass browser warnings.

    mkcert browsers

  2. Chrome. If a user is running on a local server tools that require Chrome or Puppeteer, he should use solutions like --ignore-certificate-errors flag. For example, Pa11y users should use this configuration:

    module.exports = {
        defaults: {
            chromeLaunchConfig: {
                "args": [
                    "--ignore-certificate-errors"
                    ]
            }
        }
    };
    
    
  3. Linkchecker. Linkchecker users must disable SSL certificate checking in the configuration file.

    [checking]
    sslverify=0
    
  4. Node.js. If the user runs Node.js programs such as check-pages on the local server, he may need a solution like set environment variable NODE_TLS_REJECT_UNAUTHORIZED with value 0, which disables SSL certificate checking.

4. Disclaimer

This answer is relevant for the latest versions of the tools described in it as of February 2024. In the future, data of my answer may be obsolete.

I hope that in the future my answer will be outdated and that will appear a free cross-platform solution that requires simple installation and configuration and allows users to test their projects on http-server with HTTPS without the hassle of verifying SSL certificates.

Mage answered 8/2 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.