Tecnativa / doodba-copier-template

A Copier template for Doodba projects
Boost Software License 1.0
86 stars 114 forks source link

TRAEFIK DEFAULT CERT #473

Closed norlinhenrik closed 5 months ago

norlinhenrik commented 5 months ago

The FAQ has docker compose files for Traefik version 1.6 and 2.4. I have tried both, and the result is that Traefik provides a TRAEFIK DEFAULT CERT which gives a warning in the browser that the certificate is not valid. What am I doing wrong?

Steps to reproduce:

  1. DNS configuration

  2. docker compose -p inverseproxy -f traefik24.yaml up -d

  3. doodba

    • copier copy gh:Tecnativa/doodba-copier-template --trust ce16
    • cd ce16
    • rm docker-compose.yml
    • ln -s prod.yaml docker-compose.yml
    • invoke img-build
    • ERROR: yaml: line 29: mapping values are not allowed in this context
    • nano prod.yaml
    • traefik.main-0.frontend.rule: Host()
    • invoke img-build
    • docker compose -f prod.yaml up -d

Here is my .copier-answers.yml

_commit: v6.1.5
_src_path: gh:Tecnativa/doodba-copier-template
backup_dst: ''
cidr_whitelist: null
domains_prod:
    hosts:
    - ce16.odoowebservices.com
domains_test: {}
gitlab_url: ''
odoo_dbfilter: ^prod
odoo_initial_lang: en_US
odoo_listdb: true
odoo_oci_image: ''
odoo_proxy: traefik
odoo_version: 16.0
paths_without_crawlers:
- /web
- /website/info
postgres_dbname: prod
postgres_exposed: false
postgres_username: odoo
postgres_version: '15'
project_author: Henrik
project_license: BSL-1.0
project_name: ce16
smtp_default_from: ''
smtp_relay_host: ''

Here are my docker containers: image

Expected behavior: A valid certificate

Additional context: Fresh Ubuntu 24.04 on Vultr

carlosecv commented 5 months ago

Can you give your traefik global proxy yaml file?

norlinhenrik commented 5 months ago

I used the one in PR 469.

version: "2.4"
services:
  proxy:
    image: traefik:2.4
    networks:
      shared:
        aliases: []
      private:
      public:
    volumes:
      - acme:/etc/traefik/acme:rw,Z
    ports:
      - 80:80
      - 443:443
    depends_on:
      - dockersocket
    restart: unless-stopped
    tty: true
    command:
      - "--entrypoints.web-insecure.address=:80"
      - "--entrypoints.web-main.transport.respondingTimeouts.idleTimeout=60s"
      - "--entrypoints.web-main.http.middlewares=global-error-502@docker"
      - "--log.level=info"
      - "--providers.docker.endpoint=http://dockersocket:2375"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=inverseproxy_shared"
      - "--providers.docker=true"
      - "--entrypoints.web-main.address=:443"
      - "--entrypoints.web-main.http.tls.certResolver=letsencrypt"
      - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.letsencrypt.acme.email=alerts@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme-v2.json"
      - "--entrypoints.web-insecure.http.redirections.entryPoint.to=web-main"
      - "--entrypoints.web-insecure.http.redirections.entryPoint.scheme=https"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web-insecure"
  dockersocket:
    image: tecnativa/docker-socket-proxy
    privileged: true
    networks:
      private:
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    environment:
      CONTAINERS: 1
      NETWORKS: 1
      SERVICES: 1
      SWARM: 1
      TASKS: 1
    restart: unless-stopped
  error-handling:
    image: nginx:alpine
    restart: unless-stopped
    networks:
      - shared
    volumes:
      - error-handling-config:/etc/nginx/conf.d/
      - error-handling-data:/usr/share/nginx/html/
    labels:
      traefik.docker.network: inverseproxy_shared
      traefik.enable: "true"
      traefik.http.routers.error-handling.rule: HostRegexp(`{any:.+}`)
      traefik.http.routers.error-handling.entrypoints: web-main
      traefik.http.routers.error-handling.priority: 1
      traefik.http.routers.error-handling.service: global-error-handler
      traefik.http.routers.error-handling.middlewares: global-error-502
      traefik.http.middlewares.global-error-502.errors.status: 502
      traefik.http.middlewares.global-error-502.errors.service: global-error-handler
      traefik.http.middlewares.global-error-502.errors.query: "/{status}.html"
      traefik.http.services.global-error-handler.loadbalancer.server.port: 80
networks:
  shared:
    internal: true
    driver_opts:
      encrypted: 1
  private:
    internal: true
    driver_opts:
      encrypted: 1
  public:
    driver_opts:
      encrypted: 1
volumes:
  acme:
  error-handling-config:
  error-handling-data:
norlinhenrik commented 5 months ago

@carlosecv Thank you for looking into this! :-)

