agregue mi cv en un visor pdf, falta agregar el botón de descarga

This commit is contained in:
David Itehua Xalamihua 2025-08-27 17:38:31 -06:00
parent 5dceeb5b70
commit 7d96f55670
7 changed files with 276 additions and 248 deletions

View File

@ -7,6 +7,8 @@ v = {
'me': 'more_info/about_me.html', 'me': 'more_info/about_me.html',
'np': 'new_posts.html', 'np': 'new_posts.html',
'pjs': 'more_info/personal_projects.html', 'pjs': 'more_info/personal_projects.html',
'cv': 'static/source_imgs/cv/CV_David_Itehua_Xalamihua.pdf' 'cv': 'more_info/cv.html'
} }
} }
# 'cv': 'static/source_imgs/cv/CV_David_Itehua_Xalamihua.pdf'

View File

@ -127,8 +127,12 @@ def projects():
@app.route('/more-info/cv') @app.route('/more-info/cv')
def cv(): def cv():
filePath=v['m.i.']['cv'] return render_template(v['m.i.']['cv'])
return send_file(filePath, as_attachment=True)
# @app.route('/more-info/cv')
# def cv():
# filePath=v['m.i.']['cv']
# return send_file(filePath, as_attachment=True)
# solo ayuda dix template # solo ayuda dix template
@app.route('/ayuda-template') @app.route('/ayuda-template')

View File

@ -1,7 +1,9 @@
blinker==1.9.0 blinker==1.9.0
cachelib==0.13.0
click==8.1.8 click==8.1.8
et_xmlfile==2.0.0 et_xmlfile==2.0.0
Flask==3.1.0 Flask==3.1.0
Flask-Caching==2.3.1
itsdangerous==2.2.0 itsdangerous==2.2.0
Jinja2==3.1.5 Jinja2==3.1.5
MarkupSafe==3.0.2 MarkupSafe==3.0.2

View File

@ -1,9 +1,9 @@
<!-- class="code_lightMode" --> <!-- class="code_lightMode" -->
<!-- templates/components/copy-code.html --> <!-- templates/components/copy-code.html -->
<!-- components/copy-code.html --> <!-- components/copy-code.html -->
<pre>{% if btn | default(true) %}<i class="bi bi-copy"> Copiar código</i>{% endif %} <pre>{% if btn | default(true) %}<i class="bi bi-copy"> Copiar código</i>{% endif %}
<code contenteditable="{{ isEditable | default('true') }}">{{ codigo }}</code></pre> <code contenteditable="{{ isEditable | default('true') }}">{{ codigo }}</code></pre>

View File

@ -1,2 +1,2 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

View File

