[webvr] Let's talk about HTTPS

Chris Palmer palmer at google.com
Thu Jul 14 22:30:21 UTC 2016

> On Thursday, July 14, 2016, Beau Cronin <beau.cronin at gmail.com> wrote:
>>> I mostly lurk on this list, but probably time to briefly put in my two
>>> cents.
>>> Many people, myself included, are trying to find a way to get into VR
>>> development without (yet?!?) being paid - ie., side projects. For these
>>> kinds of projects, 1) _every hour counts_, and 2) being able to demo for
>>> people with minimal headache is super important - I'm basically begging for
>>> feedback, and there are enough hurdles in place already thankyouverymuch.
>>> So I'd like to strongly endorse the arguments of the much more
>>> web-knowledgeable folks who are arguing for solutions that don't impose
>>> additional burdens on tinkering, hacking, learning, experimenting, and
>>> growing. We must preserve the ability of a SINGLE PERSON to accomplish as
>>> much as possible by his- or herself. Please don't tell me what the BBC is
>>> doing. And localhost is not enough.
I agree that it should be as easy as possible, and that one person should
be able to develop as much as possible.

Let's say for example that you want to develop a VR app on your laptop, and
then to view it from your Android phone or other VR headset using the
laptop as the server, over your home wifi. Let's assume that your
application is some HTML, CSS, and JavaScript files, and the JS calls into
APIs that require a secure origin.

Here is how to do that.

1. Set up some HTTPS web server on your laptop. Apache, nginx, Caddy, or
even a snippet of Go (see below for code).
2. Create a self-signed X.509 certificate with the openssl command line
tool (see below for an example).
3. Configure the server to use the self-signed certificate and serve your
HTML, CSS, and JS files.
4. Figure out your laptop's IP address (using e.g. the ifconfig command on
macOS or Linux, or ipconfig on Windows).
5. On your phone/headset, use Chrome to browse to or
whatever URL is appropriate for your situation.
6. Chrome will warn you that the certificate is self-signed. Tap Advanced,
then Proceed to Chrome will proceed, and will remember your
decision to accept the risk for 7 days, and won't bother you again until
day 8. Firefox can also be convinced to let you click through the warning
interstitial, and will also remember the decision.

(The reasoning for the 7-day memory policy is explained in depth here:

If you want to serve your app to your friends or to people not on your
wifi, you can set up either a free AppEngine instance or use GitHub Pages
(also free). Both take about 15 minutes to set up, and both use HTTPS by
default. I went from 0 to HTTPS on AppEngine this morning, just to make
sure it was as easy as it should be. (I don't know about GitHub Pages, but
you can also use HTTPS with custom domains on AppEngine.)

OK, now for some code.

*cert.sh: Shell Script To Generate A Key And Certificate*

openssl genrsa -out server.key 2048
openssl req -new -x509 -sha256 -key server.key -out server.pem -days 365

*server.go: Go Program To Serve Files In The Current Directory Via HTTPS*

This, https://gist.github.com/denji/12b3a568f092ab951456, is the 2nd hit on
Google for [ go https server ]. I have adapted the code somewhat to work
slightly better for our needs.

package main

import (

func HelloServer(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "hello, world!\n")

func main() {
http.HandleFunc("/hello", HelloServer)
http.Handle("/", http.FileServer(http.Dir(".")))
err := http.ListenAndServeTLS(":8443", "server.pem", "server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)

*run.sh: Shell Script To Run Everything*

if test ! -f server.pem -o ! -f server.key; then
  echo "You need to create a key and certificate. Here goes:"
echo "Your IP addresses are:"
ifconfig -a
echo "Starting the web server now:"
go run server.go

*gum.html: HTML/JS To Show That A Secure-Only Feature Works With This Setup*

(borrowed directly from

<video id="video"></video>
navigator.getUserMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||

if (navigator.getUserMedia) {
   navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720
} },
      function(stream) {
         var video = document.querySelector('video');
         video.src = window.URL.createObjectURL(stream);
         video.onloadedmetadata = function(e) {
      function(err) {
         console.log("The following error occurred: " + err.name);
} else {
   console.log("getUserMedia not supported");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/web-vr-discuss/attachments/20160714/80dc03c8/attachment.html>

More information about the web-vr-discuss mailing list