[
  {
    "path": ".dockerignore",
    "content": "LICENSE\nREADME.md\ndocker-compose.yaml\ncaddy.d\n"
  },
  {
    "path": "Caddyfile",
    "content": "import /caddy.d/*\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM alpine:3\nLABEL maintainer=\"Luis Farzati (lfarzati@gmail.com)\"\n\nARG PLUGINS=\nARG CADDYFILE=/etc/Caddyfile\nARG CADDY_D=/caddy.d\nARG STEP_CLI_VERSION=0.13.3\nARG STEP_CA_VERSION=0.13.3\nARG STEP_BINPATH=/usr/local/bin\nARG STEPPATH=/caroot\n\nENV CADDYFILE=${CADDYFILE}\nENV CADDY_D=${CADDY_D}\nENV STEPPATH=${STEPPATH}\nENV LEGO_CA_CERTIFICATES=${STEPPATH}/certs/root_ca.crt\nENV CADDY_PIDFILE=/tmp/caddy.pid\n\nEXPOSE 443\n\nRUN apk add --no-cache \\\n  ca-certificates libcap curl inotify-tools grep jq \\\n  && rm -rf /var/cache/apk/* \\\n  && curl -fsSL -o - \\\n  \"https://caddyserver.com/download/linux/amd64?plugins=${PLUGINS}&license=personal&telemetry=off\" \\\n  | tar --no-same-owner -C /usr/bin/ -xz caddy \\\n  && curl -fsSL -o - \\\n  \"https://github.com/smallstep/cli/releases/download/v${STEP_CLI_VERSION}/step_${STEP_CLI_VERSION}_linux_amd64.tar.gz\" \\\n  | tar -xz --strip-components 2 -C ${STEP_BINPATH}  \\\n  && curl -fsSL -o - \\\n  \"https://github.com/smallstep/certificates/releases/download/v${STEP_CA_VERSION}/step-certificates_${STEP_CA_VERSION}_linux_amd64.tar.gz\" \\\n  | tar -zx --strip-components 2 -C ${STEP_BINPATH} \\\n  && chmod 0755 /usr/bin/caddy \\\n  && addgroup -S caddy  \\\n  && adduser -D -S -s /sbin/nologin -G caddy caddy  \\\n  && setcap cap_net_bind_service=+ep `readlink -f /usr/bin/caddy`  \\\n  && /usr/bin/caddy -version  \\\n  && mkdir -p ${CADDY_D} ${STEPPATH}  \\\n  && chown -R caddy ${STEPPATH}\n\nCOPY Caddyfile /etc/\nCOPY start.sh /\n\nRUN chmod +x /start.sh\n\nUSER caddy\n\nENTRYPOINT [\"/start.sh\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2019 Luis Farzati\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "<img src=\"localdots.png\" height=\"56\" />\n\n![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/rnbw/localdots)\n\n## localdots — HTTPS domains for localhost\n\nInspired by https://smallstep.com/blog/step-v0-8-6-valid-https-certificates-for-dev-pre-prod/\n\n## Important/Disclaimer\n\n⚠️ **This tool installs a root CA in your system. Use it only if you know what you are doing.**\n\n### Also Important\n\nAs the title says, this tool is to be used for development. It is not meant to run at production and it hasn't been tested in CI environments either.\n\nPlease help report any issues!\n\n## Features\n\nlocaldots combines [Caddy](https://github.com/caddyserver/caddy) and [smallstep/certificates](https://github.com/smallstep/certificates) with automated configuration and hot reload.\n\n- Generates SSL/TLS certificates automatically\n- Reloads Caddy automatically with every change\n\n## Usage\n\n```yaml\n# docker-compose.yaml\n\nversion: \"3\"\n\nservices:\n  proxy:\n    image: rnbw/localdots\n    ports:\n      - 80:80 # for http->https redirection\n      - 443:443\n    volumes:\n      # contains all vhost files\n      - ./caddy.d:/caddy.d:ro\n      # contains CA config and certs\n      - ~/.caroot:/caroot\n    # only needed for *.localhost domains\n    extra_hosts:\n      - \"whoami.localhost:127.0.0.1\"\n\n  # example containers\n  whoami:\n    image: jwilder/whoami\n  hello:\n    image: nginxdemos/hello\n```\n\n```bash\n# ./caddy.d/whoami.localhost\nwhoami.localhost {\n  proxy / whoami:8000\n}\n\n# ./caddy.d/hello.dev\nhello.dev {\n  proxy / hello\n}\n```\n\n```bash\n# run all the things\ndocker-compose up -d\n\n# add the domains to your /etc/hosts file\n# *.localhost domains shouldn't need to be added for typical use cases\n127.0.0.1  hello.dev\n\n# after localdots container is up and running,\n# you will see a .caroot directory in your $HOME.\nbrew install step \\\n    && step certificate install ~/.caroot/certs/root_ca.crt\n\n# that's it, try open the sites configured above\nopen https://whoami.localhost\nopen https://hello.dev\n```\n\n## About domains\n\n### Using special TLDs\n\nWhen picking a TLD for local development, you can use one of the special domain names suggested in [RFC6761](https://tools.ietf.org/html/rfc6761), such as `test` or `localhost`.\n\n`localhost` has, [by spec](https://tools.ietf.org/html/rfc6761#section-6.3), the following particularities:\n\n```\n1.  Users are free to use localhost names as they would any other\n    domain names.  Users may assume that IPv4 and IPv6 address\n    queries for localhost names will always resolve to the respective\n    IP loopback address.\n\n2.  Application software MAY recognize localhost names as special, or\n    MAY pass them to name resolution APIs as they would for other\n    domain names.\n\n3.  Name resolution APIs and libraries SHOULD recognize localhost\n    names as special and SHOULD always return the IP loopback address\n    for address queries and negative responses for all other query\n    types.  Name resolution APIs SHOULD NOT send queries for\n    localhost names to their configured caching DNS server(s).\n```\n\nHowever, if you expect `anything.localhost` to be resolved to 127.0.0.1 automatically, that might not work. For example, you can open it in Chrome and the browser will resolve it fine. But if you ping it or curl it, you'll get an error unless you add the record in your hosts file.\n\nSee https://tools.ietf.org/html/draft-west-let-localhost-be-localhost-06.\n\n### Using any TLD\n\nUsing any of the domains above, you can be sure you won't run into any conflicts. But other than that, there's no reason why you cannot use any other \"registrable\" domain. There are [~1600 possible TLDs](https://www.iana.org/domains/root/db) you can choose from, or even invent your own!\n\nWhile this can be seen as bad practice, I leave it to you. Personally I've seen several companies or dev teams using `xyz`, `wtf`, `lol`, `dev`, `net`, `host`, or even custom ones (i.e. not in the list) such as using the company name or team.\n\nIn my opinion, as long as you 1- know what you are doing, 2- don't shadow an existing domain that you or someone in your team uses (e.g. don't use `gmail.com`...) and 3- keep it scoped to your local development environment, then just use whatever works for you.\n\nAs with special domains, remember to add the necessary entries in your hosts file. Alternatively in this case, if you own the domain then you can always add the record in your DNS.\n\n## Contributing\nBugfixes, improvements, proposals are gladly welcome!\n"
  },
  {
    "path": "caddy.d/hello.dev.example",
    "content": "hello.dev {\n  proxy / hello\n}\n"
  },
  {
    "path": "caddy.d/whoami.localhost",
    "content": "whoami.localhost {\n  proxy / whoami:8000\n}\n"
  },
  {
    "path": "docker-compose.yaml",
    "content": "version: \"3\"\n\nservices:\n  proxy:\n    image: rnbw/localdots\n    ports:\n      - 80:80 # for http->https redirection\n      - 443:443\n    volumes:\n      # contains all vhost files\n      - ./caddy.d:/caddy.d:ro\n      # contains CA config and certs\n      - ~/.caroot:/caroot\n\n  # example containers\n  whoami:\n    image: jwilder/whoami\n  hello:\n    image: nginxdemos/hello\n"
  },
  {
    "path": "start.sh",
    "content": "#!/bin/sh\n\nreload_caddy() {\n  if [ -f $CADDY_PIDFILE ]; then\n    kill -SIGUSR1 $(cat $CADDY_PIDFILE)\n  else\n    PROVISIONER=$(cat $STEPPATH/config/ca.json | jq -r \".authority.provisioners[0].name\")\n    LEGO_CA_CERTIFICATES=$STEPPATH/certs/root_ca.crt /usr/bin/caddy \\\n      --conf $CADDYFILE \\\n      --log stdout \\\n      -ca https://localhost:8443/acme/acme/directory \\\n      -email $PROVISIONER \\\n      -disable-tls-alpn-challenge \\\n      -pidfile $CADDY_PIDFILE &\n  fi\n}\n\n# First-time CA configuration\nif [ ! -f $STEPPATH/config/ca.json ]; then\n  echo \"$STEPPATH/config/ca.json not found; creating new CA\"\n\n  PROVISIONER=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)@localdots.example\n  PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \\\n    && echo $PASSWORD > /tmp/password \\\n    && step ca init \\\n      --name=localdots \\\n      --dns=localhost \\\n      --address=127.0.0.1:8443 \\\n      --provisioner=$PROVISIONER \\\n      --password-file=/tmp/password \\\n    && mv /tmp/password $STEPPATH/secrets/password \\\n    && step ca provisioner add acme --type ACME\nfi\n\n# Starts ACME server and Caddy\nstep-ca --password-file $STEPPATH/secrets/password $STEPPATH/config/ca.json &\nsleep 1\nrm -f $CADDY_PIDFILE\nreload_caddy\n\n# Caddy configuration watcher\ninotifywait -e \"create,delete,modify,move\" --monitor $CADDY_D --monitor $CADDYFILE | \\\n  while read -r notifies;\n  do\n    echo\n    echo \"$notifies\"\n    reload_caddy\n  done\n"
  }
]