Generating SSL Certs for Customer Domains and integrating with Python Flask
I guess the easier way will be using Nginx container in front of python app. Because of you can just re-read Nginx config without restarting server.
I didn't work with Dokku, so try to explain how to create infrastructure simply with docker.
- You have global IP (for example
1.1.1.1
) on your router that forwarding80
and443
port to internal server IP ( let it be192.168.1.100
). global80
to local8080
and global443
to local8443
. - You have Nginx container that listening
192.168.1.100:8080
and192.168.1.100:8443
and proxying all requests from8443
to127.0.0.1:8888
by HTTP protocol - You have application container that listening
127.0.0.1:8888
and accessible only from local server
Workflow will be:
- Customer register DNS A record:
customer.domain.com A 1.1.1.1
and pointing it to your server - Customer adds domain to your DB using some control web page (depends on your service)
- New record in DB starts worker container by some trigger
- Worker container starts to check is domain exists by using some
nslookup
tool - If domain registered, worker starts let's encrypt script and issues new certificate (by adding
.well-known/acme-challenge
file to Nginx html folder) - if certificate is successfully issued, worker adds new config file into Nginx container (the better way will be mount config directory from docker host) and reload Nginx configuration
- Profit
If you need to use your own DNS server, You must to do it controllable programmatically using some API to be able add DNS A records by worker. (Good news! in this case you can use Let's Encrypt's DNS challenge by adding acme-challenge code as DNS TXT (or maybe CNAME?) record instead of Nginx .well-known
directory)
Actually realization is deeply depends on infrastructure that you have. And that is really big task and depends on many details. So it hard to answer better without knowing it.
Your solutions is a wildcard certificate, or use app prefixing.
So I'm not sure why you need a cert per customer, but let's say you are going to do
customer1.myapp.com
-> routes to customer1 backend. For whatever reason.
Let's Encrypt lets you register *.myapp.com and therefore you can use subdomains for each customer.
The alternative is a customer prefix.
Say your app URL looks like www.myapp.com/api/v1/somecomand
you could use www.myapp.com/api/v1/customerID/somecommand
and then allow your load balancer to route based on the prefix and use a rewrite rule to remove the customerID back to the original URL.
This is more complicated, and it is load balancer dependent but so is the first solution.
All this being said, both solutions would most likely require a separate instance of your application per customer, which is a heavy solution, but fine if that's what you want and are using lightweight containers or deploying multiple instances per server.
Anyway, a lot more information would be needed to give a solid solution.