@ -1,236 +1,236 @@
<!-- 38 | haproxy | configuración web --> <!-- 38 | haproxy | configuración web -->
<!-- 38 | haproxy | configuración web --> <!-- 38 | haproxy | configuración web -->
<div id="accordion"> <div id="accordion">
<div class="card"> <div class="card">
<div class="card-header" id="headingTwo"> <div class="card-header" id="headingTwo">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" <button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false"
aria-controls="collapseTwo"> aria-controls="collapseTwo">
Puntos a considerar antes de modificar el archivo de configuración de HAProxy Puntos a considerar antes de modificar el archivo de configuración de HAProxy
</button> </button>
</h5> </h5>
</div> </div>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordion"> <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordion">
<div class="card-body"> <div class="card-body">
<ol> <ol>
<li> <li>
<p> <p>
<strong>Dominio de nuestra página web:</strong> Es el nombre que adquirimos a través de proveedores como <strong>Dominio de nuestra página web:</strong> Es el nombre que adquirimos a través de proveedores como
<i>GoDaddy</i>, <i>Google Domains</i>, <i>Hostinger</i>, entre otros. Este dominio será la dirección que <i>GoDaddy</i>, <i>Google Domains</i>, <i>Hostinger</i>, entre otros. Este dominio será la dirección que
los usuarios utilizarán para acceder a nuestro sitio web. los usuarios utilizarán para acceder a nuestro sitio web.
</p> </p>
</li> </li>
<li> <li>
<p> <p>
<strong>La IP pública:</strong> En muchos casos, la IP pública es dinámica, lo que significa que puede <strong>La IP pública:</strong> En muchos casos, la IP pública es dinámica, lo que significa que puede
cambiar con frecuencia. Esto puede ser un problema, ya que necesitamos una IP estática para garantizar la cambiar con frecuencia. Esto puede ser un problema, ya que necesitamos una IP estática para garantizar la
accesibilidad constante de nuestros servicios. Para solucionar esto, podemos utilizar servicios como <a accesibilidad constante de nuestros servicios. Para solucionar esto, podemos utilizar servicios como <a
href="https://www.duckdns.org/" target="_blank">Duck DNS</a>, que monitorea y actualiza automáticamente href="https://www.duckdns.org/" target="_blank">Duck DNS</a>, que monitorea y actualiza automáticamente
la IP dinámica. Este servicio es especialmente útil para servicios como VPN, hosting web o conexiones SSH la IP dinámica. Este servicio es especialmente útil para servicios como VPN, hosting web o conexiones SSH
(aunque este último no es recomendable por razones de seguridad). (aunque este último no es recomendable por razones de seguridad).
</p> </p>
</li> </li>
<li> <li>
<p> <p>
<strong>Configuración del router del ISP:</strong> En el router proporcionado por tu proveedor de <strong>Configuración del router del ISP:</strong> En el router proporcionado por tu proveedor de
servicios de Internet (ISP), deberás abrir el puerto 80 (para este ejemplo). La configuración varía según servicios de Internet (ISP), deberás abrir el puerto 80 (para este ejemplo). La configuración varía según
el modelo del router, pero generalmente debes buscar la opción de "Port Forwarding" o "Reenvío de el modelo del router, pero generalmente debes buscar la opción de "Port Forwarding" o "Reenvío de
puertos". Allí, deberás agregar una regla que incluya: puertos". Allí, deberás agregar una regla que incluya:
<ul> <ul>
<li>La IP estática del balanceador de carga.</li> <li>La IP estática del balanceador de carga.</li>
<li>El puerto WAN (80 en este caso).</li> <li>El puerto WAN (80 en este caso).</li>
<li>El puerto LAN (también 80).</li> <li>El puerto LAN (también 80).</li>
<li>El protocolo TCP.</li> <li>El protocolo TCP.</li>
</ul> </ul>
Este proceso deberás repetirlo si tienes más de un router en tu red. Este proceso deberás repetirlo si tienes más de un router en tu red.
</p> </p>
</li> </li>
<li> <li>
<p> <p>
<strong>IP's estáticas de los servidores en la red local:</strong> Tanto los servidores web como el <strong>IP's estáticas de los servidores en la red local:</strong> Tanto los servidores web como el
balanceador de carga deben tener direcciones IP estáticas en la red local. Esto asegura que los balanceador de carga deben tener direcciones IP estáticas en la red local. Esto asegura que los
dispositivos siempre estén accesibles y que la configuración de red sea consistente. dispositivos siempre estén accesibles y que la configuración de red sea consistente.
</p> </p>
</li> </li>
<li> <li>
<p> <p>
<strong>SSL:</strong> Adicional a los puntos anteriores, no es obligatorio pero por seguridad debes <strong>SSL:</strong> Adicional a los puntos anteriores, no es obligatorio pero por seguridad debes
considerar usar un servicio SSL ya sea que lo contrates con el proveedor del dominio o con <a considerar usar un servicio SSL ya sea que lo contrates con el proveedor del dominio o con <a
href="https://dash.cloudflare.com/" target="_blank">Cloudflare</a> que tiene una versión gratuita. href="https://dash.cloudflare.com/" target="_blank">Cloudflare</a> que tiene una versión gratuita.
</p> </p>
</li> </li>
</ol> </ol>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<p> <p>
Para este ejemplo consideraremos la siguiente información para la configuración: Para este ejemplo consideraremos la siguiente información para la configuración:
</p> </p>
<ul> <ul>
<li><strong>Dominio:</strong> ejemplo-dom.com</li> <li><strong>Dominio:</strong> ejemplo-dom.com</li>
<li><strong>IP pública:</strong> Dinámica, pero gestionada con Duck DNS (ejemplo: ejemplos.duckdns.org).</li> <li><strong>IP pública:</strong> Dinámica, pero gestionada con Duck DNS (ejemplo: ejemplos.duckdns.org).</li>
<li><strong>Router del ISP:</strong> El puerto 80 está abierto y redirigido a la IP del balanceador de carga.</li> <li><strong>Router del ISP:</strong> El puerto 80 está abierto y redirigido a la IP del balanceador de carga.</li>
<li><strong>Servidores web:</strong> Supongamos que tenemos 4 servidores web y cada uno es un espejo del otro, las <li><strong>Servidores web:</strong> Supongamos que tenemos 4 servidores web y cada uno es un espejo del otro, las
IP´s son 198.162.10.4, 198.162.10.5, 198.162.10.6 y 198.162.10.7</li> IP´s son 198.162.10.4, 198.162.10.5, 198.162.10.6 y 198.162.10.7</li>
</ul> </ul>
<p> <p>
Una vez instalado HAProxy podemos revisar si el servicio está activo con el comando: Una vez instalado HAProxy podemos revisar si el servicio está activo con el comando:
</p> </p>
{% set i %} {% set i %}
systemctl status haproxy systemctl status haproxy
{% endset %} {% endset %}
{% with codigo=i.strip(), isEditable="false" %} {% with codigo=i.strip(), isEditable="false" %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
La salida del comando debe ser algo similar a este: La salida del comando debe ser algo similar a este:
</p> </p>
{% set i %} {% set i %}
● haproxy.service - HAProxy Load Balancer ● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; preset: enabled) Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-03-17 12:12:45 CST; 2 days ago Active: active (running) since Mon 2025-03-17 12:12:45 CST; 2 days ago
Docs: man:haproxy(1) Docs: man:haproxy(1)
file:/usr/share/doc/haproxy/configuration.txt.gz file:/usr/share/doc/haproxy/configuration.txt.gz
Main PID: 2643 (haproxy) Main PID: 2643 (haproxy)
Tasks: 5 (limit: 8742) Tasks: 5 (limit: 8742)
CPU: 5min 30.311s CPU: 5min 30.311s
CGroup: /system.slice/haproxy.service CGroup: /system.slice/haproxy.service
├─2643 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock ├─2643 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
└─2645 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock └─2645 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
{% endset %} {% endset %}
{% with btn=false, codigo=i.strip(), isEditable="false" %} {% with btn=false, codigo=i.strip(), isEditable="false" %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
Como podemos ver, HAProxy está activo, entonces podemos proceder a modificar el archivo de configuración con el editor Como podemos ver, HAProxy está activo, entonces podemos proceder a modificar el archivo de configuración con el editor
de nano y permisos de superusuario: de nano y permisos de superusuario:
</p> </p>
{% set ii %} {% set ii %}
sudo nano /etc/haproxy/haproxy.cfg sudo nano /etc/haproxy/haproxy.cfg
{% endset %} {% endset %}
{% with codigo=ii.strip(), isEditable="false" %} {% with codigo=ii.strip(), isEditable="false" %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
Nos vamos hasta el final del archivo de configuración y añadimos la configuración del "frontend": Nos vamos hasta el final del archivo de configuración y añadimos la configuración del "frontend":
</p> </p>
{% set iii %} {% set iii %}
# frontend nombre_que_quieras # frontend nombre_que_quieras
frontend https_frontend frontend https_frontend
# puerto que manejará el 80 # puerto que manejará el 80
bind *:80 bind *:80
# protocolo a usar # protocolo a usar
mode http mode http
# nombre de nuestro dominio: ejemplo-dom.com # nombre de nuestro dominio: ejemplo-dom.com
# validador ejemplo-dom.com = is_ejemplo_dom_com (colocar el prefijo "is_", además los guiones medios y puntos se cambian a guiones bajos) # validador ejemplo-dom.com = is_ejemplo_dom_com (colocar el prefijo "is_", además los guiones medios y puntos se cambian a guiones bajos)
acl is_ejemplo_dom_com hdr(host) -i ejemplo-dom.com acl is_ejemplo_dom_com hdr(host) -i ejemplo-dom.com
# el nombre del backend puede ser el que tú quieras # el nombre del backend puede ser el que tú quieras
use_backend ejemplo_dom_com if is_ejemplo_dom_com use_backend ejemplo_dom_com if is_ejemplo_dom_com
{% endset %} {% endset %}
{% with codigo=iii.strip() %} {% with codigo=iii.strip() %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
Una vez configurado el frontend, continuamos en el mismo archivo y añadimos el "backend": Una vez configurado el frontend, continuamos en el mismo archivo y añadimos el "backend":
</p> </p>
{% set iv %} {% set iv %}
# backend nombre backend usado en la configuración del frontend # backend nombre backend usado en la configuración del frontend
backend ejemplo_dom_com backend ejemplo_dom_com
# protocolo de balanceo de carga (puedes dejarlo o googlear otros protocolos) # protocolo de balanceo de carga (puedes dejarlo o googlear otros protocolos)
balance roundrobin balance roundrobin
# protocolo para sitios web # protocolo para sitios web
mode http mode http
# enlistar las IPs de los servidores web o coloca la DNS de cada uno de los servidores en caso de usar un servidor DNS. # enlistar las IPs de los servidores web o coloca la DNS de cada uno de los servidores en caso de usar un servidor DNS.
server server1 198.162.10.4:80 check server server1 198.162.10.4:80 check
server server2 198.162.10.5:80 check server server2 198.162.10.5:80 check
server server3 198.162.10.6:80 check server server3 198.162.10.6:80 check
server server4 198.162.10.7:80 check server server4 198.162.10.7:80 check
# server{1-4} puede ser el nombre que tú quieras, solo es una referencia para HAProxy # server{1-4} puede ser el nombre que tú quieras, solo es una referencia para HAProxy
# 198.162.10.X:80 = indica que el servidor con esa IP tiene un servicio web activo en el puerto 80, en caso de no usar el 80 solo reemplaza ese valor # 198.162.10.X:80 = indica que el servidor con esa IP tiene un servicio web activo en el puerto 80, en caso de no usar el 80 solo reemplaza ese valor
# check = valida que el servidor esté operando antes de redirigir el tráfico # check = valida que el servidor esté operando antes de redirigir el tráfico
{% endset %} {% endset %}
{% with codigo=iv.strip() %} {% with codigo=iv.strip() %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
Una vez configurado el frontend y el backend en el archivo de HAProxy, guardamos <b>CTRL + S</b>, cerramos <b>CTRL + Una vez configurado el frontend y el backend en el archivo de HAProxy, guardamos <b>CTRL + S</b>, cerramos <b>CTRL +
X</b>. Para validar que la sintaxis de la configuración sea correcta puedes usar el comando: X</b>. Para validar que la sintaxis de la configuración sea correcta puedes usar el comando:
</p> </p>
{% set v %} {% set v %}
sudo haproxy -c -f /etc/haproxy/haproxy.cfg sudo haproxy -c -f /etc/haproxy/haproxy.cfg
{% endset %} {% endset %}
{% with codigo=v.strip(), isEditable="false" %} {% with codigo=v.strip(), isEditable="false" %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
Si todo está bien en términos de sintaxis, la salida del comando debe ser: <b style="color: green">Configuration file Si todo está bien en términos de sintaxis, la salida del comando debe ser: <b style="color: green">Configuration file
is valid</b> <br> is valid</b> <br>
Procedemos a reiniciar el servicio de HAProxy con el comando: Procedemos a reiniciar el servicio de HAProxy con el comando:
</p> </p>
{% set vi %} {% set vi %}
sudo service haproxy restart sudo service haproxy restart
{% endset %} {% endset %}
{% with codigo=vi.strip(), isEditable="false" %} {% with codigo=vi.strip(), isEditable="false" %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
<p> <p>
Listo, ahora podrás entrar a tu navegador web e ingresar el dominio <b>ejemplo-dom.com</b>. Tu proveedor de dominio Listo, ahora podrás entrar a tu navegador web e ingresar el dominio <b>ejemplo-dom.com</b>. Tu proveedor de dominio
redirigirá a Duck DNS que tiene tu IP y mandará el tráfico a tu router ISP, este a su vez lo mandará a tu balanceador redirigirá a Duck DNS que tiene tu IP y mandará el tráfico a tu router ISP, este a su vez lo mandará a tu balanceador
de carga para finalmente redirigir el tráfico al servidor web de carga para finalmente redirigir el tráfico al servidor web
que esté con menos carga. <br> que esté con menos carga. <br>
De forma práctica y simple, te recomiendo que en cada servidor web, en el HTML del sitio, en la página de inicio De forma práctica y simple, te recomiendo que en cada servidor web, en el HTML del sitio, en la página de inicio
coloques un comentario con el número de servidor, y desde el lado del navegador web refresques la página y veas cómo coloques un comentario con el número de servidor, y desde el lado del navegador web refresques la página y veas cómo
cambia el número del servidor. Esto con la finalidad de saber si el balanceo de carga está funcionando, ejemplo diagrama de flujo: cambia el número del servidor. Esto con la finalidad de saber si el balanceo de carga está funcionando, ejemplo diagrama de flujo:
</p> </p>
{% set vii %} {% set vii %}
[Usuario] [Usuario]
| |
v v
[Dominio ejemplo-dom.com] [Dominio ejemplo-dom.com]
| |
v v
[DuckDNS (resuelve IP dinámica)] [DuckDNS (resuelve IP dinámica)]
| |
v v
[Router ISP (Port Forwarding 80 -> HAProxy)] [Router ISP (Port Forwarding 80 -> HAProxy)]
| |
v v
[HAProxy] [HAProxy]
| |
+--> [Backend ejemplo_dom_com] +--> [Backend ejemplo_dom_com]
| |
+--> [Servidor 1] +--> [Servidor 1]
| |
+--> [Servidor 2] +--> [Servidor 2]
| |
+--> [Servidor 3] +--> [Servidor 3]
| |
+--> [Servidor 4] +--> [Servidor 4]
{% endset %} {% endset %}
{% with btn=false, codigo=vii.strip(), isEditable="false" %} {% with btn=false, codigo=vii.strip(), isEditable="false" %}
{% include 'components/copy-code.html' %} {% include 'components/copy-code.html' %}
{% endwith %} {% endwith %}
{% include 'components/src_collapse.html' %} {% include 'components/src_collapse.html' %}

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<style>
iframe {
width: 90%;
height: 90vh;
}
</style>
<iframe src="https://1drv.ms/b/c/94fb71847d00f5d9/IQTZ9QB9hHH7IICUNaQJAAAAATl7DPlSGna-Ko1PodcD8Wc" frameborder="0" scrolling="no"></iframe>
</body>
</html>