[{"data":1,"prerenderedAt":8939},["ShallowReactive",2],{"blog-\u002Fblog\u002Freto-tecnico-fullstack-angular-express-firebase":3,"blog-related-all":432},{"id":4,"title":5,"body":6,"date":415,"description":416,"draft":417,"extension":418,"image":419,"lang":420,"meta":421,"navigation":422,"path":423,"seo":424,"stem":425,"tags":426,"__hash__":431},"blog\u002Fblog\u002Freto-tecnico-fullstack-angular-express-firebase.md","De un reto técnico a un SPA full-stack: Angular 19, Express y Firebase",{"type":7,"value":8,"toc":406},"minimark",[9,18,23,26,60,89,92,96,99,106,113,117,120,289,296,300,303,331,335,338,371,374,391],[10,11,12,13,17],"p",{},"Una startup de mensajería en tiempo real me lanzó un reto técnico full-stack: construir una aplicación de tareas completa, con login, CRUD y estado, en pocos días. El detalle divertido es que el frontend pedía ",[14,15,16],"strong",{},"Angular",", un framework que hasta ese momento nunca había tocado. Aun así, no bajé el listón: entregué un SPA con arquitectura limpia, un API desacoplado y buenas prácticas de punta a punta. Este es el detrás de escena —las decisiones técnicas, no solo el resultado— y lo que revela de cómo trabajo.",[19,20,22],"h2",{"id":21},"el-reto","El reto",[10,24,25],{},"Sobre el papel sonaba a un «Todo app» más. En la práctica, el enunciado estaba diseñado para medir criterio de arquitectura, no para ver si sabías pintar una lista. Lo que pedían:",[27,28,29,36,42,48,54],"ul",{},[30,31,32,35],"li",{},[14,33,34],{},"Dos páginas."," Un inicio de sesión y un tablero principal con las tareas del usuario ordenadas por fecha de creación.",[30,37,38,41],{},[14,39,40],{},"Login solo con correo."," Si el usuario existe, entra directo; si no, aparece un diálogo que confirma su creación y luego pasa al tablero.",[30,43,44,47],{},[14,45,46],{},"CRUD de tareas."," Cada tarea con título, descripción, fecha de creación y estado; crear, editar, eliminar y marcar como completada o pendiente con una casilla.",[30,49,50,53],{},[14,51,52],{},"Responsive"," y usable en cualquier dispositivo.",[30,55,56,59],{},[14,57,58],{},"Un API propio"," con Express y TypeScript, desplegado en Cloud Functions, con Firestore como base de datos, y seis endpoints: listar, crear, actualizar y eliminar tareas, más buscar y crear usuario.",[61,62,64],"note",{"title":63},"Cómo se evaluaba (el listón real)",[10,65,66,67,70,71,75,76,80,81,84,85,88],{},"El enunciado era explícito: se prioriza ",[14,68,69],{},"la calidad del código y las buenas prácticas por encima de la cantidad de funcionalidades",". En concreto miraban arquitectura limpia o hexagonal, principios SOLID, patrones de diseño (repositorios, factories, singletons), observables y servicios bien estructurados en el frontend, ",[72,73,74],"code",{},"trackBy"," en las listas, guards y ",[77,78,79],"em",{},"lazy loading",", seguridad con tokens y CORS, pruebas unitarias, y un README útil. En otras palabras: no querían ver ",[77,82,83],{},"qué"," construyes, sino ",[77,86,87],{},"cómo"," decides.",[10,90,91],{},"Esa última frase fue mi brújula. Preferí entregar menos superficie, pero cada pieza en su sitio.",[19,93,95],{"id":94},"arquitectura-de-un-vistazo","Arquitectura de un vistazo",[10,97,98],{},"Antes de escribir una línea, dibujé el flujo completo: un cliente Angular que habla por HTTP con un API Express desplegado como función serverless, que a su vez persiste en Firestore. Cada petición viaja autenticada con un token; cada capa tiene una única responsabilidad.",[10,100,101],{},[102,103],"img",{"alt":104,"src":105},"Diagrama de arquitectura: el navegador ejecuta un SPA de Angular 19 con rutas lazy y guards; se comunica por HTTP con JWT contra un API Express + TypeScript desplegado en Firebase Cloud Functions, organizado en capas hexagonales (controllers, casos de uso, repositorios); los repositorios persisten en Cloud Firestore en las colecciones users y tasks","\u002Fimg\u002Fposts\u002Fblog\u002Freto-tecnico-fullstack-angular-express-firebase\u002Freto-fullstack-arquitectura.svg",[10,107,108,109,112],{},"La idea de fondo es simple: ",[14,110,111],{},"el cliente no sabe nada de Firestore y el dominio no sabe nada de Express."," Cada frontera está ahí para que una decisión de infraestructura (cambiar la base de datos, mover el hosting) no se filtre al resto.",[19,114,116],{"id":115},"las-decisiones-técnicas","Las decisiones técnicas",[10,118,119],{},"Aquí está el corazón del reto. Separé el trabajo en tres frentes y en cada uno tomé decisiones deliberadas.",[121,122,123,205,250],"tabs",{},[124,125,128,133],"tabs-item",{"icon":126,"label":127},"fab fa-angular","Frontend",[10,129,130],{},[14,131,132],{},"Angular 19, aprendido sobre la marcha, pero con criterio.",[27,134,135,149,166,176,183,195],{},[30,136,137,143,144,148],{},[14,138,139,140],{},"Componentes ",[77,141,142],{},"standalone"," y funcionalidades cargadas con ",[77,145,146],{},[14,147,79],{},", para que el navegador solo descargue lo que la ruta necesita.",[30,150,151,154,155,158,159,165],{},[14,152,153],{},"Estado con Angular Signals"," —el enfoque moderno del framework— y ",[14,156,157],{},"RxJS"," para las llamadas al API, que la plantilla consume con el ",[14,160,161,164],{},[72,162,163],{},"async"," pipe",": nada de suscripciones colgadas que limpiar a mano.",[30,167,168,171,172,175],{},[14,169,170],{},"Dos guards",": uno de autenticación protege el tablero, y otro de ",[14,173,174],{},"habilidad (CASL)"," decide qué puede hacer cada rol antes de entrar a una ruta.",[30,177,178,179,182],{},"Un ",[14,180,181],{},"interceptor HTTP"," adjunta el token a cada petición de forma centralizada.",[30,184,185,188,189,194],{},[14,186,187],{},"Formularios reactivos"," con validación tipada, y ",[14,190,191,193],{},[72,192,74],{}," en la lista"," para que Angular no repinte el DOM entero en cada cambio.",[30,196,197,200,201,204],{},[14,198,199],{},"Angular Material + TailwindCSS",", con una arquitectura modular ",[72,202,203],{},"core \u002F features \u002F shared"," y una interfaz responsive y accesible.",[124,206,209,214,217,243],{"icon":207,"label":208},"fas fa-server","Backend",[10,210,211],{},[14,212,213],{},"Express + TypeScript con arquitectura hexagonal.",[10,215,216],{},"Organicé el API en capas con dependencias que apuntan siempre hacia el dominio:",[27,218,219,225,231],{},[30,220,221,224],{},[14,222,223],{},"Controllers"," (rutas Express): reciben la petición, validan, aplican CORS y verifican el token. Nada de lógica de negocio aquí.",[30,226,227,230],{},[14,228,229],{},"Casos de uso",": las reglas del problema —crear tarea, alternar estado, dar de alta un usuario— expresadas sin depender de ningún framework. Aquí viven los principios SOLID.",[30,232,233,236,237,239,240,242],{},[14,234,235],{},"Repositorios"," (puerto y adaptador): una interfaz define ",[77,238,83],{}," se persiste; la implementación de Firestore define ",[77,241,87],{},". El dominio depende de la interfaz, no de Firebase.",[10,244,245,246,249],{},"Todo desplegado como una ",[14,247,248],{},"Cloud Function",", con DTOs para no exponer la forma interna de los datos y los secretos fuera del código.",[124,251,254,259],{"icon":252,"label":253},"fas fa-database","Datos",[10,255,256],{},[14,257,258],{},"Firestore, con un modelo mínimo y claro.",[27,260,261,270,286],{},[30,262,263,264,269],{},"Colección ",[14,265,266],{},[72,267,268],{},"users"," para el alta y la búsqueda por correo.",[30,271,263,272,277,278,281,282,285],{},[14,273,274],{},[72,275,276],{},"tasks",", cada tarea con su título, descripción, estado y ",[72,279,280],{},"createdAt",", que además sirve para devolverlas ",[14,283,284],{},"ordenadas por fecha de creación",", tal como pedía el enunciado.",[30,287,288],{},"El acceso pasa siempre por el repositorio: si mañana Firestore se cambia por Postgres, solo se reescribe ese adaptador.",[290,291,293],"tip",{"title":292},"Por qué la arquitectura hexagonal aquí",[10,294,295],{},"Para una lista de tareas puede sonar a sobreingeniería. No lo era: el reto medía justamente esto. Separar dominio, aplicación e infraestructura convierte «funciona» en «funciona y se puede mantener», y demuestra que sé dónde poner cada responsabilidad aunque el dominio sea pequeño.",[19,297,299],{"id":298},"el-flujo-de-usuario-paso-a-paso","El flujo de usuario, paso a paso",[10,301,302],{},"Con la arquitectura resuelta, la experiencia quedó exactamente como pedía el enunciado:",[304,305,306,313,319,325],"steps",{},[307,308,310],"step",{"title":309},"Inicia sesión con el correo",[10,311,312],{},"El usuario escribe solo su email. El frontend pregunta al API si ya existe.",[307,314,316],{"title":315},"Confirma la creación si es nuevo",[10,317,318],{},"Si el correo no está registrado, un diálogo pregunta si quiere crear la cuenta. Al aceptar, se da de alta y entra directo, sin fricción extra.",[307,320,322],{"title":321},"Gestiona sus tareas",[10,323,324],{},"En el tablero ve sus tareas ordenadas por fecha. Puede agregar una nueva desde un formulario, editarla o eliminarla.",[307,326,328],{"title":327},"Marca el progreso",[10,329,330],{},"Una casilla alterna cada tarea entre completada y pendiente, con la interfaz respondiendo al instante gracias a los observables.",[19,332,334],{"id":333},"qué-demuestra-esto","Qué demuestra esto",[10,336,337],{},"El reto no era la lista de tareas; era la excusa. Lo que realmente entregué fue una forma de trabajar:",[27,339,340,349,359,365],{},[30,341,342,345,346,348],{},[14,343,344],{},"Aprendí Angular sobre la marcha sin sacrificar la calidad."," Enfrentar un framework nuevo bajo presión y aun así aplicar ",[77,347,79],{},", guards y estado con signals como se debe dice más que cualquier certificación.",[30,350,351,354,355,358],{},[14,352,353],{},"Fui más allá de lo pedido donde aportaba valor."," El enunciado invitaba a sumar extras; añadí ",[14,356,357],{},"permisos por roles con CASL"," —con su guard de habilidad y su página de acceso denegado— para mostrar cómo modelo autorización de verdad, no solo un login.",[30,360,361,364],{},[14,362,363],{},"Prioricé criterio sobre cantidad",", tal como pedía la nota del enunciado: cada pieza con una arquitectura que puedo defender.",[30,366,367,370],{},[14,368,369],{},"Pensé en el mantenimiento desde el día uno."," Un dominio desacoplado de la infraestructura es lo que separa un prototipo de algo que un equipo puede hacer crecer.",[10,372,373],{},"Esa es, al final, la mentalidad senior: no solo resolver el problema de hoy, sino dejar el código listo para el de mañana.",[290,375,377],{"title":376},"¿Tienes un reto así?",[10,378,379,380,385,386,390],{},"Si necesitas a alguien que llegue a un stack nuevo y entregue arquitectura sólida —no solo código que compila—, ",[381,382,384],"a",{"href":383},"\u002Fcontact","hablemos",". Puedes ver cómo trabajo en la página de ",[381,387,389],{"href":388},"\u002Fservices","servicios",".",[10,392,393,394,400,401,390],{},"El código completo está en los repositorios del ",[381,395,399],{"href":396,"rel":397},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Ftodo-app",[398],"nofollow","frontend en Angular"," y del ",[381,402,405],{"href":403,"rel":404},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Ftodo-api",[398],"API en Express",{"title":407,"searchDepth":408,"depth":408,"links":409},"",2,[410,411,412,413,414],{"id":21,"depth":408,"text":22},{"id":94,"depth":408,"text":95},{"id":115,"depth":408,"text":116},{"id":298,"depth":408,"text":299},{"id":333,"depth":408,"text":334},"2026-08-25","Caso de estudio: cómo resolví un reto técnico full-stack —una app de tareas con login, CRUD y estado— con Angular 19, un API Express + TypeScript en Cloud Functions y Firestore, aplicando arquitectura hexagonal, SOLID y buenas prácticas.",false,"md","\u002Fimg\u002Fposts\u002Fcovers\u002Freto-tecnico-fullstack-angular-express-firebase.svg","es",{},true,"\u002Fblog\u002Freto-tecnico-fullstack-angular-express-firebase",{"title":5,"description":416},"blog\u002Freto-tecnico-fullstack-angular-express-firebase",[16,427,428,429,430],"Express","TypeScript","Firebase","Arquitectura","0UgLerbAd5O_HJgUcu3niA9PC-3vfhlDHQK8B7Z5ag4",[433,688,1243,3939,4707,6672],{"id":4,"title":5,"body":434,"date":415,"description":416,"draft":417,"extension":418,"image":419,"lang":420,"meta":685,"navigation":422,"path":423,"seo":686,"stem":425,"tags":687,"__hash__":431},{"type":7,"value":435,"toc":678},[436,440,442,444,466,480,482,484,486,490,494,496,498,608,612,614,616,634,636,638,660,662,670],[10,437,12,438,17],{},[14,439,16],{},[19,441,22],{"id":21},[10,443,25],{},[27,445,446,450,454,458,462],{},[30,447,448,35],{},[14,449,34],{},[30,451,452,41],{},[14,453,40],{},[30,455,456,47],{},[14,457,46],{},[30,459,460,53],{},[14,461,52],{},[30,463,464,59],{},[14,465,58],{},[61,467,468],{"title":63},[10,469,66,470,70,472,75,474,80,476,84,478,88],{},[14,471,69],{},[72,473,74],{},[77,475,79],{},[77,477,83],{},[77,479,87],{},[10,481,91],{},[19,483,95],{"id":94},[10,485,98],{},[10,487,488],{},[102,489],{"alt":104,"src":105},[10,491,108,492,112],{},[14,493,111],{},[19,495,116],{"id":115},[10,497,119],{},[121,499,500,552,582],{},[124,501,502,506],{"icon":126,"label":127},[10,503,504],{},[14,505,132],{},[27,507,508,518,528,534,538,546],{},[30,509,510,143,514,148],{},[14,511,139,512],{},[77,513,142],{},[77,515,516],{},[14,517,79],{},[30,519,520,154,522,158,524,165],{},[14,521,153],{},[14,523,157],{},[14,525,526,164],{},[72,527,163],{},[30,529,530,171,532,175],{},[14,531,170],{},[14,533,174],{},[30,535,178,536,182],{},[14,537,181],{},[30,539,540,188,542,194],{},[14,541,187],{},[14,543,544,193],{},[72,545,74],{},[30,547,548,200,550,204],{},[14,549,199],{},[72,551,203],{},[124,553,554,558,560,578],{"icon":207,"label":208},[10,555,556],{},[14,557,213],{},[10,559,216],{},[27,561,562,566,570],{},[30,563,564,224],{},[14,565,223],{},[30,567,568,230],{},[14,569,229],{},[30,571,572,236,574,239,576,242],{},[14,573,235],{},[77,575,83],{},[77,577,87],{},[10,579,245,580,249],{},[14,581,248],{},[124,583,584,588],{"icon":252,"label":253},[10,585,586],{},[14,587,258],{},[27,589,590,596,606],{},[30,591,263,592,269],{},[14,593,594],{},[72,595,268],{},[30,597,263,598,277,602,281,604,285],{},[14,599,600],{},[72,601,276],{},[72,603,280],{},[14,605,284],{},[30,607,288],{},[290,609,610],{"title":292},[10,611,295],{},[19,613,299],{"id":298},[10,615,302],{},[304,617,618,622,626,630],{},[307,619,620],{"title":309},[10,621,312],{},[307,623,624],{"title":315},[10,625,318],{},[307,627,628],{"title":321},[10,629,324],{},[307,631,632],{"title":327},[10,633,330],{},[19,635,334],{"id":333},[10,637,337],{},[27,639,640,646,652,656],{},[30,641,642,345,644,348],{},[14,643,344],{},[77,645,79],{},[30,647,648,354,650,358],{},[14,649,353],{},[14,651,357],{},[30,653,654,364],{},[14,655,363],{},[30,657,658,370],{},[14,659,369],{},[10,661,373],{},[290,663,664],{"title":376},[10,665,379,666,385,668,390],{},[381,667,384],{"href":383},[381,669,389],{"href":388},[10,671,393,672,400,675,390],{},[381,673,399],{"href":396,"rel":674},[398],[381,676,405],{"href":403,"rel":677},[398],{"title":407,"searchDepth":408,"depth":408,"links":679},[680,681,682,683,684],{"id":21,"depth":408,"text":22},{"id":94,"depth":408,"text":95},{"id":115,"depth":408,"text":116},{"id":298,"depth":408,"text":299},{"id":333,"depth":408,"text":334},{},{"title":5,"description":416},[16,427,428,429,430],{"id":689,"title":690,"body":691,"date":1230,"description":1231,"draft":417,"extension":418,"image":1232,"lang":420,"meta":1233,"navigation":422,"path":1234,"seo":1235,"stem":1236,"tags":1237,"__hash__":1242},"blog\u002Fblog\u002Fplayground-live-helper-chat-docker-traefik.md","Playground de Live Helper Chat con Docker, Traefik, MySQL y Redis",{"type":7,"value":692,"toc":1225},[693,699,714,720,724,735,739,746,804,808,1192,1213,1221],[10,694,695,698],{},[14,696,697],{},"Live Helper Chat"," es un chat de soporte en vivo de código abierto para aplicaciones web progresivas (PWA). Incluye integraciones con bots, voz, vídeo y pantalla compartida, inteligencia artificial y una API REST.",[10,700,701,702,705,706,709,710,713],{},"En esta guía te muestro cómo levantar un ",[77,703,704],{},"playground"," de Live Helper Chat con Docker, Traefik, MySQL y Redis. Existen dos versiones: una basada en ",[14,707,708],{},"PHP"," y otra con el complemento de ",[14,711,712],{},"NodeJS",". Elige la que prefieras; el resto del proceso es idéntico.",[10,715,716],{},[102,717],{"alt":718,"src":719},"Arquitectura del playground de Live Helper Chat con Docker: Traefik enruta al servicio web (Nginx + PHP-FPM) respaldado por MySQL y Redis, todo orquestado con docker-compose","\u002Fimg\u002Fposts\u002Fblog\u002Fplayground-live-helper-chat-docker-traefik\u002Flhc-arquitectura.svg",[19,721,723],{"id":722},"requisitos","Requisitos",[27,725,726,729,732],{},[30,727,728],{},"Git 2.2 o superior",[30,730,731],{},"Docker 20 o superior",[30,733,734],{},"Docker Compose 1.20 o superior",[19,736,738],{"id":737},"servicios-configurados","Servicios configurados",[10,740,741,742,745],{},"El ",[77,743,744],{},"stack"," levanta ocho servicios coordinados con Docker Compose:",[747,748,749,756,763,770,777,784,791,798],"card-group",{},[750,751,753],"card",{"icon":207,"title":752},"web",[10,754,755],{},"Servidor web Nginx: recibe las peticiones y las reenvía a PHP-FPM.",[750,757,760],{"icon":758,"title":759},"fab fa-php","php",[10,761,762],{},"Servicio PHP-FPM que ejecuta la aplicación.",[750,764,767],{"icon":765,"title":766},"fas fa-desktop","cobrowse",[10,768,769],{},"Co-navegación (co-browsing) sobre NodeJS.",[750,771,774],{"icon":772,"title":773},"fas fa-clock","php-cronjob",[10,775,776],{},"Tareas programadas (cron) de la aplicación.",[750,778,781],{"icon":779,"title":780},"fas fa-list-check","php-resque",[10,782,783],{},"Worker de colas php-resque para trabajos en segundo plano.",[750,785,788],{"icon":786,"title":787},"fab fa-node-js","nodejshelper",[10,789,790],{},"Complemento NodeJS para funciones en tiempo real.",[750,792,795],{"icon":793,"title":794},"fas fa-bolt","redis",[10,796,797],{},"Caché y almacén en memoria.",[750,799,801],{"icon":252,"title":800},"db",[10,802,803],{},"Base de datos MySQL.",[19,805,807],{"id":806},"instrucciones-de-docker","Instrucciones de Docker",[304,809,810,848,891,983,1089],{},[307,811,813],{"title":812},"Clona el repositorio y entra en la carpeta",[814,815,819],"pre",{"className":816,"code":817,"language":818,"meta":407,"style":407},"language-bash shiki shiki-themes vitesse-dark","git clone git@github.com:marcotorres\u002Flivechat.git docker-standalone\ncd docker-standalone\n","bash",[72,820,821,840],{"__ignoreMap":407},[822,823,826,830,834,837],"span",{"class":824,"line":825},"line",1,[822,827,829],{"class":828},"sCK9x","git",[822,831,833],{"class":832},"s7rlk"," clone",[822,835,836],{"class":832}," git@github.com:marcotorres\u002Flivechat.git",[822,838,839],{"class":832}," docker-standalone\n",[822,841,842,846],{"class":824,"line":408},[822,843,845],{"class":844},"sm68I","cd",[822,847,839],{"class":832},[307,849,851,854,870,880,883],{"title":850},"Configura las variables de entorno",[10,852,853],{},"Copia el archivo de ejemplo y edítalo:",[814,855,857],{"className":816,"code":856,"language":818,"meta":407,"style":407},"cp .env.default .env\n",[72,858,859],{"__ignoreMap":407},[822,860,861,864,867],{"class":824,"line":825},[822,862,863],{"class":828},"cp",[822,865,866],{"class":832}," .env.default",[822,868,869],{"class":832}," .env\n",[290,871,873],{"title":872},"Genera un hash seguro",[10,874,875,876,879],{},"Cambia el valor de ",[72,877,878],{},"LHC_SECRET_HASH"," por una cadena aleatoria. Es la clave que firma la sesión de la aplicación, así que no la dejes con el valor por defecto.",[10,881,882],{},"Ajusta también las variables relacionadas con la base de datos:",[814,884,889],{"className":885,"code":887,"language":888},[886],"language-text","Host - db\nDatabase name - lhc_database\nDatabase username - lhc_usr\nDatabase password - lhc_password\n","text",[72,890,887],{"__ignoreMap":407},[307,892,894,905],{"title":893},"Levanta los servicios",[10,895,896,897,900,901,904],{},"Elige la versión que quieras usar. El comando descarga las imágenes (",[72,898,899],{},"pull",") y arranca los contenedores en segundo plano (",[72,902,903],{},"up -d","); durante el arranque se verifica Live Helper Chat y las extensiones necesarias.",[121,906,907,950],{},[124,908,910,913],{"icon":758,"label":909},"Estándar (PHP)",[10,911,912],{},"Versión estándar, sin el complemento NodeJS:",[814,914,916],{"className":816,"code":915,"language":818,"meta":407,"style":407},"docker-compose -f docker-compose-standard.yml pull && docker-compose -f docker-compose-standard.yml up -d\n",[72,917,918],{"__ignoreMap":407},[822,919,920,923,927,930,933,937,940,942,944,947],{"class":824,"line":825},[822,921,922],{"class":828},"docker-compose",[822,924,926],{"class":925},"sXjYR"," -f",[822,928,929],{"class":832}," docker-compose-standard.yml",[822,931,932],{"class":832}," pull",[822,934,936],{"class":935},"s_pn2"," &&",[822,938,939],{"class":828}," docker-compose",[822,941,926],{"class":925},[822,943,929],{"class":832},[822,945,946],{"class":832}," up",[822,948,949],{"class":925}," -d\n",[124,951,952,955],{"icon":786,"label":712},[10,953,954],{},"Versión con el complemento NodeJS:",[814,956,958],{"className":816,"code":957,"language":818,"meta":407,"style":407},"docker-compose -f docker-compose-nodejs.yml pull && docker-compose -f docker-compose-nodejs.yml up -d\n",[72,959,960],{"__ignoreMap":407},[822,961,962,964,966,969,971,973,975,977,979,981],{"class":824,"line":825},[822,963,922],{"class":828},[822,965,926],{"class":925},[822,967,968],{"class":832}," docker-compose-nodejs.yml",[822,970,932],{"class":832},[822,972,936],{"class":935},[822,974,939],{"class":828},[822,976,926],{"class":925},[822,978,968],{"class":832},[822,980,946],{"class":832},[822,982,949],{"class":925},[307,984,986,993],{"title":985},"Abre el instalador",[10,987,988,989,992],{},"Navega a ",[72,990,991],{},"localhost:8081"," y sigue las instrucciones de instalación.",[61,994,996,999,1069,1072],{"title":995},"Permisos de carpetas",[10,997,998],{},"En los primeros pasos puede que necesites ajustar los permisos de algunas carpetas:",[814,1000,1002],{"className":816,"code":1001,"language":818,"meta":407,"style":407},"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",[72,1003,1004,1030,1049],{"__ignoreMap":407},[822,1005,1006,1009,1012,1015,1018,1021,1024,1027],{"class":824,"line":825},[822,1007,1008],{"class":828},"docker",[822,1010,1011],{"class":832}," exec",[822,1013,1014],{"class":925}," -it",[822,1016,1017],{"class":832}," dockerstandalone_web_1",[822,1019,1020],{"class":832}," chown",[822,1022,1023],{"class":925}," -R",[822,1025,1026],{"class":832}," www-data:www-data",[822,1028,1029],{"class":832}," \u002Fcode\u002Fcache\n",[822,1031,1032,1034,1036,1038,1040,1042,1044,1046],{"class":824,"line":408},[822,1033,1008],{"class":828},[822,1035,1011],{"class":832},[822,1037,1014],{"class":925},[822,1039,1017],{"class":832},[822,1041,1020],{"class":832},[822,1043,1023],{"class":925},[822,1045,1026],{"class":832},[822,1047,1048],{"class":832}," \u002Fcode\u002Fsettings\n",[822,1050,1052,1054,1056,1058,1060,1062,1064,1066],{"class":824,"line":1051},3,[822,1053,1008],{"class":828},[822,1055,1011],{"class":832},[822,1057,1014],{"class":925},[822,1059,1017],{"class":832},[822,1061,1020],{"class":832},[822,1063,1023],{"class":925},[822,1065,1026],{"class":832},[822,1067,1068],{"class":832}," \u002Fcode\u002Fvar\n",[10,1070,1071],{},"Estas son las carpetas afectadas:",[27,1073,1074,1079,1084],{},[30,1075,1076],{},[72,1077,1078],{},"livehelperchat\u002Flhc_web\u002Fcache",[30,1080,1081],{},[72,1082,1083],{},"livehelperchat\u002Flhc_web\u002Fsettings",[30,1085,1086],{},[72,1087,1088],{},"livehelperchat\u002Flhc_web\u002Fvar",[307,1090,1092,1095,1098,1129,1132],{"title":1091},"Configura Traefik (opcional)",[10,1093,1094],{},"Si quieres exponer el chat con HTTPS a través de Traefik, prepara la red y los archivos de configuración.",[10,1096,1097],{},"Crea la red:",[814,1099,1101],{"className":816,"code":1100,"language":818,"meta":407,"style":407},"docker network create --gateway 192.168.90.1 --subnet 192.168.90.0\u002F24 traefik\n",[72,1102,1103],{"__ignoreMap":407},[822,1104,1105,1107,1110,1113,1116,1120,1123,1126],{"class":824,"line":825},[822,1106,1008],{"class":828},[822,1108,1109],{"class":832}," network",[822,1111,1112],{"class":832}," create",[822,1114,1115],{"class":925}," --gateway",[822,1117,1119],{"class":1118},"sxA9i"," 192.168.90.1",[822,1121,1122],{"class":925}," --subnet",[822,1124,1125],{"class":832}," 192.168.90.0\u002F24",[822,1127,1128],{"class":832}," traefik\n",[10,1130,1131],{},"Copia los archivos de ejemplo y ajusta los permisos:",[814,1133,1135],{"className":816,"code":1134,"language":818,"meta":407,"style":407},"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",[72,1136,1137,1152,1166,1180],{"__ignoreMap":407},[822,1138,1139,1141,1144,1147,1149],{"class":824,"line":825},[822,1140,863],{"class":828},[822,1142,1143],{"class":832}," traefik\u002Facme.json.example",[822,1145,1146],{"class":832}," traefik\u002Facme.json",[822,1148,936],{"class":935},[822,1150,1151],{"class":925}," \\\n",[822,1153,1154,1156,1159,1162,1164],{"class":824,"line":408},[822,1155,863],{"class":828},[822,1157,1158],{"class":832}," traefik\u002Flogs\u002Ftraefik.log.example",[822,1160,1161],{"class":832}," traefik\u002Flogs\u002Ftraefik.log",[822,1163,936],{"class":935},[822,1165,1151],{"class":925},[822,1167,1168,1170,1173,1176,1178],{"class":824,"line":1051},[822,1169,863],{"class":828},[822,1171,1172],{"class":832}," traefik\u002Fshared\u002F.htpasswd.example",[822,1174,1175],{"class":832}," traefik\u002Fshared\u002F.htpasswd",[822,1177,936],{"class":935},[822,1179,1151],{"class":925},[822,1181,1183,1186,1189],{"class":824,"line":1182},4,[822,1184,1185],{"class":828},"chmod",[822,1187,1188],{"class":1118}," 0600",[822,1190,1191],{"class":832}," traefik\u002Facme.json\n",[290,1193,1195],{"title":1194},"Habilita la pantalla compartida",[10,1196,1197,1198,1201,1202,1205,1206,1209,1210,390],{},"Cuando termines la instalación, ve a ",[14,1199,1200],{},"Settings → Live helper configuration → Chat configuration → (Screen sharing)"," y marca ",[14,1203,1204],{},"«NodeJs support enabled»",". En el campo ",[14,1207,1208],{},"socket.io path"," puedes indicar, opcionalmente, ",[72,1211,1212],{},"\u002Fwsnodejs\u002Fsocket.io",[10,1214,1215,1216,390],{},"Tienes el código completo en el ",[381,1217,1220],{"href":1218,"rel":1219},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Flivechat",[398],"repositorio de GitHub",[1222,1223,1224],"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 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 .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":407,"searchDepth":408,"depth":408,"links":1226},[1227,1228,1229],{"id":722,"depth":408,"text":723},{"id":737,"depth":408,"text":738},{"id":806,"depth":408,"text":807},"2023-06-01","Guía paso a paso para levantar Live Helper Chat —el chat de soporte en vivo de código abierto— con Docker, Traefik, MySQL y Redis, en sus versiones PHP y NodeJS.","\u002Fimg\u002Fposts\u002Fcovers\u002Fplayground-live-helper-chat-docker-traefik.svg",{},"\u002Fblog\u002Fplayground-live-helper-chat-docker-traefik",{"title":690,"description":1231},"blog\u002Fplayground-live-helper-chat-docker-traefik",[1238,1239,1240,708,1241],"Chat","Docker","MySQL","Traefik","rc355QYYjnHDnCsfZ3pCWlupiuQKrBubXJuqv3b9iXY",{"id":1244,"title":1245,"body":1246,"date":3926,"description":3927,"draft":417,"extension":418,"image":3928,"lang":420,"meta":3929,"navigation":422,"path":3930,"seo":3931,"stem":3932,"tags":3933,"__hash__":3938},"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":7,"value":1247,"toc":3920},[1248,1257,1272,1278,1281,1287,1291,1303,1348,1354,1356,1370,1374,1571,1575,1578,3910,3917],[10,1249,1250,1252,1253,1256],{},[14,1251,1241],{}," es un enrutador perimetral (",[77,1254,1255],{},"edge router",") de código abierto que hace que publicar tus servicios sea sencillo. Recibe las solicitudes en nombre de tu sistema y descubre qué componente debe atender cada una.",[10,1258,1259,1260,1263,1264,1267,1268,1271],{},"Además de actuar como proxy inverso y balanceador de carga, automatiza la generación de certificados SSL con Let's Encrypt y permite configurar ",[77,1261,1262],{},"middlewares",": globales (por ejemplo, redirección de HTTP a HTTPS o ",[77,1265,1266],{},"rate limit"," para mitigar ataques DDoS) y por servicio (como una autenticación básica con ",[72,1269,1270],{},".htpasswd",").",[10,1273,1274,1275,1271],{},"Lo que lo distingue es que descubre la configuración automáticamente: inspecciona tu infraestructura, encuentra la información relevante y deduce qué servicio atiende cada solicitud. Cumple de forma nativa con las principales tecnologías de clúster —Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon…— y puede manejar varias a la vez (incluso software heredado que corre en ",[77,1276,1277],{},"bare metal",[10,1279,1280],{},"Con Traefik no necesitas mantener ni sincronizar un archivo de configuración aparte: todo ocurre automáticamente y en tiempo real, sin reinicios ni cortes de conexión. Así dedicas tu tiempo a construir funcionalidades, no a mantener la configuración.",[10,1282,1283],{},[102,1284],{"alt":1285,"src":1286},"Flujo de despliegue con Traefik: Internet y el cliente entran por Traefik (reverse proxy con TLS de Let's Encrypt) que enruta a los servicios Laravel, PWA, Redis y MySQL","\u002Fimg\u002Fposts\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa\u002Ftraefik-flow-overview.svg",[19,1288,1290],{"id":1289},"el-proyecto-traefik-sample","El proyecto: traefik-sample",[10,1292,1293,1294,1299,1300,1302],{},"A continuación describo el proyecto ",[381,1295,1298],{"href":1296,"rel":1297},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Ftraefik-sample",[398],"traefik-sample",", disponible en GitHub. Contiene una definición de plan de despliegue con ",[72,1301,922],{}," que incluye:",[747,1304,1305,1312,1322,1329,1338],{},[750,1306,1309],{"icon":1307,"title":1308},"fas fa-lock","SSL automático",[10,1310,1311],{},"Certificados TLS con Let's Encrypt, renovados automáticamente.",[750,1313,1316],{"icon":1314,"title":1315},"fas fa-shield-halved","Middlewares globales",[10,1317,1318,1319,1321],{},"Redirección de HTTP a HTTPS y ",[77,1320,1266],{}," para mitigar ataques DDoS.",[750,1323,1326],{"icon":1324,"title":1325},"fas fa-cubes-stacked","Servicios integrados",[10,1327,1328],{},"Microservicio Laravel + Nginx, PWA (React o Vue), Redis, MySQL, Adminer y Portainer.",[750,1330,1333],{"icon":1331,"title":1332},"fas fa-key","Autenticación por servicio",[10,1334,1335,1336,390],{},"Middleware de autenticación básica con ",[72,1337,1270],{},[750,1339,1342],{"icon":1340,"title":1341},"fas fa-file-lines","Logs configurables",[10,1343,1344,1345,1271],{},"Registro listo para producción (puedes rotarlo con ",[72,1346,1347],{},"logrotate",[10,1349,1350],{},[102,1351],{"alt":1352,"src":1353},"Diagrama del proyecto traefik-sample: Traefik enrutando a microservicios Laravel, PWA, Redis, MySQL y Portainer con SSL de Let's Encrypt","\u002Fimg\u002Fposts\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa\u002Ftraefik-architecture-2.png",[19,1355,723],{"id":722},[27,1357,1358,1360,1362,1364,1367],{},[30,1359,728],{},[30,1361,731],{},[30,1363,734],{},[30,1365,1366],{},"Tus claves SSH configuradas en GitHub (para clonar por SSH)",[30,1368,1369],{},"Adrenalina y buena pasión por el código",[19,1371,1373],{"id":1372},"puesta-en-marcha","Puesta en marcha",[304,1375,1376,1413,1491,1523,1543],{},[307,1377,1379,1385],{"title":1378},"Clona el repositorio",[10,1380,1381,1382,1384],{},"Clona el proyecto ",[72,1383,1298],{}," en tu directorio de trabajo, por ejemplo:",[814,1386,1388],{"className":816,"code":1387,"language":818,"meta":407,"style":407},"mkdir github\ncd github\ngit clone git@github.com:marcotorres\u002Ftraefik-sample.git\n",[72,1389,1390,1398,1404],{"__ignoreMap":407},[822,1391,1392,1395],{"class":824,"line":825},[822,1393,1394],{"class":828},"mkdir",[822,1396,1397],{"class":832}," github\n",[822,1399,1400,1402],{"class":824,"line":408},[822,1401,845],{"class":844},[822,1403,1397],{"class":832},[822,1405,1406,1408,1410],{"class":824,"line":1051},[822,1407,829],{"class":828},[822,1409,833],{"class":832},[822,1411,1412],{"class":832}," git@github.com:marcotorres\u002Ftraefik-sample.git\n",[307,1414,1416,1427],{"title":1415},"Prepara los archivos de entorno",[10,1417,1418,1419,1422,1423,1426],{},"Crea el archivo ",[72,1420,1421],{},".env"," a partir de ",[72,1424,1425],{},".env.example"," y deja listos los archivos de logs y de certificados:",[814,1428,1430],{"className":816,"code":1429,"language":818,"meta":407,"style":407},"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",[72,1431,1432,1446,1458,1470,1482],{"__ignoreMap":407},[822,1433,1434,1436,1439,1442,1444],{"class":824,"line":825},[822,1435,863],{"class":828},[822,1437,1438],{"class":832}," .env.example",[822,1440,1441],{"class":832}," .env",[822,1443,936],{"class":935},[822,1445,1151],{"class":925},[822,1447,1448,1450,1452,1454,1456],{"class":824,"line":408},[822,1449,863],{"class":828},[822,1451,1143],{"class":832},[822,1453,1146],{"class":832},[822,1455,936],{"class":935},[822,1457,1151],{"class":925},[822,1459,1460,1462,1464,1466,1468],{"class":824,"line":1051},[822,1461,863],{"class":828},[822,1463,1158],{"class":832},[822,1465,1161],{"class":832},[822,1467,936],{"class":935},[822,1469,1151],{"class":925},[822,1471,1472,1474,1476,1478,1480],{"class":824,"line":1182},[822,1473,863],{"class":828},[822,1475,1172],{"class":832},[822,1477,1175],{"class":832},[822,1479,936],{"class":935},[822,1481,1151],{"class":925},[822,1483,1485,1487,1489],{"class":824,"line":1484},5,[822,1486,1185],{"class":828},[822,1488,1188],{"class":1118},[822,1490,1191],{"class":832},[307,1492,1494,1501],{"title":1493},"Crea la red de Docker",[10,1495,1496,1497,1500],{},"Traefik usa una red externa que debe existir ",[14,1498,1499],{},"antes"," de levantar los servicios:",[814,1502,1503],{"className":816,"code":1100,"language":818,"meta":407,"style":407},[72,1504,1505],{"__ignoreMap":407},[822,1506,1507,1509,1511,1513,1515,1517,1519,1521],{"class":824,"line":825},[822,1508,1008],{"class":828},[822,1510,1109],{"class":832},[822,1512,1112],{"class":832},[822,1514,1115],{"class":925},[822,1516,1119],{"class":1118},[822,1518,1122],{"class":925},[822,1520,1125],{"class":832},[822,1522,1128],{"class":832},[307,1524,1526],{"title":1525},"Coloca tus proyectos",[61,1527,1529],{"title":1528},"Tus apps van en .\u002Fapps",[10,1530,1531,1532,1535,1536,1539,1540,390],{},"Copia tu microservicio Laravel en ",[72,1533,1534],{},".\u002Fapps\u002Fapi"," y tu PWA (React o Vue) en ",[72,1537,1538],{},".\u002Fapps\u002Fweb",". Traefik las enrutará automáticamente según las etiquetas del ",[72,1541,1542],{},"docker-compose.yml",[307,1544,1546,1549,1562,1565],{"title":1545},"Levanta el proyecto",[10,1547,1548],{},"Puedes usar Docker Compose directamente o el atajo del Makefile:",[814,1550,1552],{"className":816,"code":1551,"language":818,"meta":407,"style":407},"make start\n",[72,1553,1554],{"__ignoreMap":407},[822,1555,1556,1559],{"class":824,"line":825},[822,1557,1558],{"class":828},"make",[822,1560,1561],{"class":832}," start\n",[10,1563,1564],{},"El Makefile trae más utilidades para ver logs y estados, y para entrar a cada contenedor:",[10,1566,1567],{},[102,1568],{"alt":1569,"src":1570},"Comandos disponibles en el Makefile del proyecto traefik-sample","\u002Fimg\u002Fposts\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa\u002Fmake.png",[19,1572,1574],{"id":1573},"los-archivos-de-configuración","Los archivos de configuración",[10,1576,1577],{},"Estos son los archivos clave del proyecto. Explóralos según lo que necesites:",[121,1579,1580,1595,3120,3743],{},[124,1581,1584,1589],{"icon":1582,"label":1583},"fas fa-terminal","Makefile",[10,1585,1586,1587,390],{},"Comandos listos para iniciar, reiniciar y detener los servicios, ver sus logs y estados, y entrar a cada contenedor definido en el ",[72,1588,1542],{},[814,1590,1593],{"className":1591,"code":1592,"language":888},[886],".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",[72,1594,1592],{"__ignoreMap":407},[124,1596,1598,1601],{"icon":1597,"label":1542},"fab fa-docker",[10,1599,1600],{},"La definición del plan de despliegue de cada servicio.",[814,1602,1606],{"className":1603,"code":1604,"language":1605,"meta":407,"style":407},"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      - traefik_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",[72,1607,1608,1626,1631,1639,1646,1653,1661,1671,1679,1690,1695,1703,1711,1719,1724,1732,1737,1744,1755,1765,1776,1784,1792,1803,1811,1820,1828,1840,1852,1865,1875,1886,1897,1905,1913,1921,1929,1937,1945,1953,1961,1973,1980,1992,2004,2016,2028,2034,2046,2052,2064,2069,2077,2087,2097,2108,2118,2125,2132,2140,2147,2155,2163,2171,2179,2187,2194,2205,2210,2222,2234,2246,2258,2263,2271,2281,2291,2300,2309,2316,2323,2330,2337,2345,2352,2360,2368,2376,2383,2394,2399,2411,2423,2435,2447,2452,2460,2470,2480,2489,2496,2503,2510,2517,2525,2533,2540,2551,2556,2568,2580,2592,2604,2609,2621,2626,2634,2644,2654,2663,2673,2680,2687,2694,2701,2708,2720,2727,2735,2743,2751,2758,2769,2780,2791,2802,2807,2815,2825,2835,2844,2851,2863,2870,2877,2884,2891,2896,2904,2914,2924,2933,2944,2951,2958,2968,2975,2982,2989,2997,3004,3011,3019,3026,3037,3042,3054,3066,3078,3090,3096,3108],{"__ignoreMap":407},[822,1609,1610,1613,1616,1620,1623],{"class":824,"line":825},[822,1611,1612],{"class":844},"version",[822,1614,1615],{"class":935},":",[822,1617,1619],{"class":1618},"sNJcY"," \"",[822,1621,1622],{"class":832},"3.8",[822,1624,1625],{"class":1618},"\"\n",[822,1627,1628],{"class":824,"line":408},[822,1629,1630],{"emptyLinePlaceholder":422},"\n",[822,1632,1633,1636],{"class":824,"line":1051},[822,1634,1635],{"class":844},"networks",[822,1637,1638],{"class":935},":\n",[822,1640,1641,1644],{"class":824,"line":1182},[822,1642,1643],{"class":844},"  infra",[822,1645,1638],{"class":935},[822,1647,1648,1651],{"class":824,"line":1484},[822,1649,1650],{"class":844},"  traefik",[822,1652,1638],{"class":935},[822,1654,1656,1659],{"class":824,"line":1655},6,[822,1657,1658],{"class":844},"    external",[822,1660,1638],{"class":935},[822,1662,1664,1667,1669],{"class":824,"line":1663},7,[822,1665,1666],{"class":844},"      name",[822,1668,1615],{"class":935},[822,1670,1128],{"class":832},[822,1672,1674,1677],{"class":824,"line":1673},8,[822,1675,1676],{"class":844},"  default",[822,1678,1638],{"class":935},[822,1680,1682,1685,1687],{"class":824,"line":1681},9,[822,1683,1684],{"class":844},"    driver",[822,1686,1615],{"class":935},[822,1688,1689],{"class":832}," bridge\n",[822,1691,1693],{"class":824,"line":1692},10,[822,1694,1630],{"emptyLinePlaceholder":422},[822,1696,1698,1701],{"class":824,"line":1697},11,[822,1699,1700],{"class":844},"volumes",[822,1702,1638],{"class":935},[822,1704,1706,1709],{"class":824,"line":1705},12,[822,1707,1708],{"class":844},"  traefik_sample_data_portainer",[822,1710,1638],{"class":935},[822,1712,1714,1717],{"class":824,"line":1713},13,[822,1715,1716],{"class":844},"  traefik_sample_data_mysql",[822,1718,1638],{"class":935},[822,1720,1722],{"class":824,"line":1721},14,[822,1723,1630],{"emptyLinePlaceholder":422},[822,1725,1727,1730],{"class":824,"line":1726},15,[822,1728,1729],{"class":844},"services",[822,1731,1638],{"class":935},[822,1733,1735],{"class":824,"line":1734},16,[822,1736,1630],{"emptyLinePlaceholder":422},[822,1738,1740,1742],{"class":824,"line":1739},17,[822,1741,1650],{"class":844},[822,1743,1638],{"class":935},[822,1745,1747,1750,1752],{"class":824,"line":1746},18,[822,1748,1749],{"class":844},"    image",[822,1751,1615],{"class":935},[822,1753,1754],{"class":832}," traefik:v2.3\n",[822,1756,1758,1761,1763],{"class":824,"line":1757},19,[822,1759,1760],{"class":844},"    container_name",[822,1762,1615],{"class":935},[822,1764,1128],{"class":832},[822,1766,1768,1771,1773],{"class":824,"line":1767},20,[822,1769,1770],{"class":844},"    restart",[822,1772,1615],{"class":935},[822,1774,1775],{"class":832}," unless-stopped\n",[822,1777,1779,1782],{"class":824,"line":1778},21,[822,1780,1781],{"class":844},"    networks",[822,1783,1638],{"class":935},[822,1785,1787,1790],{"class":824,"line":1786},22,[822,1788,1789],{"class":844},"      traefik",[822,1791,1638],{"class":935},[822,1793,1795,1798,1800],{"class":824,"line":1794},23,[822,1796,1797],{"class":844},"        ipv4_address",[822,1799,1615],{"class":935},[822,1801,1802],{"class":1118}," 192.168.90.254\n",[822,1804,1806,1809],{"class":824,"line":1805},24,[822,1807,1808],{"class":844},"    security_opt",[822,1810,1638],{"class":935},[822,1812,1814,1817],{"class":824,"line":1813},25,[822,1815,1816],{"class":935},"      -",[822,1818,1819],{"class":832}," no-new-privileges:true\n",[822,1821,1823,1826],{"class":824,"line":1822},26,[822,1824,1825],{"class":844},"    ports",[822,1827,1638],{"class":935},[822,1829,1831,1833,1835,1838],{"class":824,"line":1830},27,[822,1832,1816],{"class":935},[822,1834,1619],{"class":1618},[822,1836,1837],{"class":832},"80:80",[822,1839,1625],{"class":1618},[822,1841,1843,1845,1847,1850],{"class":824,"line":1842},28,[822,1844,1816],{"class":935},[822,1846,1619],{"class":1618},[822,1848,1849],{"class":832},"443:443",[822,1851,1625],{"class":1618},[822,1853,1855,1857,1860,1862],{"class":824,"line":1854},29,[822,1856,1816],{"class":935},[822,1858,1859],{"class":844}," target",[822,1861,1615],{"class":935},[822,1863,1864],{"class":1118}," 8080\n",[822,1866,1868,1871,1873],{"class":824,"line":1867},30,[822,1869,1870],{"class":844},"        published",[822,1872,1615],{"class":935},[822,1874,1864],{"class":1118},[822,1876,1878,1881,1883],{"class":824,"line":1877},31,[822,1879,1880],{"class":844},"        protocol",[822,1882,1615],{"class":935},[822,1884,1885],{"class":832}," tcp\n",[822,1887,1889,1892,1894],{"class":824,"line":1888},32,[822,1890,1891],{"class":844},"        mode",[822,1893,1615],{"class":935},[822,1895,1896],{"class":832}," ingress\n",[822,1898,1900,1903],{"class":824,"line":1899},33,[822,1901,1902],{"class":844},"    volumes",[822,1904,1638],{"class":935},[822,1906,1908,1910],{"class":824,"line":1907},34,[822,1909,1816],{"class":935},[822,1911,1912],{"class":832}," \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n",[822,1914,1916,1918],{"class":824,"line":1915},35,[822,1917,1816],{"class":935},[822,1919,1920],{"class":832}," .\u002Ftraefik\u002Ftraefik.yml:\u002Ftraefik.yml\n",[822,1922,1924,1926],{"class":824,"line":1923},36,[822,1925,1816],{"class":935},[822,1927,1928],{"class":832}," .\u002Ftraefik\u002Facme.json:\u002Facme.json\n",[822,1930,1932,1934],{"class":824,"line":1931},37,[822,1933,1816],{"class":935},[822,1935,1936],{"class":832}," .\u002Ftraefik\u002Ftraefik.log:\u002Ftraefik.log\n",[822,1938,1940,1942],{"class":824,"line":1939},38,[822,1941,1816],{"class":935},[822,1943,1944],{"class":832}," .\u002Ftraefik\u002Frules:\u002Frules\n",[822,1946,1948,1950],{"class":824,"line":1947},39,[822,1949,1816],{"class":935},[822,1951,1952],{"class":832}," .\u002Ftraefik\u002Fshared:\u002Fshared\n",[822,1954,1956,1959],{"class":824,"line":1955},40,[822,1957,1958],{"class":844},"    labels",[822,1960,1638],{"class":935},[822,1962,1964,1966,1968,1971],{"class":824,"line":1963},41,[822,1965,1816],{"class":935},[822,1967,1619],{"class":1618},[822,1969,1970],{"class":832},"traefik.enable=true",[822,1972,1625],{"class":1618},[822,1974,1976],{"class":824,"line":1975},42,[822,1977,1979],{"class":1978},"sux-A","      # router\n",[822,1981,1983,1985,1987,1990],{"class":824,"line":1982},43,[822,1984,1816],{"class":935},[822,1986,1619],{"class":1618},[822,1988,1989],{"class":832},"traefik.http.routers.traefik-rtr.entrypoints=websecure",[822,1991,1625],{"class":1618},[822,1993,1995,1997,1999,2002],{"class":824,"line":1994},44,[822,1996,1816],{"class":935},[822,1998,1619],{"class":1618},[822,2000,2001],{"class":832},"traefik.http.routers.traefik-rtr.rule=Host(`traefik.$HOSTNAME`)",[822,2003,1625],{"class":1618},[822,2005,2007,2009,2011,2014],{"class":824,"line":2006},45,[822,2008,1816],{"class":935},[822,2010,1619],{"class":1618},[822,2012,2013],{"class":832},"traefik.http.routers.traefik-rtr.tls=true",[822,2015,1625],{"class":1618},[822,2017,2019,2021,2023,2026],{"class":824,"line":2018},46,[822,2020,1816],{"class":935},[822,2022,1619],{"class":1618},[822,2024,2025],{"class":832},"traefik.http.routers.traefik-rtr.tls.certresolver=le",[822,2027,1625],{"class":1618},[822,2029,2031],{"class":824,"line":2030},47,[822,2032,2033],{"class":1978},"      # service api\n",[822,2035,2037,2039,2041,2044],{"class":824,"line":2036},48,[822,2038,1816],{"class":935},[822,2040,1619],{"class":1618},[822,2042,2043],{"class":832},"traefik.http.routers.traefik-rtr.service=api@internal",[822,2045,1625],{"class":1618},[822,2047,2049],{"class":824,"line":2048},49,[822,2050,2051],{"class":1978},"      # middlewares\n",[822,2053,2055,2057,2059,2062],{"class":824,"line":2054},50,[822,2056,1816],{"class":935},[822,2058,1619],{"class":1618},[822,2060,2061],{"class":832},"traefik.http.routers.traefik-rtr.middlewares=rate-limit@file,myauth@file",[822,2063,1625],{"class":1618},[822,2065,2067],{"class":824,"line":2066},51,[822,2068,1630],{"emptyLinePlaceholder":422},[822,2070,2072,2075],{"class":824,"line":2071},52,[822,2073,2074],{"class":844},"  api",[822,2076,1638],{"class":935},[822,2078,2080,2082,2084],{"class":824,"line":2079},53,[822,2081,1749],{"class":844},[822,2083,1615],{"class":935},[822,2085,2086],{"class":832}," webdevops\u002Fphp-nginx:8.1-alpine\n",[822,2088,2090,2092,2094],{"class":824,"line":2089},54,[822,2091,1760],{"class":844},[822,2093,1615],{"class":935},[822,2095,2096],{"class":832}," api\n",[822,2098,2100,2103,2105],{"class":824,"line":2099},55,[822,2101,2102],{"class":844},"    working_dir",[822,2104,1615],{"class":935},[822,2106,2107],{"class":832}," \u002Fapp\n",[822,2109,2111,2113,2115],{"class":824,"line":2110},56,[822,2112,1770],{"class":844},[822,2114,1615],{"class":935},[822,2116,2117],{"class":832}," always\n",[822,2119,2121,2123],{"class":824,"line":2120},57,[822,2122,1781],{"class":844},[822,2124,1638],{"class":935},[822,2126,2128,2130],{"class":824,"line":2127},58,[822,2129,1816],{"class":935},[822,2131,1128],{"class":832},[822,2133,2135,2137],{"class":824,"line":2134},59,[822,2136,1816],{"class":935},[822,2138,2139],{"class":832}," infra\n",[822,2141,2143,2145],{"class":824,"line":2142},60,[822,2144,1902],{"class":844},[822,2146,1638],{"class":935},[822,2148,2150,2152],{"class":824,"line":2149},61,[822,2151,1816],{"class":935},[822,2153,2154],{"class":832}," .\u002Fapps\u002Fapi:\u002Fapp:rw\n",[822,2156,2158,2160],{"class":824,"line":2157},62,[822,2159,1816],{"class":935},[822,2161,2162],{"class":832}," .\u002Fnginx\u002Fnginxapi.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n",[822,2164,2166,2169],{"class":824,"line":2165},63,[822,2167,2168],{"class":844},"    environment",[822,2170,1638],{"class":935},[822,2172,2174,2176],{"class":824,"line":2173},64,[822,2175,1816],{"class":935},[822,2177,2178],{"class":832}," WEB_DOCUMENT_ROOT=\u002Fapp\u002Fpublic\n",[822,2180,2182,2184],{"class":824,"line":2181},65,[822,2183,1816],{"class":935},[822,2185,2186],{"class":832}," VIRTUAL_HOST=api.$HOSTNAME\n",[822,2188,2190,2192],{"class":824,"line":2189},66,[822,2191,1958],{"class":844},[822,2193,1638],{"class":935},[822,2195,2197,2199,2201,2203],{"class":824,"line":2196},67,[822,2198,1816],{"class":935},[822,2200,1619],{"class":1618},[822,2202,1970],{"class":832},[822,2204,1625],{"class":1618},[822,2206,2208],{"class":824,"line":2207},68,[822,2209,1979],{"class":1978},[822,2211,2213,2215,2217,2220],{"class":824,"line":2212},69,[822,2214,1816],{"class":935},[822,2216,1619],{"class":1618},[822,2218,2219],{"class":832},"traefik.http.routers.api-rtr.entrypoints=websecure",[822,2221,1625],{"class":1618},[822,2223,2225,2227,2229,2232],{"class":824,"line":2224},70,[822,2226,1816],{"class":935},[822,2228,1619],{"class":1618},[822,2230,2231],{"class":832},"traefik.http.routers.api-rtr.rule=Host(`api.$HOSTNAME`)",[822,2233,1625],{"class":1618},[822,2235,2237,2239,2241,2244],{"class":824,"line":2236},71,[822,2238,1816],{"class":935},[822,2240,1619],{"class":1618},[822,2242,2243],{"class":832},"traefik.http.routers.api-rtr.tls=true",[822,2245,1625],{"class":1618},[822,2247,2249,2251,2253,2256],{"class":824,"line":2248},72,[822,2250,1816],{"class":935},[822,2252,1619],{"class":1618},[822,2254,2255],{"class":832},"traefik.http.routers.api-rtr.tls.certresolver=le",[822,2257,1625],{"class":1618},[822,2259,2261],{"class":824,"line":2260},73,[822,2262,1630],{"emptyLinePlaceholder":422},[822,2264,2266,2269],{"class":824,"line":2265},74,[822,2267,2268],{"class":844},"  web",[822,2270,1638],{"class":935},[822,2272,2274,2276,2278],{"class":824,"line":2273},75,[822,2275,1749],{"class":844},[822,2277,1615],{"class":935},[822,2279,2280],{"class":832}," webdevops\u002Fnginx:latest\n",[822,2282,2284,2286,2288],{"class":824,"line":2283},76,[822,2285,1760],{"class":844},[822,2287,1615],{"class":935},[822,2289,2290],{"class":832}," web\n",[822,2292,2294,2296,2298],{"class":824,"line":2293},77,[822,2295,2102],{"class":844},[822,2297,1615],{"class":935},[822,2299,2107],{"class":832},[822,2301,2303,2305,2307],{"class":824,"line":2302},78,[822,2304,1770],{"class":844},[822,2306,1615],{"class":935},[822,2308,2117],{"class":832},[822,2310,2312,2314],{"class":824,"line":2311},79,[822,2313,1781],{"class":844},[822,2315,1638],{"class":935},[822,2317,2319,2321],{"class":824,"line":2318},80,[822,2320,1816],{"class":935},[822,2322,1128],{"class":832},[822,2324,2326,2328],{"class":824,"line":2325},81,[822,2327,1816],{"class":935},[822,2329,2139],{"class":832},[822,2331,2333,2335],{"class":824,"line":2332},82,[822,2334,1902],{"class":844},[822,2336,1638],{"class":935},[822,2338,2340,2342],{"class":824,"line":2339},83,[822,2341,1816],{"class":935},[822,2343,2344],{"class":832}," .\u002Fapps\u002Fweb:\u002Fapp:rw\n",[822,2346,2348,2350],{"class":824,"line":2347},84,[822,2349,2168],{"class":844},[822,2351,1638],{"class":935},[822,2353,2355,2357],{"class":824,"line":2354},85,[822,2356,1816],{"class":935},[822,2358,2359],{"class":832}," WEB_DOCUMENT_ROOT=\u002Fapp\u002Fbuild\n",[822,2361,2363,2365],{"class":824,"line":2362},86,[822,2364,1816],{"class":935},[822,2366,2367],{"class":832}," WEB_ALIAS_DOMAIN=web.$HOSTNAME\n",[822,2369,2371,2373],{"class":824,"line":2370},87,[822,2372,1816],{"class":935},[822,2374,2375],{"class":832}," WEB_DOCUMENT_INDEX=index.html\n",[822,2377,2379,2381],{"class":824,"line":2378},88,[822,2380,1958],{"class":844},[822,2382,1638],{"class":935},[822,2384,2386,2388,2390,2392],{"class":824,"line":2385},89,[822,2387,1816],{"class":935},[822,2389,1619],{"class":1618},[822,2391,1970],{"class":832},[822,2393,1625],{"class":1618},[822,2395,2397],{"class":824,"line":2396},90,[822,2398,1979],{"class":1978},[822,2400,2402,2404,2406,2409],{"class":824,"line":2401},91,[822,2403,1816],{"class":935},[822,2405,1619],{"class":1618},[822,2407,2408],{"class":832},"traefik.http.routers.intranet-rtr.entrypoints=websecure",[822,2410,1625],{"class":1618},[822,2412,2414,2416,2418,2421],{"class":824,"line":2413},92,[822,2415,1816],{"class":935},[822,2417,1619],{"class":1618},[822,2419,2420],{"class":832},"traefik.http.routers.intranet-rtr.rule=Host(`web.$HOSTNAME`)",[822,2422,1625],{"class":1618},[822,2424,2426,2428,2430,2433],{"class":824,"line":2425},93,[822,2427,1816],{"class":935},[822,2429,1619],{"class":1618},[822,2431,2432],{"class":832},"traefik.http.routers.intranet-rtr.tls=true",[822,2434,1625],{"class":1618},[822,2436,2438,2440,2442,2445],{"class":824,"line":2437},94,[822,2439,1816],{"class":935},[822,2441,1619],{"class":1618},[822,2443,2444],{"class":832},"traefik.http.routers.intranet-rtr.tls.certresolver=le",[822,2446,1625],{"class":1618},[822,2448,2450],{"class":824,"line":2449},95,[822,2451,1630],{"emptyLinePlaceholder":422},[822,2453,2455,2458],{"class":824,"line":2454},96,[822,2456,2457],{"class":844},"  adminer",[822,2459,1638],{"class":935},[822,2461,2463,2465,2467],{"class":824,"line":2462},97,[822,2464,1749],{"class":844},[822,2466,1615],{"class":935},[822,2468,2469],{"class":832}," adminer:latest\n",[822,2471,2473,2475,2477],{"class":824,"line":2472},98,[822,2474,1760],{"class":844},[822,2476,1615],{"class":935},[822,2478,2479],{"class":832}," adminer\n",[822,2481,2483,2485,2487],{"class":824,"line":2482},99,[822,2484,1770],{"class":844},[822,2486,1615],{"class":935},[822,2488,2117],{"class":832},[822,2490,2492,2494],{"class":824,"line":2491},100,[822,2493,1781],{"class":844},[822,2495,1638],{"class":935},[822,2497,2499,2501],{"class":824,"line":2498},101,[822,2500,1816],{"class":935},[822,2502,1128],{"class":832},[822,2504,2506,2508],{"class":824,"line":2505},102,[822,2507,1816],{"class":935},[822,2509,2139],{"class":832},[822,2511,2513,2515],{"class":824,"line":2512},103,[822,2514,1902],{"class":844},[822,2516,1638],{"class":935},[822,2518,2520,2522],{"class":824,"line":2519},104,[822,2521,1816],{"class":935},[822,2523,2524],{"class":832}," .\u002Fadminer\u002Fplugins-enabled:\u002Fvar\u002Fwww\u002Fhtml\u002Fplugins-enabled:rw\n",[822,2526,2528,2530],{"class":824,"line":2527},105,[822,2529,1816],{"class":935},[822,2531,2532],{"class":832}," .\u002Fadminer\u002Frobots.txt:\u002Fvar\u002Fwww\u002Fhtml\u002Frobots.txt\n",[822,2534,2536,2538],{"class":824,"line":2535},106,[822,2537,1958],{"class":844},[822,2539,1638],{"class":935},[822,2541,2543,2545,2547,2549],{"class":824,"line":2542},107,[822,2544,1816],{"class":935},[822,2546,1619],{"class":1618},[822,2548,1970],{"class":832},[822,2550,1625],{"class":1618},[822,2552,2554],{"class":824,"line":2553},108,[822,2555,1979],{"class":1978},[822,2557,2559,2561,2563,2566],{"class":824,"line":2558},109,[822,2560,1816],{"class":935},[822,2562,1619],{"class":1618},[822,2564,2565],{"class":832},"traefik.http.routers.adminer-rtr.entrypoints=websecure",[822,2567,1625],{"class":1618},[822,2569,2571,2573,2575,2578],{"class":824,"line":2570},110,[822,2572,1816],{"class":935},[822,2574,1619],{"class":1618},[822,2576,2577],{"class":832},"traefik.http.routers.adminer-rtr.rule=Host(`adminer.$HOSTNAME`)",[822,2579,1625],{"class":1618},[822,2581,2583,2585,2587,2590],{"class":824,"line":2582},111,[822,2584,1816],{"class":935},[822,2586,1619],{"class":1618},[822,2588,2589],{"class":832},"traefik.http.routers.adminer-rtr.tls=true",[822,2591,1625],{"class":1618},[822,2593,2595,2597,2599,2602],{"class":824,"line":2594},112,[822,2596,1816],{"class":935},[822,2598,1619],{"class":1618},[822,2600,2601],{"class":832},"traefik.http.routers.adminer-rtr.tls.certresolver=le",[822,2603,1625],{"class":1618},[822,2605,2607],{"class":824,"line":2606},113,[822,2608,2051],{"class":1978},[822,2610,2612,2614,2616,2619],{"class":824,"line":2611},114,[822,2613,1816],{"class":935},[822,2615,1619],{"class":1618},[822,2617,2618],{"class":832},"traefik.http.routers.adminer-rtr.middlewares=rate-limit@file,myauth@file",[822,2620,1625],{"class":1618},[822,2622,2624],{"class":824,"line":2623},115,[822,2625,1630],{"emptyLinePlaceholder":422},[822,2627,2629,2632],{"class":824,"line":2628},116,[822,2630,2631],{"class":844},"  mysql",[822,2633,1638],{"class":935},[822,2635,2637,2639,2641],{"class":824,"line":2636},117,[822,2638,1749],{"class":844},[822,2640,1615],{"class":935},[822,2642,2643],{"class":832}," mysql:8.0.25\n",[822,2645,2647,2649,2651],{"class":824,"line":2646},118,[822,2648,1760],{"class":844},[822,2650,1615],{"class":935},[822,2652,2653],{"class":832}," mysql\n",[822,2655,2657,2659,2661],{"class":824,"line":2656},119,[822,2658,2102],{"class":844},[822,2660,1615],{"class":935},[822,2662,2107],{"class":832},[822,2664,2666,2668,2670],{"class":824,"line":2665},120,[822,2667,1770],{"class":844},[822,2669,1615],{"class":935},[822,2671,2672],{"class":832}," on-failure\n",[822,2674,2676,2678],{"class":824,"line":2675},121,[822,2677,1781],{"class":844},[822,2679,1638],{"class":935},[822,2681,2683,2685],{"class":824,"line":2682},122,[822,2684,1816],{"class":935},[822,2686,2139],{"class":832},[822,2688,2690,2692],{"class":824,"line":2689},123,[822,2691,1808],{"class":844},[822,2693,1638],{"class":935},[822,2695,2697,2699],{"class":824,"line":2696},124,[822,2698,1816],{"class":935},[822,2700,1819],{"class":832},[822,2702,2704,2706],{"class":824,"line":2703},125,[822,2705,1825],{"class":844},[822,2707,1638],{"class":935},[822,2709,2711,2713,2715,2718],{"class":824,"line":2710},126,[822,2712,1816],{"class":935},[822,2714,1619],{"class":1618},[822,2716,2717],{"class":832},"3306:3306",[822,2719,1625],{"class":1618},[822,2721,2723,2725],{"class":824,"line":2722},127,[822,2724,1902],{"class":844},[822,2726,1638],{"class":935},[822,2728,2730,2732],{"class":824,"line":2729},128,[822,2731,1816],{"class":935},[822,2733,2734],{"class":832}," ${PWD}\u002Fdata:\u002Fapp:rw\n",[822,2736,2738,2740],{"class":824,"line":2737},129,[822,2739,1816],{"class":935},[822,2741,2742],{"class":832}," ${PWD}\u002Fmysql\u002Fmy.cnf:\u002Fetc\u002Fmysql\u002Fconf.d\u002Fmy-over.cnf\n",[822,2744,2746,2748],{"class":824,"line":2745},130,[822,2747,1816],{"class":935},[822,2749,2750],{"class":832}," traefik_sample_data_mysql:\u002Fvar\u002Flib\u002Fmysql\n",[822,2752,2754,2756],{"class":824,"line":2753},131,[822,2755,2168],{"class":844},[822,2757,1638],{"class":935},[822,2759,2761,2764,2766],{"class":824,"line":2760},132,[822,2762,2763],{"class":844},"      MYSQL_ROOT_PASSWORD",[822,2765,1615],{"class":935},[822,2767,2768],{"class":832}," $MYSQL_ROOT_PASSWORD\n",[822,2770,2772,2775,2777],{"class":824,"line":2771},133,[822,2773,2774],{"class":844},"      MYSQL_DATABASE",[822,2776,1615],{"class":935},[822,2778,2779],{"class":832}," $MYSQL_DATABASE\n",[822,2781,2783,2786,2788],{"class":824,"line":2782},134,[822,2784,2785],{"class":844},"      MYSQL_USER",[822,2787,1615],{"class":935},[822,2789,2790],{"class":832}," $MYSQL_USER\n",[822,2792,2794,2797,2799],{"class":824,"line":2793},135,[822,2795,2796],{"class":844},"      MYSQL_PASSWORD",[822,2798,1615],{"class":935},[822,2800,2801],{"class":832}," $MYSQL_PASSWORD\n",[822,2803,2805],{"class":824,"line":2804},136,[822,2806,1630],{"emptyLinePlaceholder":422},[822,2808,2810,2813],{"class":824,"line":2809},137,[822,2811,2812],{"class":844},"  redis",[822,2814,1638],{"class":935},[822,2816,2818,2820,2822],{"class":824,"line":2817},138,[822,2819,1749],{"class":844},[822,2821,1615],{"class":935},[822,2823,2824],{"class":832}," redis:alpine\n",[822,2826,2828,2830,2832],{"class":824,"line":2827},139,[822,2829,1760],{"class":844},[822,2831,1615],{"class":935},[822,2833,2834],{"class":832}," redis\n",[822,2836,2838,2840,2842],{"class":824,"line":2837},140,[822,2839,1770],{"class":844},[822,2841,1615],{"class":935},[822,2843,1775],{"class":832},[822,2845,2847,2849],{"class":824,"line":2846},141,[822,2848,1825],{"class":844},[822,2850,1638],{"class":935},[822,2852,2854,2856,2858,2861],{"class":824,"line":2853},142,[822,2855,1816],{"class":935},[822,2857,1619],{"class":1618},[822,2859,2860],{"class":832},"6380:6379",[822,2862,1625],{"class":1618},[822,2864,2866,2868],{"class":824,"line":2865},143,[822,2867,1781],{"class":844},[822,2869,1638],{"class":935},[822,2871,2873,2875],{"class":824,"line":2872},144,[822,2874,1816],{"class":935},[822,2876,2139],{"class":832},[822,2878,2880,2882],{"class":824,"line":2879},145,[822,2881,1808],{"class":844},[822,2883,1638],{"class":935},[822,2885,2887,2889],{"class":824,"line":2886},146,[822,2888,1816],{"class":935},[822,2890,1819],{"class":832},[822,2892,2894],{"class":824,"line":2893},147,[822,2895,1630],{"emptyLinePlaceholder":422},[822,2897,2899,2902],{"class":824,"line":2898},148,[822,2900,2901],{"class":844},"  portainer",[822,2903,1638],{"class":935},[822,2905,2907,2909,2911],{"class":824,"line":2906},149,[822,2908,1749],{"class":844},[822,2910,1615],{"class":935},[822,2912,2913],{"class":832}," portainer\u002Fportainer:latest\n",[822,2915,2917,2919,2921],{"class":824,"line":2916},150,[822,2918,1760],{"class":844},[822,2920,1615],{"class":935},[822,2922,2923],{"class":832}," portainer\n",[822,2925,2927,2929,2931],{"class":824,"line":2926},151,[822,2928,1770],{"class":844},[822,2930,1615],{"class":935},[822,2932,1775],{"class":832},[822,2934,2936,2939,2941],{"class":824,"line":2935},152,[822,2937,2938],{"class":844},"    command",[822,2940,1615],{"class":935},[822,2942,2943],{"class":832}," -H unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\n",[822,2945,2947,2949],{"class":824,"line":2946},153,[822,2948,1781],{"class":844},[822,2950,1638],{"class":935},[822,2952,2954,2956],{"class":824,"line":2953},154,[822,2955,1789],{"class":844},[822,2957,1638],{"class":935},[822,2959,2961,2963,2965],{"class":824,"line":2960},155,[822,2962,1797],{"class":844},[822,2964,1615],{"class":935},[822,2966,2967],{"class":1118}," 192.168.90.253\n",[822,2969,2971,2973],{"class":824,"line":2970},156,[822,2972,1808],{"class":844},[822,2974,1638],{"class":935},[822,2976,2978,2980],{"class":824,"line":2977},157,[822,2979,1816],{"class":935},[822,2981,1819],{"class":832},[822,2983,2985,2987],{"class":824,"line":2984},158,[822,2986,1902],{"class":844},[822,2988,1638],{"class":935},[822,2990,2992,2994],{"class":824,"line":2991},159,[822,2993,1816],{"class":935},[822,2995,2996],{"class":832}," traefik_sample_data_portainer:\u002Fdata\n",[822,2998,3000,3002],{"class":824,"line":2999},160,[822,3001,1816],{"class":935},[822,3003,1912],{"class":832},[822,3005,3007,3009],{"class":824,"line":3006},161,[822,3008,2168],{"class":844},[822,3010,1638],{"class":935},[822,3012,3014,3016],{"class":824,"line":3013},162,[822,3015,1816],{"class":935},[822,3017,3018],{"class":832}," TZ=$TZ\n",[822,3020,3022,3024],{"class":824,"line":3021},163,[822,3023,1958],{"class":844},[822,3025,1638],{"class":935},[822,3027,3029,3031,3033,3035],{"class":824,"line":3028},164,[822,3030,1816],{"class":935},[822,3032,1619],{"class":1618},[822,3034,1970],{"class":832},[822,3036,1625],{"class":1618},[822,3038,3040],{"class":824,"line":3039},165,[822,3041,1979],{"class":1978},[822,3043,3045,3047,3049,3052],{"class":824,"line":3044},166,[822,3046,1816],{"class":935},[822,3048,1619],{"class":1618},[822,3050,3051],{"class":832},"traefik.http.routers.portainer-rtr.entrypoints=websecure",[822,3053,1625],{"class":1618},[822,3055,3057,3059,3061,3064],{"class":824,"line":3056},167,[822,3058,1816],{"class":935},[822,3060,1619],{"class":1618},[822,3062,3063],{"class":832},"traefik.http.routers.portainer-rtr.rule=Host(`portainer.$HOSTNAME`)",[822,3065,1625],{"class":1618},[822,3067,3069,3071,3073,3076],{"class":824,"line":3068},168,[822,3070,1816],{"class":935},[822,3072,1619],{"class":1618},[822,3074,3075],{"class":832},"traefik.http.routers.portainer-rtr.tls=true",[822,3077,1625],{"class":1618},[822,3079,3081,3083,3085,3088],{"class":824,"line":3080},169,[822,3082,1816],{"class":935},[822,3084,1619],{"class":1618},[822,3086,3087],{"class":832},"traefik.http.routers.portainer-rtr.tls.certresolver=le",[822,3089,1625],{"class":1618},[822,3091,3093],{"class":824,"line":3092},170,[822,3094,3095],{"class":1978},"      # services\n",[822,3097,3099,3101,3103,3106],{"class":824,"line":3098},171,[822,3100,1816],{"class":935},[822,3102,1619],{"class":1618},[822,3104,3105],{"class":832},"traefik.http.routers.portainer-rtr.service=portainer-svc",[822,3107,1625],{"class":1618},[822,3109,3111,3113,3115,3118],{"class":824,"line":3110},172,[822,3112,1816],{"class":935},[822,3114,1619],{"class":1618},[822,3116,3117],{"class":832},"traefik.http.services.portainer-svc.loadbalancer.server.port=9000",[822,3119,1625],{"class":1618},[124,3121,3124,3135,3148,3151,3177],{"icon":3122,"label":3123},"fas fa-route","traefik.yml",[10,3125,3126,3127,3130,3131,3134],{},"La configuración de Traefik: ",[77,3128,3129],{},"entrypoints",", ",[77,3132,3133],{},"providers",", logs y el resolver de certificados.",[290,3136,3138],{"title":3137},"Usa el entorno de staging para tus pruebas",[10,3139,3140,3141,3144,3145,3147],{},"Si estás probando la generación del certificado SSL, descomenta la línea ",[72,3142,3143],{},"caServer"," (staging) para no agotar el ",[77,3146,1266],{}," de Let's Encrypt en producción.",[10,3149,3150],{},"Documentación útil:",[27,3152,3153,3161,3169],{},[30,3154,3155,3156],{},"Rate limit de producción: ",[381,3157,3160],{"href":3158,"rel":3159},"https:\u002F\u002Fletsencrypt.org\u002Fdocs\u002Frate-limits",[398],"letsencrypt.org\u002Fdocs\u002Frate-limits",[30,3162,3163,3164],{},"Entorno de staging: ",[381,3165,3168],{"href":3166,"rel":3167},"https:\u002F\u002Fletsencrypt.org\u002Fdocs\u002Fstaging-environment",[398],"letsencrypt.org\u002Fdocs\u002Fstaging-environment",[30,3170,3171,3172],{},"Consultar los certificados que ya emitiste: ",[381,3173,3176],{"href":3174,"rel":3175},"https:\u002F\u002Fcrt.sh",[398],"crt.sh",[814,3178,3180],{"className":1603,"code":3179,"language":1605,"meta":407,"style":407},"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 # descoméntalo para hacer pruebas\n      httpChallenge:\n        entryPoint: web\n",[72,3181,3182,3189,3200,3209,3213,3220,3226,3240,3247,3254,3261,3271,3281,3290,3297,3310,3316,3329,3333,3340,3349,3359,3368,3372,3378,3385,3399,3408,3417,3426,3433,3443,3452,3456,3463,3477,3490,3500,3504,3511,3523,3533,3541,3548,3555,3566,3575,3589,3596,3606,3613,3623,3630,3639,3646,3656,3665,3674,3678,3685,3692,3699,3709,3723,3728,3735],{"__ignoreMap":407},[822,3183,3184,3187],{"class":824,"line":825},[822,3185,3186],{"class":844},"global",[822,3188,1638],{"class":935},[822,3190,3191,3194,3196],{"class":824,"line":408},[822,3192,3193],{"class":844},"  checkNewVersion",[822,3195,1615],{"class":935},[822,3197,3199],{"class":3198},"s3QIE"," true\n",[822,3201,3202,3205,3207],{"class":824,"line":1051},[822,3203,3204],{"class":844},"  sendAnonymousUsage",[822,3206,1615],{"class":935},[822,3208,3199],{"class":3198},[822,3210,3211],{"class":824,"line":1182},[822,3212,1630],{"emptyLinePlaceholder":422},[822,3214,3215,3218],{"class":824,"line":1484},[822,3216,3217],{"class":844},"entryPoints",[822,3219,1638],{"class":935},[822,3221,3222,3224],{"class":824,"line":1655},[822,3223,2268],{"class":844},[822,3225,1638],{"class":935},[822,3227,3228,3231,3233,3235,3238],{"class":824,"line":1663},[822,3229,3230],{"class":844},"    address",[822,3232,1615],{"class":935},[822,3234,1619],{"class":1618},[822,3236,3237],{"class":832},":80",[822,3239,1625],{"class":1618},[822,3241,3242,3245],{"class":824,"line":1673},[822,3243,3244],{"class":844},"    http",[822,3246,1638],{"class":935},[822,3248,3249,3252],{"class":824,"line":1681},[822,3250,3251],{"class":844},"      redirections",[822,3253,1638],{"class":935},[822,3255,3256,3259],{"class":824,"line":1692},[822,3257,3258],{"class":844},"        entryPoint",[822,3260,1638],{"class":935},[822,3262,3263,3266,3268],{"class":824,"line":1697},[822,3264,3265],{"class":844},"          to",[822,3267,1615],{"class":935},[822,3269,3270],{"class":832}," websecure\n",[822,3272,3273,3276,3278],{"class":824,"line":1705},[822,3274,3275],{"class":844},"          scheme",[822,3277,1615],{"class":935},[822,3279,3280],{"class":832}," https\n",[822,3282,3283,3286,3288],{"class":824,"line":1713},[822,3284,3285],{"class":844},"          permanent",[822,3287,1615],{"class":935},[822,3289,3199],{"class":3198},[822,3291,3292,3295],{"class":824,"line":1721},[822,3293,3294],{"class":844},"  websecure",[822,3296,1638],{"class":935},[822,3298,3299,3301,3303,3305,3308],{"class":824,"line":1726},[822,3300,3230],{"class":844},[822,3302,1615],{"class":935},[822,3304,1619],{"class":1618},[822,3306,3307],{"class":832},":443",[822,3309,1625],{"class":1618},[822,3311,3312,3314],{"class":824,"line":1734},[822,3313,1650],{"class":844},[822,3315,1638],{"class":935},[822,3317,3318,3320,3322,3324,3327],{"class":824,"line":1739},[822,3319,3230],{"class":844},[822,3321,1615],{"class":935},[822,3323,1619],{"class":1618},[822,3325,3326],{"class":832},":8080",[822,3328,1625],{"class":1618},[822,3330,3331],{"class":824,"line":1746},[822,3332,1630],{"emptyLinePlaceholder":422},[822,3334,3335,3338],{"class":824,"line":1757},[822,3336,3337],{"class":844},"api",[822,3339,1638],{"class":935},[822,3341,3342,3345,3347],{"class":824,"line":1767},[822,3343,3344],{"class":844},"  dashboard",[822,3346,1615],{"class":935},[822,3348,3199],{"class":3198},[822,3350,3351,3354,3356],{"class":824,"line":1778},[822,3352,3353],{"class":844},"  insecure",[822,3355,1615],{"class":935},[822,3357,3358],{"class":3198}," false\n",[822,3360,3361,3364,3366],{"class":824,"line":1786},[822,3362,3363],{"class":844},"  debug",[822,3365,1615],{"class":935},[822,3367,3199],{"class":3198},[822,3369,3370],{"class":824,"line":1794},[822,3371,1630],{"emptyLinePlaceholder":422},[822,3373,3374,3376],{"class":824,"line":1805},[822,3375,3133],{"class":844},[822,3377,1638],{"class":935},[822,3379,3380,3383],{"class":824,"line":1813},[822,3381,3382],{"class":844},"  docker",[822,3384,1638],{"class":935},[822,3386,3387,3390,3392,3394,3397],{"class":824,"line":1822},[822,3388,3389],{"class":844},"    endpoint",[822,3391,1615],{"class":935},[822,3393,1619],{"class":1618},[822,3395,3396],{"class":832},"unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock",[822,3398,1625],{"class":1618},[822,3400,3401,3404,3406],{"class":824,"line":1830},[822,3402,3403],{"class":844},"    exposedByDefault",[822,3405,1615],{"class":935},[822,3407,3358],{"class":3198},[822,3409,3410,3413,3415],{"class":824,"line":1842},[822,3411,3412],{"class":844},"    network",[822,3414,1615],{"class":935},[822,3416,1128],{"class":832},[822,3418,3419,3422,3424],{"class":824,"line":1854},[822,3420,3421],{"class":844},"    swarmMode",[822,3423,1615],{"class":935},[822,3425,3358],{"class":3198},[822,3427,3428,3431],{"class":824,"line":1867},[822,3429,3430],{"class":844},"  file",[822,3432,1638],{"class":935},[822,3434,3435,3438,3440],{"class":824,"line":1877},[822,3436,3437],{"class":844},"    directory",[822,3439,1615],{"class":935},[822,3441,3442],{"class":832}," \u002Frules\n",[822,3444,3445,3448,3450],{"class":824,"line":1888},[822,3446,3447],{"class":844},"    watch",[822,3449,1615],{"class":935},[822,3451,3199],{"class":3198},[822,3453,3454],{"class":824,"line":1899},[822,3455,1630],{"emptyLinePlaceholder":422},[822,3457,3458,3461],{"class":824,"line":1907},[822,3459,3460],{"class":844},"log",[822,3462,1638],{"class":935},[822,3464,3465,3468,3470,3472,3475],{"class":824,"line":1915},[822,3466,3467],{"class":844},"  filePath",[822,3469,1615],{"class":935},[822,3471,1619],{"class":1618},[822,3473,3474],{"class":832},"\u002Flogs\u002Ftraefik.log",[822,3476,1625],{"class":1618},[822,3478,3479,3482,3484,3487],{"class":824,"line":1923},[822,3480,3481],{"class":844},"  level",[822,3483,1615],{"class":935},[822,3485,3486],{"class":832}," WARN",[822,3488,3489],{"class":1978}," # DEBUG, INFO, WARN, ERROR, FATAL, PANIC\n",[822,3491,3492,3495,3497],{"class":824,"line":1931},[822,3493,3494],{"class":844},"  format",[822,3496,1615],{"class":935},[822,3498,3499],{"class":832}," json\n",[822,3501,3502],{"class":824,"line":1939},[822,3503,1630],{"emptyLinePlaceholder":422},[822,3505,3506,3509],{"class":824,"line":1947},[822,3507,3508],{"class":844},"accessLog",[822,3510,1638],{"class":935},[822,3512,3513,3515,3517,3519,3521],{"class":824,"line":1955},[822,3514,3467],{"class":844},[822,3516,1615],{"class":935},[822,3518,1619],{"class":1618},[822,3520,3474],{"class":832},[822,3522,1625],{"class":1618},[822,3524,3525,3528,3530],{"class":824,"line":1963},[822,3526,3527],{"class":844},"  bufferingSize",[822,3529,1615],{"class":935},[822,3531,3532],{"class":1118}," 100\n",[822,3534,3535,3537,3539],{"class":824,"line":1975},[822,3536,3494],{"class":844},[822,3538,1615],{"class":935},[822,3540,3499],{"class":832},[822,3542,3543,3546],{"class":824,"line":1982},[822,3544,3545],{"class":844},"  filters",[822,3547,1638],{"class":935},[822,3549,3550,3553],{"class":824,"line":1994},[822,3551,3552],{"class":844},"    statusCodes",[822,3554,1638],{"class":935},[822,3556,3557,3559,3561,3564],{"class":824,"line":2006},[822,3558,1816],{"class":935},[822,3560,1619],{"class":1618},[822,3562,3563],{"class":832},"400-499",[822,3565,1625],{"class":1618},[822,3567,3568,3571,3573],{"class":824,"line":2018},[822,3569,3570],{"class":844},"    retryAttempts",[822,3572,1615],{"class":935},[822,3574,3199],{"class":3198},[822,3576,3577,3580,3582,3584,3587],{"class":824,"line":2030},[822,3578,3579],{"class":844},"    minDuration",[822,3581,1615],{"class":935},[822,3583,1619],{"class":1618},[822,3585,3586],{"class":832},"10ms",[822,3588,1625],{"class":1618},[822,3590,3591,3594],{"class":824,"line":2036},[822,3592,3593],{"class":844},"  fields",[822,3595,1638],{"class":935},[822,3597,3598,3601,3603],{"class":824,"line":2048},[822,3599,3600],{"class":844},"    defaultMode",[822,3602,1615],{"class":935},[822,3604,3605],{"class":832}," keep\n",[822,3607,3608,3611],{"class":824,"line":2054},[822,3609,3610],{"class":844},"    names",[822,3612,1638],{"class":935},[822,3614,3615,3618,3620],{"class":824,"line":2066},[822,3616,3617],{"class":844},"      ClientUsername",[822,3619,1615],{"class":935},[822,3621,3622],{"class":832}," drop\n",[822,3624,3625,3628],{"class":824,"line":2071},[822,3626,3627],{"class":844},"    headers",[822,3629,1638],{"class":935},[822,3631,3632,3635,3637],{"class":824,"line":2079},[822,3633,3634],{"class":844},"      defaultMode",[822,3636,1615],{"class":935},[822,3638,3605],{"class":832},[822,3640,3641,3644],{"class":824,"line":2089},[822,3642,3643],{"class":844},"      names",[822,3645,1638],{"class":935},[822,3647,3648,3651,3653],{"class":824,"line":2099},[822,3649,3650],{"class":844},"        User-Agent",[822,3652,1615],{"class":935},[822,3654,3655],{"class":832}," redact\n",[822,3657,3658,3661,3663],{"class":824,"line":2110},[822,3659,3660],{"class":844},"        Authorization",[822,3662,1615],{"class":935},[822,3664,3622],{"class":832},[822,3666,3667,3670,3672],{"class":824,"line":2120},[822,3668,3669],{"class":844},"        Content-Type",[822,3671,1615],{"class":935},[822,3673,3605],{"class":832},[822,3675,3676],{"class":824,"line":2127},[822,3677,1630],{"emptyLinePlaceholder":422},[822,3679,3680,3683],{"class":824,"line":2134},[822,3681,3682],{"class":844},"certificatesResolvers",[822,3684,1638],{"class":935},[822,3686,3687,3690],{"class":824,"line":2142},[822,3688,3689],{"class":844},"  le",[822,3691,1638],{"class":935},[822,3693,3694,3697],{"class":824,"line":2149},[822,3695,3696],{"class":844},"    acme",[822,3698,1638],{"class":935},[822,3700,3701,3704,3706],{"class":824,"line":2157},[822,3702,3703],{"class":844},"      email",[822,3705,1615],{"class":935},[822,3707,3708],{"class":832}," log@traefik-sample.com\n",[822,3710,3711,3714,3716,3718,3721],{"class":824,"line":2165},[822,3712,3713],{"class":844},"      storage",[822,3715,1615],{"class":935},[822,3717,1619],{"class":1618},[822,3719,3720],{"class":832},"\u002Facme.json",[822,3722,1625],{"class":1618},[822,3724,3725],{"class":824,"line":2173},[822,3726,3727],{"class":1978},"      #caServer: https:\u002F\u002Facme-staging-v02.api.letsencrypt.org\u002Fdirectory # descoméntalo para hacer pruebas\n",[822,3729,3730,3733],{"class":824,"line":2181},[822,3731,3732],{"class":844},"      httpChallenge",[822,3734,1638],{"class":935},[822,3736,3737,3739,3741],{"class":824,"line":2189},[822,3738,3258],{"class":844},[822,3740,1615],{"class":935},[822,3742,2290],{"class":832},[124,3744,3746,3760],{"icon":1307,"label":3745},"middlewares.toml",[10,3747,3748,3749,3752,3753,3755,3756,3759],{},"Autenticación básica con ",[72,3750,3751],{},"htpasswd"," y un ",[77,3754,1266],{}," de, a lo mucho, 100 ",[77,3757,3758],{},"requests"," por minuto para mitigar abusos.",[814,3761,3765],{"className":3762,"code":3763,"language":3764,"meta":407,"style":407},"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",[72,3766,3767,3783,3801,3823,3839,3853,3870,3891,3900],{"__ignoreMap":407},[822,3768,3769,3772,3775,3778,3780],{"class":824,"line":825},[822,3770,3771],{"class":935},"[",[822,3773,3774],{"class":828},"http",[822,3776,390],{"class":3777},"sNpkn",[822,3779,1262],{"class":828},[822,3781,3782],{"class":935},"]\n",[822,3784,3785,3788,3790,3792,3794,3796,3799],{"class":824,"line":408},[822,3786,3787],{"class":935},"    [",[822,3789,3774],{"class":828},[822,3791,390],{"class":3777},[822,3793,1262],{"class":828},[822,3795,390],{"class":3777},[822,3797,3798],{"class":828},"myauth",[822,3800,3782],{"class":935},[822,3802,3803,3806,3808,3810,3812,3814,3816,3818,3821],{"class":824,"line":1051},[822,3804,3805],{"class":935},"        [",[822,3807,3774],{"class":828},[822,3809,390],{"class":3777},[822,3811,1262],{"class":828},[822,3813,390],{"class":3777},[822,3815,3798],{"class":828},[822,3817,390],{"class":3777},[822,3819,3820],{"class":828},"basicAuth",[822,3822,3782],{"class":935},[822,3824,3825,3829,3832,3834,3837],{"class":824,"line":1182},[822,3826,3828],{"class":3827},"st-jp","            realm",[822,3830,3831],{"class":935}," =",[822,3833,1619],{"class":1618},[822,3835,3836],{"class":832},"Traefik Basic Auth",[822,3838,1625],{"class":1618},[822,3840,3841,3844,3846,3848,3851],{"class":824,"line":1484},[822,3842,3843],{"class":3827},"            usersFile",[822,3845,3831],{"class":935},[822,3847,1619],{"class":1618},[822,3849,3850],{"class":832},"\u002Fshared\u002F.htpasswd",[822,3852,1625],{"class":1618},[822,3854,3855,3857,3859,3861,3863,3865,3868],{"class":824,"line":1655},[822,3856,3787],{"class":935},[822,3858,3774],{"class":828},[822,3860,390],{"class":3777},[822,3862,1262],{"class":828},[822,3864,390],{"class":3777},[822,3866,3867],{"class":828},"rate-limit",[822,3869,3782],{"class":935},[822,3871,3872,3874,3876,3878,3880,3882,3884,3886,3889],{"class":824,"line":1663},[822,3873,3805],{"class":935},[822,3875,3774],{"class":828},[822,3877,390],{"class":3777},[822,3879,1262],{"class":828},[822,3881,390],{"class":3777},[822,3883,3867],{"class":828},[822,3885,390],{"class":3777},[822,3887,3888],{"class":828},"rateLimit",[822,3890,3782],{"class":935},[822,3892,3893,3896,3898],{"class":824,"line":1673},[822,3894,3895],{"class":3827},"            average",[822,3897,3831],{"class":935},[822,3899,3532],{"class":1118},[822,3901,3902,3905,3907],{"class":824,"line":1681},[822,3903,3904],{"class":3827},"            burst",[822,3906,3831],{"class":935},[822,3908,3909],{"class":1118}," 50\n",[10,3911,3912,3913,3916],{},"Tienes toda la documentación del proyecto en GitHub: ",[381,3914,1298],{"href":1296,"rel":3915},[398],". Espero que esta guía te sea útil. ¡Hasta la próxima!",[1222,3918,3919],{},"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":407,"searchDepth":408,"depth":408,"links":3921},[3922,3923,3924,3925],{"id":1289,"depth":408,"text":1290},{"id":722,"depth":408,"text":723},{"id":1372,"depth":408,"text":1373},{"id":1573,"depth":408,"text":1574},"2022-07-24","Plan de despliegue con Docker Compose y Traefik: proxy inverso, SSL automático con Let's Encrypt y middlewares para un microservicio Laravel y una PWA.","\u002Fimg\u002Fposts\u002Fcovers\u002Fdespliegue-docker-traefik-letsencrypt-pwa.svg",{},"\u002Fblog\u002Fdespliegue-docker-traefik-letsencrypt-pwa",{"title":1245,"description":3927},"blog\u002Fdespliegue-docker-traefik-letsencrypt-pwa",[1239,3934,3935,1240,708,3936,3937,1241],"Laravel","Letsencrypt","Portainer","Redis","LJR2DIeMMF8ER1ABG-vyoNNoujMraAP2UQAgL1X8zFA",{"id":3940,"title":3941,"body":3942,"date":4696,"description":4697,"draft":417,"extension":418,"image":4698,"lang":420,"meta":4699,"navigation":422,"path":4700,"seo":4701,"stem":4702,"tags":4703,"__hash__":4706},"blog\u002Fblog\u002Fserverless-faas-aws-lambda.md","Una explicación breve sobre Serverless, FaaS y AWS Lambda",{"type":7,"value":3943,"toc":4680},[3944,3948,3955,3968,3979,3986,3992,3997,4000,4014,4017,4020,4023,4029,4033,4040,4067,4070,4073,4078,4081,4087,4091,4099,4109,4127,4131,4134,4145,4204,4212,4216,4219,4227,4230,4239,4242,4246,4252,4275,4279,4282,4292,4295,4312,4315,4320,4324,4327,4354,4358,4361,4369,4376,4492,4495,4498,4501,4507,4510,4519,4524,4527,4533,4557,4560,4563,4569,4574,4577,4583,4586,4592,4595,4601,4605,4608,4611,4648,4656,4660,4663,4666,4672,4677],[19,3945,3947],{"id":3946},"qué-es-serverless","¿Qué es Serverless?",[10,3949,3950,3951,3954],{},"Serverless no es una tecnología específica; es un concepto. Por eso cuesta entenderlo, igual que ",[77,3952,3953],{},"The Cloud"," era un concepto abstracto y confuso allá por 2008.",[10,3956,3957,3958,3961,3962,3965,3966,1615],{},"Definir ",[77,3959,3960],{},"Serverless"," es difícil. Lo que sigue está lejos de ser la mejor definición, pero hagámoslo simple: ",[14,3963,3964],{},"Serverless se trata de administrar menos infraestructura."," Estas son algunas diferencias entre administrar tu propia infraestructura y ",[77,3967,3960],{},[27,3969,3970,3973,3976],{},[30,3971,3972],{},"En lugar de iniciar y configurar servidores, usas servicios de alto nivel que ocultan esos detalles.",[30,3974,3975],{},"En lugar de escalar los servidores, dejas que el proveedor lo haga automáticamente.",[30,3977,3978],{},"En lugar de reservar servidores y pagar un precio fijo, pagas por lo que usas.",[10,3980,3981,3982,3985],{},"Sí, existen ",[77,3983,3984],{},"infraestructuras"," Serverless: tu código tiene que ejecutarse en algún lugar. Pero lo importante es que ni siquiera tienes que pensar en ellas.",[3987,3988,3989],"blockquote",{},[10,3990,3991],{},"Serverless significa administrar menos infraestructura: dejas de pensar en servidores y empiezas a pensar en funciones.",[3993,3994,3996],"h3",{"id":3995},"un-ejemplo","Un ejemplo",[10,3998,3999],{},"Ilustrémoslo con el almacenamiento de archivos:",[27,4001,4002,4008],{},[30,4003,4004,4007],{},[14,4005,4006],{},"Enfoque tradicional:"," comprar o alquilar espacio en disco.",[30,4009,4010,4013],{},[14,4011,4012],{},"Enfoque Serverless:"," usar AWS S3 o un servicio similar.",[10,4015,4016],{},"Con el enfoque tradicional tienes que decidir de antemano el tamaño del disco. Tienes que monitorearlo, hacer copias de seguridad, escalarlo si se llena y pagar el mismo precio aunque solo uses el 10 %.",[10,4018,4019],{},"Con el enfoque Serverless simplemente envías los archivos a S3 y pagas por lo que usas.",[10,4021,4022],{},"Para ser claros: sí, AWS S3 es un PaaS. ¡Resulta que la mayoría ya llevábamos un tiempo haciendo Serverless!",[10,4024,4025],{},[102,4026],{"alt":4027,"src":4028},"Comparación entre el enfoque tradicional de almacenamiento y el enfoque Serverless con pago por uso","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002F1_x_v5NRC3TTMt1MaYl1gMUg.jpeg",[19,4030,4032],{"id":4031},"serverless-frente-a-faas","Serverless frente a FaaS",[10,4034,4035,4036,4039],{},"FaaS, o ",[77,4037,4038],{},"Function as a Service",", es un servicio concreto que ofrecen algunos proveedores. Por ejemplo:",[27,4041,4042,4050,4057,4064],{},[30,4043,4044,4049],{},[381,4045,4048],{"href":4046,"rel":4047},"https:\u002F\u002Faws.amazon.com\u002Flambda\u002F",[398],"AWS Lambda",",",[30,4051,4052,4049],{},[381,4053,4056],{"href":4054,"rel":4055},"https:\u002F\u002Fazure.microsoft.com\u002Fservices\u002Ffunctions\u002F",[398],"Funciones de Microsoft Azure",[30,4058,4059,4049],{},[381,4060,4063],{"href":4061,"rel":4062},"https:\u002F\u002Fcloud.google.com\u002Ffunctions",[398],"Funciones de Google Cloud",[30,4065,4066],{},"y muchos más.",[10,4068,4069],{},"FaaS te permite ejecutar código Serverless: no tienes que configurar ni escalar servidores. Solo subes tu código, el proveedor lo ejecuta por ti y pagas únicamente por su tiempo de ejecución.",[10,4071,4072],{},"Al igual que AWS S3 y muchos otros servicios, FaaS es un servicio Serverless. Pero es importante no confundir ambos conceptos.",[3987,4074,4075],{},[10,4076,4077],{},"FaaS es Serverless, pero Serverless es más que solo FaaS.",[10,4079,4080],{},"Dicho esto, FaaS es, por supuesto, muy interesante para quienes desarrollamos: ¡tenemos código para ejecutar!",[10,4082,4083],{},[102,4084],{"alt":4085,"src":4086},"Arquitectura basada en eventos: distintas fuentes (API Gateway, cron, cola SQS, evento S3) invocan una función AWS Lambda que escribe en servicios AWS como DynamoDB, S3 y SNS\u002FSES","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Flambda-event-architecture.svg",[19,4088,4090],{"id":4089},"aws","AWS",[10,4092,4093,4098],{},[381,4094,4097],{"href":4095,"rel":4096},"https:\u002F\u002Faws.amazon.com\u002Fwhat-is-aws\u002F",[398],"La nube de AWS"," es uno de los proveedores líderes en este momento.",[10,4100,4101,4102,4105,4106,1271],{},"Ofrece muchos servicios distintos para crear y ejecutar aplicaciones en línea. Algunos son ",[77,4103,4104],{},"serverless"," y otros no. Por ejemplo, puedes alquilar servidores con su famoso servicio AWS EC2 o ejecutar bases de datos con AWS RDS (",[77,4107,4108],{},"Relational Database Service",[10,4110,4111,4112,4114,4115,4120,4121,4126],{},"También puedes crear aplicaciones ",[77,4113,4104],{}," con otros proveedores de nube, como ",[381,4116,4119],{"href":4117,"rel":4118},"https:\u002F\u002Fazure.microsoft.com\u002F",[398],"Microsoft Azure"," o ",[381,4122,4125],{"href":4123,"rel":4124},"https:\u002F\u002Fcloud.google.com\u002F",[398],"Google Cloud",". Aun así, por ahora AWS es la solución más popular y el líder de la industria. Al enfocarnos en un solo proveedor, mantenemos esta guía simple pero concreta.",[19,4128,4130],{"id":4129},"crear-una-cuenta-de-aws","Crear una cuenta de AWS",[10,4132,4133],{},"En esta sección veremos cómo crear una cuenta de AWS nueva.",[61,4135,4137],{"title":4136},"Antes de empezar",[27,4138,4139,4142],{},[30,4140,4141],{},"Necesitas una tarjeta de crédito (aunque las cuentas de AWS son gratuitas).",[30,4143,4144],{},"Las cuentas tardan hasta 24 horas en activarse.",[304,4146,4147,4165,4171,4177,4186,4192,4198],{},[307,4148,4150],{"title":4149},"Crea la cuenta",[10,4151,4152,4153,4158,4159,4164],{},"Visita la ",[381,4154,4157],{"href":4155,"rel":4156},"https:\u002F\u002Faws.amazon.com\u002F",[398],"página de inicio de AWS"," y haz clic en «Crear una cuenta» (",[381,4160,4163],{"href":4161,"rel":4162},"https:\u002F\u002Fportal.aws.amazon.com\u002Fbilling\u002Fsignup",[398],"aquí tienes un enlace directo","). Si ya iniciaste sesión en AWS antes, quizá tengas que hacer clic primero en «Iniciar sesión en una cuenta diferente» y luego en «Crear una nueva cuenta de AWS».",[307,4166,4168],{"title":4167},"Completa el formulario",[10,4169,4170],{},"Rellena el formulario y haz clic en «Continuar».",[307,4172,4174],{"title":4173},"Elige el tipo de cuenta",[10,4175,4176],{},"«Personal» o «Profesional»: ambas tienen las mismas funciones.",[307,4178,4180],{"title":4179},"Añade la información adicional",[10,4181,4182,4183,390],{},"Complétala y haz clic en «Crear cuenta y continuar». Tu cuenta se crea, ",[14,4184,4185],{},"pero aún no está activa",[307,4187,4189],{"title":4188},"Agrega un método de pago",[10,4190,4191],{},"En la página «Información de pago».",[307,4193,4195],{"title":4194},"Verifica tu número de teléfono",[10,4196,4197],{},"Sigue el proceso de verificación que te indica AWS.",[307,4199,4201],{"title":4200},"Elige un plan de soporte",[10,4202,4203],{},"Si te lo solicitan, puedes elegir un plan de AWS Support. Hay un plan gratuito disponible.",[10,4205,4206,4207,390],{},"Ahora solo queda esperar a que tu cuenta se active por completo. Esto puede tardar hasta 24 horas. Si la activación no funciona, consulta la ",[381,4208,4211],{"href":4209,"rel":4210},"https:\u002F\u002Faws.amazon.com\u002Fpremiumsupport\u002Fknowledge-center\u002Fcreate-and-activate-aws-account\u002F",[398],"documentación oficial de AWS",[19,4213,4215],{"id":4214},"despliegue","Despliegue",[10,4217,4218],{},"Hay dos enfoques para desplegar tus aplicaciones Serverless:",[27,4220,4221,4224],{},[30,4222,4223],{},"desplegar los proyectos manualmente desde la interfaz de usuario,",[30,4225,4226],{},"o automatizar el despliegue con herramientas.",[10,4228,4229],{},"El despliegue manual no es buena idea: hay mucho margen para el error y, seamos honestos, la interfaz de AWS es bastante compleja. Usar una herramienta resultará, en realidad, más sencillo.",[10,4231,4232,4233,4238],{},"La herramienta que te mostraré es ",[381,4234,4237],{"href":4235,"rel":4236},"https:\u002F\u002Fwww.serverless.com\u002Fopen-source\u002F",[398],"Serverless Framework",". Hay varias razones para esta elección: es la más popular ahora mismo (lo que significa muchos ejemplos en línea), tiene la comunidad más grande y su formato de configuración es de los más simples.",[10,4240,4241],{},"Por supuesto, todo lo que te mostraré es compatible con otras herramientas de despliegue, como AWS SAM, AWS CDK, CloudFormation o Terraform.",[3993,4243,4245],{"id":4244},"configuración","Configuración",[10,4247,4248,4249,4251],{},"Para desplegar aplicaciones ",[77,4250,4104],{}," (incluidos los ejemplos), necesitarás:",[27,4253,4254,4257,4266],{},[30,4255,4256],{},"una cuenta de AWS;",[30,4258,4259,4260,4265],{},"la ",[381,4261,4264],{"href":4262,"rel":4263},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fcli\u002Flatest\u002Fuserguide\u002Fcli-chap-install.html",[398],"AWS CLI"," instalada (cualquier versión);",[30,4267,4268,4269,4274],{},"el ",[381,4270,4273],{"href":4271,"rel":4272},"https:\u002F\u002Fwww.serverless.com\u002Fframework\u002Fdocs\u002Fgetting-started\u002F",[398],"Serverless Framework de código abierto"," instalado (no necesitas crear una cuenta para su servicio «Pro»).",[19,4276,4278],{"id":4277},"qué-es-aws-lambda","¿Qué es AWS Lambda?",[10,4280,4281],{},"Lambda es un servicio de AWS que te permite ejecutar código sin lidiar con los detalles de la infraestructura: administrar servidores, escalarlos, etc.",[10,4283,4284,4285,4288,4289,390],{},"Lo importante de Lambda es que el código se ",[14,4286,4287],{},"activa mediante eventos",". No puedes ejecutar servidores web, demonios ni tareas de larga duración (como tareas programadas). Por eso solemos llamarlo una ",[14,4290,4291],{},"arquitectura basada en eventos",[10,4293,4294],{},"Si las «aplicaciones basadas en eventos» te suenan intimidantes, ¡tranquilo! No hay nada exótico aquí. Tu código se activa por eventos, y los eventos pueden ser:",[27,4296,4297,4300,4303,4306,4309],{},[30,4298,4299],{},"una solicitud HTTP (por ejemplo, para servir un sitio web o una API),",[30,4301,4302],{},"un cron (por ejemplo, «todos los días a medianoche, ejecuta este código»),",[30,4304,4305],{},"un mensaje en una cola (por ejemplo, para ejecutar trabajos asíncronos),",[30,4307,4308],{},"un mensaje de otra aplicación (por ejemplo, para conectar microservicios),",[30,4310,4311],{},"un mensaje de otros servicios de AWS (por ejemplo, para procesar archivos cuando se suben a S3).",[10,4313,4314],{},"Son solo ejemplos, pero seguro que uno o dos te resultan familiares. Cuando lo piensas, la mayor parte de lo que hacemos se dispara por eventos. Al adoptar esto, AWS Lambda te permite eliminar un montón de código e infraestructura «de pegamento» y centrarte en la lógica de negocio.",[3987,4316,4317],{},[10,4318,4319],{},"La mayoría de las aplicaciones ya están controladas por eventos.",[19,4321,4323],{"id":4322},"las-ventajas-de-estar-basado-en-eventos","Las ventajas de estar basado en eventos",[10,4325,4326],{},"Más allá de que Lambda se encarga de administrar el servidor por ti, su enfoque basado en eventos tiene varios beneficios:",[747,4328,4329,4336,4343],{},[750,4330,4333],{"icon":4331,"title":4332},"fas fa-code","Escribes menos código",[10,4334,4335],{},"Como tu código reacciona a eventos, no escribes ni mantienes servidores web, demonios, orquestadores (como supervisord) ni sondeos a otros sistemas.",[750,4337,4340],{"icon":4338,"title":4339},"fas fa-coins","Pagas solo por lo que usas",[10,4341,4342],{},"Ya no pagas por servidores inactivos: solo pagas cuando tu código se ejecuta, cuando ocurre un evento. ¡Las aplicaciones con poco uso pueden costar casi $0!",[750,4344,4347],{"icon":4345,"title":4346},"fas fa-arrow-up-right-dots","Escalado extremo",[10,4348,4349,4350,4353],{},"Cada evento se ejecuta de forma aislada: no hay concurrencia, ",[77,4351,4352],{},"sharding"," ni recursos compartidos. Es escalado horizontal en su unidad más pequeña: el evento.",[19,4355,4357],{"id":4356},"cómo-se-ejecuta-y-escala-lambda","¿Cómo se ejecuta y escala Lambda?",[10,4359,4360],{},"Al crear una función Lambda, lo principal es:",[27,4362,4363,4366],{},[30,4364,4365],{},"seleccionar el lenguaje (Node.js es el predeterminado),",[30,4367,4368],{},"subir tu código.",[10,4370,4371,4372,4375],{},"Así se ve el ",[77,4373,4374],{},"handler"," de Lambda más simple:",[121,4377,4378,4442],{},[124,4379,4381],{"icon":786,"label":4380},"JavaScript (Node.js)",[814,4382,4386],{"className":4383,"code":4384,"language":4385,"meta":407,"style":407},"language-javascript shiki shiki-themes vitesse-dark","exports.handler = async function(event, context) {\n    return 'Hello world!'\n}\n","javascript",[72,4387,4388,4423,4437],{"__ignoreMap":407},[822,4389,4390,4393,4395,4397,4399,4403,4406,4409,4412,4414,4417,4420],{"class":824,"line":825},[822,4391,4392],{"class":844},"exports",[822,4394,390],{"class":935},[822,4396,4374],{"class":828},[822,4398,3831],{"class":935},[822,4400,4402],{"class":4401},"s_wWq"," async",[822,4404,4405],{"class":4401}," function",[822,4407,4408],{"class":935},"(",[822,4410,4411],{"class":3827},"event",[822,4413,4049],{"class":935},[822,4415,4416],{"class":3827}," context",[822,4418,4419],{"class":935},")",[822,4421,4422],{"class":935}," {\n",[822,4424,4425,4428,4431,4434],{"class":824,"line":408},[822,4426,4427],{"class":3198},"    return",[822,4429,4430],{"class":1618}," '",[822,4432,4433],{"class":832},"Hello world!",[822,4435,4436],{"class":1618},"'\n",[822,4438,4439],{"class":824,"line":1051},[822,4440,4441],{"class":935},"}\n",[124,4443,4444],{"icon":758,"label":708},[814,4445,4448],{"className":4446,"code":4447,"language":759,"meta":407,"style":407},"language-php shiki shiki-themes vitesse-dark","return function ($event, $context) {\n    return 'Hello world!';\n}\n",[72,4449,4450,4474,4488],{"__ignoreMap":407},[822,4451,4452,4455,4457,4460,4462,4464,4467,4470,4472],{"class":824,"line":825},[822,4453,4454],{"class":3198},"return",[822,4456,4405],{"class":4401},[822,4458,4459],{"class":935}," ($",[822,4461,4411],{"class":3827},[822,4463,4049],{"class":935},[822,4465,4466],{"class":935}," $",[822,4468,4469],{"class":3827},"context",[822,4471,4419],{"class":935},[822,4473,4422],{"class":935},[822,4475,4476,4478,4480,4482,4485],{"class":824,"line":408},[822,4477,4427],{"class":3198},[822,4479,4430],{"class":1618},[822,4481,4433],{"class":832},[822,4483,4484],{"class":1618},"'",[822,4486,4487],{"class":935},";\n",[822,4489,4490],{"class":824,"line":1051},[822,4491,4441],{"class":935},[10,4493,4494],{},"Por ahora nos centraremos en el modelo de ejecución.",[10,4496,4497],{},"Una vez creada la función, no se está ejecutando nada. Lambda ejecuta tu código bajo demanda, es decir, solo cuando hay un evento que atender.",[10,4499,4500],{},"Repasemos qué ocurre cuando empiezan a llegar eventos, por ejemplo, solicitudes HTTP.",[10,4502,4503],{},[102,4504],{"alt":4505,"src":4506},"Cómo AWS Lambda escala por eventos: cold start, reutilización warm, ejecución concurrente y scale-to-zero","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Flambda-scaling.svg",[10,4508,4509],{},"En la representación de arriba, la flecha verde representa el evento. En cuanto llega, Lambda inicia una nueva instancia (la barra gris) y tu código (la barra azul) se ejecuta dentro de ella.",[10,4511,4512,4513,4518],{},"Las instancias de Lambda son entornos Linux sencillos (Amazon Linux). Son como contenedores Docker, salvo que usan ",[381,4514,4517],{"href":4515,"rel":4516},"https:\u002F\u002Ffirecracker-microvm.github.io\u002F",[398],"una tecnología diferente",". Cada función tiene sus propias instancias: no compartes el entorno con otros clientes ni con tus otras funciones.",[61,4520,4521],{},[10,4522,4523],{},"Aunque es interesante conocer estos detalles, no tienes ningún control sobre el entorno. El trabajo de AWS es ejecutar, mantener y escalar estas instancias, así como el entorno Linux.",[10,4525,4526],{},"Volviendo al escenario: quizá notaste que, aunque tu código (en azul) terminó, la instancia de Lambda (en gris) siguió viva un rato más. Esto es para que pueda atender los siguientes eventos más rápido:",[10,4528,4529],{},[102,4530],{"alt":4531,"src":4532},"La instancia de Lambda permanece activa para reutilizarse en los siguientes eventos","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Fsls2-removebg-preview.png",[10,4534,4535,4536,4539,4540,4543,4544,4539,4547,4550,4551,4556],{},"Como ves, el primer evento necesitó arrancar una instancia. Esto se llama ",[14,4537,4538],{},"arranque en frío"," (",[77,4541,4542],{},"cold start",") y puede tardar unos 200 ms. El segundo evento lo atendió una instancia ",[14,4545,4546],{},"cálida",[77,4548,4549],{},"warm","). Los arranques en frío —y cómo optimizarlos o evitarlos— son todo un tema; puedes leer más ",[381,4552,4555],{"href":4553,"rel":4554},"https:\u002F\u002Fmikhail.io\u002Fserverless\u002Fcoldstarts\u002Faws\u002F",[398],"en este gran artículo",", que se mantiene actualizado con el tiempo.",[10,4558,4559],{},"AWS mantiene activas las instancias mientras haya eventos que atender. Se eliminan tras 10 minutos de inactividad, es decir, 10 minutos sin un evento.",[10,4561,4562],{},"¿Y si llega otro evento mientras la instancia está ocupada? Se inicia otra sobre la marcha:",[10,4564,4565],{},[102,4566],{"alt":4567,"src":4568},"Una segunda instancia de Lambda se inicia para atender un evento concurrente","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Fsls3-removebg-preview.png",[3987,4570,4571],{},[10,4572,4573],{},"Una instancia de Lambda siempre atiende un evento a la vez.",[10,4575,4576],{},"Que cada evento se ejecute completamente aislado de los demás es lo que hace tan fácil el escalado: AWS simplemente inicia nuevas instancias.",[10,4578,4579],{},[102,4580],{"alt":4581,"src":4582},"Varias instancias de Lambda aisladas escalando en paralelo, una por cada evento","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Fsls4-removebg-preview.png",[10,4584,4585],{},"Por supuesto, si hay instancias disponibles (sin atender eventos), se reutilizan, ampliando el plazo antes de su eliminación:",[10,4587,4588],{},[102,4589],{"alt":4590,"src":4591},"Instancias de Lambda inactivas se reutilizan antes de ser eliminadas","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Fsls5-removebg-preview.png",[10,4593,4594],{},"Con el tiempo, tu aplicación puede reducirse a cero instancias si no hay eventos que atender. Cualquier evento nuevo iniciará una instancia de nuevo:",[10,4596,4597],{},[102,4598],{"alt":4599,"src":4600},"La aplicación Lambda se reduce a cero instancias cuando no hay eventos que atender","\u002Fimg\u002Fposts\u002Fblog\u002Fserverless-faas-aws-lambda\u002Fsls6-removebg-preview.png",[19,4602,4604],{"id":4603},"costos","Costos",[10,4606,4607],{},"A diferencia del alojamiento tradicional, con Lambda pagas en función de tu uso. Más concretamente, pagas por la cantidad de invocaciones y por el tiempo de ejecución de tu código.",[10,4609,4610],{},"No pagas por el tiempo de inactividad entre eventos (la parte gris). Solo pagas cuando tu código se está ejecutando (la parte azul).",[61,4612,4614,4634,4637],{"title":4613},"Ejemplo de cálculo",[27,4615,4616,4622,4628],{},[30,4617,4618,4619],{},"Invocaciones (o solicitudes) por mes: ",[14,4620,4621],{},"100 000",[30,4623,4624,4625],{},"Tiempo medio de ejecución por evento: ",[14,4626,4627],{},"200 ms",[30,4629,4630,4631],{},"Costo mensual estimado: ",[14,4632,4633],{},"$0.353",[10,4635,4636],{},"Notas:",[27,4638,4639,4642,4645],{},[30,4640,4641],{},"Se ignora el nivel gratuito por simplicidad.",[30,4643,4644],{},"Es el costo de una Lambda bastante potente (1024 MB). Las más lentas son hasta 8 veces más baratas.",[30,4646,4647],{},"No incluye costos de otros servicios (bases de datos, endpoints HTTP públicos, etc.).",[10,4649,4650,4651,390],{},"Encontrarás más detalles en la ",[381,4652,4655],{"href":4653,"rel":4654},"https:\u002F\u002Faws.amazon.com\u002Flambda\u002Fpricing\u002F",[398],"página de precios de AWS Lambda",[19,4657,4659],{"id":4658},"qué-pasa-entre-eventos","¿Qué pasa entre eventos?",[10,4661,4662],{},"Nada.",[10,4664,4665],{},"AWS Lambda congela tu código en cuanto terminas de procesar un evento. No hay forma de ejecutar nada entre invocaciones. Por eso tu código debe estar enfocado en eventos: no puedes correr un demonio ni tareas de larga duración.",[10,4667,4668,4669,4671],{},"Pero no te preocupes: puedes apoyarte en otros servicios de AWS para cubrir distintos casos de uso, como trabajos asíncronos, procesamiento de flujos de datos, reacción a cargas de archivos, etc. Lambda no vive en el vacío, y crear aplicaciones ",[77,4670,4104],{}," consiste justo en eso: componer servicios.",[3987,4673,4674],{},[10,4675,4676],{},"AWS Lambda es solo una pieza del rompecabezas en las aplicaciones Serverless.",[1222,4678,4679],{},"html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sCK9x, html code.shiki .sCK9x{--shiki-default:#80A665}html pre.shiki code .s_wWq, html code.shiki .s_wWq{--shiki-default:#CB7676}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}html pre.shiki code .s3QIE, html code.shiki .s3QIE{--shiki-default:#4D9375}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}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);}",{"title":407,"searchDepth":408,"depth":408,"links":4681},[4682,4685,4686,4687,4688,4691,4692,4693,4694,4695],{"id":3946,"depth":408,"text":3947,"children":4683},[4684],{"id":3995,"depth":1051,"text":3996},{"id":4031,"depth":408,"text":4032},{"id":4089,"depth":408,"text":4090},{"id":4129,"depth":408,"text":4130},{"id":4214,"depth":408,"text":4215,"children":4689},[4690],{"id":4244,"depth":1051,"text":4245},{"id":4277,"depth":408,"text":4278},{"id":4322,"depth":408,"text":4323},{"id":4356,"depth":408,"text":4357},{"id":4603,"depth":408,"text":4604},{"id":4658,"depth":408,"text":4659},"2021-07-11","Qué es Serverless, en qué se diferencia de FaaS y cómo encaja AWS Lambda: arquitectura basada en eventos, escalado y costos, explicado de forma simple.","\u002Fimg\u002Fposts\u002Fcovers\u002Fserverless-faas-aws-lambda.svg",{},"\u002Fblog\u002Fserverless-faas-aws-lambda",{"title":3941,"description":4697},"blog\u002Fserverless-faas-aws-lambda",[3960,4704,4090,4705],"FaaS","Lambda","IFHD88rjKCLcGG0kXatFp9RMMOKBU5zPX14pxsaQK2c",{"id":4708,"title":4709,"body":4710,"date":6659,"description":6660,"draft":417,"extension":418,"image":6661,"lang":420,"meta":6662,"navigation":422,"path":6663,"seo":6664,"stem":6665,"tags":6666,"__hash__":6671},"blog\u002Fblog\u002Faprovisionar-linux-nginx-mysql-php7-vagrant.md","Aprovisionar Linux con Nginx, MySQL y PHP7 mediante Vagrant",{"type":7,"value":4711,"toc":6653},[4712,4723,4756,4762,4766,4860,4862,4942,4946,4953,4956,6322,6326,6329,6640,6650],[10,4713,4714,4715,4718,4719,4722],{},"Hoy te muestro una ",[77,4716,4717],{},"box"," de Vagrant que preparé hace un tiempo para aprovisionar ",[14,4720,4721],{},"Ubuntu 19.10"," con todo un stack LEMP listo para trabajar:",[27,4724,4725,4728,4731,4734,4737,4739,4742,4744,4747,4750,4753],{},[30,4726,4727],{},"Git",[30,4729,4730],{},"Nginx",[30,4732,4733],{},"PHP 7.3",[30,4735,4736],{},"MySQL 5.7",[30,4738,3937],{},[30,4740,4741],{},"Composer",[30,4743,712],{},[30,4745,4746],{},"npm",[30,4748,4749],{},"Memcached",[30,4751,4752],{},"PHPUnit",[30,4754,4755],{},"Zsh",[10,4757,4758],{},[102,4759],{"alt":4760,"src":4761},"Aprovisionamiento del stack LEMP con Vagrant: una box de Vagrant configura Ubuntu con Nginx, MySQL y PHP 7, más Redis, Composer y NodeJS","\u002Fimg\u002Fposts\u002Fblog\u002Faprovisionar-linux-nginx-mysql-php7-vagrant\u002Flemp-vagrant-arquitectura.svg",[19,4763,4765],{"id":4764},"instalación-rápida","Instalación rápida",[304,4767,4768,4785,4827],{},[307,4769,4771],{"title":4770},"Instala VirtualBox y Vagrant",[10,4772,4773,4774,4779,4780,390],{},"Descarga e instala ",[381,4775,4778],{"href":4776,"rel":4777},"https:\u002F\u002Fwww.virtualbox.org\u002Fwiki\u002FDownloads",[398],"VirtualBox"," y ",[381,4781,4784],{"href":4782,"rel":4783},"https:\u002F\u002Fwww.vagrantup.com\u002Fdownloads.html",[398],"Vagrant",[307,4786,4787,4795],{"title":1378},[10,4788,4789,4790,1615],{},"Clona el ",[381,4791,4794],{"href":4792,"rel":4793},"https:\u002F\u002Fgithub.com\u002Fmarcotorres\u002Fubuntu-lemp-php7",[398],"repositorio del proyecto",[814,4796,4798],{"className":816,"code":4797,"language":818,"meta":407,"style":407},"git clone git@github.com:\u003Cuser>\u002Fubuntu-lemp-php7.git lemp7\n",[72,4799,4800],{"__ignoreMap":407},[822,4801,4802,4804,4806,4809,4812,4815,4818,4821,4824],{"class":824,"line":825},[822,4803,829],{"class":828},[822,4805,833],{"class":832},[822,4807,4808],{"class":832}," git@github.com:",[822,4810,4811],{"class":4401},"\u003C",[822,4813,4814],{"class":832},"use",[822,4816,4817],{"class":3777},"r",[822,4819,4820],{"class":4401},">",[822,4822,4823],{"class":832},"\u002Fubuntu-lemp-php7.git",[822,4825,4826],{"class":832}," lemp7\n",[307,4828,4830],{"title":4829},"Instala los plugins de Vagrant",[814,4831,4833],{"className":816,"code":4832,"language":818,"meta":407,"style":407},"vagrant plugin install vagrant-vbguest\nvagrant plugin install vagrant-hostmanager\n",[72,4834,4835,4849],{"__ignoreMap":407},[822,4836,4837,4840,4843,4846],{"class":824,"line":825},[822,4838,4839],{"class":828},"vagrant",[822,4841,4842],{"class":832}," plugin",[822,4844,4845],{"class":832}," install",[822,4847,4848],{"class":832}," vagrant-vbguest\n",[822,4850,4851,4853,4855,4857],{"class":824,"line":408},[822,4852,4839],{"class":828},[822,4854,4842],{"class":832},[822,4856,4845],{"class":832},[822,4858,4859],{"class":832}," vagrant-hostmanager\n",[19,4861,1373],{"id":1372},[304,4863,4864,4884,4907,4930],{},[307,4865,4867,4873],{"title":4866},"Entra al directorio del proyecto",[10,4868,4869,4870,1615],{},"Es la carpeta donde está el archivo ",[72,4871,4872],{},"README.md",[814,4874,4876],{"className":816,"code":4875,"language":818,"meta":407,"style":407},"cd lemp7\n",[72,4877,4878],{"__ignoreMap":407},[822,4879,4880,4882],{"class":824,"line":825},[822,4881,845],{"class":844},[822,4883,4826],{"class":832},[307,4885,4887,4899],{"title":4886},"Levanta la box",[814,4888,4890],{"className":816,"code":4889,"language":818,"meta":407,"style":407},"vagrant up\n",[72,4891,4892],{"__ignoreMap":407},[822,4893,4894,4896],{"class":824,"line":825},[822,4895,4839],{"class":828},[822,4897,4898],{"class":832}," up\n",[61,4900,4902],{"title":4901},"Acceso por SSH",[10,4903,4904,4905,390],{},"Al ingresar por SSH, el usuario y la contraseña son ",[72,4906,4839],{},[307,4908,4910,4917],{"title":4909},"Verifica tu archivo hosts",[10,4911,4912,4913,4916],{},"Asegúrate de que tu archivo ",[72,4914,4915],{},"hosts"," tenga esta línea:",[814,4918,4920],{"className":816,"code":4919,"language":818,"meta":407,"style":407},"192.168.2.3 lemp7.vh\n",[72,4921,4922],{"__ignoreMap":407},[822,4923,4924,4927],{"class":824,"line":825},[822,4925,4926],{"class":828},"192.168.2.3",[822,4928,4929],{"class":832}," lemp7.vh\n",[307,4931,4933],{"title":4932},"Ábrelo en el navegador",[10,4934,4935,4936,4941],{},"Visita ",[381,4937,4940],{"href":4938,"rel":4939},"http:\u002F\u002Flemp7.vh",[398],"lemp7.vh",". La próxima vez que levantes la box, arrancará mucho más rápido.",[19,4943,4945],{"id":4944},"el-script-de-aprovisionamiento","El script de aprovisionamiento",[10,4947,4948,4949,4952],{},"Lo importante al aprovisionar tu distribución —ya sea con Vagrant, Docker, o en un VPS ",[77,4950,4951],{},"on premise",", en la nube, dedicado o físico— es tener en cuenta los paquetes necesarios, las interfaces de línea de comandos y las configuraciones para que todo trabaje en armonía.",[10,4954,4955],{},"Este es el contenido del script de Bash que invoca Vagrant:",[814,4957,4959],{"className":816,"code":4958,"language":818,"meta":407,"style":407},"#!\u002Fusr\u002Fbin\u002Fenv bash\n\nmain() {\n  startGo\n  setupGo\n  toolsGo\n  nginxGo\n  mysqlGo\n  phpGo\n  composerGo\n  nodeGo\n  zshGo\n  endGo\n}\n\nstartGo() {\n  echo \"========    Lemp7 BOX - START   ========\" && \\\n  echo -e \"========================================\" && \\\n  sudo bash -c \"echo '127.0.1.1   ubuntu-disco-dingo' >> \u002Fetc\u002Fhosts\"\n}\n\nsetupGo() {\n  echo \"---------------   SETUP   --------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  export LC_ALL=en_US.UTF-8 && \\\n  export LANG=en_US.UTF-8 && \\\n  sudo add-apt-repository -y ppa:ondrej\u002Fnginx && \\\n  sudo add-apt-repository -y ppa:ondrej\u002Fphp && \\\n  sudo apt-get update\n}\n\ntoolsGo() {\n  echo \"---------------   TOOLS   --------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  sudo apt-get install -y re2c libpcre3-dev gcc mc grc cowsay figlet zsh lsb-core\n}\n\nnginxGo() {\n  echo \"---------------   NGINX   --------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  sudo apt-get install -y nginx && \\\n  sudo cp \u002Fvagrant\u002Fdata\u002Fnginx\u002Flemp7.vh.conf \u002Fetc\u002Fnginx\u002Fsites-available\u002Flemp7.vh.conf && \\\n  sudo ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Flemp7.vh.conf \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Flemp7.vh && \\\n  sudo systemctl restart nginx.service\n}\n\nmysqlGo() {\n  echo \"---------------   MYSQL   --------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  sudo apt-get install -y mysql-server && \\\n  sudo cp \u002Fvagrant\u002Fdata\u002Fmysql\u002F.my.cnf \u002Froot\u002F.my.cnf && \\\n  sudo chmod 600 \u002Froot\u002F.my.cnf && \\\n  sudo service mysql start && \\\nmysql --user=root \u003C\u003CEOF\n  ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';   \n  FLUSH PRIVILEGES;\nEOF\n}\n\nphpGo() {\n  echo \"----------------   PHP   ---------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  sudo apt-get install -y php7.3-fpm php7.3-mysql php7.3-phpdbg php7.3-mbstring php7.3-gd php-imagick && \\\n  sudo apt-get install -y php7.3-pgsql php7.3-pspell php7.3-recode php7.3-tidy php7.3-intl php7.3-curl && \\\n  sudo apt-get install -y php7.3-zip php7.3-xml php7.3-dev php-memcached mcrypt memcached phpunit && \\\n  sudo cp \u002Fvagrant\u002Fdata\u002Fphp\u002Flemp.ini \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Flemp.ini && \\\n  sudo chmod 644 \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Flemp.ini && \\\n  sudo ln -s \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Flemp.ini \u002Fetc\u002Fphp\u002F7.3\u002Fcli\u002Fconf.d\u002F100-lemp.ini && \\\n  sudo ln -s \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Flemp.ini \u002Fetc\u002Fphp\u002F7.3\u002Ffpm\u002Fconf.d\u002F100-lemp.ini && \\\n  sudo pecl install xdebug && \\\n  sudo cp \u002Fvagrant\u002Fdata\u002Fphp\u002Fxdebug.ini \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Fxdebug.ini && \\\n  sudo chmod 644 \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Fxdebug.ini && \\\n  sudo ln -s \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Fxdebug.ini \u002Fetc\u002Fphp\u002F7.3\u002Fcli\u002Fconf.d\u002F105-xdebug.ini && \\\n  sudo ln -s \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Fxdebug.ini \u002Fetc\u002Fphp\u002F7.3\u002Ffpm\u002Fconf.d\u002F105-xdebug.ini && \\\n  sudo systemctl restart php7.3-fpm\n}\n\ncomposerGo() {\n  echo \"--------------   COMPOSER   ------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  curl -sS https:\u002F\u002Fgetcomposer.org\u002Finstaller | php && \\\n  sudo mv composer.phar \u002Fusr\u002Flocal\u002Fbin\u002Fcomposer\n}\n\nnodeGo() {\n  echo \"----------------   NODE   --------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  sudo apt install -y nodejs npm\n}\n\nzshGo() {\n  echo \"----------------   ZSH   ---------------\" && \\\n  echo -e \"----------------------------------------\" && \\\n  cd \u002Ftmp && wget https:\u002F\u002Fraw.github.com\u002Frobbyrussell\u002Foh-my-zsh\u002Fmaster\u002Ftools\u002Finstall.sh && \\\n  sudo sh .\u002Finstall.sh && rm .\u002Finstall.sh && usermod --shell \u002Fbin\u002Fzsh root && \\\n  git clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-syntax-highlighting.git ~\u002F.oh-my-zsh\u002Fplugins\u002Fzsh-syntax-highlighting && \\\n  git clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-autosuggestions.git ~\u002F.oh-my-zsh\u002Fplugins\u002Fzsh-autosuggestions && \\\n  sed -i -e 's\u002Fgit\u002Fgit zsh-syntax-highlighting zsh-autosuggestions\u002F' ~\u002F.zshrc && \\\n  sed -i -e 's\u002Frobbyrussell\u002Fristo\u002F' ~\u002F.zshrc\n}\n\nendGo() {\n  sudo usermod -a -G www-data vagrant && \\\n  echo \"=========    Lemp7 BOX - END   =========\" && \\\n  echo -e \"========================================\" && \\\n  figlet Lemp7 && \\\n  cowsay -f milk \"Nunca confies en un ordenador que no puedas lanzar por una ventana. --->Steve Wozniak\"\n}\n\nmain\nexit 0\n",[72,4960,4961,4966,4970,4980,4985,4990,4995,5000,5005,5010,5015,5020,5025,5030,5034,5038,5047,5064,5082,5100,5104,5108,5117,5132,5149,5172,5191,5208,5223,5233,5237,5241,5250,5265,5281,5318,5322,5326,5335,5350,5366,5383,5400,5419,5432,5436,5440,5449,5464,5480,5497,5513,5529,5546,5560,5565,5570,5574,5578,5582,5591,5606,5622,5654,5686,5721,5737,5752,5769,5786,5802,5818,5832,5849,5866,5877,5881,5885,5894,5909,5925,5946,5959,5963,5967,5976,5991,6007,6024,6028,6032,6041,6056,6072,6092,6127,6144,6160,6184,6202,6206,6210,6219,6241,6256,6272,6284,6301,6305,6309,6314],{"__ignoreMap":407},[822,4962,4963],{"class":824,"line":825},[822,4964,4965],{"class":1978},"#!\u002Fusr\u002Fbin\u002Fenv bash\n",[822,4967,4968],{"class":824,"line":408},[822,4969,1630],{"emptyLinePlaceholder":422},[822,4971,4972,4975,4978],{"class":824,"line":1051},[822,4973,4974],{"class":828},"main",[822,4976,4977],{"class":935},"()",[822,4979,4422],{"class":935},[822,4981,4982],{"class":824,"line":1182},[822,4983,4984],{"class":828},"  startGo\n",[822,4986,4987],{"class":824,"line":1484},[822,4988,4989],{"class":828},"  setupGo\n",[822,4991,4992],{"class":824,"line":1655},[822,4993,4994],{"class":828},"  toolsGo\n",[822,4996,4997],{"class":824,"line":1663},[822,4998,4999],{"class":828},"  nginxGo\n",[822,5001,5002],{"class":824,"line":1673},[822,5003,5004],{"class":828},"  mysqlGo\n",[822,5006,5007],{"class":824,"line":1681},[822,5008,5009],{"class":828},"  phpGo\n",[822,5011,5012],{"class":824,"line":1692},[822,5013,5014],{"class":828},"  composerGo\n",[822,5016,5017],{"class":824,"line":1697},[822,5018,5019],{"class":828},"  nodeGo\n",[822,5021,5022],{"class":824,"line":1705},[822,5023,5024],{"class":828},"  zshGo\n",[822,5026,5027],{"class":824,"line":1713},[822,5028,5029],{"class":828},"  endGo\n",[822,5031,5032],{"class":824,"line":1721},[822,5033,4441],{"class":935},[822,5035,5036],{"class":824,"line":1726},[822,5037,1630],{"emptyLinePlaceholder":422},[822,5039,5040,5043,5045],{"class":824,"line":1734},[822,5041,5042],{"class":828},"startGo",[822,5044,4977],{"class":935},[822,5046,4422],{"class":935},[822,5048,5049,5052,5054,5057,5060,5062],{"class":824,"line":1739},[822,5050,5051],{"class":844},"  echo",[822,5053,1619],{"class":1618},[822,5055,5056],{"class":832},"========    Lemp7 BOX - START   ========",[822,5058,5059],{"class":1618},"\"",[822,5061,936],{"class":935},[822,5063,1151],{"class":925},[822,5065,5066,5068,5071,5073,5076,5078,5080],{"class":824,"line":1746},[822,5067,5051],{"class":844},[822,5069,5070],{"class":925}," -e",[822,5072,1619],{"class":1618},[822,5074,5075],{"class":832},"========================================",[822,5077,5059],{"class":1618},[822,5079,936],{"class":935},[822,5081,1151],{"class":925},[822,5083,5084,5087,5090,5093,5095,5098],{"class":824,"line":1757},[822,5085,5086],{"class":828},"  sudo",[822,5088,5089],{"class":832}," bash",[822,5091,5092],{"class":925}," -c",[822,5094,1619],{"class":1618},[822,5096,5097],{"class":832},"echo '127.0.1.1   ubuntu-disco-dingo' >> \u002Fetc\u002Fhosts",[822,5099,1625],{"class":1618},[822,5101,5102],{"class":824,"line":1767},[822,5103,4441],{"class":935},[822,5105,5106],{"class":824,"line":1778},[822,5107,1630],{"emptyLinePlaceholder":422},[822,5109,5110,5113,5115],{"class":824,"line":1786},[822,5111,5112],{"class":828},"setupGo",[822,5114,4977],{"class":935},[822,5116,4422],{"class":935},[822,5118,5119,5121,5123,5126,5128,5130],{"class":824,"line":1794},[822,5120,5051],{"class":844},[822,5122,1619],{"class":1618},[822,5124,5125],{"class":832},"---------------   SETUP   --------------",[822,5127,5059],{"class":1618},[822,5129,936],{"class":935},[822,5131,1151],{"class":925},[822,5133,5134,5136,5138,5140,5143,5145,5147],{"class":824,"line":1805},[822,5135,5051],{"class":844},[822,5137,5070],{"class":925},[822,5139,1619],{"class":1618},[822,5141,5142],{"class":832},"----------------------------------------",[822,5144,5059],{"class":1618},[822,5146,936],{"class":935},[822,5148,1151],{"class":925},[822,5150,5151,5154,5157,5160,5163,5165,5168,5170],{"class":824,"line":1813},[822,5152,5153],{"class":4401},"  export",[822,5155,5156],{"class":3827}," LC_ALL",[822,5158,5159],{"class":935},"=",[822,5161,5162],{"class":3827},"en_US",[822,5164,390],{"class":3777},[822,5166,5167],{"class":3827},"UTF-8",[822,5169,936],{"class":935},[822,5171,1151],{"class":925},[822,5173,5174,5176,5179,5181,5183,5185,5187,5189],{"class":824,"line":1822},[822,5175,5153],{"class":4401},[822,5177,5178],{"class":3827}," LANG",[822,5180,5159],{"class":935},[822,5182,5162],{"class":3827},[822,5184,390],{"class":3777},[822,5186,5167],{"class":3827},[822,5188,936],{"class":935},[822,5190,1151],{"class":925},[822,5192,5193,5195,5198,5201,5204,5206],{"class":824,"line":1830},[822,5194,5086],{"class":828},[822,5196,5197],{"class":832}," add-apt-repository",[822,5199,5200],{"class":925}," -y",[822,5202,5203],{"class":832}," ppa:ondrej\u002Fnginx",[822,5205,936],{"class":935},[822,5207,1151],{"class":925},[822,5209,5210,5212,5214,5216,5219,5221],{"class":824,"line":1842},[822,5211,5086],{"class":828},[822,5213,5197],{"class":832},[822,5215,5200],{"class":925},[822,5217,5218],{"class":832}," ppa:ondrej\u002Fphp",[822,5220,936],{"class":935},[822,5222,1151],{"class":925},[822,5224,5225,5227,5230],{"class":824,"line":1854},[822,5226,5086],{"class":828},[822,5228,5229],{"class":832}," apt-get",[822,5231,5232],{"class":832}," update\n",[822,5234,5235],{"class":824,"line":1867},[822,5236,4441],{"class":935},[822,5238,5239],{"class":824,"line":1877},[822,5240,1630],{"emptyLinePlaceholder":422},[822,5242,5243,5246,5248],{"class":824,"line":1888},[822,5244,5245],{"class":828},"toolsGo",[822,5247,4977],{"class":935},[822,5249,4422],{"class":935},[822,5251,5252,5254,5256,5259,5261,5263],{"class":824,"line":1899},[822,5253,5051],{"class":844},[822,5255,1619],{"class":1618},[822,5257,5258],{"class":832},"---------------   TOOLS   --------------",[822,5260,5059],{"class":1618},[822,5262,936],{"class":935},[822,5264,1151],{"class":925},[822,5266,5267,5269,5271,5273,5275,5277,5279],{"class":824,"line":1907},[822,5268,5051],{"class":844},[822,5270,5070],{"class":925},[822,5272,1619],{"class":1618},[822,5274,5142],{"class":832},[822,5276,5059],{"class":1618},[822,5278,936],{"class":935},[822,5280,1151],{"class":925},[822,5282,5283,5285,5287,5289,5291,5294,5297,5300,5303,5306,5309,5312,5315],{"class":824,"line":1915},[822,5284,5086],{"class":828},[822,5286,5229],{"class":832},[822,5288,4845],{"class":832},[822,5290,5200],{"class":925},[822,5292,5293],{"class":832}," re2c",[822,5295,5296],{"class":832}," libpcre3-dev",[822,5298,5299],{"class":832}," gcc",[822,5301,5302],{"class":832}," mc",[822,5304,5305],{"class":832}," grc",[822,5307,5308],{"class":832}," cowsay",[822,5310,5311],{"class":832}," figlet",[822,5313,5314],{"class":832}," zsh",[822,5316,5317],{"class":832}," lsb-core\n",[822,5319,5320],{"class":824,"line":1923},[822,5321,4441],{"class":935},[822,5323,5324],{"class":824,"line":1931},[822,5325,1630],{"emptyLinePlaceholder":422},[822,5327,5328,5331,5333],{"class":824,"line":1939},[822,5329,5330],{"class":828},"nginxGo",[822,5332,4977],{"class":935},[822,5334,4422],{"class":935},[822,5336,5337,5339,5341,5344,5346,5348],{"class":824,"line":1947},[822,5338,5051],{"class":844},[822,5340,1619],{"class":1618},[822,5342,5343],{"class":832},"---------------   NGINX   --------------",[822,5345,5059],{"class":1618},[822,5347,936],{"class":935},[822,5349,1151],{"class":925},[822,5351,5352,5354,5356,5358,5360,5362,5364],{"class":824,"line":1955},[822,5353,5051],{"class":844},[822,5355,5070],{"class":925},[822,5357,1619],{"class":1618},[822,5359,5142],{"class":832},[822,5361,5059],{"class":1618},[822,5363,936],{"class":935},[822,5365,1151],{"class":925},[822,5367,5368,5370,5372,5374,5376,5379,5381],{"class":824,"line":1963},[822,5369,5086],{"class":828},[822,5371,5229],{"class":832},[822,5373,4845],{"class":832},[822,5375,5200],{"class":925},[822,5377,5378],{"class":832}," nginx",[822,5380,936],{"class":935},[822,5382,1151],{"class":925},[822,5384,5385,5387,5390,5393,5396,5398],{"class":824,"line":1975},[822,5386,5086],{"class":828},[822,5388,5389],{"class":832}," cp",[822,5391,5392],{"class":832}," \u002Fvagrant\u002Fdata\u002Fnginx\u002Flemp7.vh.conf",[822,5394,5395],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Flemp7.vh.conf",[822,5397,936],{"class":935},[822,5399,1151],{"class":925},[822,5401,5402,5404,5407,5410,5412,5415,5417],{"class":824,"line":1982},[822,5403,5086],{"class":828},[822,5405,5406],{"class":832}," ln",[822,5408,5409],{"class":925}," -s",[822,5411,5395],{"class":832},[822,5413,5414],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Flemp7.vh",[822,5416,936],{"class":935},[822,5418,1151],{"class":925},[822,5420,5421,5423,5426,5429],{"class":824,"line":1994},[822,5422,5086],{"class":828},[822,5424,5425],{"class":832}," systemctl",[822,5427,5428],{"class":832}," restart",[822,5430,5431],{"class":832}," nginx.service\n",[822,5433,5434],{"class":824,"line":2006},[822,5435,4441],{"class":935},[822,5437,5438],{"class":824,"line":2018},[822,5439,1630],{"emptyLinePlaceholder":422},[822,5441,5442,5445,5447],{"class":824,"line":2030},[822,5443,5444],{"class":828},"mysqlGo",[822,5446,4977],{"class":935},[822,5448,4422],{"class":935},[822,5450,5451,5453,5455,5458,5460,5462],{"class":824,"line":2036},[822,5452,5051],{"class":844},[822,5454,1619],{"class":1618},[822,5456,5457],{"class":832},"---------------   MYSQL   --------------",[822,5459,5059],{"class":1618},[822,5461,936],{"class":935},[822,5463,1151],{"class":925},[822,5465,5466,5468,5470,5472,5474,5476,5478],{"class":824,"line":2048},[822,5467,5051],{"class":844},[822,5469,5070],{"class":925},[822,5471,1619],{"class":1618},[822,5473,5142],{"class":832},[822,5475,5059],{"class":1618},[822,5477,936],{"class":935},[822,5479,1151],{"class":925},[822,5481,5482,5484,5486,5488,5490,5493,5495],{"class":824,"line":2054},[822,5483,5086],{"class":828},[822,5485,5229],{"class":832},[822,5487,4845],{"class":832},[822,5489,5200],{"class":925},[822,5491,5492],{"class":832}," mysql-server",[822,5494,936],{"class":935},[822,5496,1151],{"class":925},[822,5498,5499,5501,5503,5506,5509,5511],{"class":824,"line":2066},[822,5500,5086],{"class":828},[822,5502,5389],{"class":832},[822,5504,5505],{"class":832}," \u002Fvagrant\u002Fdata\u002Fmysql\u002F.my.cnf",[822,5507,5508],{"class":832}," \u002Froot\u002F.my.cnf",[822,5510,936],{"class":935},[822,5512,1151],{"class":925},[822,5514,5515,5517,5520,5523,5525,5527],{"class":824,"line":2071},[822,5516,5086],{"class":828},[822,5518,5519],{"class":832}," chmod",[822,5521,5522],{"class":1118}," 600",[822,5524,5508],{"class":832},[822,5526,936],{"class":935},[822,5528,1151],{"class":925},[822,5530,5531,5533,5536,5539,5542,5544],{"class":824,"line":2079},[822,5532,5086],{"class":828},[822,5534,5535],{"class":832}," service",[822,5537,5538],{"class":832}," mysql",[822,5540,5541],{"class":832}," start",[822,5543,936],{"class":935},[822,5545,1151],{"class":925},[822,5547,5548,5551,5554,5557],{"class":824,"line":2089},[822,5549,5550],{"class":828},"mysql",[822,5552,5553],{"class":925}," --user=root",[822,5555,5556],{"class":4401}," \u003C\u003C",[822,5558,5559],{"class":1618},"EOF\n",[822,5561,5562],{"class":824,"line":2099},[822,5563,5564],{"class":832},"  ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';   \n",[822,5566,5567],{"class":824,"line":2110},[822,5568,5569],{"class":832},"  FLUSH PRIVILEGES;\n",[822,5571,5572],{"class":824,"line":2120},[822,5573,5559],{"class":1618},[822,5575,5576],{"class":824,"line":2127},[822,5577,4441],{"class":935},[822,5579,5580],{"class":824,"line":2134},[822,5581,1630],{"emptyLinePlaceholder":422},[822,5583,5584,5587,5589],{"class":824,"line":2142},[822,5585,5586],{"class":828},"phpGo",[822,5588,4977],{"class":935},[822,5590,4422],{"class":935},[822,5592,5593,5595,5597,5600,5602,5604],{"class":824,"line":2149},[822,5594,5051],{"class":844},[822,5596,1619],{"class":1618},[822,5598,5599],{"class":832},"----------------   PHP   ---------------",[822,5601,5059],{"class":1618},[822,5603,936],{"class":935},[822,5605,1151],{"class":925},[822,5607,5608,5610,5612,5614,5616,5618,5620],{"class":824,"line":2157},[822,5609,5051],{"class":844},[822,5611,5070],{"class":925},[822,5613,1619],{"class":1618},[822,5615,5142],{"class":832},[822,5617,5059],{"class":1618},[822,5619,936],{"class":935},[822,5621,1151],{"class":925},[822,5623,5624,5626,5628,5630,5632,5635,5638,5641,5644,5647,5650,5652],{"class":824,"line":2165},[822,5625,5086],{"class":828},[822,5627,5229],{"class":832},[822,5629,4845],{"class":832},[822,5631,5200],{"class":925},[822,5633,5634],{"class":832}," php7.3-fpm",[822,5636,5637],{"class":832}," php7.3-mysql",[822,5639,5640],{"class":832}," php7.3-phpdbg",[822,5642,5643],{"class":832}," php7.3-mbstring",[822,5645,5646],{"class":832}," php7.3-gd",[822,5648,5649],{"class":832}," php-imagick",[822,5651,936],{"class":935},[822,5653,1151],{"class":925},[822,5655,5656,5658,5660,5662,5664,5667,5670,5673,5676,5679,5682,5684],{"class":824,"line":2173},[822,5657,5086],{"class":828},[822,5659,5229],{"class":832},[822,5661,4845],{"class":832},[822,5663,5200],{"class":925},[822,5665,5666],{"class":832}," php7.3-pgsql",[822,5668,5669],{"class":832}," php7.3-pspell",[822,5671,5672],{"class":832}," php7.3-recode",[822,5674,5675],{"class":832}," php7.3-tidy",[822,5677,5678],{"class":832}," php7.3-intl",[822,5680,5681],{"class":832}," php7.3-curl",[822,5683,936],{"class":935},[822,5685,1151],{"class":925},[822,5687,5688,5690,5692,5694,5696,5699,5702,5705,5708,5711,5714,5717,5719],{"class":824,"line":2181},[822,5689,5086],{"class":828},[822,5691,5229],{"class":832},[822,5693,4845],{"class":832},[822,5695,5200],{"class":925},[822,5697,5698],{"class":832}," php7.3-zip",[822,5700,5701],{"class":832}," php7.3-xml",[822,5703,5704],{"class":832}," php7.3-dev",[822,5706,5707],{"class":832}," php-memcached",[822,5709,5710],{"class":832}," mcrypt",[822,5712,5713],{"class":832}," memcached",[822,5715,5716],{"class":832}," phpunit",[822,5718,936],{"class":935},[822,5720,1151],{"class":925},[822,5722,5723,5725,5727,5730,5733,5735],{"class":824,"line":2189},[822,5724,5086],{"class":828},[822,5726,5389],{"class":832},[822,5728,5729],{"class":832}," \u002Fvagrant\u002Fdata\u002Fphp\u002Flemp.ini",[822,5731,5732],{"class":832}," \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Flemp.ini",[822,5734,936],{"class":935},[822,5736,1151],{"class":925},[822,5738,5739,5741,5743,5746,5748,5750],{"class":824,"line":2196},[822,5740,5086],{"class":828},[822,5742,5519],{"class":832},[822,5744,5745],{"class":1118}," 644",[822,5747,5732],{"class":832},[822,5749,936],{"class":935},[822,5751,1151],{"class":925},[822,5753,5754,5756,5758,5760,5762,5765,5767],{"class":824,"line":2207},[822,5755,5086],{"class":828},[822,5757,5406],{"class":832},[822,5759,5409],{"class":925},[822,5761,5732],{"class":832},[822,5763,5764],{"class":832}," \u002Fetc\u002Fphp\u002F7.3\u002Fcli\u002Fconf.d\u002F100-lemp.ini",[822,5766,936],{"class":935},[822,5768,1151],{"class":925},[822,5770,5771,5773,5775,5777,5779,5782,5784],{"class":824,"line":2212},[822,5772,5086],{"class":828},[822,5774,5406],{"class":832},[822,5776,5409],{"class":925},[822,5778,5732],{"class":832},[822,5780,5781],{"class":832}," \u002Fetc\u002Fphp\u002F7.3\u002Ffpm\u002Fconf.d\u002F100-lemp.ini",[822,5783,936],{"class":935},[822,5785,1151],{"class":925},[822,5787,5788,5790,5793,5795,5798,5800],{"class":824,"line":2224},[822,5789,5086],{"class":828},[822,5791,5792],{"class":832}," pecl",[822,5794,4845],{"class":832},[822,5796,5797],{"class":832}," xdebug",[822,5799,936],{"class":935},[822,5801,1151],{"class":925},[822,5803,5804,5806,5808,5811,5814,5816],{"class":824,"line":2236},[822,5805,5086],{"class":828},[822,5807,5389],{"class":832},[822,5809,5810],{"class":832}," \u002Fvagrant\u002Fdata\u002Fphp\u002Fxdebug.ini",[822,5812,5813],{"class":832}," \u002Fetc\u002Fphp\u002F7.3\u002Fmods-available\u002Fxdebug.ini",[822,5815,936],{"class":935},[822,5817,1151],{"class":925},[822,5819,5820,5822,5824,5826,5828,5830],{"class":824,"line":2248},[822,5821,5086],{"class":828},[822,5823,5519],{"class":832},[822,5825,5745],{"class":1118},[822,5827,5813],{"class":832},[822,5829,936],{"class":935},[822,5831,1151],{"class":925},[822,5833,5834,5836,5838,5840,5842,5845,5847],{"class":824,"line":2260},[822,5835,5086],{"class":828},[822,5837,5406],{"class":832},[822,5839,5409],{"class":925},[822,5841,5813],{"class":832},[822,5843,5844],{"class":832}," \u002Fetc\u002Fphp\u002F7.3\u002Fcli\u002Fconf.d\u002F105-xdebug.ini",[822,5846,936],{"class":935},[822,5848,1151],{"class":925},[822,5850,5851,5853,5855,5857,5859,5862,5864],{"class":824,"line":2265},[822,5852,5086],{"class":828},[822,5854,5406],{"class":832},[822,5856,5409],{"class":925},[822,5858,5813],{"class":832},[822,5860,5861],{"class":832}," \u002Fetc\u002Fphp\u002F7.3\u002Ffpm\u002Fconf.d\u002F105-xdebug.ini",[822,5863,936],{"class":935},[822,5865,1151],{"class":925},[822,5867,5868,5870,5872,5874],{"class":824,"line":2273},[822,5869,5086],{"class":828},[822,5871,5425],{"class":832},[822,5873,5428],{"class":832},[822,5875,5876],{"class":832}," php7.3-fpm\n",[822,5878,5879],{"class":824,"line":2283},[822,5880,4441],{"class":935},[822,5882,5883],{"class":824,"line":2293},[822,5884,1630],{"emptyLinePlaceholder":422},[822,5886,5887,5890,5892],{"class":824,"line":2302},[822,5888,5889],{"class":828},"composerGo",[822,5891,4977],{"class":935},[822,5893,4422],{"class":935},[822,5895,5896,5898,5900,5903,5905,5907],{"class":824,"line":2311},[822,5897,5051],{"class":844},[822,5899,1619],{"class":1618},[822,5901,5902],{"class":832},"--------------   COMPOSER   ------------",[822,5904,5059],{"class":1618},[822,5906,936],{"class":935},[822,5908,1151],{"class":925},[822,5910,5911,5913,5915,5917,5919,5921,5923],{"class":824,"line":2318},[822,5912,5051],{"class":844},[822,5914,5070],{"class":925},[822,5916,1619],{"class":1618},[822,5918,5142],{"class":832},[822,5920,5059],{"class":1618},[822,5922,936],{"class":935},[822,5924,1151],{"class":925},[822,5926,5927,5930,5933,5936,5939,5942,5944],{"class":824,"line":2325},[822,5928,5929],{"class":828},"  curl",[822,5931,5932],{"class":925}," -sS",[822,5934,5935],{"class":832}," https:\u002F\u002Fgetcomposer.org\u002Finstaller",[822,5937,5938],{"class":4401}," |",[822,5940,5941],{"class":828}," php",[822,5943,936],{"class":935},[822,5945,1151],{"class":925},[822,5947,5948,5950,5953,5956],{"class":824,"line":2332},[822,5949,5086],{"class":828},[822,5951,5952],{"class":832}," mv",[822,5954,5955],{"class":832}," composer.phar",[822,5957,5958],{"class":832}," \u002Fusr\u002Flocal\u002Fbin\u002Fcomposer\n",[822,5960,5961],{"class":824,"line":2339},[822,5962,4441],{"class":935},[822,5964,5965],{"class":824,"line":2347},[822,5966,1630],{"emptyLinePlaceholder":422},[822,5968,5969,5972,5974],{"class":824,"line":2354},[822,5970,5971],{"class":828},"nodeGo",[822,5973,4977],{"class":935},[822,5975,4422],{"class":935},[822,5977,5978,5980,5982,5985,5987,5989],{"class":824,"line":2362},[822,5979,5051],{"class":844},[822,5981,1619],{"class":1618},[822,5983,5984],{"class":832},"----------------   NODE   --------------",[822,5986,5059],{"class":1618},[822,5988,936],{"class":935},[822,5990,1151],{"class":925},[822,5992,5993,5995,5997,5999,6001,6003,6005],{"class":824,"line":2370},[822,5994,5051],{"class":844},[822,5996,5070],{"class":925},[822,5998,1619],{"class":1618},[822,6000,5142],{"class":832},[822,6002,5059],{"class":1618},[822,6004,936],{"class":935},[822,6006,1151],{"class":925},[822,6008,6009,6011,6014,6016,6018,6021],{"class":824,"line":2378},[822,6010,5086],{"class":828},[822,6012,6013],{"class":832}," apt",[822,6015,4845],{"class":832},[822,6017,5200],{"class":925},[822,6019,6020],{"class":832}," nodejs",[822,6022,6023],{"class":832}," npm\n",[822,6025,6026],{"class":824,"line":2385},[822,6027,4441],{"class":935},[822,6029,6030],{"class":824,"line":2396},[822,6031,1630],{"emptyLinePlaceholder":422},[822,6033,6034,6037,6039],{"class":824,"line":2401},[822,6035,6036],{"class":828},"zshGo",[822,6038,4977],{"class":935},[822,6040,4422],{"class":935},[822,6042,6043,6045,6047,6050,6052,6054],{"class":824,"line":2413},[822,6044,5051],{"class":844},[822,6046,1619],{"class":1618},[822,6048,6049],{"class":832},"----------------   ZSH   ---------------",[822,6051,5059],{"class":1618},[822,6053,936],{"class":935},[822,6055,1151],{"class":925},[822,6057,6058,6060,6062,6064,6066,6068,6070],{"class":824,"line":2425},[822,6059,5051],{"class":844},[822,6061,5070],{"class":925},[822,6063,1619],{"class":1618},[822,6065,5142],{"class":832},[822,6067,5059],{"class":1618},[822,6069,936],{"class":935},[822,6071,1151],{"class":925},[822,6073,6074,6077,6080,6082,6085,6088,6090],{"class":824,"line":2437},[822,6075,6076],{"class":844},"  cd",[822,6078,6079],{"class":832}," \u002Ftmp",[822,6081,936],{"class":935},[822,6083,6084],{"class":828}," wget",[822,6086,6087],{"class":832}," https:\u002F\u002Fraw.github.com\u002Frobbyrussell\u002Foh-my-zsh\u002Fmaster\u002Ftools\u002Finstall.sh",[822,6089,936],{"class":935},[822,6091,1151],{"class":925},[822,6093,6094,6096,6099,6102,6104,6107,6109,6111,6114,6117,6120,6123,6125],{"class":824,"line":2449},[822,6095,5086],{"class":828},[822,6097,6098],{"class":832}," sh",[822,6100,6101],{"class":832}," .\u002Finstall.sh",[822,6103,936],{"class":935},[822,6105,6106],{"class":828}," rm",[822,6108,6101],{"class":832},[822,6110,936],{"class":935},[822,6112,6113],{"class":828}," usermod",[822,6115,6116],{"class":925}," --shell",[822,6118,6119],{"class":832}," \u002Fbin\u002Fzsh",[822,6121,6122],{"class":832}," root",[822,6124,936],{"class":935},[822,6126,1151],{"class":925},[822,6128,6129,6132,6134,6137,6140,6142],{"class":824,"line":2454},[822,6130,6131],{"class":828},"  git",[822,6133,833],{"class":832},[822,6135,6136],{"class":832}," https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-syntax-highlighting.git",[822,6138,6139],{"class":832}," ~\u002F.oh-my-zsh\u002Fplugins\u002Fzsh-syntax-highlighting",[822,6141,936],{"class":935},[822,6143,1151],{"class":925},[822,6145,6146,6148,6150,6153,6156,6158],{"class":824,"line":2462},[822,6147,6131],{"class":828},[822,6149,833],{"class":832},[822,6151,6152],{"class":832}," https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-autosuggestions.git",[822,6154,6155],{"class":832}," ~\u002F.oh-my-zsh\u002Fplugins\u002Fzsh-autosuggestions",[822,6157,936],{"class":935},[822,6159,1151],{"class":925},[822,6161,6162,6165,6168,6170,6172,6175,6177,6180,6182],{"class":824,"line":2472},[822,6163,6164],{"class":828},"  sed",[822,6166,6167],{"class":925}," -i",[822,6169,5070],{"class":925},[822,6171,4430],{"class":1618},[822,6173,6174],{"class":832},"s\u002Fgit\u002Fgit zsh-syntax-highlighting zsh-autosuggestions\u002F",[822,6176,4484],{"class":1618},[822,6178,6179],{"class":832}," ~\u002F.zshrc",[822,6181,936],{"class":935},[822,6183,1151],{"class":925},[822,6185,6186,6188,6190,6192,6194,6197,6199],{"class":824,"line":2482},[822,6187,6164],{"class":828},[822,6189,6167],{"class":925},[822,6191,5070],{"class":925},[822,6193,4430],{"class":1618},[822,6195,6196],{"class":832},"s\u002Frobbyrussell\u002Fristo\u002F",[822,6198,4484],{"class":1618},[822,6200,6201],{"class":832}," ~\u002F.zshrc\n",[822,6203,6204],{"class":824,"line":2491},[822,6205,4441],{"class":935},[822,6207,6208],{"class":824,"line":2498},[822,6209,1630],{"emptyLinePlaceholder":422},[822,6211,6212,6215,6217],{"class":824,"line":2505},[822,6213,6214],{"class":828},"endGo",[822,6216,4977],{"class":935},[822,6218,4422],{"class":935},[822,6220,6221,6223,6225,6228,6231,6234,6237,6239],{"class":824,"line":2512},[822,6222,5086],{"class":828},[822,6224,6113],{"class":832},[822,6226,6227],{"class":925}," -a",[822,6229,6230],{"class":925}," -G",[822,6232,6233],{"class":832}," www-data",[822,6235,6236],{"class":832}," vagrant",[822,6238,936],{"class":935},[822,6240,1151],{"class":925},[822,6242,6243,6245,6247,6250,6252,6254],{"class":824,"line":2519},[822,6244,5051],{"class":844},[822,6246,1619],{"class":1618},[822,6248,6249],{"class":832},"=========    Lemp7 BOX - END   =========",[822,6251,5059],{"class":1618},[822,6253,936],{"class":935},[822,6255,1151],{"class":925},[822,6257,6258,6260,6262,6264,6266,6268,6270],{"class":824,"line":2527},[822,6259,5051],{"class":844},[822,6261,5070],{"class":925},[822,6263,1619],{"class":1618},[822,6265,5075],{"class":832},[822,6267,5059],{"class":1618},[822,6269,936],{"class":935},[822,6271,1151],{"class":925},[822,6273,6274,6277,6280,6282],{"class":824,"line":2535},[822,6275,6276],{"class":828},"  figlet",[822,6278,6279],{"class":832}," Lemp7",[822,6281,936],{"class":935},[822,6283,1151],{"class":925},[822,6285,6286,6289,6291,6294,6296,6299],{"class":824,"line":2542},[822,6287,6288],{"class":828},"  cowsay",[822,6290,926],{"class":925},[822,6292,6293],{"class":832}," milk",[822,6295,1619],{"class":1618},[822,6297,6298],{"class":832},"Nunca confies en un ordenador que no puedas lanzar por una ventana. --->Steve Wozniak",[822,6300,1625],{"class":1618},[822,6302,6303],{"class":824,"line":2553},[822,6304,4441],{"class":935},[822,6306,6307],{"class":824,"line":2558},[822,6308,1630],{"emptyLinePlaceholder":422},[822,6310,6311],{"class":824,"line":2570},[822,6312,6313],{"class":828},"main\n",[822,6315,6316,6319],{"class":824,"line":2582},[822,6317,6318],{"class":844},"exit",[822,6320,6321],{"class":1118}," 0\n",[19,6323,6325],{"id":6324},"extras","Extras",[10,6327,6328],{},"Un par de instalaciones manuales que puedes hacer aparte:",[121,6330,6331,6451],{},[124,6332,6334,6339],{"icon":1582,"label":6333},"oh-my-zsh",[10,6335,6336,6337,1615],{},"Instalación manual de oh-my-zsh para el usuario ",[72,6338,4839],{},[814,6340,6342],{"className":816,"code":6341,"language":818,"meta":407,"style":407},"wget https:\u002F\u002Fraw.github.com\u002Frobbyrussell\u002Foh-my-zsh\u002Fmaster\u002Ftools\u002Finstall.sh -O - | zsh\nsudo chsh -s `which zsh`\ngit clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-syntax-highlighting.git ~\u002F.oh-my-zsh\u002Fplugins\u002Fzsh-syntax-highlighting && \\\ngit clone https:\u002F\u002Fgithub.com\u002Fzsh-users\u002Fzsh-autosuggestions.git ~\u002F.oh-my-zsh\u002Fplugins\u002Fzsh-autosuggestions && \\\nsed -i -e 's\u002Fgit\u002Fgit zsh-syntax-highlighting zsh-autosuggestions\u002F' ~\u002F.zshrc\nsed -i -e 's\u002Frobbyrussell\u002Fristo\u002F' ~\u002F.zshrc\nsource ~\u002F.zshrc\n",[72,6343,6344,6362,6383,6397,6411,6428,6444],{"__ignoreMap":407},[822,6345,6346,6349,6351,6354,6357,6359],{"class":824,"line":825},[822,6347,6348],{"class":828},"wget",[822,6350,6087],{"class":832},[822,6352,6353],{"class":925}," -O",[822,6355,6356],{"class":832}," -",[822,6358,5938],{"class":4401},[822,6360,6361],{"class":828}," zsh\n",[822,6363,6364,6367,6370,6372,6375,6378,6380],{"class":824,"line":408},[822,6365,6366],{"class":828},"sudo",[822,6368,6369],{"class":832}," chsh",[822,6371,5409],{"class":925},[822,6373,6374],{"class":935}," `",[822,6376,6377],{"class":844},"which",[822,6379,5314],{"class":832},[822,6381,6382],{"class":935},"`\n",[822,6384,6385,6387,6389,6391,6393,6395],{"class":824,"line":1051},[822,6386,829],{"class":828},[822,6388,833],{"class":832},[822,6390,6136],{"class":832},[822,6392,6139],{"class":832},[822,6394,936],{"class":935},[822,6396,1151],{"class":925},[822,6398,6399,6401,6403,6405,6407,6409],{"class":824,"line":1182},[822,6400,829],{"class":828},[822,6402,833],{"class":832},[822,6404,6152],{"class":832},[822,6406,6155],{"class":832},[822,6408,936],{"class":935},[822,6410,1151],{"class":925},[822,6412,6413,6416,6418,6420,6422,6424,6426],{"class":824,"line":1484},[822,6414,6415],{"class":828},"sed",[822,6417,6167],{"class":925},[822,6419,5070],{"class":925},[822,6421,4430],{"class":1618},[822,6423,6174],{"class":832},[822,6425,4484],{"class":1618},[822,6427,6201],{"class":832},[822,6429,6430,6432,6434,6436,6438,6440,6442],{"class":824,"line":1655},[822,6431,6415],{"class":828},[822,6433,6167],{"class":925},[822,6435,5070],{"class":925},[822,6437,4430],{"class":1618},[822,6439,6196],{"class":832},[822,6441,4484],{"class":1618},[822,6443,6201],{"class":832},[822,6445,6446,6449],{"class":824,"line":1663},[822,6447,6448],{"class":844},"source",[822,6450,6201],{"class":832},[124,6452,6454,6463],{"icon":793,"label":6453},"Redis seguro",[10,6455,6456,6457,6462],{},"Instalación y aseguramiento de Redis (",[381,6458,6461],{"href":6459,"rel":6460},"https:\u002F\u002Fwww.digitalocean.com\u002Fcommunity\u002Ftutorials\u002Fhow-to-install-and-secure-redis-on-ubuntu-18-04",[398],"documentación técnica","):",[814,6464,6466],{"className":816,"code":6465,"language":818,"meta":407,"style":407},"sudo apt install redis-server\nsudo vim \u002Fetc\u002Fredis\u002Fredis.conf > supervised systemd\nsudo systemctl restart redis.service\nsudo systemctl status redis\nsudo redis-cli\n> ping\nsudo vim \u002Fetc\u002Fredis\u002Fredis.conf > bind 127.0.0.1 ::1\nsudo systemctl restart redis\nsudo netstat -lnp | grep redis\nsudo vim \u002Fetc\u002Fredis\u002Fredis.conf\nsudo openssl rand 60 | openssl base64 -A\nsudo requirepass foobared > change pass\nsudo systemctl restart redis.service\n",[72,6467,6468,6479,6498,6509,6520,6527,6534,6553,6563,6580,6589,6612,6630],{"__ignoreMap":407},[822,6469,6470,6472,6474,6476],{"class":824,"line":825},[822,6471,6366],{"class":828},[822,6473,6013],{"class":832},[822,6475,4845],{"class":832},[822,6477,6478],{"class":832}," redis-server\n",[822,6480,6481,6483,6486,6489,6492,6495],{"class":824,"line":408},[822,6482,6366],{"class":828},[822,6484,6485],{"class":832}," vim",[822,6487,6488],{"class":832}," \u002Fetc\u002Fredis\u002Fredis.conf",[822,6490,6491],{"class":4401}," >",[822,6493,6494],{"class":832}," supervised",[822,6496,6497],{"class":832}," systemd\n",[822,6499,6500,6502,6504,6506],{"class":824,"line":1051},[822,6501,6366],{"class":828},[822,6503,5425],{"class":832},[822,6505,5428],{"class":832},[822,6507,6508],{"class":832}," redis.service\n",[822,6510,6511,6513,6515,6518],{"class":824,"line":1182},[822,6512,6366],{"class":828},[822,6514,5425],{"class":832},[822,6516,6517],{"class":832}," status",[822,6519,2834],{"class":832},[822,6521,6522,6524],{"class":824,"line":1484},[822,6523,6366],{"class":828},[822,6525,6526],{"class":832}," redis-cli\n",[822,6528,6529,6531],{"class":824,"line":1655},[822,6530,4820],{"class":4401},[822,6532,6533],{"class":3777}," ping\n",[822,6535,6536,6538,6540,6542,6544,6547,6550],{"class":824,"line":1663},[822,6537,6366],{"class":828},[822,6539,6485],{"class":832},[822,6541,6488],{"class":832},[822,6543,6491],{"class":4401},[822,6545,6546],{"class":832}," bind",[822,6548,6549],{"class":1118}," 127.0.0.1",[822,6551,6552],{"class":832}," ::1\n",[822,6554,6555,6557,6559,6561],{"class":824,"line":1673},[822,6556,6366],{"class":828},[822,6558,5425],{"class":832},[822,6560,5428],{"class":832},[822,6562,2834],{"class":832},[822,6564,6565,6567,6570,6573,6575,6578],{"class":824,"line":1681},[822,6566,6366],{"class":828},[822,6568,6569],{"class":832}," netstat",[822,6571,6572],{"class":925}," -lnp",[822,6574,5938],{"class":4401},[822,6576,6577],{"class":828}," grep",[822,6579,2834],{"class":832},[822,6581,6582,6584,6586],{"class":824,"line":1692},[822,6583,6366],{"class":828},[822,6585,6485],{"class":832},[822,6587,6588],{"class":832}," \u002Fetc\u002Fredis\u002Fredis.conf\n",[822,6590,6591,6593,6596,6599,6602,6604,6606,6609],{"class":824,"line":1697},[822,6592,6366],{"class":828},[822,6594,6595],{"class":832}," openssl",[822,6597,6598],{"class":832}," rand",[822,6600,6601],{"class":1118}," 60",[822,6603,5938],{"class":4401},[822,6605,6595],{"class":828},[822,6607,6608],{"class":832}," base64",[822,6610,6611],{"class":925}," -A\n",[822,6613,6614,6616,6619,6622,6624,6627],{"class":824,"line":1705},[822,6615,6366],{"class":828},[822,6617,6618],{"class":832}," requirepass",[822,6620,6621],{"class":832}," foobared",[822,6623,6491],{"class":4401},[822,6625,6626],{"class":832}," change",[822,6628,6629],{"class":832}," pass\n",[822,6631,6632,6634,6636,6638],{"class":824,"line":1713},[822,6633,6366],{"class":828},[822,6635,5425],{"class":832},[822,6637,5428],{"class":832},[822,6639,6508],{"class":832},[10,6641,6642,6645,6646,390],{},[14,6643,6644],{},"Referencia:"," ",[381,6647,6649],{"href":4792,"rel":6648},[398],"repositorio alojado en GitHub",[1222,6651,6652],{},"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 .s_wWq, html code.shiki .s_wWq{--shiki-default:#CB7676}html pre.shiki code .sNpkn, html code.shiki .sNpkn{--shiki-default:#DBD7CAEE}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 .sux-A, html code.shiki .sux-A{--shiki-default:#758575DD}html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}html pre.shiki code .sXjYR, html code.shiki .sXjYR{--shiki-default:#C99076}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}html pre.shiki code .sxA9i, html code.shiki .sxA9i{--shiki-default:#4C9A91}",{"title":407,"searchDepth":408,"depth":408,"links":6654},[6655,6656,6657,6658],{"id":4764,"depth":408,"text":4765},{"id":1372,"depth":408,"text":1373},{"id":4944,"depth":408,"text":4945},{"id":6324,"depth":408,"text":6325},"2020-04-21","Una guía para aprovisionar Ubuntu 19.10 con un stack LEMP completo incluyendo herramientas como Redis, Composer, NodeJS y más mediante Vagrant.","\u002Fimg\u002Fposts\u002Fcovers\u002Faprovisionar-linux-nginx-mysql-php7-vagrant.svg",{},"\u002Fblog\u002Faprovisionar-linux-nginx-mysql-php7-vagrant",{"title":4709,"description":6660},"blog\u002Faprovisionar-linux-nginx-mysql-php7-vagrant",[6667,4727,6668,6669,1240,4730,708,3937,6670,4784,4755],"Bash","Github","Linux","Ubuntu","gSQlVPb0nA5exqdju7pesSGTyO9uGoTtIoXSvj_DChw",{"id":6673,"title":6674,"body":6675,"date":8925,"description":8926,"draft":417,"extension":418,"image":8927,"lang":420,"meta":8928,"navigation":422,"path":8929,"seo":8930,"stem":8931,"tags":8932,"__hash__":8938},"blog\u002Fblog\u002Faprovisionar-ubuntu-server-jira-bitbucket-confluence.md","Aprovisionar Ubuntu Server con Jira, Bitbucket y Confluence",{"type":7,"value":6676,"toc":8914},[6677,6681,6688,6694,6698,6733,6737,6741,6781,6785,6790,6813,6817,6889,6893,6961,6965,7006,7010,7017,7155,7159,7212,7216,7232,7236,7286,7290,7300,7314,7318,7333,7336,7353,7357,7360,7364,7496,7500,7525,7529,7803,7807,7832,7836,7840,7887,7891,7981,7985,7988,8908,8911],[19,6678,6680],{"id":6679},"arquitectura-de-la-solución","Arquitectura de la solución",[10,6682,6683,6684,6687],{},"Esta guía detalla el aprovisionamiento de la ",[77,6685,6686],{},"suite"," Atlassian sobre Ubuntu Server 18.04. La configuración de la infraestructura en AWS y los ajustes de WAF\u002FDNS los cubriré en publicaciones aparte.",[10,6689,6690],{},[102,6691],{"alt":6692,"src":6693},"Arquitectura de la Suite Atlassian en Ubuntu Server sobre AWS EC2: Nginx como proxy reverso con SSL enruta a Jira, Bitbucket y Confluence, respaldados por PostgreSQL","\u002Fimg\u002Fposts\u002Fblog\u002Faprovisionar-ubuntu-server-jira-bitbucket-confluence\u002Fatlassian-arquitectura.svg",[19,6695,6697],{"id":6696},"requerimientos","Requerimientos",[27,6699,6700,6707,6710,6713,6727,6730],{},[30,6701,6702,6703,6706],{},"Las 4 aplicaciones (Jira, Jira Service Desk, Bitbucket y Confluence) requieren ~2 GB de RAM cada una. Usa una instancia AWS EC2 ",[72,6704,6705],{},"t2.xlarge"," (16 GB de RAM, 4 vCPU) o una AWS Lightsail equivalente.",[30,6708,6709],{},"Una distribución Ubuntu Server 18.04 limpia (también es compatible AWS Linux AMI).",[30,6711,6712],{},"Una dirección IP elástica estática.",[30,6714,6715,6716],{},"Acceso a tu gestor de dominios para configurar los subdominios:\n",[27,6717,6718,6721,6724],{},[30,6719,6720],{},"jira.midominio.com",[30,6722,6723],{},"bitbucket.midominio.com",[30,6725,6726],{},"confluence.midominio.com",[30,6728,6729],{},"Certificados SSL (opcional; se admite Let's Encrypt gratuito).",[30,6731,6732],{},"Jira y Jira Service Desk comparten el dominio jira.midominio.com.",[19,6734,6736],{"id":6735},"guía-detallada","Guía detallada",[3993,6738,6740],{"id":6739},"_1-actualiza-el-sistema-operativo","1. Actualiza el sistema operativo",[814,6742,6744],{"className":816,"code":6743,"language":818,"meta":407,"style":407},"sudo apt update && \\\nsudo apt upgrade -y && \\\nsudo reboot\n",[72,6745,6746,6759,6774],{"__ignoreMap":407},[822,6747,6748,6750,6752,6755,6757],{"class":824,"line":825},[822,6749,6366],{"class":828},[822,6751,6013],{"class":832},[822,6753,6754],{"class":832}," update",[822,6756,936],{"class":935},[822,6758,1151],{"class":925},[822,6760,6761,6763,6765,6768,6770,6772],{"class":824,"line":408},[822,6762,6366],{"class":828},[822,6764,6013],{"class":832},[822,6766,6767],{"class":832}," upgrade",[822,6769,5200],{"class":925},[822,6771,936],{"class":935},[822,6773,1151],{"class":925},[822,6775,6776,6778],{"class":824,"line":1051},[822,6777,6366],{"class":828},[822,6779,6780],{"class":832}," reboot\n",[3993,6782,6784],{"id":6783},"_2-instala-nginx-y-configura-los-subdominios-con-virtual-hosts","2. Instala Nginx y configura los subdominios con virtual hosts",[6786,6787,6789],"h4",{"id":6788},"_21-instala-nginx","2.1. Instala Nginx",[814,6791,6793],{"className":816,"code":6792,"language":818,"meta":407,"style":407},"sudo apt-get install -y nginx  > \u002Fdev\u002Fnull\n",[72,6794,6795],{"__ignoreMap":407},[822,6796,6797,6799,6801,6803,6805,6807,6810],{"class":824,"line":825},[822,6798,6366],{"class":828},[822,6800,5229],{"class":832},[822,6802,4845],{"class":832},[822,6804,5200],{"class":925},[822,6806,5378],{"class":832},[822,6808,6809],{"class":4401},"  >",[822,6811,6812],{"class":832}," \u002Fdev\u002Fnull\n",[6786,6814,6816],{"id":6815},"_22-instala-certbot-para-gestionar-el-certificado-ssl","2.2. Instala Certbot para gestionar el certificado SSL",[814,6818,6820],{"className":816,"code":6819,"language":818,"meta":407,"style":407},"sudo apt-get install software-properties-common && \\\nsudo add-apt-repository universe && \\\nsudo add-apt-repository ppa:certbot\u002Fcertbot && \\\nsudo apt-get update && \\\nsudo apt-get install certbot python-certbot-nginx\n",[72,6821,6822,6837,6850,6863,6875],{"__ignoreMap":407},[822,6823,6824,6826,6828,6830,6833,6835],{"class":824,"line":825},[822,6825,6366],{"class":828},[822,6827,5229],{"class":832},[822,6829,4845],{"class":832},[822,6831,6832],{"class":832}," software-properties-common",[822,6834,936],{"class":935},[822,6836,1151],{"class":925},[822,6838,6839,6841,6843,6846,6848],{"class":824,"line":408},[822,6840,6366],{"class":828},[822,6842,5197],{"class":832},[822,6844,6845],{"class":832}," universe",[822,6847,936],{"class":935},[822,6849,1151],{"class":925},[822,6851,6852,6854,6856,6859,6861],{"class":824,"line":1051},[822,6853,6366],{"class":828},[822,6855,5197],{"class":832},[822,6857,6858],{"class":832}," ppa:certbot\u002Fcertbot",[822,6860,936],{"class":935},[822,6862,1151],{"class":925},[822,6864,6865,6867,6869,6871,6873],{"class":824,"line":1182},[822,6866,6366],{"class":828},[822,6868,5229],{"class":832},[822,6870,6754],{"class":832},[822,6872,936],{"class":935},[822,6874,1151],{"class":925},[822,6876,6877,6879,6881,6883,6886],{"class":824,"line":1484},[822,6878,6366],{"class":828},[822,6880,5229],{"class":832},[822,6882,4845],{"class":832},[822,6884,6885],{"class":832}," certbot",[822,6887,6888],{"class":832}," python-certbot-nginx\n",[6786,6890,6892],{"id":6891},"_23-crea-directorios-de-prueba-para-los-virtual-hosts","2.3. Crea directorios de prueba para los virtual hosts",[814,6894,6896],{"className":816,"code":6895,"language":818,"meta":407,"style":407},"mkdir \u002Fvar\u002Fwww\u002Fjira.midominio.com && \\\nmkdir \u002Fvar\u002Fwww\u002Fbitbucket.midominio.com && \\\nmkdir \u002Fvar\u002Fwww\u002Fconfluence.midominio.com && \\\ntouch \u002Fvar\u002Fwww\u002Fjira.midominio.com\u002Findex.html && \\\ntouch \u002Fvar\u002Fwww\u002Fbitbucket.midominio.com\u002Findex.html && \\\ntouch \u002Fvar\u002Fwww\u002Fconfluence.midominio.com\u002Findex.html\n",[72,6897,6898,6909,6920,6931,6943,6954],{"__ignoreMap":407},[822,6899,6900,6902,6905,6907],{"class":824,"line":825},[822,6901,1394],{"class":828},[822,6903,6904],{"class":832}," \u002Fvar\u002Fwww\u002Fjira.midominio.com",[822,6906,936],{"class":935},[822,6908,1151],{"class":925},[822,6910,6911,6913,6916,6918],{"class":824,"line":408},[822,6912,1394],{"class":828},[822,6914,6915],{"class":832}," \u002Fvar\u002Fwww\u002Fbitbucket.midominio.com",[822,6917,936],{"class":935},[822,6919,1151],{"class":925},[822,6921,6922,6924,6927,6929],{"class":824,"line":1051},[822,6923,1394],{"class":828},[822,6925,6926],{"class":832}," \u002Fvar\u002Fwww\u002Fconfluence.midominio.com",[822,6928,936],{"class":935},[822,6930,1151],{"class":925},[822,6932,6933,6936,6939,6941],{"class":824,"line":1182},[822,6934,6935],{"class":828},"touch",[822,6937,6938],{"class":832}," \u002Fvar\u002Fwww\u002Fjira.midominio.com\u002Findex.html",[822,6940,936],{"class":935},[822,6942,1151],{"class":925},[822,6944,6945,6947,6950,6952],{"class":824,"line":1484},[822,6946,6935],{"class":828},[822,6948,6949],{"class":832}," \u002Fvar\u002Fwww\u002Fbitbucket.midominio.com\u002Findex.html",[822,6951,936],{"class":935},[822,6953,1151],{"class":925},[822,6955,6956,6958],{"class":824,"line":1655},[822,6957,6935],{"class":828},[822,6959,6960],{"class":832}," \u002Fvar\u002Fwww\u002Fconfluence.midominio.com\u002Findex.html\n",[6786,6962,6964],{"id":6963},"_24-crea-los-archivos-de-configuración-de-los-virtual-hosts","2.4. Crea los archivos de configuración de los virtual hosts",[814,6966,6968],{"className":816,"code":6967,"language":818,"meta":407,"style":407},"sudo touch \u002Fetc\u002Fnginx\u002Fsites-available\u002Fjira.midominio.com.conf && \\\nsudo touch \u002Fetc\u002Fnginx\u002Fsites-available\u002Fbitbucket.midominio.com.conf && \\\nsudo touch \u002Fetc\u002Fnginx\u002Fsites-available\u002Fconfluence.midominio.com.conf\n",[72,6969,6970,6984,6997],{"__ignoreMap":407},[822,6971,6972,6974,6977,6980,6982],{"class":824,"line":825},[822,6973,6366],{"class":828},[822,6975,6976],{"class":832}," touch",[822,6978,6979],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fjira.midominio.com.conf",[822,6981,936],{"class":935},[822,6983,1151],{"class":925},[822,6985,6986,6988,6990,6993,6995],{"class":824,"line":408},[822,6987,6366],{"class":828},[822,6989,6976],{"class":832},[822,6991,6992],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fbitbucket.midominio.com.conf",[822,6994,936],{"class":935},[822,6996,1151],{"class":925},[822,6998,6999,7001,7003],{"class":824,"line":1051},[822,7000,6366],{"class":828},[822,7002,6976],{"class":832},[822,7004,7005],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fconfluence.midominio.com.conf\n",[6786,7007,7009],{"id":7008},"_25-agrega-la-configuración-a-cada-archivo","2.5. Agrega la configuración a cada archivo",[10,7011,7012,7013,7016],{},"Abre cada archivo con ",[72,7014,7015],{},"sudo vim \u002Fetc\u002Fnginx\u002Fsites-available\u002F\u003Cdominio>.conf"," y pega el bloque correspondiente:",[121,7018,7019,7069,7112],{},[124,7020,7022],{"icon":7021,"label":6720},"fab fa-jira",[814,7023,7027],{"className":7024,"code":7025,"language":7026,"meta":407,"style":407},"language-nginx shiki shiki-themes vitesse-dark","server {\n     root \u002Fvar\u002Fwww\u002Fjira.midominio.com\u002F;\n     index index.html;\n     server_name jira.midominio.com;\n}\n","nginx",[72,7028,7029,7036,7046,7056,7065],{"__ignoreMap":407},[822,7030,7031,7034],{"class":824,"line":825},[822,7032,7033],{"class":4401},"server",[822,7035,4422],{"class":3777},[822,7037,7038,7041,7044],{"class":824,"line":408},[822,7039,7040],{"class":3198},"     root ",[822,7042,7043],{"class":3777},"\u002Fvar\u002Fwww\u002Fjira.midominio.com\u002F",[822,7045,4487],{"class":935},[822,7047,7048,7051,7054],{"class":824,"line":1051},[822,7049,7050],{"class":3198},"     index ",[822,7052,7053],{"class":3777},"index.html",[822,7055,4487],{"class":935},[822,7057,7058,7061,7063],{"class":824,"line":1182},[822,7059,7060],{"class":3198},"     server_name ",[822,7062,6720],{"class":3777},[822,7064,4487],{"class":935},[822,7066,7067],{"class":824,"line":1484},[822,7068,4441],{"class":3777},[124,7070,7072],{"icon":7071,"label":6723},"fab fa-bitbucket",[814,7073,7075],{"className":7024,"code":7074,"language":7026,"meta":407,"style":407},"server {\n     root \u002Fvar\u002Fwww\u002Fbitbucket.midominio.com\u002F;\n     index index.html;\n     server_name bitbucket.midominio.com;\n}\n",[72,7076,7077,7083,7092,7100,7108],{"__ignoreMap":407},[822,7078,7079,7081],{"class":824,"line":825},[822,7080,7033],{"class":4401},[822,7082,4422],{"class":3777},[822,7084,7085,7087,7090],{"class":824,"line":408},[822,7086,7040],{"class":3198},[822,7088,7089],{"class":3777},"\u002Fvar\u002Fwww\u002Fbitbucket.midominio.com\u002F",[822,7091,4487],{"class":935},[822,7093,7094,7096,7098],{"class":824,"line":1051},[822,7095,7050],{"class":3198},[822,7097,7053],{"class":3777},[822,7099,4487],{"class":935},[822,7101,7102,7104,7106],{"class":824,"line":1182},[822,7103,7060],{"class":3198},[822,7105,6723],{"class":3777},[822,7107,4487],{"class":935},[822,7109,7110],{"class":824,"line":1484},[822,7111,4441],{"class":3777},[124,7113,7115],{"icon":7114,"label":6726},"fab fa-confluence",[814,7116,7118],{"className":7024,"code":7117,"language":7026,"meta":407,"style":407},"server {\n     root \u002Fvar\u002Fwww\u002Fconfluence.midominio.com\u002F;\n     index index.html;\n     server_name confluence.midominio.com;\n}\n",[72,7119,7120,7126,7135,7143,7151],{"__ignoreMap":407},[822,7121,7122,7124],{"class":824,"line":825},[822,7123,7033],{"class":4401},[822,7125,4422],{"class":3777},[822,7127,7128,7130,7133],{"class":824,"line":408},[822,7129,7040],{"class":3198},[822,7131,7132],{"class":3777},"\u002Fvar\u002Fwww\u002Fconfluence.midominio.com\u002F",[822,7134,4487],{"class":935},[822,7136,7137,7139,7141],{"class":824,"line":1051},[822,7138,7050],{"class":3198},[822,7140,7053],{"class":3777},[822,7142,4487],{"class":935},[822,7144,7145,7147,7149],{"class":824,"line":1182},[822,7146,7060],{"class":3198},[822,7148,6726],{"class":3777},[822,7150,4487],{"class":935},[822,7152,7153],{"class":824,"line":1484},[822,7154,4441],{"class":3777},[6786,7156,7158],{"id":7157},"_26-crea-los-enlaces-simbólicos","2.6. Crea los enlaces simbólicos",[814,7160,7162],{"className":816,"code":7161,"language":818,"meta":407,"style":407},"sudo ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fjira.midominio.com.conf \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fjira.midominio.com && \\\nsudo ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fbitbucket.midominio.com.conf \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fbitbucket.midominio.com && \\\nsudo ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fconfluence.midominio.com.conf \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fconfluence.midominio.com\n",[72,7163,7164,7181,7198],{"__ignoreMap":407},[822,7165,7166,7168,7170,7172,7174,7177,7179],{"class":824,"line":825},[822,7167,6366],{"class":828},[822,7169,5406],{"class":832},[822,7171,5409],{"class":925},[822,7173,6979],{"class":832},[822,7175,7176],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fjira.midominio.com",[822,7178,936],{"class":935},[822,7180,1151],{"class":925},[822,7182,7183,7185,7187,7189,7191,7194,7196],{"class":824,"line":408},[822,7184,6366],{"class":828},[822,7186,5406],{"class":832},[822,7188,5409],{"class":925},[822,7190,6992],{"class":832},[822,7192,7193],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fbitbucket.midominio.com",[822,7195,936],{"class":935},[822,7197,1151],{"class":925},[822,7199,7200,7202,7204,7206,7209],{"class":824,"line":1051},[822,7201,6366],{"class":828},[822,7203,5406],{"class":832},[822,7205,5409],{"class":925},[822,7207,7208],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fconfluence.midominio.com.conf",[822,7210,7211],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fconfluence.midominio.com\n",[6786,7213,7215],{"id":7214},"_27-reinicia-nginx","2.7. Reinicia Nginx",[814,7217,7219],{"className":816,"code":7218,"language":818,"meta":407,"style":407},"sudo service nginx restart\n",[72,7220,7221],{"__ignoreMap":407},[822,7222,7223,7225,7227,7229],{"class":824,"line":825},[822,7224,6366],{"class":828},[822,7226,5535],{"class":832},[822,7228,5378],{"class":832},[822,7230,7231],{"class":832}," restart\n",[6786,7233,7235],{"id":7234},"_28-configura-el-dns-en-tu-gestor-de-dominios","2.8. Configura el DNS en tu gestor de dominios",[7237,7238,7239,7255],"table",{},[7240,7241,7242],"thead",{},[7243,7244,7245,7249,7252],"tr",{},[7246,7247,7248],"th",{},"DOMAIN\u002FIP",[7246,7250,7251],{},"DOMAIN",[7246,7253,7254],{},"DNS TYPE",[7256,7257,7258,7269,7278],"tbody",{},[7243,7259,7260,7264,7266],{},[7261,7262,7263],"td",{},"xxx.xxx.xxx.xxx",[7261,7265,6720],{},[7261,7267,7268],{},"A",[7243,7270,7271,7273,7275],{},[7261,7272,6720],{},[7261,7274,6723],{},[7261,7276,7277],{},"CNAME",[7243,7279,7280,7282,7284],{},[7261,7281,6720],{},[7261,7283,6726],{},[7261,7285,7277],{},[6786,7287,7289],{"id":7288},"_29-crea-el-certificado-ssl","2.9. Crea el certificado SSL",[61,7291,7293],{"title":7292},"Antes de ejecutar Certbot",[10,7294,7295,7296,7299],{},"Asegúrate de que el puerto 443 esté habilitado a nivel de ",[77,7297,7298],{},"firewall",". Durante la ejecución, elige la opción para redirigir HTTP a HTTPS.",[814,7301,7303],{"className":816,"code":7302,"language":818,"meta":407,"style":407},"sudo certbot --nginx\n",[72,7304,7305],{"__ignoreMap":407},[822,7306,7307,7309,7311],{"class":824,"line":825},[822,7308,6366],{"class":828},[822,7310,6885],{"class":832},[822,7312,7313],{"class":925}," --nginx\n",[6786,7315,7317],{"id":7316},"_210-programa-la-renovación-automática-del-certificado","2.10. Programa la renovación automática del certificado",[814,7319,7321],{"className":816,"code":7320,"language":818,"meta":407,"style":407},"sudo crontab -e\n",[72,7322,7323],{"__ignoreMap":407},[822,7324,7325,7327,7330],{"class":824,"line":825},[822,7326,6366],{"class":828},[822,7328,7329],{"class":832}," crontab",[822,7331,7332],{"class":925}," -e\n",[10,7334,7335],{},"Agrega el siguiente contenido:",[814,7337,7341],{"className":7338,"code":7339,"language":7340,"meta":407,"style":407},"language-cron shiki shiki-themes vitesse-dark","# m h dom mon dow command\n0 2 * * * certbot renew --dry-run\n","cron",[72,7342,7343,7348],{"__ignoreMap":407},[822,7344,7345],{"class":824,"line":825},[822,7346,7347],{},"# m h dom mon dow command\n",[822,7349,7350],{"class":824,"line":408},[822,7351,7352],{},"0 2 * * * certbot renew --dry-run\n",[3993,7354,7356],{"id":7355},"_3-instala-y-configura-postgresql","3. Instala y configura PostgreSQL",[10,7358,7359],{},"Valida la compatibilidad de versiones. Aquí uso PostgreSQL 9.6 (compatible con Jira Software 8.8, Bitbucket Server 7.1.x y Confluence 7.3).",[6786,7361,7363],{"id":7362},"_31-instalación","3.1. Instalación",[814,7365,7367],{"className":816,"code":7366,"language":818,"meta":407,"style":407},"sudo sh -c 'echo \"deb http:\u002F\u002Fapt.postgresql.org\u002Fpub\u002Frepos\u002Fapt\u002F `lsb_release -cs`-pgdg main\" >> \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fpgdg.list' && \\\nwget -q https:\u002F\u002Fwww.postgresql.org\u002Fmedia\u002Fkeys\u002FACCC4CF8.asc -O - | sudo apt-key add - && \\\nsudo apt-get update && \\\nsudo apt-get upgrade && \\\nsudo dpkg --get-selections | grep postgres && \\\nsudo apt-get install postgresql postgresql-contrib libpq-dev && \\\nsudo apt-get install postgresql-9.6\n",[72,7368,7369,7388,7419,7431,7443,7464,7485],{"__ignoreMap":407},[822,7370,7371,7373,7375,7377,7379,7382,7384,7386],{"class":824,"line":825},[822,7372,6366],{"class":828},[822,7374,6098],{"class":832},[822,7376,5092],{"class":925},[822,7378,4430],{"class":1618},[822,7380,7381],{"class":832},"echo \"deb http:\u002F\u002Fapt.postgresql.org\u002Fpub\u002Frepos\u002Fapt\u002F `lsb_release -cs`-pgdg main\" >> \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fpgdg.list",[822,7383,4484],{"class":1618},[822,7385,936],{"class":935},[822,7387,1151],{"class":925},[822,7389,7390,7392,7395,7398,7400,7402,7404,7407,7410,7413,7415,7417],{"class":824,"line":408},[822,7391,6348],{"class":828},[822,7393,7394],{"class":925}," -q",[822,7396,7397],{"class":832}," https:\u002F\u002Fwww.postgresql.org\u002Fmedia\u002Fkeys\u002FACCC4CF8.asc",[822,7399,6353],{"class":925},[822,7401,6356],{"class":832},[822,7403,5938],{"class":4401},[822,7405,7406],{"class":828}," sudo",[822,7408,7409],{"class":832}," apt-key",[822,7411,7412],{"class":832}," add",[822,7414,6356],{"class":832},[822,7416,936],{"class":935},[822,7418,1151],{"class":925},[822,7420,7421,7423,7425,7427,7429],{"class":824,"line":1051},[822,7422,6366],{"class":828},[822,7424,5229],{"class":832},[822,7426,6754],{"class":832},[822,7428,936],{"class":935},[822,7430,1151],{"class":925},[822,7432,7433,7435,7437,7439,7441],{"class":824,"line":1182},[822,7434,6366],{"class":828},[822,7436,5229],{"class":832},[822,7438,6767],{"class":832},[822,7440,936],{"class":935},[822,7442,1151],{"class":925},[822,7444,7445,7447,7450,7453,7455,7457,7460,7462],{"class":824,"line":1484},[822,7446,6366],{"class":828},[822,7448,7449],{"class":832}," dpkg",[822,7451,7452],{"class":925}," --get-selections",[822,7454,5938],{"class":4401},[822,7456,6577],{"class":828},[822,7458,7459],{"class":832}," postgres",[822,7461,936],{"class":935},[822,7463,1151],{"class":925},[822,7465,7466,7468,7470,7472,7475,7478,7481,7483],{"class":824,"line":1655},[822,7467,6366],{"class":828},[822,7469,5229],{"class":832},[822,7471,4845],{"class":832},[822,7473,7474],{"class":832}," postgresql",[822,7476,7477],{"class":832}," postgresql-contrib",[822,7479,7480],{"class":832}," libpq-dev",[822,7482,936],{"class":935},[822,7484,1151],{"class":925},[822,7486,7487,7489,7491,7493],{"class":824,"line":1663},[822,7488,6366],{"class":828},[822,7490,5229],{"class":832},[822,7492,4845],{"class":832},[822,7494,7495],{"class":832}," postgresql-9.6\n",[6786,7497,7499],{"id":7498},"_32-cambia-de-usuario-e-ingresa-a-psql","3.2. Cambia de usuario e ingresa a psql",[814,7501,7503],{"className":816,"code":7502,"language":818,"meta":407,"style":407},"sudo -i -u postgres && \\\npsql\n",[72,7504,7505,7520],{"__ignoreMap":407},[822,7506,7507,7509,7511,7514,7516,7518],{"class":824,"line":825},[822,7508,6366],{"class":828},[822,7510,6167],{"class":925},[822,7512,7513],{"class":925}," -u",[822,7515,7459],{"class":832},[822,7517,936],{"class":935},[822,7519,1151],{"class":925},[822,7521,7522],{"class":824,"line":408},[822,7523,7524],{"class":828},"psql\n",[6786,7526,7528],{"id":7527},"_33-crea-los-roles-las-bases-de-datos-y-asigna-privilegios","3.3. Crea los roles, las bases de datos y asigna privilegios",[814,7530,7534],{"className":7531,"code":7532,"language":7533,"meta":407,"style":407},"language-sql shiki shiki-themes vitesse-dark","CREATE ROLE jirarole WITH LOGIN ENCRYPTED PASSWORD 'password';\nCREATE DATABASE jira WITH ENCODING 'UNICODE' LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0;\nGRANT ALL PRIVILEGES ON DATABASE jira TO jirarole;\nCREATE ROLE bitbucketrole WITH LOGIN ENCRYPTED PASSWORD 'password';\nCREATE DATABASE bitbucket WITH ENCODING='UTF8' OWNER=bitbucketrole CONNECTION LIMIT=-1;\nGRANT ALL PRIVILEGES ON DATABASE bitbucket TO bitbucketrole;\nCREATE ROLE confluencerole WITH LOGIN ENCRYPTED PASSWORD 'password';\nCREATE DATABASE confluence WITH ENCODING='UTF8' OWNER=confluencerole CONNECTION LIMIT=-1;\nGRANT ALL PRIVILEGES ON DATABASE confluence TO confluencerole;\n","sql",[72,7535,7536,7568,7613,7635,7660,7704,7722,7747,7785],{"__ignoreMap":407},[822,7537,7538,7541,7544,7547,7550,7553,7556,7559,7561,7564,7566],{"class":824,"line":825},[822,7539,7540],{"class":3198},"CREATE",[822,7542,7543],{"class":3198}," ROLE",[822,7545,7546],{"class":3777}," jirarole ",[822,7548,7549],{"class":3198},"WITH",[822,7551,7552],{"class":3198}," LOGIN",[822,7554,7555],{"class":3198}," ENCRYPTED",[822,7557,7558],{"class":3198}," PASSWORD",[822,7560,4430],{"class":1618},[822,7562,7563],{"class":832},"password",[822,7565,4484],{"class":1618},[822,7567,4487],{"class":3777},[822,7569,7570,7572,7575,7578,7581,7584,7586,7589,7591,7594,7596,7599,7601,7604,7606,7608,7610],{"class":824,"line":408},[822,7571,7540],{"class":3198},[822,7573,7574],{"class":3198}," DATABASE",[822,7576,7577],{"class":828}," jira",[822,7579,7580],{"class":3198}," WITH",[822,7582,7583],{"class":3198}," ENCODING",[822,7585,4430],{"class":1618},[822,7587,7588],{"class":832},"UNICODE",[822,7590,4484],{"class":1618},[822,7592,7593],{"class":3777}," LC_COLLATE ",[822,7595,4484],{"class":1618},[822,7597,7598],{"class":832},"C",[822,7600,4484],{"class":1618},[822,7602,7603],{"class":3777}," LC_CTYPE ",[822,7605,4484],{"class":1618},[822,7607,7598],{"class":832},[822,7609,4484],{"class":1618},[822,7611,7612],{"class":3777}," TEMPLATE template0;\n",[822,7614,7615,7618,7621,7624,7626,7629,7632],{"class":824,"line":1051},[822,7616,7617],{"class":3198},"GRANT",[822,7619,7620],{"class":3777}," ALL PRIVILEGES ",[822,7622,7623],{"class":3198},"ON",[822,7625,7574],{"class":3198},[822,7627,7628],{"class":3777}," jira ",[822,7630,7631],{"class":3198},"TO",[822,7633,7634],{"class":3777}," jirarole;\n",[822,7636,7637,7639,7641,7644,7646,7648,7650,7652,7654,7656,7658],{"class":824,"line":1182},[822,7638,7540],{"class":3198},[822,7640,7543],{"class":3198},[822,7642,7643],{"class":3777}," bitbucketrole ",[822,7645,7549],{"class":3198},[822,7647,7552],{"class":3198},[822,7649,7555],{"class":3198},[822,7651,7558],{"class":3198},[822,7653,4430],{"class":1618},[822,7655,7563],{"class":832},[822,7657,4484],{"class":1618},[822,7659,4487],{"class":3777},[822,7661,7662,7664,7666,7669,7671,7673,7675,7677,7680,7682,7685,7687,7690,7693,7696,7699,7702],{"class":824,"line":1484},[822,7663,7540],{"class":3198},[822,7665,7574],{"class":3198},[822,7667,7668],{"class":828}," bitbucket",[822,7670,7580],{"class":3198},[822,7672,7583],{"class":3198},[822,7674,5159],{"class":4401},[822,7676,4484],{"class":1618},[822,7678,7679],{"class":832},"UTF8",[822,7681,4484],{"class":1618},[822,7683,7684],{"class":3198}," OWNER",[822,7686,5159],{"class":4401},[822,7688,7689],{"class":3777},"bitbucketrole ",[822,7691,7692],{"class":3198},"CONNECTION",[822,7694,7695],{"class":3198}," LIMIT",[822,7697,7698],{"class":4401},"=-",[822,7700,7701],{"class":1118},"1",[822,7703,4487],{"class":3777},[822,7705,7706,7708,7710,7712,7714,7717,7719],{"class":824,"line":1655},[822,7707,7617],{"class":3198},[822,7709,7620],{"class":3777},[822,7711,7623],{"class":3198},[822,7713,7574],{"class":3198},[822,7715,7716],{"class":3777}," bitbucket ",[822,7718,7631],{"class":3198},[822,7720,7721],{"class":3777}," bitbucketrole;\n",[822,7723,7724,7726,7728,7731,7733,7735,7737,7739,7741,7743,7745],{"class":824,"line":1663},[822,7725,7540],{"class":3198},[822,7727,7543],{"class":3198},[822,7729,7730],{"class":3777}," confluencerole ",[822,7732,7549],{"class":3198},[822,7734,7552],{"class":3198},[822,7736,7555],{"class":3198},[822,7738,7558],{"class":3198},[822,7740,4430],{"class":1618},[822,7742,7563],{"class":832},[822,7744,4484],{"class":1618},[822,7746,4487],{"class":3777},[822,7748,7749,7751,7753,7756,7758,7760,7762,7764,7766,7768,7770,7772,7775,7777,7779,7781,7783],{"class":824,"line":1673},[822,7750,7540],{"class":3198},[822,7752,7574],{"class":3198},[822,7754,7755],{"class":828}," confluence",[822,7757,7580],{"class":3198},[822,7759,7583],{"class":3198},[822,7761,5159],{"class":4401},[822,7763,4484],{"class":1618},[822,7765,7679],{"class":832},[822,7767,4484],{"class":1618},[822,7769,7684],{"class":3198},[822,7771,5159],{"class":4401},[822,7773,7774],{"class":3777},"confluencerole ",[822,7776,7692],{"class":3198},[822,7778,7695],{"class":3198},[822,7780,7698],{"class":4401},[822,7782,7701],{"class":1118},[822,7784,4487],{"class":3777},[822,7786,7787,7789,7791,7793,7795,7798,7800],{"class":824,"line":1681},[822,7788,7617],{"class":3198},[822,7790,7620],{"class":3777},[822,7792,7623],{"class":3198},[822,7794,7574],{"class":3198},[822,7796,7797],{"class":3777}," confluence ",[822,7799,7631],{"class":3198},[822,7801,7802],{"class":3777}," confluencerole;\n",[6786,7804,7806],{"id":7805},"_34-verifica-y-sal-de-psql","3.4. Verifica y sal de psql",[814,7808,7810],{"className":7531,"code":7809,"language":7533,"meta":407,"style":407},"\\l\n\\du\n\\q\nexit\n",[72,7811,7812,7817,7822,7827],{"__ignoreMap":407},[822,7813,7814],{"class":824,"line":825},[822,7815,7816],{"class":3777},"\\l\n",[822,7818,7819],{"class":824,"line":408},[822,7820,7821],{"class":3777},"\\du\n",[822,7823,7824],{"class":824,"line":1051},[822,7825,7826],{"class":3777},"\\q\n",[822,7828,7829],{"class":824,"line":1182},[822,7830,7831],{"class":3777},"exit\n",[3993,7833,7835],{"id":7834},"_4-prepara-la-instalación-de-las-aplicaciones","4. Prepara la instalación de las aplicaciones",[6786,7837,7839],{"id":7838},"_41-sube-los-archivos-bin-al-servidor-con-scp","4.1. Sube los archivos .bin al servidor con SCP",[814,7841,7843],{"className":816,"code":7842,"language":818,"meta":407,"style":407},"scp -i \u002Fpath_to_pem\u002Fcredential.pem \u002Fpath_to_bin\u002Fatlassian-bitbucket-version-x64.bin ubuntu@xxx.xxx.xxx.xxx:~\u002F.\nscp -i \u002Fpath_to_pem\u002Fcredential.pem \u002Fpath_to_bin\u002Fatlassian-jira-software-version-x64.bin ubuntu@xxx.xxx.xxx.xxx:~\u002F.\nscp -i \u002Fpath_to_pem\u002Fcredential.pem \u002Fpath_to_bin\u002Fatlassian-confluence-version-x64.bin ubuntu@xxx.xxx.xxx.xxx:~\u002F.\n",[72,7844,7845,7861,7874],{"__ignoreMap":407},[822,7846,7847,7850,7852,7855,7858],{"class":824,"line":825},[822,7848,7849],{"class":828},"scp",[822,7851,6167],{"class":925},[822,7853,7854],{"class":832}," \u002Fpath_to_pem\u002Fcredential.pem",[822,7856,7857],{"class":832}," \u002Fpath_to_bin\u002Fatlassian-bitbucket-version-x64.bin",[822,7859,7860],{"class":832}," ubuntu@xxx.xxx.xxx.xxx:~\u002F.\n",[822,7862,7863,7865,7867,7869,7872],{"class":824,"line":408},[822,7864,7849],{"class":828},[822,7866,6167],{"class":925},[822,7868,7854],{"class":832},[822,7870,7871],{"class":832}," \u002Fpath_to_bin\u002Fatlassian-jira-software-version-x64.bin",[822,7873,7860],{"class":832},[822,7875,7876,7878,7880,7882,7885],{"class":824,"line":1051},[822,7877,7849],{"class":828},[822,7879,6167],{"class":925},[822,7881,7854],{"class":832},[822,7883,7884],{"class":832}," \u002Fpath_to_bin\u002Fatlassian-confluence-version-x64.bin",[822,7886,7860],{"class":832},[6786,7888,7890],{"id":7889},"_42-crea-la-carpeta-de-instalación-mueve-los-archivos-y-dales-permisos-de-ejecución","4.2. Crea la carpeta de instalación, mueve los archivos y dales permisos de ejecución",[814,7892,7894],{"className":816,"code":7893,"language":818,"meta":407,"style":407},"cd \u002F && \\\nsudo mkdir software && \\\nsudo mv \u002Fhome\u002Fubuntu\u002Fatlassian-* \u002Fsoftware && \\\nsudo chown -R root:root \u002Fsoftware && \\\nsudo chmod -R a+x \u002Fsoftware && \\\ncd \u002Fsoftware\n",[72,7895,7896,7907,7921,7940,7957,7974],{"__ignoreMap":407},[822,7897,7898,7900,7903,7905],{"class":824,"line":825},[822,7899,845],{"class":844},[822,7901,7902],{"class":832}," \u002F",[822,7904,936],{"class":935},[822,7906,1151],{"class":925},[822,7908,7909,7911,7914,7917,7919],{"class":824,"line":408},[822,7910,6366],{"class":828},[822,7912,7913],{"class":832}," mkdir",[822,7915,7916],{"class":832}," software",[822,7918,936],{"class":935},[822,7920,1151],{"class":925},[822,7922,7923,7925,7927,7930,7933,7936,7938],{"class":824,"line":1051},[822,7924,6366],{"class":828},[822,7926,5952],{"class":832},[822,7928,7929],{"class":832}," \u002Fhome\u002Fubuntu\u002Fatlassian-",[822,7931,7932],{"class":925},"*",[822,7934,7935],{"class":832}," \u002Fsoftware",[822,7937,936],{"class":935},[822,7939,1151],{"class":925},[822,7941,7942,7944,7946,7948,7951,7953,7955],{"class":824,"line":1182},[822,7943,6366],{"class":828},[822,7945,1020],{"class":832},[822,7947,1023],{"class":925},[822,7949,7950],{"class":832}," root:root",[822,7952,7935],{"class":832},[822,7954,936],{"class":935},[822,7956,1151],{"class":925},[822,7958,7959,7961,7963,7965,7968,7970,7972],{"class":824,"line":1484},[822,7960,6366],{"class":828},[822,7962,5519],{"class":832},[822,7964,1023],{"class":925},[822,7966,7967],{"class":832}," a+x",[822,7969,7935],{"class":832},[822,7971,936],{"class":935},[822,7973,1151],{"class":925},[822,7975,7976,7978],{"class":824,"line":1655},[822,7977,845],{"class":844},[822,7979,7980],{"class":832}," \u002Fsoftware\n",[3993,7982,7984],{"id":7983},"_5-instala-jira-software-confluence-y-bitbucket-server","5. Instala Jira Software, Confluence y Bitbucket Server",[10,7986,7987],{},"Cada aplicación sigue un flujo muy parecido. Elige la pestaña de la que estés instalando:",[121,7989,7990,8342,8648],{},[124,7991,7993],{"icon":7021,"label":7992},"Jira Software",[304,7994,7995,8017,8194,8296],{},[307,7996,7998,8005],{"title":7997},"Ejecuta el instalador",[10,7999,8000,8001,8004],{},"Selecciona la instalación estándar y ",[14,8002,8003],{},"niega"," la ejecución al terminar.",[814,8006,8008],{"className":816,"code":8007,"language":818,"meta":407,"style":407},"sudo .\u002Fatlassian-jira-software-version-x64.bin\n",[72,8009,8010],{"__ignoreMap":407},[822,8011,8012,8014],{"class":824,"line":825},[822,8013,6366],{"class":828},[822,8015,8016],{"class":832}," .\u002Fatlassian-jira-software-version-x64.bin\n",[307,8018,8020,8034,8040],{"title":8019},"Modifica el archivo server.xml",[814,8021,8023],{"className":816,"code":8022,"language":818,"meta":407,"style":407},"sudo vim \u002Fopt\u002Fatlassian\u002Fjira\u002Fconf\u002Fserver.xml\n",[72,8024,8025],{"__ignoreMap":407},[822,8026,8027,8029,8031],{"class":824,"line":825},[822,8028,6366],{"class":828},[822,8030,6485],{"class":832},[822,8032,8033],{"class":832}," \u002Fopt\u002Fatlassian\u002Fjira\u002Fconf\u002Fserver.xml\n",[10,8035,8036,8037,1615],{},"Modifica el tag ",[72,8038,8039],{},"connector",[814,8041,8045],{"className":8042,"code":8043,"language":8044,"meta":407,"style":407},"language-xml shiki shiki-themes vitesse-dark","\u003Cconnector acceptcount=\"10\" connectiontimeout=\"20000\" enablelookups=\"false\"\nmaxthreads=\"200\" minsparethreads=\"10\" port=\"8080\" proxyname=\"jira.midominio.com\"\nproxyport=\"443\" scheme=\"https\" secure=\"true\" uriencoding=\"UTF-8\">\u003C\u002Fconnector>\n","xml",[72,8046,8047,8089,8137],{"__ignoreMap":407},[822,8048,8049,8051,8053,8056,8058,8060,8063,8065,8068,8070,8072,8075,8077,8080,8082,8084,8087],{"class":824,"line":825},[822,8050,4811],{"class":935},[822,8052,8039],{"class":3198},[822,8054,8055],{"class":3827}," acceptcount",[822,8057,5159],{"class":3777},[822,8059,5059],{"class":1618},[822,8061,8062],{"class":832},"10",[822,8064,5059],{"class":1618},[822,8066,8067],{"class":3827}," connectiontimeout",[822,8069,5159],{"class":3777},[822,8071,5059],{"class":1618},[822,8073,8074],{"class":832},"20000",[822,8076,5059],{"class":1618},[822,8078,8079],{"class":3827}," enablelookups",[822,8081,5159],{"class":3777},[822,8083,5059],{"class":1618},[822,8085,8086],{"class":832},"false",[822,8088,1625],{"class":1618},[822,8090,8091,8094,8096,8098,8101,8103,8106,8108,8110,8112,8114,8117,8119,8121,8124,8126,8129,8131,8133,8135],{"class":824,"line":408},[822,8092,8093],{"class":3827},"maxthreads",[822,8095,5159],{"class":3777},[822,8097,5059],{"class":1618},[822,8099,8100],{"class":832},"200",[822,8102,5059],{"class":1618},[822,8104,8105],{"class":3827}," minsparethreads",[822,8107,5159],{"class":3777},[822,8109,5059],{"class":1618},[822,8111,8062],{"class":832},[822,8113,5059],{"class":1618},[822,8115,8116],{"class":3827}," port",[822,8118,5159],{"class":3777},[822,8120,5059],{"class":1618},[822,8122,8123],{"class":832},"8080",[822,8125,5059],{"class":1618},[822,8127,8128],{"class":3827}," proxyname",[822,8130,5159],{"class":3777},[822,8132,5059],{"class":1618},[822,8134,6720],{"class":832},[822,8136,1625],{"class":1618},[822,8138,8139,8142,8144,8146,8149,8151,8154,8156,8158,8161,8163,8166,8168,8170,8173,8175,8178,8180,8182,8184,8186,8189,8191],{"class":824,"line":1051},[822,8140,8141],{"class":3827},"proxyport",[822,8143,5159],{"class":3777},[822,8145,5059],{"class":1618},[822,8147,8148],{"class":832},"443",[822,8150,5059],{"class":1618},[822,8152,8153],{"class":3827}," scheme",[822,8155,5159],{"class":3777},[822,8157,5059],{"class":1618},[822,8159,8160],{"class":832},"https",[822,8162,5059],{"class":1618},[822,8164,8165],{"class":3827}," secure",[822,8167,5159],{"class":3777},[822,8169,5059],{"class":1618},[822,8171,8172],{"class":832},"true",[822,8174,5059],{"class":1618},[822,8176,8177],{"class":3827}," uriencoding",[822,8179,5159],{"class":3777},[822,8181,5059],{"class":1618},[822,8183,5167],{"class":832},[822,8185,5059],{"class":1618},[822,8187,8188],{"class":935},">\u003C\u002F",[822,8190,8039],{"class":3198},[822,8192,8193],{"class":935},">\n",[307,8195,8197,8211,8213],{"title":8196},"Configura el proxy inverso en Nginx",[814,8198,8200],{"className":816,"code":8199,"language":818,"meta":407,"style":407},"sudo vim \u002Fetc\u002Fnginx\u002Fsites-available\u002Fjira.midominio.com.conf\n",[72,8201,8202],{"__ignoreMap":407},[822,8203,8204,8206,8208],{"class":824,"line":825},[822,8205,6366],{"class":828},[822,8207,6485],{"class":832},[822,8209,8210],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fjira.midominio.com.conf\n",[10,8212,7335],{},[814,8214,8216],{"className":7024,"code":8215,"language":7026,"meta":407,"style":407},"location \u002F {\n     proxy_set_header X-Forwarded-Host $host;\n     proxy_set_header X-Forwarded-Server $host;\n     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n     proxy_pass http:\u002F\u002F127.0.0.1:8080;\n     client_max_body_size 100M;\n}\n",[72,8217,8218,8229,8245,8258,8272,8282,8292],{"__ignoreMap":407},[822,8219,8220,8223,8226],{"class":824,"line":825},[822,8221,8222],{"class":4401},"location",[822,8224,8225],{"class":828}," \u002F ",[822,8227,8228],{"class":3777},"{\n",[822,8230,8231,8234,8237,8240,8243],{"class":824,"line":408},[822,8232,8233],{"class":3198},"     proxy_set_header ",[822,8235,8236],{"class":3777},"X-Forwarded-Host ",[822,8238,8239],{"class":935},"$",[822,8241,8242],{"class":3827},"host",[822,8244,4487],{"class":935},[822,8246,8247,8249,8252,8254,8256],{"class":824,"line":1051},[822,8248,8233],{"class":3198},[822,8250,8251],{"class":3777},"X-Forwarded-Server ",[822,8253,8239],{"class":935},[822,8255,8242],{"class":3827},[822,8257,4487],{"class":935},[822,8259,8260,8262,8265,8267,8270],{"class":824,"line":1182},[822,8261,8233],{"class":3198},[822,8263,8264],{"class":3777},"X-Forwarded-For ",[822,8266,8239],{"class":935},[822,8268,8269],{"class":3827},"proxy_add_x_forwarded_for",[822,8271,4487],{"class":935},[822,8273,8274,8277,8280],{"class":824,"line":1484},[822,8275,8276],{"class":3198},"     proxy_pass ",[822,8278,8279],{"class":3777},"http:\u002F\u002F127.0.0.1:8080",[822,8281,4487],{"class":935},[822,8283,8284,8287,8290],{"class":824,"line":1655},[822,8285,8286],{"class":3198},"     client_max_body_size ",[822,8288,8289],{"class":1118},"100M",[822,8291,4487],{"class":935},[822,8293,8294],{"class":824,"line":1663},[822,8295,4441],{"class":3777},[307,8297,8299,8332],{"title":8298},"Reinicia Nginx e inicia el programa",[814,8300,8302],{"className":816,"code":8301,"language":818,"meta":407,"style":407},"sudo service nginx restart\ncd \u002Fopt\u002Fatlassian\u002Fjira\u002Fbin && \\\nsudo .\u002Fstartup.sh\n",[72,8303,8304,8314,8325],{"__ignoreMap":407},[822,8305,8306,8308,8310,8312],{"class":824,"line":825},[822,8307,6366],{"class":828},[822,8309,5535],{"class":832},[822,8311,5378],{"class":832},[822,8313,7231],{"class":832},[822,8315,8316,8318,8321,8323],{"class":824,"line":408},[822,8317,845],{"class":844},[822,8319,8320],{"class":832}," \u002Fopt\u002Fatlassian\u002Fjira\u002Fbin",[822,8322,936],{"class":935},[822,8324,1151],{"class":925},[822,8326,8327,8329],{"class":824,"line":1051},[822,8328,6366],{"class":828},[822,8330,8331],{"class":832}," .\u002Fstartup.sh\n",[10,8333,4935,8334,8337,8338,8341],{},[72,8335,8336],{},"https:\u002F\u002Fjira.midominio.com",", completa la instalación en modo producción, conecta la base de datos PostgreSQL ",[72,8339,8340],{},"jira"," y configura las credenciales SMTP si las tienes.",[124,8343,8345],{"icon":7114,"label":8344},"Confluence",[304,8346,8347,8365,8519,8606],{},[307,8348,8349,8353],{"title":7997},[10,8350,8000,8351,8004],{},[14,8352,8003],{},[814,8354,8356],{"className":816,"code":8355,"language":818,"meta":407,"style":407},"sudo .\u002Fatlassian-confluence-version-x64.bin\n",[72,8357,8358],{"__ignoreMap":407},[822,8359,8360,8362],{"class":824,"line":825},[822,8361,6366],{"class":828},[822,8363,8364],{"class":832}," .\u002Fatlassian-confluence-version-x64.bin\n",[307,8366,8367,8381,8385],{"title":8019},[814,8368,8370],{"className":816,"code":8369,"language":818,"meta":407,"style":407},"sudo vim \u002Fopt\u002Fatlassian\u002Fconfluence\u002Fconf\u002Fserver.xml\n",[72,8371,8372],{"__ignoreMap":407},[822,8373,8374,8376,8378],{"class":824,"line":825},[822,8375,6366],{"class":828},[822,8377,6485],{"class":832},[822,8379,8380],{"class":832}," \u002Fopt\u002Fatlassian\u002Fconfluence\u002Fconf\u002Fserver.xml\n",[10,8382,8036,8383,1615],{},[72,8384,8039],{},[814,8386,8388],{"className":8042,"code":8387,"language":8044,"meta":407,"style":407},"\u003Cconnector acceptcount=\"10\" connectiontimeout=\"20000\" enablelookups=\"false\"\nmaxthreads=\"200\" minsparethreads=\"10\" port=\"8080\" proxyname=\"confluence.midominio.com\" \nproxyport=\"443\" scheme=\"https\" secure=\"true\" uriencoding=\"UTF-8\">\u003C\u002Fconnector>\n",[72,8389,8390,8426,8471],{"__ignoreMap":407},[822,8391,8392,8394,8396,8398,8400,8402,8404,8406,8408,8410,8412,8414,8416,8418,8420,8422,8424],{"class":824,"line":825},[822,8393,4811],{"class":935},[822,8395,8039],{"class":3198},[822,8397,8055],{"class":3827},[822,8399,5159],{"class":3777},[822,8401,5059],{"class":1618},[822,8403,8062],{"class":832},[822,8405,5059],{"class":1618},[822,8407,8067],{"class":3827},[822,8409,5159],{"class":3777},[822,8411,5059],{"class":1618},[822,8413,8074],{"class":832},[822,8415,5059],{"class":1618},[822,8417,8079],{"class":3827},[822,8419,5159],{"class":3777},[822,8421,5059],{"class":1618},[822,8423,8086],{"class":832},[822,8425,1625],{"class":1618},[822,8427,8428,8430,8432,8434,8436,8438,8440,8442,8444,8446,8448,8450,8452,8454,8456,8458,8460,8462,8464,8466,8468],{"class":824,"line":408},[822,8429,8093],{"class":3827},[822,8431,5159],{"class":3777},[822,8433,5059],{"class":1618},[822,8435,8100],{"class":832},[822,8437,5059],{"class":1618},[822,8439,8105],{"class":3827},[822,8441,5159],{"class":3777},[822,8443,5059],{"class":1618},[822,8445,8062],{"class":832},[822,8447,5059],{"class":1618},[822,8449,8116],{"class":3827},[822,8451,5159],{"class":3777},[822,8453,5059],{"class":1618},[822,8455,8123],{"class":832},[822,8457,5059],{"class":1618},[822,8459,8128],{"class":3827},[822,8461,5159],{"class":3777},[822,8463,5059],{"class":1618},[822,8465,6726],{"class":832},[822,8467,5059],{"class":1618},[822,8469,8470],{"class":3777}," \n",[822,8472,8473,8475,8477,8479,8481,8483,8485,8487,8489,8491,8493,8495,8497,8499,8501,8503,8505,8507,8509,8511,8513,8515,8517],{"class":824,"line":1051},[822,8474,8141],{"class":3827},[822,8476,5159],{"class":3777},[822,8478,5059],{"class":1618},[822,8480,8148],{"class":832},[822,8482,5059],{"class":1618},[822,8484,8153],{"class":3827},[822,8486,5159],{"class":3777},[822,8488,5059],{"class":1618},[822,8490,8160],{"class":832},[822,8492,5059],{"class":1618},[822,8494,8165],{"class":3827},[822,8496,5159],{"class":3777},[822,8498,5059],{"class":1618},[822,8500,8172],{"class":832},[822,8502,5059],{"class":1618},[822,8504,8177],{"class":3827},[822,8506,5159],{"class":3777},[822,8508,5059],{"class":1618},[822,8510,5167],{"class":832},[822,8512,5059],{"class":1618},[822,8514,8188],{"class":935},[822,8516,8039],{"class":3198},[822,8518,8193],{"class":935},[307,8520,8521,8534,8536],{"title":8196},[814,8522,8524],{"className":816,"code":8523,"language":818,"meta":407,"style":407},"sudo vim \u002Fetc\u002Fnginx\u002Fsites-available\u002Fconfluence.midominio.com.conf\n",[72,8525,8526],{"__ignoreMap":407},[822,8527,8528,8530,8532],{"class":824,"line":825},[822,8529,6366],{"class":828},[822,8531,6485],{"class":832},[822,8533,7005],{"class":832},[10,8535,7335],{},[814,8537,8539],{"className":7024,"code":8538,"language":7026,"meta":407,"style":407},"location \u002F {\n     proxy_set_header X-Forwarded-Host $host;\n     proxy_set_header X-Forwarded-Server $host;\n     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n     proxy_pass http:\u002F\u002F127.0.0.1:8090;\n     client_max_body_size 100M;\n}\n",[72,8540,8541,8549,8561,8573,8585,8594,8602],{"__ignoreMap":407},[822,8542,8543,8545,8547],{"class":824,"line":825},[822,8544,8222],{"class":4401},[822,8546,8225],{"class":828},[822,8548,8228],{"class":3777},[822,8550,8551,8553,8555,8557,8559],{"class":824,"line":408},[822,8552,8233],{"class":3198},[822,8554,8236],{"class":3777},[822,8556,8239],{"class":935},[822,8558,8242],{"class":3827},[822,8560,4487],{"class":935},[822,8562,8563,8565,8567,8569,8571],{"class":824,"line":1051},[822,8564,8233],{"class":3198},[822,8566,8251],{"class":3777},[822,8568,8239],{"class":935},[822,8570,8242],{"class":3827},[822,8572,4487],{"class":935},[822,8574,8575,8577,8579,8581,8583],{"class":824,"line":1182},[822,8576,8233],{"class":3198},[822,8578,8264],{"class":3777},[822,8580,8239],{"class":935},[822,8582,8269],{"class":3827},[822,8584,4487],{"class":935},[822,8586,8587,8589,8592],{"class":824,"line":1484},[822,8588,8276],{"class":3198},[822,8590,8591],{"class":3777},"http:\u002F\u002F127.0.0.1:8090",[822,8593,4487],{"class":935},[822,8595,8596,8598,8600],{"class":824,"line":1655},[822,8597,8286],{"class":3198},[822,8599,8289],{"class":1118},[822,8601,4487],{"class":935},[822,8603,8604],{"class":824,"line":1663},[822,8605,4441],{"class":3777},[307,8607,8608,8640],{"title":8298},[814,8609,8611],{"className":816,"code":8610,"language":818,"meta":407,"style":407},"sudo service nginx restart\ncd \u002Fopt\u002Fatlassian\u002Fconfluence\u002Fbin && \\\nsudo .\u002Fstartup.sh\n",[72,8612,8613,8623,8634],{"__ignoreMap":407},[822,8614,8615,8617,8619,8621],{"class":824,"line":825},[822,8616,6366],{"class":828},[822,8618,5535],{"class":832},[822,8620,5378],{"class":832},[822,8622,7231],{"class":832},[822,8624,8625,8627,8630,8632],{"class":824,"line":408},[822,8626,845],{"class":844},[822,8628,8629],{"class":832}," \u002Fopt\u002Fatlassian\u002Fconfluence\u002Fbin",[822,8631,936],{"class":935},[822,8633,1151],{"class":925},[822,8635,8636,8638],{"class":824,"line":1051},[822,8637,6366],{"class":828},[822,8639,8331],{"class":832},[10,8641,4935,8642,8337,8645,8341],{},[72,8643,8644],{},"https:\u002F\u002Fconfluence.midominio.com",[72,8646,8647],{},"confluence",[124,8649,8651],{"icon":7071,"label":8650},"Bitbucket Server",[304,8652,8653,8672,8682,8715,8781,8869],{},[307,8654,8655,8660],{"title":7997},[10,8656,8000,8657,8004],{},[14,8658,8659],{},"acepta",[814,8661,8663],{"className":816,"code":8662,"language":818,"meta":407,"style":407},"sudo .\u002Fatlassian-bitbucket-version-x64.bin\n",[72,8664,8665],{"__ignoreMap":407},[822,8666,8667,8669],{"class":824,"line":825},[822,8668,6366],{"class":828},[822,8670,8671],{"class":832}," .\u002Fatlassian-bitbucket-version-x64.bin\n",[307,8673,8675],{"title":8674},"Configura el security group",[10,8676,8677,8678,8681],{},"Configura el ",[77,8679,8680],{},"security group"," de la instancia, sobre todo las reglas de entrada, como se muestra en la documentación.",[307,8683,8685,8692],{"title":8684},"Configura la base de datos",[10,8686,8687,8688,8691],{},"Accede vía ",[72,8689,8690],{},"http:\u002F\u002Fxxx.xxx.xxx.xxx:7990",", configura la base de datos y luego detén el programa:",[814,8693,8695],{"className":816,"code":8694,"language":818,"meta":407,"style":407},"cd \u002Fopt\u002Fatlassian\u002Fbitbucket\u002F6.4.1\u002Fbin && \\\nsudo .\u002Fstop-bitbucket.sh\n",[72,8696,8697,8708],{"__ignoreMap":407},[822,8698,8699,8701,8704,8706],{"class":824,"line":825},[822,8700,845],{"class":844},[822,8702,8703],{"class":832}," \u002Fopt\u002Fatlassian\u002Fbitbucket\u002F6.4.1\u002Fbin",[822,8705,936],{"class":935},[822,8707,1151],{"class":925},[822,8709,8710,8712],{"class":824,"line":408},[822,8711,6366],{"class":828},[822,8713,8714],{"class":832}," .\u002Fstop-bitbucket.sh\n",[307,8716,8718,8732,8734],{"title":8717},"Configura el archivo properties",[814,8719,8721],{"className":816,"code":8720,"language":818,"meta":407,"style":407},"sudo vim \u002Fvar\u002Fatlassian\u002Fapplication-data\u002Fbitbucket\u002Fshared\u002Fbitbucket.properties\n",[72,8722,8723],{"__ignoreMap":407},[822,8724,8725,8727,8729],{"class":824,"line":825},[822,8726,6366],{"class":828},[822,8728,6485],{"class":832},[822,8730,8731],{"class":832}," \u002Fvar\u002Fatlassian\u002Fapplication-data\u002Fbitbucket\u002Fshared\u002Fbitbucket.properties\n",[10,8733,7335],{},[814,8735,8739],{"className":8736,"code":8737,"language":8738,"meta":407,"style":407},"language-properties shiki shiki-themes vitesse-dark","server.secure=true\nserver.scheme=https\nserver.proxy-port=443\nserver.proxy-name=bitbucket.midominio.com\n","properties",[72,8740,8741,8751,8761,8771],{"__ignoreMap":407},[822,8742,8743,8746,8748],{"class":824,"line":825},[822,8744,8745],{"class":3198},"server.secure",[822,8747,5159],{"class":935},[822,8749,8750],{"class":3777},"true\n",[822,8752,8753,8756,8758],{"class":824,"line":408},[822,8754,8755],{"class":3198},"server.scheme",[822,8757,5159],{"class":935},[822,8759,8760],{"class":3777},"https\n",[822,8762,8763,8766,8768],{"class":824,"line":1051},[822,8764,8765],{"class":3198},"server.proxy-port",[822,8767,5159],{"class":935},[822,8769,8770],{"class":3777},"443\n",[822,8772,8773,8776,8778],{"class":824,"line":1182},[822,8774,8775],{"class":3198},"server.proxy-name",[822,8777,5159],{"class":935},[822,8779,8780],{"class":3777},"bitbucket.midominio.com\n",[307,8782,8783,8797,8799],{"title":8196},[814,8784,8786],{"className":816,"code":8785,"language":818,"meta":407,"style":407},"sudo vim \u002Fetc\u002Fnginx\u002Fsites-available\u002Fbitbucket.midominio.com.conf\n",[72,8787,8788],{"__ignoreMap":407},[822,8789,8790,8792,8794],{"class":824,"line":825},[822,8791,6366],{"class":828},[822,8793,6485],{"class":832},[822,8795,8796],{"class":832}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fbitbucket.midominio.com.conf\n",[10,8798,7335],{},[814,8800,8802],{"className":7024,"code":8801,"language":7026,"meta":407,"style":407},"location \u002F {\n     proxy_set_header X-Forwarded-Host $host;\n     proxy_set_header X-Forwarded-Server $host;\n     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n     proxy_pass http:\u002F\u002F127.0.0.1:7990;\n     client_max_body_size 100M;\n}\n",[72,8803,8804,8812,8824,8836,8848,8857,8865],{"__ignoreMap":407},[822,8805,8806,8808,8810],{"class":824,"line":825},[822,8807,8222],{"class":4401},[822,8809,8225],{"class":828},[822,8811,8228],{"class":3777},[822,8813,8814,8816,8818,8820,8822],{"class":824,"line":408},[822,8815,8233],{"class":3198},[822,8817,8236],{"class":3777},[822,8819,8239],{"class":935},[822,8821,8242],{"class":3827},[822,8823,4487],{"class":935},[822,8825,8826,8828,8830,8832,8834],{"class":824,"line":1051},[822,8827,8233],{"class":3198},[822,8829,8251],{"class":3777},[822,8831,8239],{"class":935},[822,8833,8242],{"class":3827},[822,8835,4487],{"class":935},[822,8837,8838,8840,8842,8844,8846],{"class":824,"line":1182},[822,8839,8233],{"class":3198},[822,8841,8264],{"class":3777},[822,8843,8239],{"class":935},[822,8845,8269],{"class":3827},[822,8847,4487],{"class":935},[822,8849,8850,8852,8855],{"class":824,"line":1484},[822,8851,8276],{"class":3198},[822,8853,8854],{"class":3777},"http:\u002F\u002F127.0.0.1:7990",[822,8856,4487],{"class":935},[822,8858,8859,8861,8863],{"class":824,"line":1655},[822,8860,8286],{"class":3198},[822,8862,8289],{"class":1118},[822,8864,4487],{"class":935},[822,8866,8867],{"class":824,"line":1663},[822,8868,4441],{"class":3777},[307,8870,8871,8903],{"title":8298},[814,8872,8874],{"className":816,"code":8873,"language":818,"meta":407,"style":407},"sudo service nginx restart\ncd \u002Fopt\u002Fatlassian\u002Fbitbucket\u002F6.4.1\u002Fbin && \\\nsudo .\u002Fstart-bitbucket.sh\n",[72,8875,8876,8886,8896],{"__ignoreMap":407},[822,8877,8878,8880,8882,8884],{"class":824,"line":825},[822,8879,6366],{"class":828},[822,8881,5535],{"class":832},[822,8883,5378],{"class":832},[822,8885,7231],{"class":832},[822,8887,8888,8890,8892,8894],{"class":824,"line":408},[822,8889,845],{"class":844},[822,8891,8703],{"class":832},[822,8893,936],{"class":935},[822,8895,1151],{"class":925},[822,8897,8898,8900],{"class":824,"line":1051},[822,8899,6366],{"class":828},[822,8901,8902],{"class":832}," .\u002Fstart-bitbucket.sh\n",[10,8904,4935,8905,390],{},[72,8906,8907],{},"https:\u002F\u002Fbitbucket.midominio.com",[10,8909,8910],{},"Espero que puedas ponerlo en práctica. ¡Hasta la próxima!",[1222,8912,8913],{},"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 .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sXjYR, html code.shiki .sXjYR{--shiki-default:#C99076}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_wWq, html code.shiki .s_wWq{--shiki-default:#CB7676}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}html pre.shiki code .sNpkn, html code.shiki .sNpkn{--shiki-default:#DBD7CAEE}html pre.shiki code .s3QIE, html code.shiki .s3QIE{--shiki-default:#4D9375}html pre.shiki code .sxA9i, html code.shiki .sxA9i{--shiki-default:#4C9A91}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}",{"title":407,"searchDepth":408,"depth":408,"links":8915},[8916,8917,8918],{"id":6679,"depth":408,"text":6680},{"id":6696,"depth":408,"text":6697},{"id":6735,"depth":408,"text":6736,"children":8919},[8920,8921,8922,8923,8924],{"id":6739,"depth":1051,"text":6740},{"id":6783,"depth":1051,"text":6784},{"id":7355,"depth":1051,"text":7356},{"id":7834,"depth":1051,"text":7835},{"id":7983,"depth":1051,"text":7984},"2020-04-10","Guía completa para aprovisionar Ubuntu Server 18.04 con los productos Atlassian Jira, Bitbucket y Confluence usando PostgreSQL, proxy reverso Nginx y certificados SSL.","\u002Fimg\u002Fposts\u002Fcovers\u002Faprovisionar-ubuntu-server-jira-bitbucket-confluence.svg",{},"\u002Fblog\u002Faprovisionar-ubuntu-server-jira-bitbucket-confluence",{"title":6674,"description":8926},"blog\u002Faprovisionar-ubuntu-server-jira-bitbucket-confluence",[8933,4090,8650,8934,8344,8935,7992,3935,4730,8936,8937,6670],"Atlassian","Certbot","EC2","Proxy Reverso","SSL","yq0UJTcqv0N_V1xV8ORBR2S-QOhqi8TqJSr8aauqDXM",1787721650733]