Releases: AaronMcHale/web-router
Release 0.1: the first experimental release of web-router
I am please to share the first experimental release of web-router!
This is an experimental release, web-router is still in active development, breaking changes may be made between releases, as such there are no guarantees about backwards combability.
This first early release is exciting because it sets the architectural groundwork for future development releases. I started with a simple mission, to make my Traefik configs public, along with the various supporting services. The "supporting services" part is important, my ultimate goal here is to streamline the process of hosting applications, and reduce repeating services. What I mean by that is, through self-hosting my own Docker-based projects, I've learnt that the more environment specific logic which can be abstracted away, that less boilerplate and complexity each application needs.
My objectives for web-router
As of right now, these are in the README, but as this project continues to be built out, the README will evolve. So I'm adding these here, so that they don't get lost.
- Using environment variables to configure things.
- Creating a logical separation of concerns, splitting up each service into its own folder.
- Security by design, you shall not run as root!
- Add automated tests for everything (or at least try to)!
- Use this on production, but also for local development. That means I'll be adding things like, being able to swap between Let's Encrypt and mkcert depending on the environment.
- The actual applications that I'm hosting should not need any modifications depending on the environment. For example, I'm going to add an SMTP server, which means something like Postfix will be used on production, but for local development something like Mailhog, so that outgoing mail is captured. This should be totally transparent to the applications being ran, in other words the SMTP host and credentials should be the same.
- Similarly, this repository will provide services, like SMTP, so that each application doesn't have to, streamlining things and reducing boilerplate code/config in every application.
The 0.1 release
So, with that all in mind, what's in the 0.1 release
The service loader
The service loader is the foundation for how web-router works, it allows for dynamically loading services per-environment. Services are folders, which live under the /services directory.
A service folder may contain:
- One or more
docker-compose.ymlfiles. - Scripts for loading a service, mainly a
defaults.env.shand aenv.sh. - All resources needed to run the service.
The service loader in the top-level env.sh script looks for each of these at the top level of each service folder.
You can read more about how services work in the README in the services directory.
The env.sh script
Speaking of env.sh, this is a concept I've used across projects, the env .sh script is designed to be sourced, it's main purpose is to load environment variables, but it also contains the service loader.
Before running any docker commands in web-router, you must first sourced env.sh. It not only loads environment variables, but also sources the defaults.env.sh script of each services, and the env.sh script of each enabled service.
Services can be enabled and disabled
This is such a key part of what makes web-router work that I wanted to highlight it. Using environment variables, services can be enabled and disabled, some services may be enabled by default, for example Traefik, but most will be disabled by default.
This makes web-router a really powerful tool for building environment-specific services.
Traefik, the first service
This initial relase also adds the Traefik service, although only in a minimal state.
The Traefik service has http and https entrypoints, which are setup by default on all routes. Technically speaking, only the https (websecure) entrypoint is, the http (web) entrypoint is a wildcard redirect to websecure. However, the nice thing about this approach is that using web-router with other applications means that those applications do not need to specify entrypoints, the entrypoints will be setup automatically.
To illustrait why this is so useful, the following docker-compose.yml is all that is needed to setup a nginx container and make it accessible over http and https through Traefik:
# docker-compose.yml
networks:
web-router:
external: true
services:
nginx:
image: nginx
networks: [ web-router ]
labels:
traefik.enable: true
traefik.http.routers.example-com.rule: "Host(`example.com`)"
We don't even need to specify any entrypoints, it's all setup for us. We don't even need to specify or expose any additional ports, since by default nginx exposes port 80, if a Docker container only exposes a single port, Traefik will use that port without any additional configuration.
Pretty neat!
The Traefik service also enables the Traefik API and Dashboard, but by leveraging the power of the env.sh script and service loader, the API and Dashboard can be disable simply by setting the TRAEFIK_API_DASHBOARD environment variable to 0.
The API and Dashboard are also loaded automatically on localhost, the DEFAULT_DOMAIN environment variable is used to specify the domain which should be used for any web-facing interfaces, like the Dashboard. In future releases, other services will also use this, meaning that only one environment variable needs to be set on each environment for services to be accessible on the correct domain.
There's a lot more to come in future releases for Traefik, but I'd encourage reading the README in the Traefik service to find out more about how it's setup.
Read the Traefik service's README for more details on how it is setup
Other environment variables, examples and more documentation
There more documentation and examples in the top-level README.md, including a table on all currently supported environment variables.
A big focus on test coverage
I've been making sure that everything I add has solid test coverage. This meant though that most of the time spent on web-router so far has been on writing tests, and essentially creating a small test framework, because as it turns out writing tests in shell scripts is not the most straightforward thing ever.
I'm particularly pleased with the asserts.sh script, which includes functions for asserting things during a test, it really simplifies the test files. It includes basic things like asserting a file exists, but also more advanced things, like asserting that a curl request returns a particular status code, or that the returned headers contain a specific string. Definitely makes the test more consistent and easier to read.
Tests are executed using run.sh in the tests directory, which by default will run all tests, or if you only want to run a specific set of tests, you can pass in a relative path to one of the test shell scripts. For example, from within the tests directory, running ./run.sh traefik/test-traefik.sh will run the base Traefik tests.
More to come
There is so much more to come, I have a lot of config that's still in a private repository which I want to bring across, and a lot more functionality I want to add.
The next release will have a big focus on SSL/TLS. I really want to get Let's Encrypt integrated, but doing so in a way that works for non-production and local environments. This means integrating tools like mkcert to generate locally trusted certificates, but using the same ACME process that Let's Encrypt uses to provision them.
Change log
What's Changed
- Add web-router network with tests and docs by @AaronMcHale in #1
- Issue #2: Dynamic service loading by @AaronMcHale in #7
- Use alpine varient of nginx image for running tests by @AaronMcHale in #9
- Issue #11: Allow specifying path to env file by @AaronMcHale in #14
- Issue #8: Refactor env file loading to fix when file is empty and comments by @AaronMcHale in #15
- Issue #12: Add "assert" helper functions for tests by @AaronMcHale in #16
- Issue #3: Add traefik service by @AaronMcHale in #10
New Contributors
- @AaronMcHale made their first contribution in #1
Full Changelog: https://github.com/AaronMcHale/web-router/commits/0.1