Traefik
===

One component which we often use on our dev environment is [Traefik](https://containo.us/traefik/) as reverse proxy.
It allows us to run dockerized projects and access them in our browser using `project.test` as DNS for example.

The feature does not install traefik or handle the configuration of your host to map the DNS entry to the IP,
but it handles the generation of traefik configuration file for your project if there is certificates for HTTPS 
access.

Feature configuration
---

- `disabled`: Definition of the status of the feature. If set to True, traefik feature will not be triggered.
    - type: boolean
    - default: `False`
- `certs_directory`: The directory in which all certs are stored
    - type: string
    - default: `$HOME/.docker-devbox/certs` (for Linux based systems)
- `config_directory`: The traefik configuration directory
    - type: string
    - default: `$HOME/.docker-devbox/traefik/config` (for Linux based systems)
- `mapped_certs_directory`: The directory in which certificates are generated (public and private key)
    - type: string
    - default: `/cert`
- `ssl_config_template`: The Jinja template for the traefik configuration file registering CFSSL SSL certificates. 
    - type: string
    - default: A jinja template
- `extra-services`: A dict of {id: ExtraService} configuration
    - type: list of Spec configuration
    - default: `{}`
- `extra_services_config_template`: The Jinja template for extra-services configuration file. 
    - type: string
    - default: A jinja template

!!! example "Configuration"
    ```yaml
    traefik:
      certs_directory: /home/vagrant/.docker-devbox/certs
      config_directory: /home/vagrant/.docker-devbox/traefik/config
      disabled: false
      mapped_certs_directory: /certs
      ssl_config_template: "# This configuration file has been automatically generated\
        \ by ddb\n[[tls.certificates]]\n  certFile = \"%s\"\n  keyFile = \"%s\"\n"
      extra_services: {}
      extra_services_config_template: "# This configuration file has been automatically\
        \ generated by ddb\n[http.routers]\n  [http.routers.extra-service-{{_local.id}}]\n\
        \    rule = \"{{_local.rule}}\"\n    entrypoints = [{% if _local.https is true\
        \ %}\"https\"{% elif _local.https is false %}\"http\"{% else %}\"http\", \"https\"\
        {% endif %}]\n    service = \"extra-service-{{_local.id}}\"\n{%- if _local.certresolver\
        \ is defined %}\n [http.routers.extra-service-{{_local.service}}.tls]\n    certResolver\
        \ = \"{{_local.certresolver}}\"\n{%- endif %}\n\n[http.services]\n  [http.services.extra-service-{{_local.id}}.loadBalancer]\n\
        \    [[http.services.extra-service-{{_local.id}}.loadBalancer.servers]]\n    \
        \  url = \"{{_local.url}}\"\n"
    ```
    
ExtraService configuration
---
If you need to register an external service into your docker network, you should define an external_service entry.

It can be used when a service should better run on the developer host instead of inside a docker container.
  
- `url`: URL to access the service to proxy from traefik container
    - type: string
- `domain`: Domain to use for SSL certificate generation
    - type: string
    - default: `None`
- `https`: Use http and/or https to expose the service. If `None`, it is exposed with both http and https
    - type: string
    - default: `None`
- `redirect_to_https`: If `https` is `None` and `redirect_to_https` is `True`, requesting the http url of the service 
    will redirect to https.
    - type: string
    - default: `None` (Use the value of `docker.reverse_proxy.redirect_to_https`)
- `rule`: The traefik router rule. You should customize it only if you have to support many domains on the same service
    - type: string
    - default: ``Host(`{{_local.domain}}`)``
    
Jinja templating is available for `url`, `domain` and `rule` fields, with the usual configuration as data context, 
and additional `_local` dict containing the extra_service entry configuration.

!!! example "Bring back a dockerized service inside your IDE"

    Running the server component inside the developer editor may more convenient in some cases.
    
    If the application is running on port 8080 right on the host, you can write this kind of configuration:
    
    ```yaml
    traefik:
      extra_services: 
        api:
          domain: api.{{core.domain.sub}}.{{core.domain.ext}}
          url: http://{{docker.debug.host}}:8080
    ```
    
    It will expose the server component throw the traefik docker network, with the domain name and HTTPS support.
        
Certificates Installation Feature
---

If your project have certificates for SSL access, Traefik needs a bit a configuration in order to use them.

This is done on `ddb configure` command. For instance, if your have defined a certresolver with `null` value in your 
docker-compose.yml.jsonnet (check feature [jsonnet](./jsonnet.md) for more details), 
it will create a label `ddb.emit.certs:generate: <the vhost>`. 
It will then be processed by the [certs](./certs.md) feature and will generate a SSL certificate.

Then, the `certs:available` event will be triggered, which is handled by the traefik feature.

When triggered, it will generate the right configuration file in order to tell Traefik that there is a certificate 
defined for the given domain.
    
Certificates Uninstallation Feature
---

For some reason, you might want to remove HTTPS on your project and move back to HTTP. 

This is done on `ddb configure` command. 
If you have previously defined a certresolver to null, it will be detected that you removed it. 
The `certs:removed` event will be triggered, which is handled by the traefik feature.

When triggered, it will remove the configuration file and both public and private key in order to tell Traefik 
that there is no more certificate defined for the given domain.
