Apple Pay for Web to a major clothing retailer. One of the requirements for Apple Pay for Web is that the connection must be over HTTPS. Most of the time when I’m developing locally, I do not use HTTPS. Local, meaning the application code is running on my laptop. In most cases, HTTPS is just run in staging and production environments and not handled directly by your app code.
So this posed a problem. I didn’t want to work on the server where it provides an HTTPS connection, that’s a pain. Also, if you’re not familiar with HTTPS servers, you need to have a valid certificate and more. So this solution requires a few steps to get working, but once it does, it works nicely.
It’s most likely not a good idea to use your production SSL certificate and key when doing local development, so you’ll want to create a fake version.
It’s entirely possible to purchase legitimate SSL certifates and use them, but this is not always possible, and it’s free to make your own
Update this code and run it on a Mac or Linux machine
sudo openssl req -x509 -sha256 -newkey rsa:2048 -keyout cert.key -out cert.pem -days 1024 -nodes -subj '/CN=www.example.com'
You now have files called cert.key
and cert.pem
for a certificate that is valid for the next 10 years.
Caveat: Your browser will not like this certificate, but since you trust it, you can override the browser to accept the certificate and not complain.
Save those files, we’ll use them in just a minute
Now we want to create a docker container that will use our certificate and proxy all requests to our app running on port 3000. We will use docker compose to accomplish the configuration of the container.
First, you’ll want to create a directory where you can hold the docker compose yaml file, the nginx configuration, and the ssl certificates. Mine looks like this:
.
├── docker-compose.yml
├── proxy.conf
└── ssl
├── cert.key
└── cert.pem
The docker-compose.yml
file is really pretty short. Here it is.
version: '2'
services:
nginx:
image: nginx:stable-alpine
volumes:
- ./proxy.conf:/etc/nginx/conf.d/default.conf
- ./ssl:/etc/nginx/ssl
ports:
- 443:443
As you can see:
proxy.conf
file and the ssl
folder that holds our certs.Now lets take a look at our proxy.conf
file.
server {
listen 443 ssl;
server_name localhost;
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate ssl/cert.pem;
ssl_certificate_key ssl/cert.key;
location / {
proxy_pass http://host.docker.internal:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-HTTPS 'True';
}
}
In here you’ll notice a few items of interest:
ssl/*
folder we mounted in our docker-compose.yml filehost.docker.internal:3000
, this will resolve to your localhost:3000 on your machine.Inside your folder that has the docker-compose.yml
file, all you need to do is run docker-compose up -d
. That will start your HTTPS proxy and put it in the background.
Check if it started successfully by running docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
ssltesting_nginx_1 nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 80/tcp
Now we need to tell our computer that www.example.com
is not something it should ask DNS about, but can get it’s answer right from /etc/hosts
. Just so you understand, when your browser needs to resolve an address to a domain name, it will first look in /etc/hosts
, then ask DNS.
So we just need to add this to our /etc/hosts
file.
127.0.0.1 www.example.com
This pretty easy, if you are going to be flipping this on/off I would suggest an app like Gas Mask or HostBuddy.
This is something you’ll have to figure out yourself.
Now it’s time to open the application in the browser and test the whole thing. Go ahead and open up https://www.example.com in the browser. If we’ve done everything right, we should see a warning
What the?!
![Chrome warning](/images/Screen Shot 2016-10-03 at 9.00.31 PM.png)
This is a good thing, Chrome doesn’t trust our self signed certification, so now we just tell Chrome to trust it by clicking Advanced > Proceed to www.example.com (unsafe))
If you get a 502 Bad Gateway it means that Nginx cannot reach your app on port 3000. Most likely because there is a problem with your container talking to your host. Remember I said it’s not as easy as it seems :(
So now you have a local HTTPS server that imitates a production one. It’s now possible to do any type of development locally in your app that might require an HTTPS connection, like Apple Pay for the Web.
If your company needs help implementing Apple Pay for the Web, please contact me. I contract out my services and can have your site accepting Apple Pay payments in short order.