josep-tecnativa commented 5 months ago

Hi, i think that the problem is that you need to specify your certresolver, in this case, letsencrypt. So, it would be something like this:

domains_prod:
    - cert_resolver: letsencrypt
      hosts:
        - ce16.odoowebservices.com
norlinhenrik commented 5 months ago

@pedrobaeza @josep-tecnativa Thank you for your responses. I just filled in the contact form on tecnativa.com to get direct help deploying Doodba ASAP.

The copier.yml help says that the cert_resolver is letsencrypt by default. And certResolver: letsencrypt exists in prod.yaml:

version: "2.4"

services:
  odoo:
    extends:
      file: common.yaml
      service: odoo
    restart: unless-stopped
    hostname: ""
    env_file:
      - .docker/odoo.env
      - .docker/db-access.env
    environment:
      DB_FILTER: "^prod"
      DOODBA_ENVIRONMENT: "${DOODBA_ENVIRONMENT-prod}"
      INITIAL_LANG: "en_US"
    depends_on:
      - db
    networks:
      default:
      inverseproxy_shared:
    labels:
      doodba.domain.main: ""
      traefik.enable: "true"
      traefik.domain: ""
      traefik.forbiddenCrawlers-0.frontend.headers.customResponseHeaders:
        "X-Robots-Tag:noindex, nofollow"
      traefik.forbiddenCrawlers-0.frontend.rule: Host:;Path:/web,/web/{anything:.*},/website/info,/website/info/{anything:.*}
      traefik.main-0.frontend.rule: Host()
      traefik.longpolling-0.frontend.rule: Host:;Path:/websocket,/websocket/{anything:.*}
      traefik.longpolling-0.port: 8072
      traefik.http.middlewares.ce16-16-0-prod-buffering.buffering.retryExpression:
        IsNetworkError() && Attempts() < 5
      traefik.http.middlewares.ce16-16-0-prod-compress.compress: "true"
      traefik.http.middlewares.ce16-16-0-prod-forbid-crawlers.headers.customResponseHeaders.X-Robots-Tag:
        "noindex, nofollow"
      traefik.http.middlewares.ce16-16-0-prod-addSTS.headers.forceSTSHeader: "true"
      traefik.http.middlewares.ce16-16-0-prod-forceSecure.redirectScheme.scheme: https
      traefik.http.middlewares.ce16-16-0-prod-forceSecure.redirectScheme.permanent: "true"
      traefik.http.services.ce16-16-0-prod-main.loadbalancer.server.port: 8069
      traefik.http.services.ce16-16-0-prod-longpolling.loadbalancer.server.port: 8072
      traefik.http.routers.ce16-16-0-prod-main-0.rule: Host()
      traefik.http.routers.ce16-16-0-prod-main-0.service: ce16-16-0-prod-main
      traefik.http.routers.ce16-16-0-prod-main-0.middlewares:
        ce16-16-0-prod-addSTS, ce16-16-0-prod-buffering, ce16-16-0-prod-compress,
        ce16-16-0-prod-forceSecure
      traefik.http.routers.ce16-16-0-prod-main-secure-0.rule: Host()
      traefik.http.routers.ce16-16-0-prod-main-secure-0.service: ce16-16-0-prod-main
      traefik.http.routers.ce16-16-0-prod-main-secure-0.middlewares:
        ce16-16-0-prod-addSTS, ce16-16-0-prod-buffering, ce16-16-0-prod-compress,
        ce16-16-0-prod-forceSecure
      traefik.http.routers.ce16-16-0-prod-main-secure-0.tls: "true"
      traefik.http.routers.ce16-16-0-prod-main-secure-0.tls.certResolver: letsencrypt
      traefik.http.routers.ce16-16-0-prod-longpolling-0.rule:
        Host() && Path(`/websocket`)
      traefik.http.routers.ce16-16-0-prod-longpolling-0.service: ce16-16-0-prod-longpolling
      traefik.http.routers.ce16-16-0-prod-longpolling-0.middlewares:
        ce16-16-0-prod-addSTS, ce16-16-0-prod-forceSecure
      traefik.http.routers.ce16-16-0-prod-longpolling-secure-0.rule:
        Host() && Path(`/websocket`)
      traefik.http.routers.ce16-16-0-prod-longpolling-secure-0.service: ce16-16-0-prod-longpolling
      traefik.http.routers.ce16-16-0-prod-longpolling-secure-0.middlewares:
        ce16-16-0-prod-addSTS, ce16-16-0-prod-forceSecure
      traefik.http.routers.ce16-16-0-prod-longpolling-secure-0.tls: "true"
      traefik.http.routers.ce16-16-0-prod-longpolling-secure-0.tls.certResolver: letsencrypt
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-0.rule:
        Host() && (PathPrefix(`/web/`, `/website/info/`) || Path(`/web`,
        `/website/info`))
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-0.service: ce16-16-0-prod-main
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-0.middlewares:
        ce16-16-0-prod-addSTS, ce16-16-0-prod-buffering, ce16-16-0-prod-compress,
        ce16-16-0-prod-forbid-crawlers, ce16-16-0-prod-forceSecure
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-secure-0.rule:
        Host() && (PathPrefix(`/web/`, `/website/info/`) || Path(`/web`,
        `/website/info`))
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-secure-0.service: ce16-16-0-prod-main
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-secure-0.middlewares:
        ce16-16-0-prod-addSTS, ce16-16-0-prod-buffering, ce16-16-0-prod-compress,
        ce16-16-0-prod-forbid-crawlers, ce16-16-0-prod-forceSecure
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-secure-0.tls: "true"
      traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-secure-0.tls.certResolver: letsencrypt

  db:
    extends:
      file: common.yaml
      service: db
    env_file:
      - .docker/db-creation.env
    restart: unless-stopped

