{"id":13496208,"url":"https://github.com/wemake-services/caddy-gen","last_synced_at":"2025-04-06T06:08:57.916Z","repository":{"id":26997928,"uuid":"109709289","full_name":"wemake-services/caddy-gen","owner":"wemake-services","description":"Automated Caddy reverse proxy for docker containers","archived":false,"fork":false,"pushed_at":"2024-09-11T17:43:42.000Z","size":107,"stargazers_count":250,"open_issues_count":9,"forks_count":24,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-29T23:52:01.759Z","etag":null,"topics":["caddy","caddy-gen","caddy-plugin","caddy-server","docker","docker-image","proxy-server","scale"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/wemakeservices/caddy-gen","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wemake-services.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"wemake-services","custom":"https://boosty.to/sobolevn"}},"created_at":"2017-11-06T14:57:10.000Z","updated_at":"2024-10-24T16:48:37.000Z","dependencies_parsed_at":"2024-11-07T01:44:28.010Z","dependency_job_id":null,"html_url":"https://github.com/wemake-services/caddy-gen","commit_stats":{"total_commits":88,"total_committers":17,"mean_commits":5.176470588235294,"dds":0.6704545454545454,"last_synced_commit":"865b8b2fa2418ec93812ee42334ea7c86187f56e"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wemake-services%2Fcaddy-gen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wemake-services%2Fcaddy-gen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wemake-services%2Fcaddy-gen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wemake-services%2Fcaddy-gen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wemake-services","download_url":"https://codeload.github.com/wemake-services/caddy-gen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441052,"owners_count":20939239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caddy","caddy-gen","caddy-plugin","caddy-server","docker","docker-image","proxy-server","scale"],"created_at":"2024-07-31T19:01:43.877Z","updated_at":"2025-04-06T06:08:57.893Z","avatar_url":"https://github.com/wemake-services.png","language":"Dockerfile","funding_links":["https://github.com/sponsors/wemake-services","https://boosty.to/sobolevn"],"categories":["Dockerfile","docker","Go Template"],"sub_categories":[],"readme":"# caddy-gen\n\n[![wemake.services](https://img.shields.io/badge/-wemake.services-green.svg?label=%20\u0026logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC%2FxhBQAAAAFzUkdCAK7OHOkAAAAbUExURQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP%2F%2F%2F5TvxDIAAAAIdFJOUwAjRA8xXANAL%2Bv0SAAAADNJREFUGNNjYCAIOJjRBdBFWMkVQeGzcHAwksJnAPPZGOGAASzPzAEHEGVsLExQwE7YswCb7AFZSF3bbAAAAABJRU5ErkJggg%3D%3D)](https://wemake.services)\n[![test](https://github.com/wemake-services/caddy-gen/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/wemake-services/caddy-gen/actions/workflows/test.yml)\n[![Dockerhub](https://img.shields.io/docker/pulls/wemakeservices/caddy-gen.svg)](https://hub.docker.com/r/wemakeservices/caddy-gen/)\n\nA perfect mix of [`Caddy`](https://github.com/mholt/caddy), [`docker-gen`](https://github.com/jwilder/docker-gen), and [`forego`](https://github.com/jwilder/forego). Inspired by [`nginx-proxy`](https://github.com/jwilder/nginx-proxy).\n\nDownload:\n- https://hub.docker.com/r/wemakeservices/caddy-gen\n- https://ghcr.io/wemake-services/caddy-gen\n\n---\n\n## Why\n\nUsing `Caddy` as your primary web server is super simple.\nBut when you need to scale your application Caddy is limited to its static configuration.\n\nTo overcome this issue we are using `docker-gen` to generate configuration everytime a container spawns or dies.\nNow scaling is easy!\n\n## Configuration / Options\n\n`caddy-gen` is configured with [`labels`](https://docs.docker.com/engine/userguide/labels-custom-metadata/).\n\nThe main idea is simple.\nEvery labeled service exposes a `virtual.host` to be handled.\nThen, every container represents a single `upstream` to serve requests.\n\nNOTE: Caddy2 was introduced in [version 0.3.0](https://github.com/wemake-services/caddy-gen/releases/tag/0.3.0) causing BREAKING CHANGES.\n\nMain configuration options:\n\n- `virtual.host` (required) domain name, don't pass `http://` or `https://`, you can separate them with spaces.\n- `virtual.alias` domain alias, useful for `www` prefix with redirect. For example `www.myapp.com`. Alias will always redirect to the host above.\n- `virtual.port` port exposed by container, e.g. `3000` for React apps in development.\n- `virtual.tls-email` the email address to use for the ACME account managing the site's certificates (required to enable HTTPS).\n- `virtual.tls` alias of `virtual.tls-email`.\n- `virtual.host.directives` set custom [Caddyfile directives](https://caddyserver.com/docs/caddyfile/directives) for the host. These will be inlined into the site block.\n- `virtual.host.import` include Caddyfile directives for the host from a file on the container's filesystem. See [Caddy import](https://caddyserver.com/docs/caddyfile/directives/import).\n\n[Basic authentication](https://caddyserver.com/docs/caddyfile/directives/basicauth) options:\n- `virtual.auth.path` with\n- `virtual.auth.username` and\n- `virtual.auth.password` together enable HTTP basic authentication. (Password should be a string `base64` encoded from `bcrypt` hash. You can use https://bcrypt-generator.com/ with default config and https://www.base64encode.org/.)\n\n[Reverse proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) options:\n- `virtual.proxy.matcher` have the reverse proxy only match certain paths.\n- `virtual.proxy.lb_policy` specify load balancer policy, defaults to `round_robin`.\n- `virtual.proxy.directives` include any reverse_proxy directives. These will be inlined into the reverse proxy block.\n- `virtual.proxy.import` include any reverse_proxy directives from a file on the container's filesystem. See [Caddy import](https://caddyserver.com/docs/caddyfile/directives/import).\n\nTo include a custom template:\n- mount a volume containing your custom template and/or snippet (they both may\n  be Go templates and will be loaded by `docker-gen`).\n- set the environment variable `CADDY_TEMPLATE` to the mounted file containining\n  your custom Caddyfile template. This will replace the default template.\n- set the environment variable `CADDY_SNIPPET` to the mounted file containining\n  your custom Caddyfile snippet. This will be prepended to the caddy template,\n  so you may use it to set [Global Options](https://caddyserver.com/docs/caddyfile/options),\n  define [snippet blocks](https://caddyserver.com/docs/caddyfile/concepts#snippets),\n  or [add custom address blocks](https://caddyserver.com/docs/caddyfile/concepts).\n- See [example \"Use a custom Caddy template for `docker-gen`\"](#use-a-custom-caddy-template-for-docker-gen)\n\n### Version build-time arguments\n\nThis image supports two [build-time](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg) arguments:\n\n- `FOREGO_VERSION` to change the current version of [`forego`](https://github.com/jwilder/forego/releases)\n- `DOCKER_GEN_VERSION` to change the current version of [`docker-gen`](https://github.com/jwilder/docker-gen/releases)\n\n## Usage\n\nCaddy-gen is created to be used in a single container. It will act as a reverse\nproxy for the whoami service.\n\n```yaml\nversion: \"3\"\nservices:\n  caddy-gen:\n    container_name: caddy-gen\n    image: wemakeservices/caddy-gen:latest # or ghcr.io/wemake-services/caddy-gen:latest\n    restart: always\n    volumes:\n      - /var/run/docker.sock:/tmp/docker.sock:ro # needs socket to read events\n      - ./caddy-info:/data/caddy # needs volume to back up certificates\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    depends_on:\n      - whoami\n\n  whoami: # this is your service\n    image: \"katacoda/docker-http-server:v2\"\n    labels:\n      - \"virtual.host=myapp.com\" # your domain\n      - \"virtual.alias=www.myapp.com\" # alias for your domain (optional)\n      - \"virtual.port=80\" # exposed port of this container\n      - \"virtual.tls-email=admin@myapp.com\" # ssl is now on\n      - \"virtual.auth.path=/secret/*\" # path basic authentication applies to\n      - \"virtual.auth.username=admin\" # Optionally add http basic authentication\n      - \"virtual.auth.password=JDJ5JDEyJEJCdzJYM0pZaWtMUTR4UVBjTnRoUmVJeXQuOC84QTdMNi9ONnNlbDVRcHltbjV3ME1pd2pLCg==\" # By specifying both username and password hash\n```\n\nSee [`docker-compose.yml`](https://github.com/wemake-services/caddy-gen/blob/master/example/docker-compose.yml) example file.\n\n\u003e [!NOTE]\n\u003e Literal `$` should be doubled (`$$`) to avoid [docker compose interpolation](https://docs.docker.com/reference/compose-file/interpolation), e.g.:\n\u003e ```yaml\n\u003e labels:\n\u003e   virtual.host.directives: |\n\u003e     basic_auth {\n\u003e       usr $2a$14$aSp4Ch...  # will fail\n\u003e       usr $2a$14$$aSp4Ch... # works\n\u003e     }\n\u003e ```\n\n### Backing up certificates\n\nTo backup certificates make a volume:\n\n```yaml\nservices:\n  caddy:\n    volumes:\n      - ./caddy-info:/data/caddy\n```\n\n### Add or modify reverse_proxy headers\n\nWith the following settings, the upstream host will see its own address instead\nof the original incoming value. See [Headers](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#headers).\n\n```yaml\nversion: \"3\"\nservices:\n  caddy-gen:\n    image: wemakeservices/caddy-gen:latest # or ghcr.io/wemake-services/caddy-gen:latest\n    restart: always\n    volumes:\n      - /var/run/docker.sock:/tmp/docker.sock:ro # needs socket to read events\n      - ./caddy-info:/data/caddy # needs volume to back up certificates\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    depends_on:\n      - whoami\n\n  whoami:\n    image: \"katacoda/docker-http-server:v2\"\n    labels:\n      virtual.host: myapp.com\n      virtual.port: 80\n      virtual.tls: admin@myapp.com\n      virtual.proxy.directives: |\n        header_up Host {http.reverse_proxy.upstream.hostport}\n```\n\n### Set up a static file server for a host\n\nWith the following settings, myapp.com will serve files from directory `www`\nand only requests to `/api/*` will be routed to the whoami service.  See\n[file_server](https://caddyserver.com/docs/caddyfile/directives/file_server).\n\n```yaml\nversion: \"3\"\nservices:\n  caddy-gen:\n    image: wemakeservices/caddy-gen:latest # or ghcr.io/wemake-services/caddy-gen:latest\n    restart: always\n    volumes:\n      - /var/run/docker.sock:/tmp/docker.sock:ro # needs socket to read events\n      - ./caddy-info:/data/caddy # needs volume to back up certificates\n      - ./www:/srv/myapp/www # files served by myapp.com\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    depends_on:\n      - whoami\n\n  whoami:\n    image: \"katacoda/docker-http-server:v2\"\n    labels:\n      virtual.host: myapp.com\n      virtual.port: 80\n      virtual.tls: admin@myapp.com\n      virtual.proxy.matcher: /api/*\n      virtual.host.directives: |\n        root * /srv/myapp/www\n        templates\n        file_server\n```\n\n### Use a custom Caddy template for `docker-gen`\n\nWith this custom template, Caddy-gen will act as a reverse proxy for service\ncontainers and store their logs under the appropriate host folder in\n`/var/logs`.\n\n```caddy\n# file: ./caddy/template\n(redirectHttps) {\n  @http {\n    protocol http\n  }\n  redir @http https://{host}{uri}\n}\n\n(logFile) {\n  log {\n    output file /var/caddy/{host}/logs {\n      roll_keep_for 7\n    }\n  }\n}\n\n{{ $hosts := groupByLabel $ \"virtual.host\" }}\n{{ range $h, $containers := $hosts }}\n{{ range $t, $host := split (trim (index $c.Labels \"virtual.host\")) \" \" }}\n{{ $tls = trim (index $c.Labels \"virtual.tls\") }}\n{{ $host }} {\n  {{ if $tls }}\n  tls {{ $tls }}\n  import redirectHttps\n  {{ end }}\n  reverse_proxy {\n    lb_policy round_robin\n    {{ range $i, $container := $containers }}\n    {{ range $j, $net := $container.Networks }}\n    to {{ $net.IP}}:{{ or (trim (index $container.Labels \"virtual.port\")) \"80\" }}\n    {{ end }}\n    {{ end }}\n  }\n  encode zstd gzip\n  import logFile\n}\n```\n\n```yaml\n# file: docker-compose.yml\nservices:\n  caddy-gen:\n    volumes:\n      # mount the template file into the container\n      - ./caddy/template:/tmp/caddy/template\n    environment:\n      # CADDY_TEMPLATE will replace the default caddy template\n      CADDY_TEMPLATE: /tmp/caddy/template\n```\n\n### Set [global options](https://caddyserver.com/docs/caddyfile/options) for Caddy\n\nWith this snippet, Caddy will request SSL certificates from the [Let's Encrypt\nstaging environment](https://letsencrypt.org/docs/staging-environment/). This\nis [useful for testing](https://caddyserver.com/docs/automatic-https#testing)\nwithout running up against rate limits when you want to deploy.\n\n```caddy\n# file: ./caddy/global_options\n{\n  acme_ca https://acme-staging-v02.api.letsencrypt.org/directory\n}\n```\n\n```yaml\n# file: docker-compose.yml\nservices:\n  caddy-gen:\n    volumes:\n      # mount the template file into the container\n      - ./caddy/global_options:/tmp/caddy/global_options\n    environment:\n      # CADDY_SNIPPET will prepend to the default caddy template\n      CADDY_SNIPPET: /tmp/caddy/global_options\n```\n\n## See also\n\n- Raw `Caddy` [image](https://github.com/wemake-services/caddy-docker)\n- [Django project template](https://github.com/wemake-services/wemake-django-template) with `Caddy`\n- Tool to limit your `docker` [image size](https://github.com/wemake-services/docker-image-size-limit)\n\n## Changelog\n\nFull changelog is available [here](https://github.com/wemake-services/caddy-gen/blob/master/CHANGELOG.md).\n\n## License\n\nMIT. See [LICENSE](https://github.com/wemake-services/caddy-gen/blob/master/LICENSE) for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwemake-services%2Fcaddy-gen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwemake-services%2Fcaddy-gen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwemake-services%2Fcaddy-gen/lists"}