[{"data":1,"prerenderedAt":3464},["ShallowReactive",2],{"home-latest-posts":3},[4,454,3035],{"id":5,"title":6,"body":7,"date":436,"description":437,"draft":438,"extension":439,"image":440,"lang":441,"meta":442,"navigation":443,"path":444,"seo":445,"stem":446,"tags":447,"__hash__":453},"blog\u002Fblog\u002Fplayground-live-helper-chat-docker-traefik.md","Playground de Live Helper Chat con Docker, Traefik, MySQL y Redis",{"type":8,"value":9,"toc":430},"minimark",[10,14,17,22,35,39,65,69,72,101,104,117,120,136,139,142,150,153,190,193,221,224,227,298,301,312,316,319,350,353,413,416,426],[11,12,13],"p",{},"Live Helper es un chat de soporte en vivo de código abierto para aplicaciones web progresivas con integraciones de bot, Voz & Video & ScreenShare, AI y API Rest",[11,15,16],{},"A continuación describiré unos playgrounds que le ayudarán a levantar Live Helper Chat con Docker, Traefik, MySQL y Redis, existe dos versiones una compatible con PHP y otra con NodeJS, dependiendo de cual sea el de tu preferencia.",[18,19,21],"h2",{"id":20},"requisitos","Requisitos:",[23,24,25,29,32],"ul",{},[26,27,28],"li",{},"git 2.2 or higher",[26,30,31],{},"docker 20 or higher",[26,33,34],{},"docker-compose 1.20 or higher",[18,36,38],{"id":37},"servicios-configurados","Servicios configurados:",[23,40,41,44,47,50,53,56,59,62],{},[26,42,43],{},"web - nginx service",[26,45,46],{},"php - php-fpm service",[26,48,49],{},"cobrowse - co browsing running NodeJS service",[26,51,52],{},"php-cronjob - cron jobs running service",[26,54,55],{},"php-resque - php-resque worker running service",[26,57,58],{},"nodejshelper - NodeJS Helper NodeJS running service",[26,60,61],{},"redis - Redis service",[26,63,64],{},"db - Database service",[18,66,68],{"id":67},"instrucciones-de-docker","Instrucciones de Docker:",[11,70,71],{},"Clona el repositorio:",[73,74,79],"pre",{"className":75,"code":76,"language":77,"meta":78,"style":78},"language-bash shiki shiki-themes vitesse-dark","git clone git@github.com:marcotorres\u002Flivechat.git docker-standalone\n","bash","",[80,81,82],"code",{"__ignoreMap":78},[83,84,87,91,95,98],"span",{"class":85,"line":86},"line",1,[83,88,90],{"class":89},"sCK9x","git",[83,92,94],{"class":93},"s7rlk"," clone",[83,96,97],{"class":93}," git@github.com:marcotorres\u002Flivechat.git",[83,99,100],{"class":93}," docker-standalone\n",[11,102,103],{},"Nos ubicamos en:",[73,105,107],{"className":75,"code":106,"language":77,"meta":78,"style":78},"cd docker-standalone\n",[80,108,109],{"__ignoreMap":78},[83,110,111,115],{"class":85,"line":86},[83,112,114],{"class":113},"sm68I","cd",[83,116,100],{"class":93},[11,118,119],{},"Copia:",[73,121,123],{"className":75,"code":122,"language":77,"meta":78,"style":78},"cp .env.default .env\n",[80,124,125],{"__ignoreMap":78},[83,126,127,130,133],{"class":85,"line":86},[83,128,129],{"class":89},"cp",[83,131,132],{"class":93}," .env.default",[83,134,135],{"class":93}," .env\n",[11,137,138],{},"Edita el archivo .env y cambia LHC_SECRET_HASH por un random string",[11,140,141],{},"Cambiar las variables de entorno relacionado a la BD:",[73,143,148],{"className":144,"code":146,"language":147},[145],"language-text","Host - db\nDatabase name - lhc_database\nDatabase username - lhc_usr\nDatabase password - lhc_password\n","text",[80,149,146],{"__ignoreMap":78},[11,151,152],{},"Para la versión estándar sin ejecutar el complemento NodeJS, ejecuta install.sh esto verificará Live Helper Chat y las extensiones requeridas",[73,154,156],{"className":75,"code":155,"language":77,"meta":78,"style":78},"docker-compose -f docker-compose-standard.yml pull && docker-compose -f docker-compose-standard.yml up -d\n",[80,157,158],{"__ignoreMap":78},[83,159,160,163,167,170,173,177,180,182,184,187],{"class":85,"line":86},[83,161,162],{"class":89},"docker-compose",[83,164,166],{"class":165},"sXjYR"," -f",[83,168,169],{"class":93}," docker-compose-standard.yml",[83,171,172],{"class":93}," pull",[83,174,176],{"class":175},"s_pn2"," &&",[83,178,179],{"class":89}," docker-compose",[83,181,166],{"class":165},[83,183,169],{"class":93},[83,185,186],{"class":93}," up",[83,188,189],{"class":165}," -d\n",[11,191,192],{},"Para la versión con complemento NodeJS, ejecute install-nodejs.sh, esto verificará Live Helper Chat y las extensiones requeridas",[73,194,196],{"className":75,"code":195,"language":77,"meta":78,"style":78},"docker-compose -f docker-compose-nodejs.yml pull && docker-compose -f docker-compose-nodejs.yml up -d\n",[80,197,198],{"__ignoreMap":78},[83,199,200,202,204,207,209,211,213,215,217,219],{"class":85,"line":86},[83,201,162],{"class":89},[83,203,166],{"class":165},[83,205,206],{"class":93}," docker-compose-nodejs.yml",[83,208,172],{"class":93},[83,210,176],{"class":175},[83,212,179],{"class":89},[83,214,166],{"class":165},[83,216,206],{"class":93},[83,218,186],{"class":93},[83,220,189],{"class":165},[11,222,223],{},"Navegue hasta localhost:8081 y siga las instrucciones de instalación.",[11,225,226],{},"En los primeros pasos de instalación, es posible que deba ejecutar estos comandos para cambiar los permisos de las carpetas.",[73,228,230],{"className":75,"code":229,"language":77,"meta":78,"style":78},"docker exec -it dockerstandalone_web_1 chown -R www-data:www-data \u002Fcode\u002Fcache\ndocker exec -it dockerstandalone_web_1 chown -R www-data:www-data \u002Fcode\u002Fsettings\ndocker exec -it dockerstandalone_web_1 chown -R www-data:www-data \u002Fcode\u002Fvar\n",[80,231,232,258,278],{"__ignoreMap":78},[83,233,234,237,240,243,246,249,252,255],{"class":85,"line":86},[83,235,236],{"class":89},"docker",[83,238,239],{"class":93}," exec",[83,241,242],{"class":165}," -it",[83,244,245],{"class":93}," dockerstandalone_web_1",[83,247,248],{"class":93}," chown",[83,250,251],{"class":165}," -R",[83,253,254],{"class":93}," www-data:www-data",[83,256,257],{"class":93}," \u002Fcode\u002Fcache\n",[83,259,261,263,265,267,269,271,273,275],{"class":85,"line":260},2,[83,262,236],{"class":89},[83,264,239],{"class":93},[83,266,242],{"class":165},[83,268,245],{"class":93},[83,270,248],{"class":93},[83,272,251],{"class":165},[83,274,254],{"class":93},[83,276,277],{"class":93}," \u002Fcode\u002Fsettings\n",[83,279,281,283,285,287,289,291,293,295],{"class":85,"line":280},3,[83,282,236],{"class":89},[83,284,239],{"class":93},[83,286,242],{"class":165},[83,288,245],{"class":93},[83,290,248],{"class":93},[83,292,251],{"class":165},[83,294,254],{"class":93},[83,296,297],{"class":93}," \u002Fcode\u002Fvar\n",[11,299,300],{},"o cambiar el permiso de estas carpetas:",[23,302,303,306,309],{},[26,304,305],{},"livehelperchat\u002Flhc_web\u002Fcache",[26,307,308],{},"livehelperchat\u002Flhc_web\u002Fsettings",[26,310,311],{},"livehelperchat\u002Flhc_web\u002Fvar",[18,313,315],{"id":314},"para-traefik","Para Traefik:",[11,317,318],{},"Crear una red:",[73,320,322],{"className":75,"code":321,"language":77,"meta":78,"style":78},"docker network create --gateway 192.168.90.1 --subnet 192.168.90.0\u002F24 traefik\n",[80,323,324],{"__ignoreMap":78},[83,325,326,328,331,334,337,341,344,347],{"class":85,"line":86},[83,327,236],{"class":89},[83,329,330],{"class":93}," network",[83,332,333],{"class":93}," create",[83,335,336],{"class":165}," --gateway",[83,338,340],{"class":339},"sxA9i"," 192.168.90.1",[83,342,343],{"class":165}," --subnet",[83,345,346],{"class":93}," 192.168.90.0\u002F24",[83,348,349],{"class":93}," traefik\n",[11,351,352],{},"Ejecutar:",[73,354,356],{"className":75,"code":355,"language":77,"meta":78,"style":78},"cp traefik\u002Facme.json.example traefik\u002Facme.json && \\\ncp traefik\u002Flogs\u002Ftraefik.log.example traefik\u002Flogs\u002Ftraefik.log && \\\ncp traefik\u002Fshared\u002F.htpasswd.example traefik\u002Fshared\u002F.htpasswd && \\\nchmod 0600 traefik\u002Facme.json\n",[80,357,358,373,387,401],{"__ignoreMap":78},[83,359,360,362,365,368,370],{"class":85,"line":86},[83,361,129],{"class":89},[83,363,364],{"class":93}," traefik\u002Facme.json.example",[83,366,367],{"class":93}," traefik\u002Facme.json",[83,369,176],{"class":175},[83,371,372],{"class":165}," \\\n",[83,374,375,377,380,383,385],{"class":85,"line":260},[83,376,129],{"class":89},[83,378,379],{"class":93}," traefik\u002Flogs\u002Ftraefik.log.example",[83,381,382],{"class":93}," traefik\u002Flogs\u002Ftraefik.log",[83,384,176],{"class":175},[83,386,372],{"class":165},[83,388,389,391,394,397,399],{"class":85,"line":280},[83,390,129],{"class":89},[83,392,393],{"class":93}," traefik\u002Fshared\u002F.htpasswd.example",[83,395,396],{"class":93}," traefik\u002Fshared\u002F.htpasswd",[83,398,176],{"class":175},[83,400,372],{"class":165},[83,402,404,407,410],{"class":85,"line":403},4,[83,405,406],{"class":89},"chmod",[83,408,409],{"class":339}," 0600",[83,411,412],{"class":93}," traefik\u002Facme.json\n",[11,414,415],{},"Después de instalar todo, vaya a Settings -> Live help confgiuration -> Chat configuration -> (Screen sharing) y Check NodeJs support enabled In socket.io path, optional enter \u002Fwsnodejs\u002Fsocket.io",[11,417,418,419],{},"Link del repositorio en ",[420,421,425],"a",{"href":422,"rel":423},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Flivechat",[424],"nofollow","github",[427,428,429],"style",{},"html pre.shiki code .sCK9x, html code.shiki .sCK9x{--shiki-default:#80A665}html pre.shiki code .s7rlk, html code.shiki .s7rlk{--shiki-default:#C98A7D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}html pre.shiki code .sXjYR, html code.shiki .sXjYR{--shiki-default:#C99076}html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sxA9i, html code.shiki .sxA9i{--shiki-default:#4C9A91}",{"title":78,"searchDepth":260,"depth":260,"links":431},[432,433,434,435],{"id":20,"depth":260,"text":21},{"id":37,"depth":260,"text":38},{"id":67,"depth":260,"text":68},{"id":314,"depth":260,"text":315},"2023-06-01","Live Helper es un chat de soporte en vivo de código abierto para aplicaciones web progresivas con integraciones de bot, Voz & Video & ScreenShare, AI y API Rest.",false,"md","\u002Fimg\u002Fposts\u002Fblog\u002Fplayground-live-helper-chat-docker-traefik\u002Flive-helper-chat.jpg","es",{},true,"\u002Fblog\u002Fplayground-live-helper-chat-docker-traefik",{"title":6,"description":437},"blog\u002Fplayground-live-helper-chat-docker-traefik",[448,449,450,451,452],"Chat","Docker","MySQL","PHP","Traefik","_T-tFe2shX6NESr6WGe9V9St6oJRBB4ST59Dpm6FjRY",{"id":455,"title":456,"body":457,"date":3022,"description":3023,"draft":438,"extension":439,"image":3024,"lang":441,"meta":3025,"navigation":443,"path":3026,"seo":3027,"stem":3028,"tags":3029,"__hash__":3034},"blog\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa.md","Cómo preparar un plan de despliegue con Docker, Traefik y Let’s Encrypt para un Microservicio y una PWA",{"type":8,"value":458,"toc":3020},[459,462,465,468,471,474,481,484,487,496,513,518,524,541,546,549,577,582,585,591,596,599,2119,2124,2127,2150,2717,2722,2725,2877,2882,2885,2948,2953,2956,2978,2983,2986,2999,3002,3008,3014,3017],[11,460,461],{},"Traefik es un enrutador perimetral de código abierto que hace que la publicación de sus servicios sea una experiencia fácil y divertida. Recibe solicitudes en nombre de su sistema y descubre qué componentes son responsables de manejarlas.",[11,463,464],{},"Traefik también puede cumplir la función de proxy inverso y balanceador de carga, automatiza la generación de certificados SSL con Letsencrypt, permite configurar middlewares globales por ejemplo para redirección de http a https, prevención de ataques DDOS, y middlewares por servicio como por ejemplo para lanzar una autenticación con .htpasswd.",[11,466,467],{},"Lo que distingue a Traefik, además de sus muchas funciones, es que descubre automáticamente la configuración adecuada para sus servicios. La magia sucede cuando Traefik inspecciona su infraestructura, donde encuentra información relevante y descubre qué servicio atiende qué solicitud.",[11,469,470],{},"Traefik cumple de forma nativa con todas las principales tecnologías de clúster, como Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, y la lista continúa ; y puede manejar muchos al mismo tiempo. (Incluso funciona para software heredado que se ejecuta en bare metal).",[11,472,473],{},"Con Traefik, no hay necesidad de mantener y sincronizar un archivo de configuración separado: todo sucede automáticamente, en tiempo real (sin reinicios, sin interrupciones de conexión). Con Traefik, dedica tiempo a desarrollar e implementar nuevas funciones en su sistema, y ya no a configurar y mantener su estado de funcionamiento.",[11,475,476],{},[477,478],"img",{"alt":479,"src":480},"Traefik Architecture","\u002Fimg\u002Fposts\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa\u002Ftraefik-architecture.png",[11,482,483],{},"El objetivo principal de Traefik es hacerlo simple y que el usuario disfrute de ello.",[11,485,486],{},"Descripción del proyecto y como utilizarlo",[11,488,489,490,495],{},"A continuación se describe el proyecto ",[420,491,494],{"href":492,"rel":493},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Ftraefik-sample",[424],"traefik-sample",", disponible en github, contiene una definición de plan de despliegue con docker-compose, además de:",[23,497,498,501,504,507,510],{},[26,499,500],{},"Generación automática de certificados SSL con Letsencrypt",[26,502,503],{},"Middlewares globales (redirección http a https, rate limit para prevención de ataques DDOS",[26,505,506],{},"Integración con servicios (microservicios con Laravel, Nginx, PWA sea React o Vue, Redis, MySQL, Adminer y Portainer)",[26,508,509],{},"Middleware de servicio para lanzamiento de autenticación htpasswd",[26,511,512],{},"Configuración de logs (si deseas optimizarlo puedes usar logrotate)",[11,514,515],{},[477,516],{"alt":78,"src":517},"\u002Fimg\u002Fposts\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa\u002Ftraefik-architecture-2.png",[11,519,520],{},[521,522,523],"strong",{},"Requisitos",[23,525,526,529,532,535,538],{},[26,527,528],{},"git 2.2 o superior",[26,530,531],{},"docker 20 o superior",[26,533,534],{},"docker-compose 1.20 o superior",[26,536,537],{},"Configura tus claves públicas y privadas con Github para siempre usar SSH con git",[26,539,540],{},"Adrenalina y buena pasión por el código",[11,542,543],{},[521,544,545],{},"## Clona el repositorio",[11,547,548],{},"Clona el proyecto de traefik-sample en tu directorio de trabajo, por ejemplo:",[73,550,552],{"className":75,"code":551,"language":77,"meta":78,"style":78},"mkdir github\ncd github\ngit clone git@github.com:marcotorres\u002Ftraefik-sample.git\n",[80,553,554,562,568],{"__ignoreMap":78},[83,555,556,559],{"class":85,"line":86},[83,557,558],{"class":89},"mkdir",[83,560,561],{"class":93}," github\n",[83,563,564,566],{"class":85,"line":260},[83,565,114],{"class":113},[83,567,561],{"class":93},[83,569,570,572,574],{"class":85,"line":280},[83,571,90],{"class":89},[83,573,94],{"class":93},[83,575,576],{"class":93}," git@github.com:marcotorres\u002Ftraefik-sample.git\n",[11,578,579],{},[521,580,581],{},"## Makefile",[11,583,584],{},"Este repositorio contiene un archivo Makefile con comandos preparados para iniciar los servicios de los contenedores, ver los los, estados de los servicios y poder ingresar a cada contenedor definido en el plan de despliegue del docker-compose.yml",[73,586,589],{"className":587,"code":588,"language":147},[145],".PHONY: help\n\nCMD ?= ''\n\nhelp: ## This help.\n    @awk 'BEGIN {FS = \":.*?## \"} \u002F^[a-zA-Z_-]+:.*?## \u002F {printf \"\\033[36m%-30s\\033[0m %s\\n\", $$1, $$2}' $(MAKEFILE_LIST)\n\n.DEFAULT_GOAL := help\n\nstart:  ## Start the application\n    @echo \"Starting the application\"\n    @docker-compose up -d\n\nrestart:  ## Restart the application\n    @echo \"Restarting the application\"\n    @docker-compose restart\n\nstop:  ## Stop the application\n    @echo \"Stopping the application\"\n    @docker-compose down\n\nstatus:  ## Status the application\n    @echo \"Showing the status for the application\"\n    @docker-compose ps\n\nlogs:   ## Show the all Logs from the application\n    @echo \"Showing all logs for every container\"\n    @docker-compose logs -f --tail=\"50\"\n\ncli_api:  ## Enter to container console from API\n    @echo \"Entering to container console from API\"\n    @docker exec -ti api bash\n\ncli_web:  ## Enter to container console from WEB\n    @echo \"Entering to container console from WEB\"\n    @docker exec -ti web sh\n\ncli_db:  ## Enter to container console from MySQL\n    @echo \"Entering to container console from MySQL\"\n    @docker exec -ti mysql bash\n",[80,590,588],{"__ignoreMap":78},[11,592,593],{},[521,594,595],{},"## docker-compose.yml",[11,597,598],{},"A continuación se muestra el contenido del archivo docker-compose.yml, podemos observar las definición del plan de despliegue de cada servicio.",[73,600,604],{"className":601,"code":602,"language":603,"meta":78,"style":78},"language-yaml shiki shiki-themes vitesse-dark","version: \"3.8\"\n\nnetworks:\n  infra:\n  traefik:\n    external:\n      name: traefik\n  default:\n    driver: bridge\n\nvolumes:\n  traefik_sample_data_portainer:\n  traefik_sample_data_mysql:\n\nservices:\n\n  traefik:\n    image: traefik:v2.3\n    container_name: traefik\n    restart: unless-stopped\n    networks:\n      traefik:\n        ipv4_address: 192.168.90.254\n    security_opt:\n      - no-new-privileges:true\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n      - target: 8080\n        published: 8080\n        protocol: tcp\n        mode: ingress\n    volumes:\n      - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n      - .\u002Ftraefik\u002Ftraefik.yml:\u002Ftraefik.yml\n      - .\u002Ftraefik\u002Facme.json:\u002Facme.json\n      - .\u002Ftraefik\u002Ftraefik.log:\u002Ftraefik.log\n      - .\u002Ftraefik\u002Frules:\u002Frules\n      - .\u002Ftraefik\u002Fshared:\u002Fshared\n    labels:\n      - \"traefik.enable=true\"\n      # router\n      - \"traefik.http.routers.traefik-rtr.entrypoints=websecure\"\n      - \"traefik.http.routers.traefik-rtr.rule=Host(`traefik.$HOSTNAME`)\"\n      - \"traefik.http.routers.traefik-rtr.tls=true\"\n      - \"traefik.http.routers.traefik-rtr.tls.certresolver=le\"\n      # service api\n      - \"traefik.http.routers.traefik-rtr.service=api@internal\"\n      # middlewares\n      - \"traefik.http.routers.traefik-rtr.middlewares=rate-limit@file,myauth@file\"\n\n  api:\n    image: webdevops\u002Fphp-nginx:8.1-alpine\n    container_name: api\n    working_dir: \u002Fapp\n    restart: always\n    networks:\n      - traefik\n      - infra\n    volumes:\n      - .\u002Fapps\u002Fapi:\u002Fapp:rw\n      - .\u002Fnginx\u002Fnginxapi.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n    environment:\n      - WEB_DOCUMENT_ROOT=\u002Fapp\u002Fpublic\n      - VIRTUAL_HOST=api.$HOSTNAME\n    labels:\n      - \"traefik.enable=true\"\n      # router\n      - \"traefik.http.routers.api-rtr.entrypoints=websecure\"\n      - \"traefik.http.routers.api-rtr.rule=Host(`api.$HOSTNAME`)\"\n      - \"traefik.http.routers.api-rtr.tls=true\"\n      - \"traefik.http.routers.api-rtr.tls.certresolver=le\"\n\n  web:\n    image: webdevops\u002Fnginx:latest\n    container_name: web\n    working_dir: \u002Fapp\n    restart: always\n    networks:\n      - traefik\n      - infra\n    volumes:\n      - .\u002Fapps\u002Fweb:\u002Fapp:rw\n    environment:\n      - WEB_DOCUMENT_ROOT=\u002Fapp\u002Fbuild\n      - WEB_ALIAS_DOMAIN=web.$HOSTNAME\n      - WEB_DOCUMENT_INDEX=index.html\n    labels:\n      - \"traefik.enable=true\"\n      # router\n      - \"traefik.http.routers.intranet-rtr.entrypoints=websecure\"\n      - \"traefik.http.routers.intranet-rtr.rule=Host(`web.$HOSTNAME`)\"\n      - \"traefik.http.routers.intranet-rtr.tls=true\"\n      - \"traefik.http.routers.intranet-rtr.tls.certresolver=le\"\n\n  adminer:\n    image: adminer:latest\n    container_name: adminer\n    restart: always\n    networks:\n      - traefik\n      - infra\n    volumes:\n      - .\u002Fadminer\u002Fplugins-enabled:\u002Fvar\u002Fwww\u002Fhtml\u002Fplugins-enabled:rw\n      - .\u002Fadminer\u002Frobots.txt:\u002Fvar\u002Fwww\u002Fhtml\u002Frobots.txt\n    labels:\n      - \"traefik.enable=true\"\n      # router\n      - \"traefik.http.routers.adminer-rtr.entrypoints=websecure\"\n      - \"traefik.http.routers.adminer-rtr.rule=Host(`adminer.$HOSTNAME`)\"\n      - \"traefik.http.routers.adminer-rtr.tls=true\"\n      - \"traefik.http.routers.adminer-rtr.tls.certresolver=le\"\n      # middlewares\n      - \"traefik.http.routers.adminer-rtr.middlewares=rate-limit@file,myauth@file\"\n\n  mysql:\n    image: mysql:8.0.25\n    container_name: mysql\n    working_dir: \u002Fapp\n    restart: on-failure\n    networks:\n      - infra\n    security_opt:\n      - no-new-privileges:true\n    ports:\n      - \"3306:3306\"\n    volumes:\n      - ${PWD}\u002Fdata:\u002Fapp:rw\n      - ${PWD}\u002Fmysql\u002Fmy.cnf:\u002Fetc\u002Fmysql\u002Fconf.d\u002Fmy-over.cnf\n      - traefik_sample_data_mysql:\u002Fvar\u002Flib\u002Fmysql\n    environment:\n      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD\n      MYSQL_DATABASE: $MYSQL_DATABASE\n      MYSQL_USER: $MYSQL_USER\n      MYSQL_PASSWORD: $MYSQL_PASSWORD\n\n  redis:\n    image: redis:alpine\n    container_name: redis\n    restart: unless-stopped\n    ports:\n      - \"6380:6379\"\n    networks:\n      - infra\n    security_opt:\n      - no-new-privileges:true\n\n  portainer:\n    image: portainer\u002Fportainer:latest\n    container_name: portainer\n    restart: unless-stopped\n    command: -H unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\n    networks:\n      traefik:\n        ipv4_address: 192.168.90.253\n    security_opt:\n      - no-new-privileges:true\n    volumes:\n      - itraefik_sample_data_portainer:\u002Fdata\n      - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n    environment:\n      - TZ=$TZ\n    labels:\n      - \"traefik.enable=true\"\n      # router\n      - \"traefik.http.routers.portainer-rtr.entrypoints=websecure\"\n      - \"traefik.http.routers.portainer-rtr.rule=Host(`portainer.$HOSTNAME`)\"\n      - \"traefik.http.routers.portainer-rtr.tls=true\"\n      - \"traefik.http.routers.portainer-rtr.tls.certresolver=le\"\n      # services\n      - \"traefik.http.routers.portainer-rtr.service=portainer-svc\"\n      - \"traefik.http.services.portainer-svc.loadbalancer.server.port=9000\"\n","yaml",[80,605,606,624,629,637,644,652,660,670,678,689,694,702,710,718,723,731,736,743,754,764,775,783,791,802,810,819,827,839,851,864,874,885,896,904,912,920,928,936,944,952,960,972,979,991,1003,1015,1027,1033,1045,1051,1063,1068,1076,1086,1096,1107,1117,1124,1131,1139,1146,1154,1162,1170,1178,1186,1193,1204,1209,1221,1233,1245,1257,1262,1270,1280,1290,1299,1308,1315,1322,1329,1336,1344,1351,1359,1367,1375,1382,1393,1398,1410,1422,1434,1446,1451,1459,1469,1479,1488,1495,1502,1509,1516,1524,1532,1539,1550,1555,1567,1579,1591,1603,1608,1620,1625,1633,1643,1653,1662,1672,1679,1686,1693,1700,1707,1719,1726,1734,1742,1750,1757,1768,1779,1790,1801,1806,1814,1824,1834,1843,1850,1862,1869,1876,1883,1890,1895,1903,1913,1923,1932,1943,1950,1957,1967,1974,1981,1988,1996,2003,2010,2018,2025,2036,2041,2053,2065,2077,2089,2095,2107],{"__ignoreMap":78},[83,607,608,611,614,618,621],{"class":85,"line":86},[83,609,610],{"class":113},"version",[83,612,613],{"class":175},":",[83,615,617],{"class":616},"sNJcY"," \"",[83,619,620],{"class":93},"3.8",[83,622,623],{"class":616},"\"\n",[83,625,626],{"class":85,"line":260},[83,627,628],{"emptyLinePlaceholder":443},"\n",[83,630,631,634],{"class":85,"line":280},[83,632,633],{"class":113},"networks",[83,635,636],{"class":175},":\n",[83,638,639,642],{"class":85,"line":403},[83,640,641],{"class":113},"  infra",[83,643,636],{"class":175},[83,645,647,650],{"class":85,"line":646},5,[83,648,649],{"class":113},"  traefik",[83,651,636],{"class":175},[83,653,655,658],{"class":85,"line":654},6,[83,656,657],{"class":113},"    external",[83,659,636],{"class":175},[83,661,663,666,668],{"class":85,"line":662},7,[83,664,665],{"class":113},"      name",[83,667,613],{"class":175},[83,669,349],{"class":93},[83,671,673,676],{"class":85,"line":672},8,[83,674,675],{"class":113},"  default",[83,677,636],{"class":175},[83,679,681,684,686],{"class":85,"line":680},9,[83,682,683],{"class":113},"    driver",[83,685,613],{"class":175},[83,687,688],{"class":93}," bridge\n",[83,690,692],{"class":85,"line":691},10,[83,693,628],{"emptyLinePlaceholder":443},[83,695,697,700],{"class":85,"line":696},11,[83,698,699],{"class":113},"volumes",[83,701,636],{"class":175},[83,703,705,708],{"class":85,"line":704},12,[83,706,707],{"class":113},"  traefik_sample_data_portainer",[83,709,636],{"class":175},[83,711,713,716],{"class":85,"line":712},13,[83,714,715],{"class":113},"  traefik_sample_data_mysql",[83,717,636],{"class":175},[83,719,721],{"class":85,"line":720},14,[83,722,628],{"emptyLinePlaceholder":443},[83,724,726,729],{"class":85,"line":725},15,[83,727,728],{"class":113},"services",[83,730,636],{"class":175},[83,732,734],{"class":85,"line":733},16,[83,735,628],{"emptyLinePlaceholder":443},[83,737,739,741],{"class":85,"line":738},17,[83,740,649],{"class":113},[83,742,636],{"class":175},[83,744,746,749,751],{"class":85,"line":745},18,[83,747,748],{"class":113},"    image",[83,750,613],{"class":175},[83,752,753],{"class":93}," traefik:v2.3\n",[83,755,757,760,762],{"class":85,"line":756},19,[83,758,759],{"class":113},"    container_name",[83,761,613],{"class":175},[83,763,349],{"class":93},[83,765,767,770,772],{"class":85,"line":766},20,[83,768,769],{"class":113},"    restart",[83,771,613],{"class":175},[83,773,774],{"class":93}," unless-stopped\n",[83,776,778,781],{"class":85,"line":777},21,[83,779,780],{"class":113},"    networks",[83,782,636],{"class":175},[83,784,786,789],{"class":85,"line":785},22,[83,787,788],{"class":113},"      traefik",[83,790,636],{"class":175},[83,792,794,797,799],{"class":85,"line":793},23,[83,795,796],{"class":113},"        ipv4_address",[83,798,613],{"class":175},[83,800,801],{"class":339}," 192.168.90.254\n",[83,803,805,808],{"class":85,"line":804},24,[83,806,807],{"class":113},"    security_opt",[83,809,636],{"class":175},[83,811,813,816],{"class":85,"line":812},25,[83,814,815],{"class":175},"      -",[83,817,818],{"class":93}," no-new-privileges:true\n",[83,820,822,825],{"class":85,"line":821},26,[83,823,824],{"class":113},"    ports",[83,826,636],{"class":175},[83,828,830,832,834,837],{"class":85,"line":829},27,[83,831,815],{"class":175},[83,833,617],{"class":616},[83,835,836],{"class":93},"80:80",[83,838,623],{"class":616},[83,840,842,844,846,849],{"class":85,"line":841},28,[83,843,815],{"class":175},[83,845,617],{"class":616},[83,847,848],{"class":93},"443:443",[83,850,623],{"class":616},[83,852,854,856,859,861],{"class":85,"line":853},29,[83,855,815],{"class":175},[83,857,858],{"class":113}," target",[83,860,613],{"class":175},[83,862,863],{"class":339}," 8080\n",[83,865,867,870,872],{"class":85,"line":866},30,[83,868,869],{"class":113},"        published",[83,871,613],{"class":175},[83,873,863],{"class":339},[83,875,877,880,882],{"class":85,"line":876},31,[83,878,879],{"class":113},"        protocol",[83,881,613],{"class":175},[83,883,884],{"class":93}," tcp\n",[83,886,888,891,893],{"class":85,"line":887},32,[83,889,890],{"class":113},"        mode",[83,892,613],{"class":175},[83,894,895],{"class":93}," ingress\n",[83,897,899,902],{"class":85,"line":898},33,[83,900,901],{"class":113},"    volumes",[83,903,636],{"class":175},[83,905,907,909],{"class":85,"line":906},34,[83,908,815],{"class":175},[83,910,911],{"class":93}," \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n",[83,913,915,917],{"class":85,"line":914},35,[83,916,815],{"class":175},[83,918,919],{"class":93}," .\u002Ftraefik\u002Ftraefik.yml:\u002Ftraefik.yml\n",[83,921,923,925],{"class":85,"line":922},36,[83,924,815],{"class":175},[83,926,927],{"class":93}," .\u002Ftraefik\u002Facme.json:\u002Facme.json\n",[83,929,931,933],{"class":85,"line":930},37,[83,932,815],{"class":175},[83,934,935],{"class":93}," .\u002Ftraefik\u002Ftraefik.log:\u002Ftraefik.log\n",[83,937,939,941],{"class":85,"line":938},38,[83,940,815],{"class":175},[83,942,943],{"class":93}," .\u002Ftraefik\u002Frules:\u002Frules\n",[83,945,947,949],{"class":85,"line":946},39,[83,948,815],{"class":175},[83,950,951],{"class":93}," .\u002Ftraefik\u002Fshared:\u002Fshared\n",[83,953,955,958],{"class":85,"line":954},40,[83,956,957],{"class":113},"    labels",[83,959,636],{"class":175},[83,961,963,965,967,970],{"class":85,"line":962},41,[83,964,815],{"class":175},[83,966,617],{"class":616},[83,968,969],{"class":93},"traefik.enable=true",[83,971,623],{"class":616},[83,973,975],{"class":85,"line":974},42,[83,976,978],{"class":977},"sux-A","      # router\n",[83,980,982,984,986,989],{"class":85,"line":981},43,[83,983,815],{"class":175},[83,985,617],{"class":616},[83,987,988],{"class":93},"traefik.http.routers.traefik-rtr.entrypoints=websecure",[83,990,623],{"class":616},[83,992,994,996,998,1001],{"class":85,"line":993},44,[83,995,815],{"class":175},[83,997,617],{"class":616},[83,999,1000],{"class":93},"traefik.http.routers.traefik-rtr.rule=Host(`traefik.$HOSTNAME`)",[83,1002,623],{"class":616},[83,1004,1006,1008,1010,1013],{"class":85,"line":1005},45,[83,1007,815],{"class":175},[83,1009,617],{"class":616},[83,1011,1012],{"class":93},"traefik.http.routers.traefik-rtr.tls=true",[83,1014,623],{"class":616},[83,1016,1018,1020,1022,1025],{"class":85,"line":1017},46,[83,1019,815],{"class":175},[83,1021,617],{"class":616},[83,1023,1024],{"class":93},"traefik.http.routers.traefik-rtr.tls.certresolver=le",[83,1026,623],{"class":616},[83,1028,1030],{"class":85,"line":1029},47,[83,1031,1032],{"class":977},"      # service api\n",[83,1034,1036,1038,1040,1043],{"class":85,"line":1035},48,[83,1037,815],{"class":175},[83,1039,617],{"class":616},[83,1041,1042],{"class":93},"traefik.http.routers.traefik-rtr.service=api@internal",[83,1044,623],{"class":616},[83,1046,1048],{"class":85,"line":1047},49,[83,1049,1050],{"class":977},"      # middlewares\n",[83,1052,1054,1056,1058,1061],{"class":85,"line":1053},50,[83,1055,815],{"class":175},[83,1057,617],{"class":616},[83,1059,1060],{"class":93},"traefik.http.routers.traefik-rtr.middlewares=rate-limit@file,myauth@file",[83,1062,623],{"class":616},[83,1064,1066],{"class":85,"line":1065},51,[83,1067,628],{"emptyLinePlaceholder":443},[83,1069,1071,1074],{"class":85,"line":1070},52,[83,1072,1073],{"class":113},"  api",[83,1075,636],{"class":175},[83,1077,1079,1081,1083],{"class":85,"line":1078},53,[83,1080,748],{"class":113},[83,1082,613],{"class":175},[83,1084,1085],{"class":93}," webdevops\u002Fphp-nginx:8.1-alpine\n",[83,1087,1089,1091,1093],{"class":85,"line":1088},54,[83,1090,759],{"class":113},[83,1092,613],{"class":175},[83,1094,1095],{"class":93}," api\n",[83,1097,1099,1102,1104],{"class":85,"line":1098},55,[83,1100,1101],{"class":113},"    working_dir",[83,1103,613],{"class":175},[83,1105,1106],{"class":93}," \u002Fapp\n",[83,1108,1110,1112,1114],{"class":85,"line":1109},56,[83,1111,769],{"class":113},[83,1113,613],{"class":175},[83,1115,1116],{"class":93}," always\n",[83,1118,1120,1122],{"class":85,"line":1119},57,[83,1121,780],{"class":113},[83,1123,636],{"class":175},[83,1125,1127,1129],{"class":85,"line":1126},58,[83,1128,815],{"class":175},[83,1130,349],{"class":93},[83,1132,1134,1136],{"class":85,"line":1133},59,[83,1135,815],{"class":175},[83,1137,1138],{"class":93}," infra\n",[83,1140,1142,1144],{"class":85,"line":1141},60,[83,1143,901],{"class":113},[83,1145,636],{"class":175},[83,1147,1149,1151],{"class":85,"line":1148},61,[83,1150,815],{"class":175},[83,1152,1153],{"class":93}," .\u002Fapps\u002Fapi:\u002Fapp:rw\n",[83,1155,1157,1159],{"class":85,"line":1156},62,[83,1158,815],{"class":175},[83,1160,1161],{"class":93}," .\u002Fnginx\u002Fnginxapi.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n",[83,1163,1165,1168],{"class":85,"line":1164},63,[83,1166,1167],{"class":113},"    environment",[83,1169,636],{"class":175},[83,1171,1173,1175],{"class":85,"line":1172},64,[83,1174,815],{"class":175},[83,1176,1177],{"class":93}," WEB_DOCUMENT_ROOT=\u002Fapp\u002Fpublic\n",[83,1179,1181,1183],{"class":85,"line":1180},65,[83,1182,815],{"class":175},[83,1184,1185],{"class":93}," VIRTUAL_HOST=api.$HOSTNAME\n",[83,1187,1189,1191],{"class":85,"line":1188},66,[83,1190,957],{"class":113},[83,1192,636],{"class":175},[83,1194,1196,1198,1200,1202],{"class":85,"line":1195},67,[83,1197,815],{"class":175},[83,1199,617],{"class":616},[83,1201,969],{"class":93},[83,1203,623],{"class":616},[83,1205,1207],{"class":85,"line":1206},68,[83,1208,978],{"class":977},[83,1210,1212,1214,1216,1219],{"class":85,"line":1211},69,[83,1213,815],{"class":175},[83,1215,617],{"class":616},[83,1217,1218],{"class":93},"traefik.http.routers.api-rtr.entrypoints=websecure",[83,1220,623],{"class":616},[83,1222,1224,1226,1228,1231],{"class":85,"line":1223},70,[83,1225,815],{"class":175},[83,1227,617],{"class":616},[83,1229,1230],{"class":93},"traefik.http.routers.api-rtr.rule=Host(`api.$HOSTNAME`)",[83,1232,623],{"class":616},[83,1234,1236,1238,1240,1243],{"class":85,"line":1235},71,[83,1237,815],{"class":175},[83,1239,617],{"class":616},[83,1241,1242],{"class":93},"traefik.http.routers.api-rtr.tls=true",[83,1244,623],{"class":616},[83,1246,1248,1250,1252,1255],{"class":85,"line":1247},72,[83,1249,815],{"class":175},[83,1251,617],{"class":616},[83,1253,1254],{"class":93},"traefik.http.routers.api-rtr.tls.certresolver=le",[83,1256,623],{"class":616},[83,1258,1260],{"class":85,"line":1259},73,[83,1261,628],{"emptyLinePlaceholder":443},[83,1263,1265,1268],{"class":85,"line":1264},74,[83,1266,1267],{"class":113},"  web",[83,1269,636],{"class":175},[83,1271,1273,1275,1277],{"class":85,"line":1272},75,[83,1274,748],{"class":113},[83,1276,613],{"class":175},[83,1278,1279],{"class":93}," webdevops\u002Fnginx:latest\n",[83,1281,1283,1285,1287],{"class":85,"line":1282},76,[83,1284,759],{"class":113},[83,1286,613],{"class":175},[83,1288,1289],{"class":93}," web\n",[83,1291,1293,1295,1297],{"class":85,"line":1292},77,[83,1294,1101],{"class":113},[83,1296,613],{"class":175},[83,1298,1106],{"class":93},[83,1300,1302,1304,1306],{"class":85,"line":1301},78,[83,1303,769],{"class":113},[83,1305,613],{"class":175},[83,1307,1116],{"class":93},[83,1309,1311,1313],{"class":85,"line":1310},79,[83,1312,780],{"class":113},[83,1314,636],{"class":175},[83,1316,1318,1320],{"class":85,"line":1317},80,[83,1319,815],{"class":175},[83,1321,349],{"class":93},[83,1323,1325,1327],{"class":85,"line":1324},81,[83,1326,815],{"class":175},[83,1328,1138],{"class":93},[83,1330,1332,1334],{"class":85,"line":1331},82,[83,1333,901],{"class":113},[83,1335,636],{"class":175},[83,1337,1339,1341],{"class":85,"line":1338},83,[83,1340,815],{"class":175},[83,1342,1343],{"class":93}," .\u002Fapps\u002Fweb:\u002Fapp:rw\n",[83,1345,1347,1349],{"class":85,"line":1346},84,[83,1348,1167],{"class":113},[83,1350,636],{"class":175},[83,1352,1354,1356],{"class":85,"line":1353},85,[83,1355,815],{"class":175},[83,1357,1358],{"class":93}," WEB_DOCUMENT_ROOT=\u002Fapp\u002Fbuild\n",[83,1360,1362,1364],{"class":85,"line":1361},86,[83,1363,815],{"class":175},[83,1365,1366],{"class":93}," WEB_ALIAS_DOMAIN=web.$HOSTNAME\n",[83,1368,1370,1372],{"class":85,"line":1369},87,[83,1371,815],{"class":175},[83,1373,1374],{"class":93}," WEB_DOCUMENT_INDEX=index.html\n",[83,1376,1378,1380],{"class":85,"line":1377},88,[83,1379,957],{"class":113},[83,1381,636],{"class":175},[83,1383,1385,1387,1389,1391],{"class":85,"line":1384},89,[83,1386,815],{"class":175},[83,1388,617],{"class":616},[83,1390,969],{"class":93},[83,1392,623],{"class":616},[83,1394,1396],{"class":85,"line":1395},90,[83,1397,978],{"class":977},[83,1399,1401,1403,1405,1408],{"class":85,"line":1400},91,[83,1402,815],{"class":175},[83,1404,617],{"class":616},[83,1406,1407],{"class":93},"traefik.http.routers.intranet-rtr.entrypoints=websecure",[83,1409,623],{"class":616},[83,1411,1413,1415,1417,1420],{"class":85,"line":1412},92,[83,1414,815],{"class":175},[83,1416,617],{"class":616},[83,1418,1419],{"class":93},"traefik.http.routers.intranet-rtr.rule=Host(`web.$HOSTNAME`)",[83,1421,623],{"class":616},[83,1423,1425,1427,1429,1432],{"class":85,"line":1424},93,[83,1426,815],{"class":175},[83,1428,617],{"class":616},[83,1430,1431],{"class":93},"traefik.http.routers.intranet-rtr.tls=true",[83,1433,623],{"class":616},[83,1435,1437,1439,1441,1444],{"class":85,"line":1436},94,[83,1438,815],{"class":175},[83,1440,617],{"class":616},[83,1442,1443],{"class":93},"traefik.http.routers.intranet-rtr.tls.certresolver=le",[83,1445,623],{"class":616},[83,1447,1449],{"class":85,"line":1448},95,[83,1450,628],{"emptyLinePlaceholder":443},[83,1452,1454,1457],{"class":85,"line":1453},96,[83,1455,1456],{"class":113},"  adminer",[83,1458,636],{"class":175},[83,1460,1462,1464,1466],{"class":85,"line":1461},97,[83,1463,748],{"class":113},[83,1465,613],{"class":175},[83,1467,1468],{"class":93}," adminer:latest\n",[83,1470,1472,1474,1476],{"class":85,"line":1471},98,[83,1473,759],{"class":113},[83,1475,613],{"class":175},[83,1477,1478],{"class":93}," adminer\n",[83,1480,1482,1484,1486],{"class":85,"line":1481},99,[83,1483,769],{"class":113},[83,1485,613],{"class":175},[83,1487,1116],{"class":93},[83,1489,1491,1493],{"class":85,"line":1490},100,[83,1492,780],{"class":113},[83,1494,636],{"class":175},[83,1496,1498,1500],{"class":85,"line":1497},101,[83,1499,815],{"class":175},[83,1501,349],{"class":93},[83,1503,1505,1507],{"class":85,"line":1504},102,[83,1506,815],{"class":175},[83,1508,1138],{"class":93},[83,1510,1512,1514],{"class":85,"line":1511},103,[83,1513,901],{"class":113},[83,1515,636],{"class":175},[83,1517,1519,1521],{"class":85,"line":1518},104,[83,1520,815],{"class":175},[83,1522,1523],{"class":93}," .\u002Fadminer\u002Fplugins-enabled:\u002Fvar\u002Fwww\u002Fhtml\u002Fplugins-enabled:rw\n",[83,1525,1527,1529],{"class":85,"line":1526},105,[83,1528,815],{"class":175},[83,1530,1531],{"class":93}," .\u002Fadminer\u002Frobots.txt:\u002Fvar\u002Fwww\u002Fhtml\u002Frobots.txt\n",[83,1533,1535,1537],{"class":85,"line":1534},106,[83,1536,957],{"class":113},[83,1538,636],{"class":175},[83,1540,1542,1544,1546,1548],{"class":85,"line":1541},107,[83,1543,815],{"class":175},[83,1545,617],{"class":616},[83,1547,969],{"class":93},[83,1549,623],{"class":616},[83,1551,1553],{"class":85,"line":1552},108,[83,1554,978],{"class":977},[83,1556,1558,1560,1562,1565],{"class":85,"line":1557},109,[83,1559,815],{"class":175},[83,1561,617],{"class":616},[83,1563,1564],{"class":93},"traefik.http.routers.adminer-rtr.entrypoints=websecure",[83,1566,623],{"class":616},[83,1568,1570,1572,1574,1577],{"class":85,"line":1569},110,[83,1571,815],{"class":175},[83,1573,617],{"class":616},[83,1575,1576],{"class":93},"traefik.http.routers.adminer-rtr.rule=Host(`adminer.$HOSTNAME`)",[83,1578,623],{"class":616},[83,1580,1582,1584,1586,1589],{"class":85,"line":1581},111,[83,1583,815],{"class":175},[83,1585,617],{"class":616},[83,1587,1588],{"class":93},"traefik.http.routers.adminer-rtr.tls=true",[83,1590,623],{"class":616},[83,1592,1594,1596,1598,1601],{"class":85,"line":1593},112,[83,1595,815],{"class":175},[83,1597,617],{"class":616},[83,1599,1600],{"class":93},"traefik.http.routers.adminer-rtr.tls.certresolver=le",[83,1602,623],{"class":616},[83,1604,1606],{"class":85,"line":1605},113,[83,1607,1050],{"class":977},[83,1609,1611,1613,1615,1618],{"class":85,"line":1610},114,[83,1612,815],{"class":175},[83,1614,617],{"class":616},[83,1616,1617],{"class":93},"traefik.http.routers.adminer-rtr.middlewares=rate-limit@file,myauth@file",[83,1619,623],{"class":616},[83,1621,1623],{"class":85,"line":1622},115,[83,1624,628],{"emptyLinePlaceholder":443},[83,1626,1628,1631],{"class":85,"line":1627},116,[83,1629,1630],{"class":113},"  mysql",[83,1632,636],{"class":175},[83,1634,1636,1638,1640],{"class":85,"line":1635},117,[83,1637,748],{"class":113},[83,1639,613],{"class":175},[83,1641,1642],{"class":93}," mysql:8.0.25\n",[83,1644,1646,1648,1650],{"class":85,"line":1645},118,[83,1647,759],{"class":113},[83,1649,613],{"class":175},[83,1651,1652],{"class":93}," mysql\n",[83,1654,1656,1658,1660],{"class":85,"line":1655},119,[83,1657,1101],{"class":113},[83,1659,613],{"class":175},[83,1661,1106],{"class":93},[83,1663,1665,1667,1669],{"class":85,"line":1664},120,[83,1666,769],{"class":113},[83,1668,613],{"class":175},[83,1670,1671],{"class":93}," on-failure\n",[83,1673,1675,1677],{"class":85,"line":1674},121,[83,1676,780],{"class":113},[83,1678,636],{"class":175},[83,1680,1682,1684],{"class":85,"line":1681},122,[83,1683,815],{"class":175},[83,1685,1138],{"class":93},[83,1687,1689,1691],{"class":85,"line":1688},123,[83,1690,807],{"class":113},[83,1692,636],{"class":175},[83,1694,1696,1698],{"class":85,"line":1695},124,[83,1697,815],{"class":175},[83,1699,818],{"class":93},[83,1701,1703,1705],{"class":85,"line":1702},125,[83,1704,824],{"class":113},[83,1706,636],{"class":175},[83,1708,1710,1712,1714,1717],{"class":85,"line":1709},126,[83,1711,815],{"class":175},[83,1713,617],{"class":616},[83,1715,1716],{"class":93},"3306:3306",[83,1718,623],{"class":616},[83,1720,1722,1724],{"class":85,"line":1721},127,[83,1723,901],{"class":113},[83,1725,636],{"class":175},[83,1727,1729,1731],{"class":85,"line":1728},128,[83,1730,815],{"class":175},[83,1732,1733],{"class":93}," ${PWD}\u002Fdata:\u002Fapp:rw\n",[83,1735,1737,1739],{"class":85,"line":1736},129,[83,1738,815],{"class":175},[83,1740,1741],{"class":93}," ${PWD}\u002Fmysql\u002Fmy.cnf:\u002Fetc\u002Fmysql\u002Fconf.d\u002Fmy-over.cnf\n",[83,1743,1745,1747],{"class":85,"line":1744},130,[83,1746,815],{"class":175},[83,1748,1749],{"class":93}," traefik_sample_data_mysql:\u002Fvar\u002Flib\u002Fmysql\n",[83,1751,1753,1755],{"class":85,"line":1752},131,[83,1754,1167],{"class":113},[83,1756,636],{"class":175},[83,1758,1760,1763,1765],{"class":85,"line":1759},132,[83,1761,1762],{"class":113},"      MYSQL_ROOT_PASSWORD",[83,1764,613],{"class":175},[83,1766,1767],{"class":93}," $MYSQL_ROOT_PASSWORD\n",[83,1769,1771,1774,1776],{"class":85,"line":1770},133,[83,1772,1773],{"class":113},"      MYSQL_DATABASE",[83,1775,613],{"class":175},[83,1777,1778],{"class":93}," $MYSQL_DATABASE\n",[83,1780,1782,1785,1787],{"class":85,"line":1781},134,[83,1783,1784],{"class":113},"      MYSQL_USER",[83,1786,613],{"class":175},[83,1788,1789],{"class":93}," $MYSQL_USER\n",[83,1791,1793,1796,1798],{"class":85,"line":1792},135,[83,1794,1795],{"class":113},"      MYSQL_PASSWORD",[83,1797,613],{"class":175},[83,1799,1800],{"class":93}," $MYSQL_PASSWORD\n",[83,1802,1804],{"class":85,"line":1803},136,[83,1805,628],{"emptyLinePlaceholder":443},[83,1807,1809,1812],{"class":85,"line":1808},137,[83,1810,1811],{"class":113},"  redis",[83,1813,636],{"class":175},[83,1815,1817,1819,1821],{"class":85,"line":1816},138,[83,1818,748],{"class":113},[83,1820,613],{"class":175},[83,1822,1823],{"class":93}," redis:alpine\n",[83,1825,1827,1829,1831],{"class":85,"line":1826},139,[83,1828,759],{"class":113},[83,1830,613],{"class":175},[83,1832,1833],{"class":93}," redis\n",[83,1835,1837,1839,1841],{"class":85,"line":1836},140,[83,1838,769],{"class":113},[83,1840,613],{"class":175},[83,1842,774],{"class":93},[83,1844,1846,1848],{"class":85,"line":1845},141,[83,1847,824],{"class":113},[83,1849,636],{"class":175},[83,1851,1853,1855,1857,1860],{"class":85,"line":1852},142,[83,1854,815],{"class":175},[83,1856,617],{"class":616},[83,1858,1859],{"class":93},"6380:6379",[83,1861,623],{"class":616},[83,1863,1865,1867],{"class":85,"line":1864},143,[83,1866,780],{"class":113},[83,1868,636],{"class":175},[83,1870,1872,1874],{"class":85,"line":1871},144,[83,1873,815],{"class":175},[83,1875,1138],{"class":93},[83,1877,1879,1881],{"class":85,"line":1878},145,[83,1880,807],{"class":113},[83,1882,636],{"class":175},[83,1884,1886,1888],{"class":85,"line":1885},146,[83,1887,815],{"class":175},[83,1889,818],{"class":93},[83,1891,1893],{"class":85,"line":1892},147,[83,1894,628],{"emptyLinePlaceholder":443},[83,1896,1898,1901],{"class":85,"line":1897},148,[83,1899,1900],{"class":113},"  portainer",[83,1902,636],{"class":175},[83,1904,1906,1908,1910],{"class":85,"line":1905},149,[83,1907,748],{"class":113},[83,1909,613],{"class":175},[83,1911,1912],{"class":93}," portainer\u002Fportainer:latest\n",[83,1914,1916,1918,1920],{"class":85,"line":1915},150,[83,1917,759],{"class":113},[83,1919,613],{"class":175},[83,1921,1922],{"class":93}," portainer\n",[83,1924,1926,1928,1930],{"class":85,"line":1925},151,[83,1927,769],{"class":113},[83,1929,613],{"class":175},[83,1931,774],{"class":93},[83,1933,1935,1938,1940],{"class":85,"line":1934},152,[83,1936,1937],{"class":113},"    command",[83,1939,613],{"class":175},[83,1941,1942],{"class":93}," -H unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\n",[83,1944,1946,1948],{"class":85,"line":1945},153,[83,1947,780],{"class":113},[83,1949,636],{"class":175},[83,1951,1953,1955],{"class":85,"line":1952},154,[83,1954,788],{"class":113},[83,1956,636],{"class":175},[83,1958,1960,1962,1964],{"class":85,"line":1959},155,[83,1961,796],{"class":113},[83,1963,613],{"class":175},[83,1965,1966],{"class":339}," 192.168.90.253\n",[83,1968,1970,1972],{"class":85,"line":1969},156,[83,1971,807],{"class":113},[83,1973,636],{"class":175},[83,1975,1977,1979],{"class":85,"line":1976},157,[83,1978,815],{"class":175},[83,1980,818],{"class":93},[83,1982,1984,1986],{"class":85,"line":1983},158,[83,1985,901],{"class":113},[83,1987,636],{"class":175},[83,1989,1991,1993],{"class":85,"line":1990},159,[83,1992,815],{"class":175},[83,1994,1995],{"class":93}," itraefik_sample_data_portainer:\u002Fdata\n",[83,1997,1999,2001],{"class":85,"line":1998},160,[83,2000,815],{"class":175},[83,2002,911],{"class":93},[83,2004,2006,2008],{"class":85,"line":2005},161,[83,2007,1167],{"class":113},[83,2009,636],{"class":175},[83,2011,2013,2015],{"class":85,"line":2012},162,[83,2014,815],{"class":175},[83,2016,2017],{"class":93}," TZ=$TZ\n",[83,2019,2021,2023],{"class":85,"line":2020},163,[83,2022,957],{"class":113},[83,2024,636],{"class":175},[83,2026,2028,2030,2032,2034],{"class":85,"line":2027},164,[83,2029,815],{"class":175},[83,2031,617],{"class":616},[83,2033,969],{"class":93},[83,2035,623],{"class":616},[83,2037,2039],{"class":85,"line":2038},165,[83,2040,978],{"class":977},[83,2042,2044,2046,2048,2051],{"class":85,"line":2043},166,[83,2045,815],{"class":175},[83,2047,617],{"class":616},[83,2049,2050],{"class":93},"traefik.http.routers.portainer-rtr.entrypoints=websecure",[83,2052,623],{"class":616},[83,2054,2056,2058,2060,2063],{"class":85,"line":2055},167,[83,2057,815],{"class":175},[83,2059,617],{"class":616},[83,2061,2062],{"class":93},"traefik.http.routers.portainer-rtr.rule=Host(`portainer.$HOSTNAME`)",[83,2064,623],{"class":616},[83,2066,2068,2070,2072,2075],{"class":85,"line":2067},168,[83,2069,815],{"class":175},[83,2071,617],{"class":616},[83,2073,2074],{"class":93},"traefik.http.routers.portainer-rtr.tls=true",[83,2076,623],{"class":616},[83,2078,2080,2082,2084,2087],{"class":85,"line":2079},169,[83,2081,815],{"class":175},[83,2083,617],{"class":616},[83,2085,2086],{"class":93},"traefik.http.routers.portainer-rtr.tls.certresolver=le",[83,2088,623],{"class":616},[83,2090,2092],{"class":85,"line":2091},170,[83,2093,2094],{"class":977},"      # services\n",[83,2096,2098,2100,2102,2105],{"class":85,"line":2097},171,[83,2099,815],{"class":175},[83,2101,617],{"class":616},[83,2103,2104],{"class":93},"traefik.http.routers.portainer-rtr.service=portainer-svc",[83,2106,623],{"class":616},[83,2108,2110,2112,2114,2117],{"class":85,"line":2109},172,[83,2111,815],{"class":175},[83,2113,617],{"class":616},[83,2115,2116],{"class":93},"traefik.http.services.portainer-svc.loadbalancer.server.port=9000",[83,2118,623],{"class":616},[11,2120,2121],{},[521,2122,2123],{},"## traefik.yml",[11,2125,2126],{},"En esta parte observamos la definición del plan de despliegue de Traefik contenido en traefik.yml, en este punto recuerda que si estas haciendo pruebas con generación del certificado SSL, es mejor que lo hagas descomentando la sección del caServer, para más información sobre el rate limit de letsencrypt puedes revisar la siguiente documentación:",[23,2128,2129,2136,2143],{},[26,2130,2131,2132],{},"Rate limit Letsencrypt production: ",[420,2133,2134],{"href":2134,"rel":2135},"https:\u002F\u002Fletsencrypt.org\u002Fdocs\u002Frate-limits",[424],[26,2137,2138,2139],{},"Rate limit Letsencrypt staging: ",[420,2140,2141],{"href":2141,"rel":2142},"https:\u002F\u002Fletsencrypt.org\u002Fdocs\u002Fstaging-environment",[424],[26,2144,2145,2146],{},"Para consultar la cantidad de certificados que tienes generados: ",[420,2147,2148],{"href":2148,"rel":2149},"https:\u002F\u002Fcrt.sh",[424],[73,2151,2153],{"className":601,"code":2152,"language":603,"meta":78,"style":78},"global:\n  checkNewVersion: true\n  sendAnonymousUsage: true\n\nentryPoints:\n  web:\n    address: \":80\"\n    http:\n      redirections:\n        entryPoint:\n          to: websecure\n          scheme: https\n          permanent: true\n  websecure:\n    address: \":443\"\n  traefik:\n    address: \":8080\"\n\napi:\n  dashboard: true\n  insecure: false\n  debug: true\n\nproviders:\n  docker:\n    endpoint: \"unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\"\n    exposedByDefault: false\n    network: traefik\n    swarmMode: false\n  file:\n    directory: \u002Frules\n    watch: true\n\nlog:\n  filePath: \"\u002Flogs\u002Ftraefik.log\"\n  level: WARN # DEBUG, INFO, WARN, ERROR, FATAL, PANIC\n  format: json\n\naccessLog:\n  filePath: \"\u002Flogs\u002Ftraefik.log\"\n  bufferingSize: 100\n  format: json\n  filters:\n    statusCodes:\n      - \"400-499\"\n    retryAttempts: true\n    minDuration: \"10ms\"\n  fields:\n    defaultMode: keep\n    names:\n      ClientUsername: drop\n    headers:\n      defaultMode: keep\n      names:\n        User-Agent: redact\n        Authorization: drop\n        Content-Type: keep\n\ncertificatesResolvers:\n  le:\n    acme:\n      email: log@traefik-sample.com\n      storage: \"\u002Facme.json\"\n      #caServer: https:\u002F\u002Facme-staging-v02.api.letsencrypt.org\u002Fdirectory # no comentar para pruebas indefinidas\n      httpChallenge:\n        entryPoint: web\n",[80,2154,2155,2162,2173,2182,2186,2193,2199,2213,2220,2227,2234,2244,2254,2263,2270,2283,2289,2302,2306,2313,2322,2332,2341,2345,2352,2359,2373,2382,2391,2400,2407,2417,2426,2430,2437,2451,2464,2474,2478,2485,2497,2507,2515,2522,2529,2540,2549,2563,2570,2580,2587,2597,2604,2613,2620,2630,2639,2648,2652,2659,2666,2673,2683,2697,2702,2709],{"__ignoreMap":78},[83,2156,2157,2160],{"class":85,"line":86},[83,2158,2159],{"class":113},"global",[83,2161,636],{"class":175},[83,2163,2164,2167,2169],{"class":85,"line":260},[83,2165,2166],{"class":113},"  checkNewVersion",[83,2168,613],{"class":175},[83,2170,2172],{"class":2171},"s3QIE"," true\n",[83,2174,2175,2178,2180],{"class":85,"line":280},[83,2176,2177],{"class":113},"  sendAnonymousUsage",[83,2179,613],{"class":175},[83,2181,2172],{"class":2171},[83,2183,2184],{"class":85,"line":403},[83,2185,628],{"emptyLinePlaceholder":443},[83,2187,2188,2191],{"class":85,"line":646},[83,2189,2190],{"class":113},"entryPoints",[83,2192,636],{"class":175},[83,2194,2195,2197],{"class":85,"line":654},[83,2196,1267],{"class":113},[83,2198,636],{"class":175},[83,2200,2201,2204,2206,2208,2211],{"class":85,"line":662},[83,2202,2203],{"class":113},"    address",[83,2205,613],{"class":175},[83,2207,617],{"class":616},[83,2209,2210],{"class":93},":80",[83,2212,623],{"class":616},[83,2214,2215,2218],{"class":85,"line":672},[83,2216,2217],{"class":113},"    http",[83,2219,636],{"class":175},[83,2221,2222,2225],{"class":85,"line":680},[83,2223,2224],{"class":113},"      redirections",[83,2226,636],{"class":175},[83,2228,2229,2232],{"class":85,"line":691},[83,2230,2231],{"class":113},"        entryPoint",[83,2233,636],{"class":175},[83,2235,2236,2239,2241],{"class":85,"line":696},[83,2237,2238],{"class":113},"          to",[83,2240,613],{"class":175},[83,2242,2243],{"class":93}," websecure\n",[83,2245,2246,2249,2251],{"class":85,"line":704},[83,2247,2248],{"class":113},"          scheme",[83,2250,613],{"class":175},[83,2252,2253],{"class":93}," https\n",[83,2255,2256,2259,2261],{"class":85,"line":712},[83,2257,2258],{"class":113},"          permanent",[83,2260,613],{"class":175},[83,2262,2172],{"class":2171},[83,2264,2265,2268],{"class":85,"line":720},[83,2266,2267],{"class":113},"  websecure",[83,2269,636],{"class":175},[83,2271,2272,2274,2276,2278,2281],{"class":85,"line":725},[83,2273,2203],{"class":113},[83,2275,613],{"class":175},[83,2277,617],{"class":616},[83,2279,2280],{"class":93},":443",[83,2282,623],{"class":616},[83,2284,2285,2287],{"class":85,"line":733},[83,2286,649],{"class":113},[83,2288,636],{"class":175},[83,2290,2291,2293,2295,2297,2300],{"class":85,"line":738},[83,2292,2203],{"class":113},[83,2294,613],{"class":175},[83,2296,617],{"class":616},[83,2298,2299],{"class":93},":8080",[83,2301,623],{"class":616},[83,2303,2304],{"class":85,"line":745},[83,2305,628],{"emptyLinePlaceholder":443},[83,2307,2308,2311],{"class":85,"line":756},[83,2309,2310],{"class":113},"api",[83,2312,636],{"class":175},[83,2314,2315,2318,2320],{"class":85,"line":766},[83,2316,2317],{"class":113},"  dashboard",[83,2319,613],{"class":175},[83,2321,2172],{"class":2171},[83,2323,2324,2327,2329],{"class":85,"line":777},[83,2325,2326],{"class":113},"  insecure",[83,2328,613],{"class":175},[83,2330,2331],{"class":2171}," false\n",[83,2333,2334,2337,2339],{"class":85,"line":785},[83,2335,2336],{"class":113},"  debug",[83,2338,613],{"class":175},[83,2340,2172],{"class":2171},[83,2342,2343],{"class":85,"line":793},[83,2344,628],{"emptyLinePlaceholder":443},[83,2346,2347,2350],{"class":85,"line":804},[83,2348,2349],{"class":113},"providers",[83,2351,636],{"class":175},[83,2353,2354,2357],{"class":85,"line":812},[83,2355,2356],{"class":113},"  docker",[83,2358,636],{"class":175},[83,2360,2361,2364,2366,2368,2371],{"class":85,"line":821},[83,2362,2363],{"class":113},"    endpoint",[83,2365,613],{"class":175},[83,2367,617],{"class":616},[83,2369,2370],{"class":93},"unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock",[83,2372,623],{"class":616},[83,2374,2375,2378,2380],{"class":85,"line":829},[83,2376,2377],{"class":113},"    exposedByDefault",[83,2379,613],{"class":175},[83,2381,2331],{"class":2171},[83,2383,2384,2387,2389],{"class":85,"line":841},[83,2385,2386],{"class":113},"    network",[83,2388,613],{"class":175},[83,2390,349],{"class":93},[83,2392,2393,2396,2398],{"class":85,"line":853},[83,2394,2395],{"class":113},"    swarmMode",[83,2397,613],{"class":175},[83,2399,2331],{"class":2171},[83,2401,2402,2405],{"class":85,"line":866},[83,2403,2404],{"class":113},"  file",[83,2406,636],{"class":175},[83,2408,2409,2412,2414],{"class":85,"line":876},[83,2410,2411],{"class":113},"    directory",[83,2413,613],{"class":175},[83,2415,2416],{"class":93}," \u002Frules\n",[83,2418,2419,2422,2424],{"class":85,"line":887},[83,2420,2421],{"class":113},"    watch",[83,2423,613],{"class":175},[83,2425,2172],{"class":2171},[83,2427,2428],{"class":85,"line":898},[83,2429,628],{"emptyLinePlaceholder":443},[83,2431,2432,2435],{"class":85,"line":906},[83,2433,2434],{"class":113},"log",[83,2436,636],{"class":175},[83,2438,2439,2442,2444,2446,2449],{"class":85,"line":914},[83,2440,2441],{"class":113},"  filePath",[83,2443,613],{"class":175},[83,2445,617],{"class":616},[83,2447,2448],{"class":93},"\u002Flogs\u002Ftraefik.log",[83,2450,623],{"class":616},[83,2452,2453,2456,2458,2461],{"class":85,"line":922},[83,2454,2455],{"class":113},"  level",[83,2457,613],{"class":175},[83,2459,2460],{"class":93}," WARN",[83,2462,2463],{"class":977}," # DEBUG, INFO, WARN, ERROR, FATAL, PANIC\n",[83,2465,2466,2469,2471],{"class":85,"line":930},[83,2467,2468],{"class":113},"  format",[83,2470,613],{"class":175},[83,2472,2473],{"class":93}," json\n",[83,2475,2476],{"class":85,"line":938},[83,2477,628],{"emptyLinePlaceholder":443},[83,2479,2480,2483],{"class":85,"line":946},[83,2481,2482],{"class":113},"accessLog",[83,2484,636],{"class":175},[83,2486,2487,2489,2491,2493,2495],{"class":85,"line":954},[83,2488,2441],{"class":113},[83,2490,613],{"class":175},[83,2492,617],{"class":616},[83,2494,2448],{"class":93},[83,2496,623],{"class":616},[83,2498,2499,2502,2504],{"class":85,"line":962},[83,2500,2501],{"class":113},"  bufferingSize",[83,2503,613],{"class":175},[83,2505,2506],{"class":339}," 100\n",[83,2508,2509,2511,2513],{"class":85,"line":974},[83,2510,2468],{"class":113},[83,2512,613],{"class":175},[83,2514,2473],{"class":93},[83,2516,2517,2520],{"class":85,"line":981},[83,2518,2519],{"class":113},"  filters",[83,2521,636],{"class":175},[83,2523,2524,2527],{"class":85,"line":993},[83,2525,2526],{"class":113},"    statusCodes",[83,2528,636],{"class":175},[83,2530,2531,2533,2535,2538],{"class":85,"line":1005},[83,2532,815],{"class":175},[83,2534,617],{"class":616},[83,2536,2537],{"class":93},"400-499",[83,2539,623],{"class":616},[83,2541,2542,2545,2547],{"class":85,"line":1017},[83,2543,2544],{"class":113},"    retryAttempts",[83,2546,613],{"class":175},[83,2548,2172],{"class":2171},[83,2550,2551,2554,2556,2558,2561],{"class":85,"line":1029},[83,2552,2553],{"class":113},"    minDuration",[83,2555,613],{"class":175},[83,2557,617],{"class":616},[83,2559,2560],{"class":93},"10ms",[83,2562,623],{"class":616},[83,2564,2565,2568],{"class":85,"line":1035},[83,2566,2567],{"class":113},"  fields",[83,2569,636],{"class":175},[83,2571,2572,2575,2577],{"class":85,"line":1047},[83,2573,2574],{"class":113},"    defaultMode",[83,2576,613],{"class":175},[83,2578,2579],{"class":93}," keep\n",[83,2581,2582,2585],{"class":85,"line":1053},[83,2583,2584],{"class":113},"    names",[83,2586,636],{"class":175},[83,2588,2589,2592,2594],{"class":85,"line":1065},[83,2590,2591],{"class":113},"      ClientUsername",[83,2593,613],{"class":175},[83,2595,2596],{"class":93}," drop\n",[83,2598,2599,2602],{"class":85,"line":1070},[83,2600,2601],{"class":113},"    headers",[83,2603,636],{"class":175},[83,2605,2606,2609,2611],{"class":85,"line":1078},[83,2607,2608],{"class":113},"      defaultMode",[83,2610,613],{"class":175},[83,2612,2579],{"class":93},[83,2614,2615,2618],{"class":85,"line":1088},[83,2616,2617],{"class":113},"      names",[83,2619,636],{"class":175},[83,2621,2622,2625,2627],{"class":85,"line":1098},[83,2623,2624],{"class":113},"        User-Agent",[83,2626,613],{"class":175},[83,2628,2629],{"class":93}," redact\n",[83,2631,2632,2635,2637],{"class":85,"line":1109},[83,2633,2634],{"class":113},"        Authorization",[83,2636,613],{"class":175},[83,2638,2596],{"class":93},[83,2640,2641,2644,2646],{"class":85,"line":1119},[83,2642,2643],{"class":113},"        Content-Type",[83,2645,613],{"class":175},[83,2647,2579],{"class":93},[83,2649,2650],{"class":85,"line":1126},[83,2651,628],{"emptyLinePlaceholder":443},[83,2653,2654,2657],{"class":85,"line":1133},[83,2655,2656],{"class":113},"certificatesResolvers",[83,2658,636],{"class":175},[83,2660,2661,2664],{"class":85,"line":1141},[83,2662,2663],{"class":113},"  le",[83,2665,636],{"class":175},[83,2667,2668,2671],{"class":85,"line":1148},[83,2669,2670],{"class":113},"    acme",[83,2672,636],{"class":175},[83,2674,2675,2678,2680],{"class":85,"line":1156},[83,2676,2677],{"class":113},"      email",[83,2679,613],{"class":175},[83,2681,2682],{"class":93}," log@traefik-sample.com\n",[83,2684,2685,2688,2690,2692,2695],{"class":85,"line":1164},[83,2686,2687],{"class":113},"      storage",[83,2689,613],{"class":175},[83,2691,617],{"class":616},[83,2693,2694],{"class":93},"\u002Facme.json",[83,2696,623],{"class":616},[83,2698,2699],{"class":85,"line":1172},[83,2700,2701],{"class":977},"      #caServer: https:\u002F\u002Facme-staging-v02.api.letsencrypt.org\u002Fdirectory # no comentar para pruebas indefinidas\n",[83,2703,2704,2707],{"class":85,"line":1180},[83,2705,2706],{"class":113},"      httpChallenge",[83,2708,636],{"class":175},[83,2710,2711,2713,2715],{"class":85,"line":1188},[83,2712,2231],{"class":113},[83,2714,613],{"class":175},[83,2716,1289],{"class":93},[11,2718,2719],{},[521,2720,2721],{},"## middlewares.toml",[11,2723,2724],{},"A continuación se muestra el contenido del archivo middlewares.toml, aquí tenemos la definición de los middlewares para una autenticación básica con htpasswd y prevención de ataques http con un rate limit por minuto de a lo mucho 100 request.",[73,2726,2730],{"className":2727,"code":2728,"language":2729,"meta":78,"style":78},"language-toml shiki shiki-themes vitesse-dark","[http.middlewares]\n    [http.middlewares.myauth]\n        [http.middlewares.myauth.basicAuth]\n            realm = \"Traefik Basic Auth\"\n            usersFile = \"\u002Fshared\u002F.htpasswd\"\n    [http.middlewares.rate-limit]\n        [http.middlewares.rate-limit.rateLimit]\n            average = 100\n            burst = 50\n","toml",[80,2731,2732,2750,2768,2790,2806,2820,2837,2858,2867],{"__ignoreMap":78},[83,2733,2734,2737,2740,2744,2747],{"class":85,"line":86},[83,2735,2736],{"class":175},"[",[83,2738,2739],{"class":89},"http",[83,2741,2743],{"class":2742},"sNpkn",".",[83,2745,2746],{"class":89},"middlewares",[83,2748,2749],{"class":175},"]\n",[83,2751,2752,2755,2757,2759,2761,2763,2766],{"class":85,"line":260},[83,2753,2754],{"class":175},"    [",[83,2756,2739],{"class":89},[83,2758,2743],{"class":2742},[83,2760,2746],{"class":89},[83,2762,2743],{"class":2742},[83,2764,2765],{"class":89},"myauth",[83,2767,2749],{"class":175},[83,2769,2770,2773,2775,2777,2779,2781,2783,2785,2788],{"class":85,"line":280},[83,2771,2772],{"class":175},"        [",[83,2774,2739],{"class":89},[83,2776,2743],{"class":2742},[83,2778,2746],{"class":89},[83,2780,2743],{"class":2742},[83,2782,2765],{"class":89},[83,2784,2743],{"class":2742},[83,2786,2787],{"class":89},"basicAuth",[83,2789,2749],{"class":175},[83,2791,2792,2796,2799,2801,2804],{"class":85,"line":403},[83,2793,2795],{"class":2794},"st-jp","            realm",[83,2797,2798],{"class":175}," =",[83,2800,617],{"class":616},[83,2802,2803],{"class":93},"Traefik Basic Auth",[83,2805,623],{"class":616},[83,2807,2808,2811,2813,2815,2818],{"class":85,"line":646},[83,2809,2810],{"class":2794},"            usersFile",[83,2812,2798],{"class":175},[83,2814,617],{"class":616},[83,2816,2817],{"class":93},"\u002Fshared\u002F.htpasswd",[83,2819,623],{"class":616},[83,2821,2822,2824,2826,2828,2830,2832,2835],{"class":85,"line":654},[83,2823,2754],{"class":175},[83,2825,2739],{"class":89},[83,2827,2743],{"class":2742},[83,2829,2746],{"class":89},[83,2831,2743],{"class":2742},[83,2833,2834],{"class":89},"rate-limit",[83,2836,2749],{"class":175},[83,2838,2839,2841,2843,2845,2847,2849,2851,2853,2856],{"class":85,"line":662},[83,2840,2772],{"class":175},[83,2842,2739],{"class":89},[83,2844,2743],{"class":2742},[83,2846,2746],{"class":89},[83,2848,2743],{"class":2742},[83,2850,2834],{"class":89},[83,2852,2743],{"class":2742},[83,2854,2855],{"class":89},"rateLimit",[83,2857,2749],{"class":175},[83,2859,2860,2863,2865],{"class":85,"line":672},[83,2861,2862],{"class":2794},"            average",[83,2864,2798],{"class":175},[83,2866,2506],{"class":339},[83,2868,2869,2872,2874],{"class":85,"line":680},[83,2870,2871],{"class":2794},"            burst",[83,2873,2798],{"class":175},[83,2875,2876],{"class":339}," 50\n",[11,2878,2879],{},[521,2880,2881],{},"## .env, logs y acme.json",[11,2883,2884],{},"Para poder iniciar el proyecto no te olvides de crear el archivo .env basado en .env.example, puedes ejecutar los siguientes comandos como una pequeña configuración inicial.",[73,2886,2888],{"className":75,"code":2887,"language":77,"meta":78,"style":78},"cp .env.example .env && \\\ncp traefik\u002Facme.json.example traefik\u002Facme.json && \\\ncp traefik\u002Flogs\u002Ftraefik.log.example traefik\u002Flogs\u002Ftraefik.log && \\\ncp traefik\u002Fshared\u002F.htpasswd.example traefik\u002Fshared\u002F.htpasswd && \\\nchmod 0600 traefik\u002Facme.json\n",[80,2889,2890,2904,2916,2928,2940],{"__ignoreMap":78},[83,2891,2892,2894,2897,2900,2902],{"class":85,"line":86},[83,2893,129],{"class":89},[83,2895,2896],{"class":93}," .env.example",[83,2898,2899],{"class":93}," .env",[83,2901,176],{"class":175},[83,2903,372],{"class":165},[83,2905,2906,2908,2910,2912,2914],{"class":85,"line":260},[83,2907,129],{"class":89},[83,2909,364],{"class":93},[83,2911,367],{"class":93},[83,2913,176],{"class":175},[83,2915,372],{"class":165},[83,2917,2918,2920,2922,2924,2926],{"class":85,"line":280},[83,2919,129],{"class":89},[83,2921,379],{"class":93},[83,2923,382],{"class":93},[83,2925,176],{"class":175},[83,2927,372],{"class":165},[83,2929,2930,2932,2934,2936,2938],{"class":85,"line":403},[83,2931,129],{"class":89},[83,2933,393],{"class":93},[83,2935,396],{"class":93},[83,2937,176],{"class":175},[83,2939,372],{"class":165},[83,2941,2942,2944,2946],{"class":85,"line":646},[83,2943,406],{"class":89},[83,2945,409],{"class":339},[83,2947,412],{"class":93},[11,2949,2950],{},[521,2951,2952],{},"## Docker network y repositorios propios",[11,2954,2955],{},"No te olvides de que en la carpera .\u002Fapps\u002Fapi y .\u002Fapps\u002Fweb deben de ir tus proyectos que están en Laravel (microservicio) y React o Vue (PWA) y que antes de levantar los servicios tengas creado un docker network externo, puedes crearlo con el siguiente comando:",[73,2957,2958],{"className":75,"code":321,"language":77,"meta":78,"style":78},[80,2959,2960],{"__ignoreMap":78},[83,2961,2962,2964,2966,2968,2970,2972,2974,2976],{"class":85,"line":86},[83,2963,236],{"class":89},[83,2965,330],{"class":93},[83,2967,333],{"class":93},[83,2969,336],{"class":165},[83,2971,340],{"class":339},[83,2973,343],{"class":165},[83,2975,346],{"class":93},[83,2977,349],{"class":93},[11,2979,2980],{},[521,2981,2982],{},"## Make CLI",[11,2984,2985],{},"Levanta el proyecto ya sea con docker-compose o con make así:",[73,2987,2989],{"className":75,"code":2988,"language":77,"meta":78,"style":78},"make start\n",[80,2990,2991],{"__ignoreMap":78},[83,2992,2993,2996],{"class":85,"line":86},[83,2994,2995],{"class":89},"make",[83,2997,2998],{"class":93}," start\n",[11,3000,3001],{},"Otras utilidades del Makefile:",[11,3003,3004],{},[477,3005],{"alt":3006,"src":3007},"makefile","\u002Fimg\u002Fposts\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa\u002Fmake.png",[11,3009,3010,3011],{},"Más documentación del proyecto en Github, ",[420,3012,494],{"href":492,"rel":3013},[424],[11,3015,3016],{},"Espero que esta guía te haya servido de ayuda, hasta una proxima oportunidad.",[427,3018,3019],{},"html pre.shiki code .sCK9x, html code.shiki .sCK9x{--shiki-default:#80A665}html pre.shiki code .s7rlk, html code.shiki .s7rlk{--shiki-default:#C98A7D}html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sXjYR, html code.shiki .sXjYR{--shiki-default:#C99076}html pre.shiki code .sxA9i, html code.shiki .sxA9i{--shiki-default:#4C9A91}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}html pre.shiki code .sux-A, html code.shiki .sux-A{--shiki-default:#758575DD}html pre.shiki code .s3QIE, html code.shiki .s3QIE{--shiki-default:#4D9375}html pre.shiki code .sNpkn, html code.shiki .sNpkn{--shiki-default:#DBD7CAEE}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}",{"title":78,"searchDepth":260,"depth":260,"links":3021},[],"2022-07-24","Traefik es un enrutador perimetral de código abierto que hace que la publicación de sus servicios sea una experiencia fácil y divertida.","\u002Fimg\u002Fposts\u002Ftraefik-gin-go-mongo-docker-digital-ocean.png",{},"\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa",{"title":456,"description":3023},"blog\u002Fdespliegue-docker-traefik-letsencrypt-pwa",[449,3030,3031,450,451,3032,3033,452],"Laravel","Letsencrypt","Portainer","Redis","kn1NqZ5FxcOLZx_U7OGaB1LtuexIK95Dw6Fedzr1-mA",{"id":3036,"title":3037,"body":3038,"date":3453,"description":3454,"draft":438,"extension":439,"image":3455,"lang":441,"meta":3456,"navigation":443,"path":3457,"seo":3458,"stem":3459,"tags":3460,"__hash__":3463},"blog\u002Fblog\u002Finstalar-oh-my-zsh-con-esteroides.md","Cómo instalar Oh My Zsh con esteroides",{"type":8,"value":3039,"toc":3451},[3040,3043,3046,3049,3061,3080,3083,3099,3104,3130,3143,3175,3180,3211,3214,3277,3280,3283,3291,3339,3342,3355,3358,3363,3366,3381,3384,3426,3429,3440,3448],[11,3041,3042],{},"Oh My Zsh es un marco de código de abierto, motivo por el cual es mantenido por la comunidad, esto nos permite administrar y mejorar nuestra configuración con la shell zsh.",[11,3044,3045],{},"La shell zsh solo está disponible para sistemas operativos basados en UNIX; en el caso de Linux describiremos la instalación para las distros basados en Debian (Ubuntu) y Fedora (Centos).",[11,3047,3048],{},"Siga los siguientes pasos para poder instalar tanto la shell como Oh My Zsh:",[11,3050,3051,3054,3057],{},[521,3052,3053],{},"1. Instalar Oh My Zsh",[3055,3056],"br",{},[3058,3059,3060],"em",{},"Ubuntu",[73,3062,3064],{"className":75,"code":3063,"language":77,"meta":78,"style":78},"sudo apt-get install zsh\n",[80,3065,3066],{"__ignoreMap":78},[83,3067,3068,3071,3074,3077],{"class":85,"line":86},[83,3069,3070],{"class":89},"sudo",[83,3072,3073],{"class":93}," apt-get",[83,3075,3076],{"class":93}," install",[83,3078,3079],{"class":93}," zsh\n",[11,3081,3082],{},"En la última versión de la distro ya no es necesario instalar git, pero en caso lo necesite",[73,3084,3086],{"className":75,"code":3085,"language":77,"meta":78,"style":78},"sudo apt-get install git-core\n",[80,3087,3088],{"__ignoreMap":78},[83,3089,3090,3092,3094,3096],{"class":85,"line":86},[83,3091,3070],{"class":89},[83,3093,3073],{"class":93},[83,3095,3076],{"class":93},[83,3097,3098],{"class":93}," git-core\n",[11,3100,3101],{},[3058,3102,3103],{},"Centos",[73,3105,3107],{"className":75,"code":3106,"language":77,"meta":78,"style":78},"sudo yum install zsh\nsudo yum install git-core\n",[80,3108,3109,3120],{"__ignoreMap":78},[83,3110,3111,3113,3116,3118],{"class":85,"line":86},[83,3112,3070],{"class":89},[83,3114,3115],{"class":93}," yum",[83,3117,3076],{"class":93},[83,3119,3079],{"class":93},[83,3121,3122,3124,3126,3128],{"class":85,"line":260},[83,3123,3070],{"class":89},[83,3125,3115],{"class":93},[83,3127,3076],{"class":93},[83,3129,3098],{"class":93},[11,3131,3132,3135,3137,3138,3140],{},[521,3133,3134],{},"2. Instalar shell Zsh",[3055,3136],{},"\nRecuerda que al momento de instalar Oh My Zsh, este se instala para el usuario actual que está utilizando la distro.",[3055,3139],{},[3058,3141,3142],{},"Vía curl",[73,3144,3146],{"className":75,"code":3145,"language":77,"meta":78,"style":78},"sh -c \"$(curl -fsSL https:\u002F\u002Fraw.github.com\u002Fohmyzsh\u002Fohmyzsh\u002Fmaster\u002Ftools\u002Finstall.sh)\"\n",[80,3147,3148],{"__ignoreMap":78},[83,3149,3150,3153,3156,3158,3161,3164,3167,3170,3173],{"class":85,"line":86},[83,3151,3152],{"class":89},"sh",[83,3154,3155],{"class":165}," -c",[83,3157,617],{"class":616},[83,3159,3160],{"class":175},"$(",[83,3162,3163],{"class":89},"curl",[83,3165,3166],{"class":165}," -fsSL",[83,3168,3169],{"class":93}," https:\u002F\u002Fraw.github.com\u002Fohmyzsh\u002Fohmyzsh\u002Fmaster\u002Ftools\u002Finstall.sh",[83,3171,3172],{"class":175},")",[83,3174,623],{"class":616},[11,3176,3177],{},[3058,3178,3179],{},"Vía wget",[73,3181,3183],{"className":75,"code":3182,"language":77,"meta":78,"style":78},"sh -c \"$(wget https:\u002F\u002Fraw.github.com\u002Fohmyzsh\u002Fohmyzsh\u002Fmaster\u002Ftools\u002Finstall.sh -O -)\"\n",[80,3184,3185],{"__ignoreMap":78},[83,3186,3187,3189,3191,3193,3195,3198,3201,3204,3207,3209],{"class":85,"line":86},[83,3188,3152],{"class":89},[83,3190,3155],{"class":165},[83,3192,617],{"class":616},[83,3194,3160],{"class":175},[83,3196,3197],{"class":89},"wget",[83,3199,3200],{"class":93}," https:\u002F\u002Fraw.github.com\u002Fohmyzsh\u002Fohmyzsh\u002Fmaster\u002Ftools\u002Finstall.sh ",[83,3202,3203],{"class":165},"-O",[83,3205,3206],{"class":93}," -",[83,3208,3172],{"class":175},[83,3210,623],{"class":616},[11,3212,3213],{},"En ocasiones es necesario establecer zsh como shell por defecto, a continuación varios comandos a tomar en cuenta:",[73,3215,3217],{"className":75,"code":3216,"language":77,"meta":78,"style":78},"chsh -s `which zsh`\nchsh -s $(which zsh)\nusermod -s $(which zsh) $(whoami)\n",[80,3218,3219,3239,3255],{"__ignoreMap":78},[83,3220,3221,3224,3227,3230,3233,3236],{"class":85,"line":86},[83,3222,3223],{"class":89},"chsh",[83,3225,3226],{"class":165}," -s",[83,3228,3229],{"class":175}," `",[83,3231,3232],{"class":113},"which",[83,3234,3235],{"class":93}," zsh",[83,3237,3238],{"class":175},"`\n",[83,3240,3241,3243,3245,3248,3250,3252],{"class":85,"line":260},[83,3242,3223],{"class":89},[83,3244,3226],{"class":165},[83,3246,3247],{"class":175}," $(",[83,3249,3232],{"class":113},[83,3251,3235],{"class":93},[83,3253,3254],{"class":175},")\n",[83,3256,3257,3260,3262,3264,3266,3268,3270,3272,3275],{"class":85,"line":280},[83,3258,3259],{"class":89},"usermod",[83,3261,3226],{"class":165},[83,3263,3247],{"class":175},[83,3265,3232],{"class":113},[83,3267,3235],{"class":93},[83,3269,3172],{"class":175},[83,3271,3247],{"class":175},[83,3273,3274],{"class":89},"whoami",[83,3276,3254],{"class":175},[11,3278,3279],{},"Si te aparece el mensaje non-standard shell, tendrás que añadir la nueva shell a la lista de shells permitidas por el sistema operativo, para ello copia la ruta completa de la shell (que puedes averiguar con el comando which zsh) y pégala en el archivo \u002Fetc\u002Fshells, una vez realizado esto vuelve a ejecutar el comando antes mencionado.",[11,3281,3282],{},"También puedes editar manualmente el archivo \u002Fetc\u002Fpasswd",[11,3284,3285,3288,3290],{},[521,3286,3287],{},"3. Instalar plugins",[3055,3289],{},"\nYa ubicados con la shell zsh, clonamos los siguientes plugins adicionales:",[73,3292,3294],{"className":75,"code":3293,"language":77,"meta":78,"style":78},"git clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-syntax-highlighting.git $ZSH_CUSTOM\u002Fplugins\u002Fzsh-syntax-highlighting\ngit clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-autosuggestions $ZSH_CUSTOM\u002Fplugins\u002Fzsh-autosuggestions\ngit clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fantigen.git $ZSH_CUSTOM\u002Fplugins\u002Fantigen\n",[80,3295,3296,3311,3325],{"__ignoreMap":78},[83,3297,3298,3300,3302,3305,3308],{"class":85,"line":86},[83,3299,90],{"class":89},[83,3301,94],{"class":93},[83,3303,3304],{"class":93}," https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-syntax-highlighting.git",[83,3306,3307],{"class":2794}," $ZSH_CUSTOM",[83,3309,3310],{"class":93},"\u002Fplugins\u002Fzsh-syntax-highlighting\n",[83,3312,3313,3315,3317,3320,3322],{"class":85,"line":260},[83,3314,90],{"class":89},[83,3316,94],{"class":93},[83,3318,3319],{"class":93}," https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-autosuggestions",[83,3321,3307],{"class":2794},[83,3323,3324],{"class":93},"\u002Fplugins\u002Fzsh-autosuggestions\n",[83,3326,3327,3329,3331,3334,3336],{"class":85,"line":280},[83,3328,90],{"class":89},[83,3330,94],{"class":93},[83,3332,3333],{"class":93}," https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fantigen.git",[83,3335,3307],{"class":2794},[83,3337,3338],{"class":93},"\u002Fplugins\u002Fantigen\n",[11,3340,3341],{},"Editamos con vim el siguiente archivo ~\u002F.zshrc:",[73,3343,3345],{"className":75,"code":3344,"language":77,"meta":78,"style":78},"vim ~\u002F.zshrc\n",[80,3346,3347],{"__ignoreMap":78},[83,3348,3349,3352],{"class":85,"line":86},[83,3350,3351],{"class":89},"vim",[83,3353,3354],{"class":93}," ~\u002F.zshrc\n",[11,3356,3357],{},"Configuramos en los siguientes puntos:",[11,3359,3360],{},[477,3361],{"alt":78,"src":3362},"\u002Fimg\u002Fposts\u002Fblog\u002Finstalar-oh-my-zsh-con-esteroides\u002Fzshrc-config.png",[11,3364,3365],{},"Configuramos la sección de plugins:",[73,3367,3369],{"className":75,"code":3368,"language":77,"meta":78,"style":78},"git zsh-syntax-highlighting zsh-autosuggestions\n",[80,3370,3371],{"__ignoreMap":78},[83,3372,3373,3375,3378],{"class":85,"line":86},[83,3374,90],{"class":89},[83,3376,3377],{"class":93}," zsh-syntax-highlighting",[83,3379,3380],{"class":93}," zsh-autosuggestions\n",[11,3382,3383],{},"Antigen es un gestor de plugins para zsh, que actúa de intermediario entre nosotros y el fichero de configuración .zshrc (con antigen es mucho más fácil su gestión).",[73,3385,3387],{"className":75,"code":3386,"language":77,"meta":78,"style":78},"source ${ZSH_CUSTOM:-~\u002F.oh-my-zsh\u002Fcustom}\u002Fplugins\u002Fantigen\u002Fantigen.zsh\n",[80,3388,3389],{"__ignoreMap":78},[83,3390,3391,3394,3397,3400,3404,3407,3410,3412,3415,3417,3420,3423],{"class":85,"line":86},[83,3392,3393],{"class":113},"source",[83,3395,3396],{"class":175}," ${",[83,3398,3399],{"class":2794},"ZSH_CUSTOM",[83,3401,3403],{"class":3402},"s_wWq",":-",[83,3405,3406],{"class":2742},"~",[83,3408,3409],{"class":3402},"\u002F",[83,3411,2743],{"class":2742},[83,3413,3414],{"class":2794},"oh-my-zsh",[83,3416,3409],{"class":3402},[83,3418,3419],{"class":2794},"custom",[83,3421,3422],{"class":175},"}",[83,3424,3425],{"class":93},"\u002Fplugins\u002Fantigen\u002Fantigen.zsh\n",[11,3427,3428],{},"Recargamos la configuración:",[73,3430,3432],{"className":75,"code":3431,"language":77,"meta":78,"style":78},"source ~\u002F.zshrc\n",[80,3433,3434],{"__ignoreMap":78},[83,3435,3436,3438],{"class":85,"line":86},[83,3437,3393],{"class":113},[83,3439,3354],{"class":93},[11,3441,3442,3443],{},"Documentación del producto en ",[420,3444,3447],{"href":3445,"rel":3446},"https:\u002F\u002Fohmyz.sh",[424],"Oh My Zsh",[427,3449,3450],{},"html pre.shiki code .sCK9x, html code.shiki .sCK9x{--shiki-default:#80A665}html pre.shiki code .s7rlk, html code.shiki .s7rlk{--shiki-default:#C98A7D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sXjYR, html code.shiki .sXjYR{--shiki-default:#C99076}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}html pre.shiki code .s_wWq, html code.shiki .s_wWq{--shiki-default:#CB7676}html pre.shiki code .sNpkn, html code.shiki .sNpkn{--shiki-default:#DBD7CAEE}",{"title":78,"searchDepth":260,"depth":260,"links":3452},[],"2022-07-18","Oh My Zsh es un marco de código abierto, motivo por el cual es mantenido por la comunidad; esto nos permite administrar y mejorar nuestra configuración con la shell zsh.","\u002Fimg\u002Fposts\u002Foh-my-zsh.png",{},"\u002Fblog\u002Finstalar-oh-my-zsh-con-esteroides",{"title":3037,"description":3454},"blog\u002Finstalar-oh-my-zsh-con-esteroides",[3461,3462,3447],"Shell","Zsh","jKvsV7I_NHI1ywkE0rjBiW7sN21d6z5x-bP3L-a6eu4",1786343040832]