Back to list of posts

Supporting Local Development

Posted Jan 27, 2021 by Michael Irwin

To better support local development, DevCom provides a few services and tools.

A global name that resolves locally

Often, when working locally, we need to use a hostname that is not localhost. To support these use cases, *.localhost.devcom.vt.edu has been configured to resolve locally, for both IPv4 and IPv6. You are welcome to use these names for any local development.

> dig localhost.devcom.vt.edu
;; ANSWER SECTION:
localhost.devcom.vt.edu. 86400	IN	A	127.0.0.1

> dig anything.localhost.devcom.vt.edu
;; ANSWER SECTION:
anything.localhost.devcom.vt.edu. 86400	IN A	127.0.0.1

> dig localhost.devcom.vt.edu AAAA
;; ANSWER SECTION:
localhost.devcom.vt.edu. 86400	IN	AAAA	::1

> dig anything.localhost.devcom.vt.edu AAAA
;; ANSWER SECTION:
anything.localhost.devcom.vt.edu. 86400	IN AAAA	::1

Why use these names?

Great question! There are several reasons, but here are a few to highlight:

  • Automatic VT Login support - if your app needs to authenticate users using VT Login, no registration is required as all *.vt.edu services are automatically authorized.
  • No need for custom /etc/hosts entries - many teams/developers create their own names and point them locally using custom host records. Now, no more machine-specific config is needed!
  • No need for a custom name and static IP (for dev) - a few developers had their own DNS name with a static IP associated with it. While this works, it also requires the ability to get that static IP, which is impossible when working remotely or using another machine. Granted, this does make it easier to support remote login or to let someone quickly check out something you’re working on.
  • A single name the entire team can share - using these names, you can easily create a project README with links that will work for everyone on the team

Signed/Trusted Certs for Local Development

The devcom/devcom-localhost-proxy repo contains a /cert directory that has a signed/trusted cert issued by LetsEncrypt for the *.localhost.devcom.vt.edu names.

Note: in most cases, you will want to use a localhost proxy, rather than using the cert directly. But, it’s available if you need it.

Why use HTTPS during local development?

Beyond simply saying “use HTTPS everywhere”, there are a few specific reasons to use HTTPS during local development:

  • Some libraries will require it - as an example, if you run a mock CAS server (details below), it must be behind HTTPS because all CAS client libraries require a HTTPS connection when validating the CAS ticket. While you can use a self-signed cert, you would then have to configure the CAS library with the CA or tell it to ignore the certificate (not recommended)
  • It more closely aligns with production - most of our prod environments have load balancers or other reverse proxies sitting in front of our apps, who are performing TLS termination. But doing this locally (possibly by a proxy below), we can validate our apps are configured to require a TLS connection, use the correct headers for redirects, etc.

Localhost Proxies

To enable the easier usage of the TLS certificates, we additionally provide container images that are already configured to use the certs. By simply starting the container, you can have a smart proxy ready to send traffic to other containers. This is a simple wrapper around Traefik, so will listen for other containers.

A quick Docker example

After running the following command, you will have the proxy up and running on your machine! We mount the Docker socket in so Traefik can watch for container events and update its routing configuration accordingly.

docker run -d \
    -p 80:80 -p 443:443 \
    -v /var/run/docker.sock:/var/run/docker.sock 
    dtr.it.vt.edu/devcom/devcom-localhost-proxy:traefik-2.3

Now, we can start another app behind the proxy. While this is a static website, it could be any other container of your choice, including a development container!

docker run -d \
    --label 'traefik.http.routers.app.rule=Host(`app.localhost.devcom.vt.edu`)' \
    nginx:alpine

With this command, you should be able to open https://app.localhost.devcom.vt.edu and see the nginx welcome page! How? What happened? Here’s what happened…

  1. When the container nginx started, Traefik (the proxy) saw the container start, looked at its labels, and updated its configuration to send requests with a hostname of app.localhost.devcom.vt.edu to the container.
  2. When the browser opened app.localhost.devcom.vt.edu, it connected to port 443 on the local machine, which is the proxy.
  3. The proxy received the request and used its configuration to find the correct target. The nginx container was chosen, so forwarded the request to it.

Labels to Know

While you can specify many configuration points using Docker labels, the following are going to be the most important to know:

  • traefik.http.routers.<app-name>.rule - the routing rule that must be satisfied in order for traffic to be sent to this container. To view all supported rules, head to the Traefik router rules documentation
  • traefik.http.services.<app-name>.loadbalancer.server.port - the container port that the proxy should send traffic to. This defaults to 80 if not defined.