Local HTTPS development in Python with Mkcert
About mkcert
mkcert allows you to have a local certificate authority (CA). This means that you can run your development web server using HTTPS. You'll see the green lock in your browser.
You might not need it most of the time, but more and more features require HTTPS by default in the browser, like web bluetooth, service workers, web authentication and websockets in some cases where SSL is already enabled.
Configuring mkcert
Install the dependencies for your os. In my case I'm using a Linux Debian based os.
Download the binary for your distribution from mkcert release page
Rename the file to mkcert
and give execution permissions
Install the certificate authorities (CA) using
Create certificates for the domains you'd like to use
This will create a cert.pem
and a key.pem
files in your current directory.
We are gonna use this 2 files along the post.
Python frameworks
Now that we have created the certficates for those domains, we just need to know how to tell our app to use them.
I'll assume you have a virtualenv already created.
Let's see how to do this in some different python frameworks and tools.
Uvicorn + Starlette
Update: uvicorn now has SSL support.
I've used starlette because it's simpler than writing a uvicorn App, but it's not required.
I guess this should be fairly similar for FastAPI, Bocadillo and Responder.
In your terminal run
Now create a file star_app.py
# star_app.py from starlette.applications import Starlette from starlette.responses import JSONResponse import uvicorn import ssl app = Starlette() @app.route("/") async def homepage(request): return JSONResponse({"hello": "world"}) if __name__ == "__main__": uvicorn.run( app, host="0.0.0.0", port=8433, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_OPTIONAL, ssl_keyfile="./key.pem", # Note that the generated certificates ssl_certfile="./cert.pem", # are used here )
And then just run
Go to https://0.0.0.0:8443
in your browser
Django SSL Server
django-sslserver is a small library which adds the ability to run a secure debug server with the certificates we just created.
Update your settings.py
And in your terminal run
Django extensions
There's another alternative which I haven't tested, but it has a lot of extra functionality, which I don't need, so I've skipped it.
Feel free to try django-extensions
I guess it would be something like
Flask
Install flask
Create a file flask_app.py
# flask_app.py from flask import Flask application = Flask(__name__) @application.route("/") def hello(): return "<h1 style='color:blue'>Hello There!</h1>" if __name__ == "__main__": application.run(ssl_context=('cert.pem', 'key.pem'))
Run in your terminal
Gunicorn
Install gunicorn.
Let's continue with the previous flask example
UWSGI
Install uwsgi.
Create a file called wsgi.py
# wsgi.py def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b"Hello World"]
Run in your terminal
Go to https://0.0.0.0:8443
Security concerns
DO NOT use this certificates in production. This is only for development. Use Let's Encrypt instead.
You don't need to commit the generated certificates. Looks like each machine will have to install mkcert, create and work with its own certificates.
This will only work on your local machine, where the server is running, if you want to access from a mobile device read the docs.
Conclusion
Many times, I've had the need to test something with HTTPS, but it took me a lot of time to do it.
I think mkcert
is a really easy to use tool which achieves this smoothly.
Do you have any other (security) concerns? Feedback is appreciated.
If you have drop-in examples for other frameworks or tools I'll update the post.
Thanks for reading and happy coding!
Edit: gunicorn example + uvicorn now supports ssl.