diff --git a/Documentation/kubernetes.md b/Documentation/kubernetes.md
new file mode 100644
index 0000000000000000000000000000000000000000..836001abdbbb5235afaeb0093b6d423a7386b568
--- /dev/null
+++ b/Documentation/kubernetes.md
@@ -0,0 +1,116 @@
+# Kubernetes authentication through dex
+
+## Overview
+
+This document covers setting up the [Kubernetes OpenID Connect token authenticator plugin][k8s-oidc] with dex.
+
+Token responses from OpenID Connect providers include a signed JWT called an ID Token. ID Tokens contain names, emails, unique identifiers, and in dex's case, a set of groups that can be used to identify the user. OpenID Connect providers, like dex, publish public keys; the Kubernetes API server understands how to use these to verify ID Tokens.
+
+The authentication flow looks like:
+
+1. OAuth2 client logs a user in through dex.
+2. That client uses the returned ID Token as a bearer token when talking to the Kubernetes API.
+3. Kubernetes uses dex's public keys to verify the ID Token.
+4. A claim designated as the username (and optionally group information) will be associated with that request.
+
+Username and group information can be combined with Kubernetes [authorization plugins][k8s-authz], such as roles based access control (RBAC), to enforce policy.
+
+## Configuring the OpenID Connect plugin
+
+Configuring the API server to use the OpenID Connect [authentcation plugin][k8s-oidc] requires:
+
+* Deploying an API server with specific flags.
+* Dex is running on HTTPS.
+  * Custom CA files must be accessible by the API server (likely through volume mounts).
+* Dex is accessible to both your browser and the Kubernetes API server.
+
+Use the following flags to point your API server(s) at dex. `dex.example.com` should be replaced by whatever DNS name or IP address dex is running under.
+
+```
+--oidc-issuer-url=https://dex.example.com:32000
+--oidc-client-id=example-app
+--oidc-ca-file=/etc/kubernetes/ssl/openid-ca.pem
+--oidc-username-claim=email
+--oidc-groups-claim=groups
+```
+
+Additional notes:
+
+* The API server configured with OpenID Connect flags doesn't require dex to be available upfront.
+  * Other authenticators, such as client certs, can still be used.
+  * Dex doesn't need to be running when you start your API server.
+* Kubernetes only trusts ID Tokens issued to a single client.
+  * As a work around dex allows clients to [trust other clients][trusted-peers] to mint tokens on their behalf.
+* If a claim other than "email" is used for username, for example "sub", it will be prefixed by `"(value of --oidc-issuer-url)#"`. This is to namespace user controlled claims which may be used for privilege escalation.
+
+## Deploying dex on Kubernetes
+
+The dex repo contains scripts for running dex on a Kubernetes cluster with authentication through GitHub. The dex service is exposed using a [node port][node-port] on port 32000. This likely requires a custom `/etc/hosts` entry pointed at one of the cluster's workers.
+
+There are many different ways to spin up a Kubernetes development cluster, each with different host requirements and support for API server reconfiguration. At this time, this guide does not have copy-pastable examples, but can recommend the following methods for spinning up a cluster:
+
+* [coreos-kubernetes][coreos-kubernetes] repo for vagrant and VirtualBox users.
+* [coreos-baremetal][coreos-baremetal] repo for Linux QEMU/KVM users.
+
+To run dex on Kubernetes perform the following steps:
+
+1. Generate TLS assets for dex.
+2. Spin up a Kubernetes cluster with the appropriate flags and CA volume mount.
+3. Create a secret containing your [GitHub OAuth2 client credentials][github-oauth2].
+4. Deploy dex.
+
+The TLS assets can be created using the following command:
+
+```
+$ cd examles/k8s
+$ ./gencert.sh
+```
+
+The created `ssl/ca.pem` must then be mounted into your API server deployment. Once the cluster is up and correctly configured, use kubectl to add the serving certs as secrets.
+
+```
+$ kubectl create secret tls dex.example.com.tls --cert=ssl/cert.pem --key=ssl/key.pem
+```
+
+Then create a secret for the GitHub OAuth2 client.
+
+```
+$ kubectl create secret \
+    generic github-client \
+    --from-literal=client-id=$GITHUB_CLIENT_ID \
+    --from-literal=client-secret=$GITHUB_CLIENT_SECRET
+```
+
+Finally, create the dex deployment, configmap, and node port service.
+
+```
+$ kubectl create -f dex.yaml
+```
+
+__Caveats:__ No health checking is configured because dex does its own TLS termination complicating the setup. This is a known issue and can be tracked [here][dex-healthz].
+
+## Logging into the cluster
+
+The example app can be used to log into the cluster. Choose the GitHub option and grant access to dex to view your profile.
+
+```
+$ ./bin/example-app --issuer https://dex.example.com:32000 --issuer-root-ca examples/k8s/ssl/ca.pem
+```
+
+The printed ID Token can then be used as a bearer token to authenticate against the API server.
+
+```
+$ token='(id token)'
+$ curl -H "Authorization: Bearer $token" -k https://( API server host ):443/api/v1/nodes
+```
+
+[k8s-authz]: http://kubernetes.io/docs/admin/authorization/
+[k8s-oidc]: http://kubernetes.io/docs/admin/authentication/#openid-connect-tokens
+[trusted-peers]: https://godoc.org/github.com/coreos/dex/storage#Client
+[coreos-kubernetes]: https://github.com/coreos/coreos-kubernetes/
+[coreos-baremetal]: https://github.com/coreos/coreos-baremetal/
+[dex-healthz]: https://github.com/coreos/dex/issues/682
+[github-oauth2]: https://github.com/settings/applications/new
+[node-port]: http://kubernetes.io/docs/user-guide/services/#type-nodeport 
+[coreos-kubernetes]: https://github.com/coreos/coreos-kubernetes
+[coreos-baremetal]: https://github.com/coreos/coreos-baremetal
diff --git a/examples/k8s/README.md b/examples/k8s/README.md
deleted file mode 100644
index 1b195199d8d1ff2afe978869de06c4bb30eef62f..0000000000000000000000000000000000000000
--- a/examples/k8s/README.md
+++ /dev/null
@@ -1,124 +0,0 @@
-# Running dex as the Kubernetes authenticator
-
-Running dex as the Kubernetes authenticator requires.
-
-* dex is running on HTTPS.
-* Your browser can navigate to dex at the same address Kubernetes refers to it as.
-
-To accomplish this locally, these scripts assume you're using the single host
-vagrant setup provided by the [coreos-kubernetes](
-https://github.com/coreos/coreos-kubernetes) repo with a couple of changes (a
-complete diff is provided at the bottom of this document). Namely that:
-
-* The API server isn't running on host port 443.
-* The virtual machine has a populated `/etc/hosts`
-
-The following entry must be added to your host's `/etc/hosts` file as well as
-the VM. 
-
-```
-172.17.4.99        dex.example.com
-```
-
-In the future this document will provide instructions for a more general
-Kubernetes installation.
-
-Once you have Kubernetes configured, set up the ThirdPartyResources and a
-ConfigMap for dex to use. These run dex as a deployment with configuration and
-storage, allowing it to get started. 
-
-```
-kubectl create configmap dex-config --from-file=config.yaml=config-k8s.yaml
-kubectl create -f deployment.yaml
-```
-
-To get dex running at an HTTPS endpoint, create an ingress controller, some
-self-signed TLS assets and an ingress rule for dex. These TLS assest should
-normally be provided by an actual CA (public or internal).
-
-```
-kubectl create -f https://raw.githubusercontent.com/kubernetes/contrib/master/ingress/controllers/nginx/rc.yaml
-./gencert.sh
-kubectl create secret tls dex.example.com.tls --cert=ssl/cert.pem --key=ssl/key.pem
-kubectl create -f dex-ingress.yaml
-```
-
-To test that the everything has been installed correctly. Configure a client
-with some credentials, and run the `example-app` (run `make` at the top level
-of this repo if you haven't already). The second command will error out if your
-example-app can't find dex.
-
-```
-kubectl create -f client.yaml
-../../bin/example-app --issuer https://dex.example.com --issuer-root-ca ssl/ca.pem
-```
-
-Navigate to `127.0.0.1:5555` and try to login. You should be redirected to
-`dex.example.com` with lots of TLS errors. Proceed around them, authorize the
-`example-app`'s OAuth2 client and you should be redirected back to the
-`example-app` with valid OpenID Connect credentials.
-
-Finally, to configure Kubernetes to use dex as its authenticator, copy
-`ssl/ca.pem` to `/etc/kubernetes/ssl/openid-ca.pem` onto the VM and update the
-API server's manifest at `/etc/kubernetes/manifests/kube-apiserver.yaml` to add
-the following flags.
-
-```
---oidc-issuer-url=https://dex.example.com
---oidc-client-id=example-app
---oidc-ca-file=/etc/kubernetes/ssl/openid-ca.pem
---oidc-username-claim=email
---oidc-groups-claim=groups
-```
-
-Kick the API server by killing its Docker container, and when it comes up again
-it should be using dex. Login again through the `example-app` and you should be
-able to use the provided token as a bearer token to hit the Kubernetes API.
-
-## Changes to coreos-kubernetes
-
-The following is a diff to the [coreos-kubernetes](https://github.com/coreos/coreos-kubernetes)
-repo that accomplishes the required changes.
-
-```diff
-diff --git a/single-node/user-data b/single-node/user-data
-index f419f09..ed42055 100644
---- a/single-node/user-data
-+++ b/single-node/user-data
-@@ -80,6 +80,15 @@ function init_flannel {
- }
- 
- function init_templates {
-+    local TEMPLATE=/etc/hosts
-+    if [ ! -f $TEMPLATE ]; then
-+        echo "TEMPLATE: $TEMPLATE"
-+        mkdir -p $(dirname $TEMPLATE)
-+        cat << EOF > $TEMPLATE
-+172.17.4.99		dex.example.com
-+EOF
-+    fi
-+
-     local TEMPLATE=/etc/systemd/system/kubelet.service
-     if [ ! -f $TEMPLATE ]; then
-         echo "TEMPLATE: $TEMPLATE"
-@@ -195,7 +204,7 @@ spec:
-     - --etcd-servers=${ETCD_ENDPOINTS}
-     - --allow-privileged=true
-     - --service-cluster-ip-range=${SERVICE_IP_RANGE}
--    - --secure-port=443
-+    - --secure-port=8443
-     - --advertise-address=${ADVERTISE_IP}
-     - --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota
-     - --tls-cert-file=/etc/kubernetes/ssl/apiserver.pem
-@@ -211,8 +220,8 @@ spec:
-       initialDelaySeconds: 15
-       timeoutSeconds: 15
-     ports:
--    - containerPort: 443
--      hostPort: 443
-+    - containerPort: 8443
-+      hostPort: 8443
-       name: https
-     - containerPort: 8080
-       hostPort: 8080
-```
diff --git a/examples/k8s/client.yaml b/examples/k8s/client.yaml
deleted file mode 100644
index b294c6f9cfce86245432a5211d3f559de69fe720..0000000000000000000000000000000000000000
--- a/examples/k8s/client.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-kind: OAuth2Client
-apiVersion: oauth2clients.oidc.coreos.com/v1
-metadata:
-  name: example-app
-  namespace: default
-
-secret: ZXhhbXBsZS1hcHAtc2VjcmV0
-redirectURIs:
-- http://127.0.0.1:5555/callback
-name: Example App
diff --git a/examples/k8s/config-k8s.yaml b/examples/k8s/config-k8s.yaml
deleted file mode 100644
index a27200164d8449474334535d3e057a9ee02ae465..0000000000000000000000000000000000000000
--- a/examples/k8s/config-k8s.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-issuer: https://dex.example.com
-storage:
-  type: kubernetes
-  config:
-    inCluster: true
-
-web:
-  http: 0.0.0.0:5556
-
-connectors:
-- type: mock
-  id: mock
-  name: Mock
diff --git a/examples/k8s/deployment.yaml b/examples/k8s/deployment.yaml
deleted file mode 100644
index ed1338bd6e7633d6898497c5b28d911fd6b48204..0000000000000000000000000000000000000000
--- a/examples/k8s/deployment.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  labels:
-    app: dex
-  name: dex
-spec:
-  replicas: 1
-  template:
-    metadata:
-      labels:
-        app: dex
-    spec:
-      containers:
-      - image: quay.io/ericchiang/dex
-        name: dex
-        command:
-        - "/dex"
-        - "serve"
-        - "/dex/config.yaml"
-        env:
-        # A value required for dex's Kubernetes client.
-        - name: KUBERNETES_POD_NAMESPACE
-          valueFrom:
-            fieldRef:
-              fieldPath: metadata.namespace
-
-        ports:
-        - containerPort: 5556
-          name: worker-port
-
-        volumeMounts:
-        - name: config-volume
-          mountPath: /dex
-      volumes:
-      - name: config-volume
-        configMap:
-          name: dex-config
diff --git a/examples/k8s/dex-ingress.yaml b/examples/k8s/dex-ingress.yaml
deleted file mode 100644
index 1c52fb09d22ef3e3680fd41fcd1905b86e30d079..0000000000000000000000000000000000000000
--- a/examples/k8s/dex-ingress.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: dex
-spec:
-  ports:
-    - name: dex
-      port: 5556
-  selector:
-    app: dex
----
-apiVersion: extensions/v1beta1
-kind: Ingress
-metadata:
-  name: dex
-spec:
-  tls:
-  - secretName: dex.example.com.tls
-    hosts:
-    - dex.example.com
-  rules:
-  - host: dex.example.com
-    http:
-      paths:
-      - backend:
-          serviceName: dex
-          servicePort: 5556
-        path: /
diff --git a/examples/k8s/dex.yaml b/examples/k8s/dex.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..01fdab9ea7e55e11810fbcddfe9746aebef686c3
--- /dev/null
+++ b/examples/k8s/dex.yaml
@@ -0,0 +1,106 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  labels:
+    app: dex
+  name: dex
+spec:
+  replicas: 3
+  template:
+    metadata:
+      labels:
+        app: dex
+    spec:
+      containers:
+      - image: quay.io/coreos/dex:v2.0.0-beta.1
+        name: dex
+        command: ["/usr/local/bin/dex", "serve", "/etc/dex/cfg/config.yaml"]
+
+        ports:
+        - name: https
+          containerPort: 5556
+
+        volumeMounts:
+        - name: config
+          mountPath: /etc/dex/cfg
+        - name: tls
+          mountPath: /etc/dex/tls
+
+        env:
+        - name: GITHUB_CLIENT_ID
+          valueFrom:
+            secretKeyRef:
+              name: github-client
+              key: client-id
+        - name: GITHUB_CLIENT_SECRET
+          valueFrom:
+            secretKeyRef:
+              name: github-client
+              key: client-secret
+      volumes:
+      - name: config
+        configMap:
+          name: dex
+          items:
+          - key: config.yaml
+            path: config.yaml
+      - name: tls
+        secret:
+          secretName: dex.example.com.tls
+---
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: dex
+data:
+  config.yaml: |
+    issuer: https://dex.example.com:32000
+    storage:
+      type: kubernetes
+      config:
+        inCluster: true
+    web:
+      https: 0.0.0.0:5556
+      tlsCert: /etc/dex/tls/tls.crt
+      tlsKey: /etc/dex/tls/tls.key
+    connectors:
+    - type: github
+      id: github
+      name: GitHub
+      config:
+        clientID: $GITHUB_CLIENT_ID
+        clientSecret: $GITHUB_CLIENT_SECRET
+        redirectURI: https://dex.example.com:32000/callback
+        org: kubernetes
+    oauth2:
+      skipApprovalScreen: true
+
+    staticClients:
+    - id: example-app
+      redirectURIs:
+      - 'http://127.0.0.1:5555/callback'
+      name: 'Example App'
+      secret: ZXhhbXBsZS1hcHAtc2VjcmV0
+
+    enablePasswordDB: true
+    staticPasswords:
+    - email: "admin@example.com"
+      # bcrypt hash of the string "password"
+      hash: "$2a$10$33EMT0cVYVlPy6WAMCLsceLYjWhuHpbz5yuZxu/GAFj03J9Lytjuy"
+      username: "admin"
+      userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: dex
+spec:
+  type: NodePort
+  ports:
+  - name: dex
+    port: 5556
+    protocol: TCP
+    targetPort: 5556
+    nodePort: 32000
+  selector:
+    app: dex
diff --git a/examples/k8s/nginx-ingress.yaml b/examples/k8s/nginx-ingress.yaml
deleted file mode 100644
index 9740ff5a6ee873a99bc2abc4431f7971503f416d..0000000000000000000000000000000000000000
--- a/examples/k8s/nginx-ingress.yaml
+++ /dev/null
@@ -1,100 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: default-http-backend
-  labels:
-    k8s-app: default-http-backend
-spec:
-  ports:
-  - port: 80
-    targetPort: 8080
-    protocol: TCP
-    name: http
-  selector:
-    k8s-app: default-http-backend
----
-apiVersion: v1
-kind: ReplicationController
-metadata:
-  name: default-http-backend
-spec:
-  replicas: 1
-  selector:
-    k8s-app: default-http-backend
-  template:
-    metadata:
-      labels:
-        k8s-app: default-http-backend
-    spec:
-      terminationGracePeriodSeconds: 60
-      containers:
-      - name: default-http-backend
-        # Any image is permissable as long as:
-        # 1. It serves a 404 page at /
-        # 2. It serves 200 on a /healthz endpoint
-        image: gcr.io/google_containers/defaultbackend:1.0
-        livenessProbe:
-          httpGet:
-            path: /healthz
-            port: 8080
-            scheme: HTTP
-          initialDelaySeconds: 30
-          timeoutSeconds: 5
-        ports:
-        - containerPort: 8080
-        resources:
-          limits:
-            cpu: 10m
-            memory: 20Mi
-          requests:
-            cpu: 10m
-            memory: 20Mi
----
-apiVersion: extensions/v1beta1
-kind: DaemonSet
-metadata:
-  name: nginx-ingress-controller
-  labels:
-    k8s-app: nginx-ingress-lb
-spec:
-  replicas: 1
-  selector:
-    web-frontend
-  template:
-    metadata:
-      labels:
-        k8s-app: nginx-ingress-lb
-        name: nginx-ingress-lb
-    spec:
-      terminationGracePeriodSeconds: 60
-      containers:
-      - image: gcr.io/google_containers/nginx-ingress-controller:0.8.2
-        name: nginx-ingress-lb
-        imagePullPolicy: Always
-        livenessProbe:
-          httpGet:
-            path: /healthz
-            port: 10249
-            scheme: HTTP
-          initialDelaySeconds: 30
-          timeoutSeconds: 5
-        # use downward API
-        env:
-          - name: POD_NAME
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.name
-          - name: POD_NAMESPACE
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.namespace
-        ports:
-        - containerPort: 443
-          hostPort: 443
-        # we expose 18080 to access nginx stats in url /nginx-status
-        # this is optional
-        - containerPort: 18080
-          hostPort: 18080
-        args:
-        - /nginx-ingress-controller
-        - --default-backend-service=default/default-http-backend