networks:
  default:
    driver_opts:
      encrypted: 1

  inverseproxy_shared:
    external: true

volumes:
  filestore:
  db:
josep-tecnativa commented 5 months ago

Based on that prod.yml, I would say it has been built incorrectly, as you can see, for example, in these labels, the Host() part is empty:

traefik.http.routers.ce16-16-0-prod-forbiddenCrawlers-secure-0.rule:
    Host() && (PathPrefix(`/web/`, `/website/info/`) || Path(`/web`,
    `/website/info`))

Have you tried answering as I suggested when copier asks you for domains_prod?

norlinhenrik commented 5 months ago

copier update --trust caused a conflict in prod.yaml. copier copy gh:Tecnativa/doodba-copier-template --trust . caused this error when committing the changes:

prod.yaml
[error] prod.yaml: SyntaxError: Nested mappings are not allowed in compact mappings (29:37)
[error]   27 |         "X-Robots-Tag:noindex, nofollow"
[error]   28 |       traefik.forbiddenCrawlers-0.frontend.rule: Host:;Path:/web,/web/{anything:.*},/website/info,/website/info/{anything:.*}
[error] > 29 |       traefik.main-0.frontend.rule: Host:
[error]      |                                     ^^^^^
[error] > 30 |       traefik.longpolling-0.frontend.rule: Host:;Path:/websocket,/websocket/{anything:.*}
[error]      | ^
[error]   31 |       traefik.longpolling-0.port: 8072
[error]   32 |       traefik.forbiddenCrawlers-1.frontend.headers.customResponseHeaders:
[error]   33 |         "X-Robots-Tag:noindex, nofollow"

So I renamed ce16 to something else and started over again with copier copy gh:Tecnativa/doodba-copier-template --trust ce16 On the domain_prod question I answered: {'hosts': ['ce16.odoowebservices.com'], 'cert_resolver': 'letsencrypt'} I still get the TRAEFIK DEFAULT CERT.

@josep-tecnativa Would you like to try the steps to reproduce the error?

josep-tecnativa commented 5 months ago

The format to answer domain_prod question is like this:

- cert_resolver: letsencrypt
  hosts:
    - ce16.odoowebservices.com
norlinhenrik commented 5 months ago
henrik@doodba:~/doodba/ce16$ cat .copier-answers.yml 
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
_commit: v6.1.5
_src_path: gh:Tecnativa/doodba-copier-template
backup_dst: ''
cidr_whitelist: null
domains_prod:
    cert_resolver: letsencrypt
    hosts:
    - ce16.odoowebservices.com
domains_test: {}
gitlab_url: ''
odoo_dbfilter: ^prod
odoo_initial_lang: en_US
odoo_listdb: true
odoo_oci_image: ''
odoo_proxy: traefik
odoo_version: 16.0
paths_without_crawlers:
- /web
- /website/info
postgres_dbname: prod
postgres_exposed: false
postgres_username: odoo
postgres_version: '15'
project_author: Henrik
project_license: BSL-1.0
project_name: ce16
smtp_default_from: ''
smtp_relay_host: ''
norlinhenrik commented 5 months ago

Thank you @josep-tecnativa I made PR 475 to improve the documentation.

It still didn't solve my problem.

josep-tecnativa commented 5 months ago

Thank you @josep-tecnativa I made PR 475 to improve the documentation.

It still didn't solve my problem.

I think that your syntax is still no correct. You are missing dash symbol ( - ) and correct indentation. Look at my example:

- cert_resolver: letsencrypt
  hosts:
    - ce16.odoowebservices.com
norlinhenrik commented 5 months ago

Thank you @josep-tecnativa I believe I followed your recommendation the other day, without success. Yesterday I spent time learning Traefik, and trying again, your recommendation works. 👍 But inverseproxy_shared was missing and gave an error. So I updated the documentation slightly in PR 475. I will close this issue now.