dash
dash copied to clipboard
HTTPS for local development
(Moved from #24) I hate that so many use https in production but they don't in development. This causes multiple errors constantly. For example devs don't notice mixed content errors.
We could selfsign a wildcard certificate with something like *.dash.test
or *.d.test
and then use it for jwilder/nginx-proxy
. Then if we use domains like my-application.dash.test
for containers they would have https enabled by default.
jwilder/nginx-proxy already supports this, we only need to mount the generated cert folder into the container. These certificates could be stored locally in ~/.dash/
for example. If stored locally we could add more domains later with a command something like $ dev ssl add *.site.test
.
This would also allow testing the real certificates by changing production.address
in /etc/hosts.
I checked and tested but it's not possible to use self-signed certificate for tld eg *.test
. Safari will accept this without a question (if it's in keychain) but chrome is more clever and denies this.
You can trust self-generated keys in OS-X by:
system "sudo security add-trusted-cert -d -r trustRoot -k '/Library/Keychains/System.keychain' #{ssl_cert_path}/development.crt"
I can do PR for this in couple of days. I just want to hear your opinions about these as well.
@silvamerica you mentioned in #24 that we could use same certificate which docker creates. Well we could that but then we can't make the development environment to think that the certificate is trusted. Or at least I don't know how to do it.
TL;DR
If we use docker certificate we would get error like:
(because the certificate CN won't match the domain)
But if we create certificate with specific CN and add it into keychain it will look like this:
Non trusted self-signed certs have caused some problems for me in some setups. So in order to have trusted self-signed certs we could do something like this:
For example Here's my docker-machine certificate. Note that it misses CN section.
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
16:83:1b:9b:a5:0e:ad:7d:97:82:3b:bf:63:52:c4:7a
Signature Algorithm: sha256WithRSAEncryption
Issuer: O=onnimonni
Validity
Not Before: Feb 18 10:55:00 2016 GMT
Not After : Feb 2 10:55:00 2019 GMT
Subject: O=onnimonni.<bootstrap>
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:cb:fe:fe:c3:76:23:f4:0c:87:0f:6f:9d:26:b2:
21:97:0a:2f:8e:34:aa:d2:d0:47:1f:74:7b:6f:cc:
7a:f3:d7:a6:03:dc:ab:fd:f5:36:05:c3:37:3f:44:
63:ea:ce:68:00:b4:a4:8c:89:32:2d:23:de:75:fa:
26:1a:24:f8:b3:c7:21:3c:0e:f2:a9:64:b4:0b:1f:
00:62:07:7c:6e:01:ae:4c:6e:24:f6:ed:c6:3d:eb:
4c:72:04:57:f4:2e:8c:52:41:cb:f1:47:46:ce:87:
e9:17:50:3b:92:59:ee:d2:4a:30:c1:39:cc:68:55:
26:76:d1:ad:a0:63:8b:80:19:b8:3a:fe:81:0e:3e:
5b:06:04:4b:79:7b:f3:34:e9:dc:d5:97:d8:57:e0:
48:4d:91:a8:b6:08:4c:e4:41:26:dd:21:e9:45:b7:
08:a9:54:2c:1c:f4:92:6d:27:07:15:92:5f:31:10:
cf:60:8f:d2:a7:8f:07:8a:0c:c5:e1:a9:f0:14:d4:
2f:86:c5:d5:14:f7:67:69:23:46:2f:b0:ca:e1:a9:
b5:af:d4:bc:6e:f8:c2:dd:d9:97:98:b6:ce:c2:37:
b7:98:50:f0:c3:b6:e3:42:41:50:c1:12:a3:24:fb:
f6:84:22:d9:35:62:3e:36:82:c6:b1:f9:b1:26:9d:
d0:31
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
Signature Algorithm: sha256WithRSAEncryption
ac:bf:e0:18:c7:05:18:5c:9c:87:73:75:3b:15:0a:4c:31:60:
9f:9a:18:84:04:66:07:44:40:d9:9c:8b:d6:ad:e2:19:7f:c4:
99:df:86:dc:98:0b:cc:9c:79:32:84:cc:f1:42:d1:fe:93:77:
b6:9d:06:4b:42:61:4e:d6:62:70:31:d3:96:f6:52:bf:f9:7d:
55:c0:e0:3a:63:4d:46:51:a6:ae:37:b4:a7:ed:33:c9:9a:71:
db:f9:23:8d:cb:64:87:21:6b:27:14:dd:0c:bc:c7:d0:39:ad:
63:3c:c3:52:b6:e3:4e:93:06:2f:f0:05:f0:60:a0:1f:24:d8:
64:24:a1:17:b0:be:0c:20:aa:db:b5:9c:46:dc:18:6f:c6:60:
ac:ae:99:74:de:63:eb:48:dc:b1:28:07:9f:cc:f7:cd:f9:8d:
e7:3b:e2:2a:b2:a4:0b:0a:fa:bf:c7:f9:bb:60:ac:52:0e:30:
6a:57:3e:05:54:28:13:b8:58:93:8e:d2:77:84:2b:19:10:17:
03:56:ee:79:bf:5f:2d:bf:1e:a4:19:b0:01:32:d0:62:f8:75:
96:c2:23:23:9c:f1:ab:75:45:39:41:65:bb:26:29:28:6c:93:
f3:fa:d0:a0:5b:ab:4f:8c:d4:11:fa:48:c5:06:1a:2e:ac:67:
d8:98:50:9e
And the certificate we would need looks like one below. This example is for *.g.dev
. See the CN sections below.
$ openssl x509 -text -noout -in development.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
f5:78:28:0c:22:9e:5b:a7
Signature Algorithm: sha1WithRSAEncryption
Issuer: CN=*.g.dev
Validity
Not Before: Feb 16 12:53:06 2016 GMT
Not After : Feb 13 12:53:06 2026 GMT
Subject: CN=*.g.dev
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:d5:03:73:5d:46:89:04:f0:86:de:46:86:31:10:
b8:f6:7c:3b:0f:60:34:de:35:ed:80:08:a1:c7:17:
8a:00:8c:1b:02:47:7f:4d:ac:0c:80:7e:a7:5c:fd:
26:53:82:1d:fa:80:85:ac:e1:93:fe:21:a4:55:04:
05:45:fc:aa:a8:bf:34:31:d1:40:81:db:4b:6e:67:
df:0a:a9:c4:f7:73:97:78:91:2d:7f:cd:11:53:df:
29:0e:3e:ef:10:0c:3a:70:6d:aa:a8:b2:51:67:27:
c6:e0:c7:50:f3:cc:c7:06:92:df:ee:fc:63:a7:fd:
50:99:08:aa:88:33:c7:87:af:ca:c5:de:74:df:d2:
3f:91:e8:68:4c:58:d7:33:eb:25:95:02:c1:45:27:
88:d6:13:c0:7b:fe:9d:03:6c:dd:dd:e4:96:3b:0e:
84:cd:ff:e5:06:c3:11:b5:18:da:c7:cb:cd:e2:34:
f7:b6:bf:52:7b:c5:c9:7f:5f:9d:a0:47:7a:11:68:
7e:7b:57:88:6e:bf:16:40:34:1e:e6:a7:b5:bc:7e:
5c:57:25:e4:03:22:6d:9f:bc:f7:e5:ef:3b:eb:a9:
08:01:d2:65:21:59:df:15:04:df:56:9e:31:e2:1f:
40:d0:10:69:82:9a:3d:d4:fa:47:75:5d:d7:bd:e9:
6d:15
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:*.g.dev
Signature Algorithm: sha1WithRSAEncryption
8e:7d:6f:7b:d7:d2:ec:cd:71:45:fb:5d:dd:45:b7:32:61:ab:
9c:dc:4f:75:4d:a3:5a:2b:3e:ad:c4:ce:25:10:d6:68:63:98:
64:b8:2a:84:fc:a2:ff:e1:6d:ea:77:b9:e5:da:26:e2:bc:b0:
ac:f8:64:34:52:63:0f:5f:08:61:85:cf:db:db:1f:63:65:36:
0d:62:3e:88:b7:d6:8c:c7:ec:0d:c6:01:b2:11:ef:a0:31:07:
0b:c7:9e:b0:54:3e:76:7b:dd:50:4e:cf:0d:c7:8d:fa:0c:ff:
46:50:06:4d:86:18:82:86:94:35:73:5f:16:1f:0c:5d:a4:58:
55:24:70:dc:5f:81:fc:ca:6d:13:bc:0f:36:f8:3e:d3:3b:16:
7b:57:19:4f:d1:61:fc:03:41:08:81:df:4c:e0:00:49:fe:5e:
6f:7c:81:f9:dc:99:82:14:9e:d3:40:58:2e:c5:5f:61:2d:88:
99:21:58:e0:52:96:b5:c2:df:b8:09:58:e7:2a:5f:82:e0:03:
1e:e5:ae:0d:86:a9:9f:30:78:35:9a:60:7a:bc:3a:b1:25:42:
2d:c5:9d:e7:4e:5f:90:c3:44:72:57:08:e7:b9:60:1c:5d:e1:
a8:55:23:0d:c2:10:47:ee:c3:17:dc:7b:36:51:6e:31:6c:7e:
71:c8:59:a0
We can make certs with correct CN by:
$ openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ssl.key -out ssl.crt -config ./openssl.cnf -newkey rsa:2048
Example openssl.cnf
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = *.g.dev
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.g.dev
DNS.2 = *.web.g.dev
DNS.3 = other.dev
I think it makes sense to not use the machine cert, but rather ask users to create their own, or have the bootstrap script handle this task. I'd rather not reuse an existing cert for convenience, as that may cause unexpected issues of some kind. Separating the certs will also give us more control over the Dash cert, rather than rely on what machine gives us.
Or we could just parse the docker-compose.yml and create matching certs for the domain names in nginx-proxy mounted certs folder.
I mean we could do this in: $ dev up
Yeah, I'll backpeddle on using the machine cert, as all of your points against it are good ones.
@onnimonni would we be able to have matching certs in nginx-proxy
without scanning all possible docker-compose.yml
files? I'm not exactly sure what you're suggesting. Maybe the nginx-proxy
module could create certs on the fly with a trusted CA that we create during bootstrapping?
I think I could make a new container like this: JrCs/docker-letsencrypt-nginx-proxy-companion but only for local development and self-signed certs.
The container can listen docker.sock
and could generate new certificates on the fly and our install script should only add the self-signed ca to trusted list. Then pass the ca for this container. And mount the same /certs/
folder inside this container and jwilder/nginx-proxy.
Should these certificates be stored in project directory or in user directory ~/.dash
?
~/.dash
hasn't been something that we've used before, but I'm not opposed to it. For that matter, I mostly arbitrarily picked /usr/local/dev-env
. Does it make more sense to put them in the project directory, but move the project directory to ~? (We could make another topic for that)
I made this certificate generator container during weekend: https://github.com/onnimonni/signaler
If you add HTTPS_HOST: example.dev
into docker-compose.yml
this container will create example.dev
certificate automatically.
I'm doing the HTTPS already in our fork: https://github.com/devgeniem/gdev/blob/master/docker/services.yml
I'm using user home folder for certs and mounting the folder in nginx and signaler containers.
I was in such a hurry so I didn't make a pull request (at least not yet), would something similiar work in dash?