Saturday, August 6, 2022

#UVDVILAS #OnceARoshkerAlwaysARoshkero







Bueno fin de una etapa, fin de una novela, fin de la polémica(al menos de parte mía jajaja), no me queda mas que agradecer a la vida, haber caído en este lugar en un momento que necesite, en un momento complicado, agradezco a tantas personas que siguen estando y que ya no están hoy en día en la organización, ROSHKA me hizo no solo conocer grandes profesionales sino amigos de la vida que nunca me dejaron en una situación complicada, y que se muy bien van a seguir estando hombro a hombro conmigo en lo que se venga, gracias a los directores por recibirme, vine gateando a este lugar y creo que ahora no quiero decir salgo corriendo, capaz caminando aun, viendo a tanta gente capa en un solo lugar, es un lujo de venir gateando ahora salir caminando, aun me falta mucho por crecer, pero acá me dieron las herramientas para la vida profesional y la vida misma, principalmente a Pablo Welti y Alejandro, que fueron los que velaron por mi para entrar, porque Pablo Santa me había dicho que si era por el no me contrataba ajajajajajaja, nooo mentira también gracias Pablo S, por bancar muchas veces mi inutilidad, de ahí a hacer las cosas que no sabia hacer y decir que soy tu jefe, fuiste un gran líder y compañero en todos estos tiempos, gracias también a FranBenz que muchas veces también golpee tu puerta para pedirte ayuda en muchas cosas, esta de mas decir que les considero amigos a ustedes, muchas veces en el día a día terminábamos hablando de cosas no precisamente laborales, gracias por la confianza que me dieron, algo habré hecho bien para ganarme eso.


A la gente de los otros staff como TH y Gerencia, por hacer lo posible para que el día a día laboral sea más ameno y divertido, se sigue creciendo y se nota que cada vez esto va ir mejorando, me hubiese gustado seguir siendo parte del progreso de la cultura ROSHKA.


En lo que respecta a los roshkeros en si, gracias a todos mis amigos de antes y ahora que me bancaron en todo este tiempo, mi buena onda, mi argeleria, mis problemas personales, no voy a dar nombres ustedes saben quienes son, gracias por estar en un momento tan complicado de mi vida organizando de todo para ayudarme, hasta cerrar un boliche recuerdo, de verdad cada pequeño y gran gesto valió muchísimo para mi, espero que tenga tiempo en esta vida para poder recompensarlos todo eso, para los que somos creyentes mi hermano, que también era bienvenido acá siempre, los va guiar desde arriba.


Capaz no conozco a mucha gente hoy en día, desde que entré hubo muchos cambios, pero este mensaje les dejo a todos, los nuevos, los nuevos no tan nuevos y mismo los antiguos, yo gane mucho aca en materia profesional, pero gane más en lo personal, gánense eso, cayeron un lugar impecable para crecer en todo sentido, con líderes y con gente capisima en todos los ámbitos, aprovechen todo y cada día en este lugar, lo que ganas en ROSHKA lo llevas para afuera a donde vayas.



PD: Dejen de malcriarnos mucho, sean más duros y fríos porque después uno ya no quiere salir de acá después jajajaja.


No me quiero ir pero así es la vida..


Tengo muchas mas cosas que decir pero voy a estar hasta mañana, gracias totales ROSHKA QUERIDA #OnceARoshkeroAlwaysARoshkero #BESTPLACETOWORK.


Monday, July 11, 2022

XAIX: La Solución de Roshka para SPI

El SPI (Sistema de Pagos Instantáneos) del Paraguay es una red de pagos instantáneos del Banco Central del Paraguay (en adelante, BCP) que permite a todos los clientes de bancos y financieras reguladas por el ente del estado, hagan transferencias instantáneas, validadas en origen y en destino, con confirmación inmediata, durante las 24 horas de los 7 días de la semana.

 


Desde el año 2004, trabajamos muy de cerca con todo el sector financiero en el desarrollo de sus canales digitales, por lo que nos pareció natural para nuestros clientes actuales, y potenciales nuevos clientes, proponer una solución que permita, con la menor cantidad de cambios posibles, poder integrar los CORES FINANCIEROS de cada uno, con el protocolo propuesto desde el BCP. Así nació la idea de XAIX en Agosto de 2021.

No hubo mucho debate ni análisis sobre el nombre. Tenemos un sistema al que llamamos internamente XAI que sirve para conectar entidades financieras al SIPAP. Como se puede considerar que el SPI es un complemento o extensión del SIPAP, nos hizo sentido que el sistema para conectar entidades financieras al SPI se llame XAIX (XAI - extended).

La mensajería de este protocolo está basada en el estándar ISO-20022 usando como transporte, un intercambio de mensajes firmados digitalmente por los participantes (bancos y financieras) a través de colas manejadas por un REST API (tanto para escritura como para lectura) alojado en el BCP.

Identificamos 5 (cinco) desafíos fundamentales para el proyecto:

1. Conseguir clientes

Necesitábamos por lo menos a 3 clientes que adopten nuestra solución para que el esfuerzo y el compromiso de cumplir con los estrictos plazos del BCP valgan la pena.

Armamos una linda presentación, sin tener aun las especificaciones técnicas del BCP (que a esa altura no existían) y se la hicimos a todos nuestros clientes, así como también a otras entidades financieras tratando de sumar adeptos. En esa presentación poníamos de manifiesto la arquitectura de la solución, el stack tecnológico, los requerimientos para desplegarla, la carga estimada que soportaba, así como también cómo iba a ser el proceso de integración con cada uno de los CORE FINANCIEROS

Nuestra presentación cerraba así, por lo que estábamos muy confiados.



Recién en Diciembre nos confirmó el primer cliente. Grande. Pero solo era uno. Necesitábamos por lo menos dos más. La apuesta ya estaba hecha ya que el desarrollo ya estaba en marcha (no podíamos darnos el lujo de esperar las confirmaciones) y cada día que pasaba crecía la ansiedad. Igual, como lo que nos gusta es hacer Software, nos estábamos divirtiendo bastante con el desarrollo a esa altura, entonces eso hacía pasar un poco el nerviosismo.

En Enero 2022, empezaron a llegar las demás confirmaciones.

Finalmente, de los 3 que queríamos, terminamos aceptando trabajar con 10 (diez) entidades. Así que, cambiamos el nerviosismo de no tener las entidades mínimas necesarias, al nerviosismo de cómo hacer para manejar, en tan poco tiempo tantos procesos de desarrollo, con bases de datos distintas, con CORE FINANCIEROS distintos y con clientes con formas de trabajo bien distintas.

Hay 25 entidades en total que están sumadas al proyecto de SPI del BCP. Diez (40%) optaron por XAIX. Nada mal.



2. Armar el equipo

De las más de 180 personas que trabajan con nosotros, teníamos que conformar un equipo COMANDO que lleve adelante el proyecto, sin desatender los proyectos comprometidos que están en curso.

Parece fácil, pero no es. Los equipos de desarrollo de sistema sufren mucho las rotaciones de personas que tienen, entonces teníamos que elegir bien, sin romper los proyectos en curso.

Terminamos armando un equipo de 10 personas, divididos en tres sub equipos comando.


Equipo XAIX

Encargado de desarrollar el corazón de XAIX, que iba a ser común a las 10 implementaciones que teníamos.

Plugins de Integración

Encargado de interactuar con todos los clientes que iban a desarrollar la parte correspondiente al CORE FINANCIERO, para poder integrarlo al SPI a través de XAIX, desarrollando un microservicio al que llamamos plugin

Despliegue

Encargado de desarrollar y definir con cada cliente la estrategia de despliegue en producción de acuerdo a la infraestructura de cada uno.

3. Diseñar una solución flexible y extensible

Cualquier solución que se tiene que integrar con a CORE FINANCIEROS diferentes, que tienen sistemas gestores de base de datos diferentes, tiene que ser extensible desde la concepción misma de la solución. Esta es la arquitectura de XAIX.



Tiene cuatro microservicios fundamentales:

XAIX SPIConnect

Se encarga de toda la comunicación con BCP, incluyendo la mensajería ISO-20022, y la firma digital criptográfica de los mensajes salientes y su correspondiente validación en los mensajes entrantes.




XAIX API

Se encarga de orquestar a todos los componentes, así como también de ser la única interfaz de entrada para darle instrucciones al XAIX a través de un API REST.




XAIX Plugin

Se encarga de comunicad de manera estandarizada a XAIX con los CORE FINANCIEROS de cada una de las 10 implementaciones. Estas son todas las alternativas que podíamos implementar en cada uno de los plugins para poder integrarnos a las soluciones de CORE FINANCIERO de los clientes.





XAIX WEB Admin

Administrador WEB para MONITOREO del estado general del sistema, así como también con las interfaces de usuario de administración para todo lo que tenga que ver con gestiones que se hacen en el BCP, así como también mantenimiento y configuraciones del XAIX. Los datos presentados en la captura de pantalla son ficticios, obviamente.


Para apreciar lo extensible y flexible de la solución, esto era lo que soportamos a nivel de tecnologías de bases de datos relacionales, en memoria y de tiempo (para estadísticas y monitoreo):


Y esto es lo que soportamos a nivel de despliegue:



Finalmente:

* De nuestras diez implementaciones 4 eligieron Oracle, 3 Microsoft SQL Server y 3 PostgreSQL.
* De nuestras diez implementaciones 3 desplegaron en un CLUSTER de K8S, 6 desplegaron en contenedores DOCKER usando Linux, y 1 desplegó usando un Servidor de Aplicaciones convencional.
* 4 usan nuestros APIs REST de manera síncrona y 6 usan nuestros APIs REST de manera asíncrona.

Todo usando exactamente la mismísima solución, donde lo único específico de cada implementación es el microservicio que contiene al PLUGIN de conexión.

Hablame de flexibilidad...

4. Diseñar una solución robusta y escalable

Esto era clave desde el día cero. El crecimiento de SIPAP, sobre todo en pandemia fue exponencial. Los números están a la vista la WEB del BCP. Por las características de los pagos, se calcula que el SPI va a manejar más del 90% de los pagos electrónicos bancarios del Paraguay en el modelo 365/7/24 (todos los días del año, sin concepto de días hábiles, 7 días a la semana durante 24 horas cada día). Por lo tanto, SPI tiene que ser escalable y, sobre todo, robusto.

Para esto, solo dependemos de un componente estratégico para administrar la comunicación interna de los microservicios que es la base de datos de alta performance en memoria REDIS. El sistema puede funcionar temporalmente sin base de datos de tiempo y sin base de datos relacional, pero no sin REDIS. Esta base de datos se puede instalar en un CLUSTER redundante para tener failover en caso de algún mal funcionamiento temporal de la misma.

Cada microservicio de XAIX: XAIX API, XAIX SPI Connect, XAIX Plugin, XAIX Admin, puede escalar horizontalmente agregando más nodos (contenedores, servidores) de cada tipo de manera transparente para toda la solución.

5. Cumplir con los demandantes plazos del BCP

El BCP puso plazos muy justos para toda la implementación. La primera gran prueba empezó en un proceso que denominaron CERTFICACIÓN el Lunes 23 de Mayo y se extendió por casi 3 semanas. De nuestras 10 implementaciones, las 10 pasaron con éxito el proceso.



Y finalmente y más importante, si bien hoy 11 de Julio de 2022 es el lanzamiento al público oficial del sistema en modalidad 24/7, el sistema ya estaba funcionando sin inconvenientes en esa modalidad desde el 4 de Julio de 2022 con nuestras 10 implementaciones diciendo presente desde el primer día en este hito histórico del desarrollo tecnológico financiero del Paraguay.

Concluyendo

El SPI presenta un gran servicio para todos los paraguayos que vamos a poder hacer transferencias a toda hora. También una gran oportunidad para todos los comercios que probablemente van a empezar a adoptar con más formalidad y más fuerza este medio de cobros gratuito para sus clientes. Así mismo, una gran oportunidad para todo el ecosistema FINTECH del Paraguay que va a poder desarrollar nuevos productos y servicios que mejoren las experiencias de productos existentes.

Agradecemos públicamente a nuestros clientes por la confianza de siempre depositada y en Roshka estamos felices de ser parte de esta revolución. Por la envergadura de nuestros clientes que nos eligieron para sus implementaciones, sabemos que más de la mitad de todos los pagos instantáneos del Paraguay van a pasar por tecnología nuestra. Porque La Vanguardia, es así.




Friday, December 31, 2021

NGINX was not responding after restart

TL;DR: NGINX was not launching correctly. Since no logs were being written by the process, had to use strace to debug what was going on.

There was a weird thing going on with one of our NGINX servers. The sequence of events was like this:

1. Our server rebooted (after many, many months of uptime). 

2. After reboot, NGINX was running but not responding to requests

Even if I curled localhost like this, nothing happened:

root@amy:/tmp# curl -v http://localhost
* Rebuilt URL to: http://localhost/
* Hostname was NOT found in DNS cache
*   Trying ::1...
* Connected to localhost (::1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost
> Accept: */*

Curl was stacked at that part.

3. Checked error and access logs. Nothing was being written in logs after reboot

That was weird...

4. Did a ps to check if process was running at all. And it was. But realized that no NGINX workers were spawned after launch. How come?

This is what the output looked like:

* Connection #0 to host localhost left intact
root@amy:/tmp# ps aux | grep nginx
root       880  0.0  0.1  43424  5968 ?        Ss   08:40   0:00 nginx: master process /usr/local/nginx/sbin/nginx -g daemon on; master_process on;
root@amy:/tmp# 

5. Looked at journalctl's output to see if anything was going on with the service.

This was all I had:

Dec 31 08:40:11 amy systemd[1]: Stopping A high performance web server and a reverse proxy server...
Dec 31 08:40:11 amy systemd[1]: Stopped A high performance web server and a reverse proxy server.
Dec 31 08:40:15 amy systemd[1]: Starting A high performance web server and a reverse proxy server...
Dec 31 08:40:15 amy systemd[1]: Started A high performance web server and a reverse proxy server.

Nothing else.

6. So I had to resort to heavy machinery: strace

Launched strace attaching it to NGINX's using its PID.

# strace -p 513 -s 10000 -v -f

On a different terminal reloaded NGINX

# systemctl reload nginx

Then strace's output gave me the reason no workers were being spawned.

[pid   844] prctl(PR_SET_DUMPABLE, 1)   = 0
[pid   844] chdir("/tmp/cores")         = -1 ENOENT (No such file or directory)
[pid   844] write(16, "2021/12/31 08:38:08 [alert] 844#0: chdir(\"/tmp/cores\") failed (2: No such file or directory)\n", 93) = 93
[pid   846] fstat(20,  <unfinished ...>
[pid   844] exit_group(2)               = ?
[pid   844] +++ exited with 2 +++

7. Turned out I directory I configured a long time ago to evaluate a SIGSEGV I was having, was deleted on reboot so workers were failing to spawn. After that, created the directory again and NGINX was responding to my requests once again.

====

End of (sad) story. Half an hour I will never get back. 

Happy New Year!



Thursday, October 7, 2021

Librería de código abierto para comunicación con SIFEN

 En el marco de la implementación de SIFEN (Sistema Integrado de Facturación Electrónica), nos juntamos con la empresa TAXit! para liberar como código abierto, una librería en Java (Java 8 en adelante) que facilite la comunicación de los sistemas con la SET.

La librería, fundamentalmente ahorra tiempo en:

* Entender cómo hacer funcionar un cliente HTTP con Client Certificate Authentication para hacer peticiones al sistema de SIFEN

* Entender cómo usar estándares para FIRMA ELECTRÓNICA en documentos XML

* Poder poner información de las facturas en el formato que pide el sistema SIFEN.

Una de las cosas que buscamos con el proyecto es no depender de otras librerías para llevar adelante la tarea, de tal forma a que el footprint de lo que se agregue a un proyecto que la utiliza, no sufra demasiado incremento.

Todo el código está publicado en un repositorio en GitHub, y también, para mayor comodidad, se puede usar MavenCentral para incluir automáticamente las dependencias en proyectos que usan Maven o Gradle para administrarlas. Las colaboraciones son bienvenidas para proveer de más funcionalidades a la librería.

Además, estuvimos en un conversatorio con la gente encargada del proyecto en Tributaciones, para comentar un poco al respecto. Acá la entrevista:




Tuesday, July 20, 2021

¡8 años en Roshka!

El desafío del primer trabajo.

Tenés entusiasmo, ganas de aprender y cierta inteligencia, pero, ¿cómo plasmar eso en una hoja de vida? Aún escribiéndolo, no podés plasmar ninguna garantía. Entonces, ¿qué se necesita? Para mí la respuesta fue: una oportunidad.

Desde aquel día de la entrevista, hasta hoy, 8 años después, la oportunidad es una constante en Roshka, la oportunidad de demostrar lo que puedo hacer, la oportunidad de aprender y la oportunidad de crecer, tanto profesional como personalmente.


Un entorno impecable.


En cada equipo de la empresa en el que pude participar, tuve la misma sensación, estar rodeado de un equipo que en diferentes formas siempre me daba no sólo la oportunidad, sino también el empuje para seguir mejorando, seguir buscando más y aprender día a día algo nuevo. Es un entorno de personas que no sólo tienen un conocimiento espectacular, sino que además no tienen problema alguno en compartirlo contigo, definitivamente todo lo que aprendí se debe que siempre estuve rodeado de un equipo humano impecable. 

Tomar desafíos.

Empezar en desarrollo web front end, backend, luego desarrollo mobile, todas fueron en su momento ideas desafiantes. Creo que lo que me empujó a tomar estos desafíos fueron algunas ideas que siempre están presentes en Roshka: Mejorar constantemente, dar siempre lo mejor, tener confianza y trabajar en equipo.


Siempre se puede aprender más.


Mirando atrás de nuevo, puedo decir que mi camino en Roshka fue siempre un camino de subida, de crecimiento. En este camino, algo que me aprendí bien, es que ¡siempre se puede aprender más!

¡Salud Roshka! Y gracias por la oportunidad y el empuje desde aquel 1 de Julio del 2013 para crecer hasta lo que soy hoy día
.


Thursday, February 11, 2021

Install PGBADGER on a remote server

 PGBADGER is an awesome tool: A fast, PostgreSQL log analysis report.

It works by analyzing PostgreSQL logs, and generating HTML reports that will give you a lot of information on query performance, locking queries, errors, connections, vacuums and pretty much everything you need to analyze a PostgreSQL server.

A (very) simplified PGBADGER installation goes something like this:

Simplified PGBADGER setup

I've seen PGBADGER installations update log analysis daily, hourly, every ten minutes, etc. I usually like to keep my log analyzer as updated as possible.

On small PostgreSQL installations, PGBADGER usually runs on the very same server the PostgreSQL is installed on. This is fine for most use cases.

However, if the PostgreSQL is a busy server (high load) this is not recommended. PGBADGER script, when dealing with huge log files, can be very demanding as expected. So, what I like in those cases is either:

a) Run just once a day, at times when the server is mostly idle (after midnight). This is not always possible, specially if PostgreSQL is serving an application that is run in different timezones.

b) Or, just send the logs periodically to a different server and do the log analysis there (my preferred way).

The installation will be something like this:

So, here is what I usually do (YMMV):

1. Configure PostgreSQL in SERVER A so it will write LOGs that PGBADGER will be able to process. In this example, I am going to rotate and ship PostgreSQL every ten minutes.

2. Install PGBADGER in SERVER B

Make sure there is enough storage to hold PostgreSQL history for at least 36 months. It is usually a good idea to keep history to reflect some possible software or application load changes over time. It saved the day for me more than you would think.

In my case (a mostly DEBIAN/APT based distribution guy) it is just:

# apt install pgbadger
These are the parameters I change in postgresql.conf file:
logging_collector = on
log_directory = '/var/log/postgresql'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 10min
log_min_duration_statement = 0
log_checkpoints = on
log_connections = on
log_disconnections = on
log_duration = on
log_line_prefix = '%t [%p]: user=%u,db=%d,app=%a,client=%h '
log_lock_waits = on
log_autovacuum_min_duration = 0

3. Configure ssh-key based authentication for ssh access from SERVER A to SERVER B

This is important: you don't have to, but it will make it easier for you if you use postgres user in SERVER A to do this because it already have access to the log files.

These are the steps you need:

3.1 SERVER A - Create a ssh-key for the postgres user.

This will create two files. If you use the default values on a debian based system, the will be:
/var/lib/postgresql/.ssh/id_rsa
/var/lib/postgresql/.ssh/id_rsa.pub
3.2 SERVER B - Create the user that will own the log files and run the PGBADGER commands

Since the analyzed files reports will be HTML files, it will become very handy if this user has access to a directory that can be exposed through a WebServer (Apache, NGINX, IIS, or any other you use).

In this user's home, if it does not already exist, create this file:
/home/username/.ssh/authorized_keys
Two important things here:

a) /home/username is just an example here. Make sure you use the home directory for the created user.
b) this file, and the directory containing it MUST REVOKE ANY TYPE OF ACCESS to GROUP and OTHERs so make sure permissions are correct for it.

If you need to, change file permissions like this:

chmod 600 ~/.ssh/authorized_keys
In this created or existing file, append the contents of file id_rsa.pub that was created in step 3.1.

3.3 SERVER A -  Check that you can login on SERVER B without using password.

This is easy. Logged in as the postgres user make sure you can ssh access ERVER B without typing a password.

SERVER A> $ ssh username@SERVERB
SERVER B> $ echo I am in in SERVER B and I did not type a password to login
4. SERVER B - Create a script to run PGBADGER remotely

File name should be: /home/username/bin/run-pgbadger.sh

#!/bin/bash

LOGS_DIR=/home/username/pgbadger/tmp_files
PGBADGER_HTML_DIR=/var/www/html/pgbadger/
NJOBS=10

echo "Unzipping log files"
gunzip -v $LOGS_DIR/*.log.gz
echo "Processing pgbadger with $NJOBS jobs"
pgbadger -j $NJOBS -I --outdir $PGBADGER_HTML_DIR $LOGS_DIR/*.log
echo "Removing log files"
rm -v $LOGS_DIR/*.log
echo "DONE"

And make sure it has EXECUTION permissions.

$ chmod 750 /home/user/bin/run-pgbadger.sh

Important script variables:

a) LOGS_DIR: where log files are going to be temporarily stored when shipped from SERVER A
b) PGBADGER_HTML: where analysis result with be incrementally calculated and stored. It will be useful if this directory is accesible through a WEB SERVER. Example: http://server-b/pgbadger
c) NJOBS: how many jobs will process the analyzed files in parallel. 

5. SERVER A - Create a log shipping script to run on SERVER A every 10 minutes

File name should be: /var/lib/postgresql/bin/ship-logs-to-pgbadger.sh

#!/bin/bash
LOGS_DIR=/var/log/postgresql
REMOTE_DIR=/home/username/pgbadger/tmp_files
REMOTE_PROCESS=/home/username/bin/run-pgbadger.sh
SERVER_B=username@SERVERB

echo "Compressing files"
find $LOGS_DIR -cmin +1 -exec gzip -v {} \;
echo "Sending files and removing them afterwards"
rsync --remove-source-files -av $LOGS_DIR/*.log.gz $SERVER_B:$REMOTE_DIR
echo "Executing remotely PGBADGER"
ssh $SERVER_B "$REMOTE_PROCESS"
echo "Done"
Important script variables:

a) LOGS_DIR: where PostgreSQL's log files are stored
b) REMOTE_DIR: this is SERVER B's directory that will have the log files temporarily (MUST match what you've configured in step 4).
c) REMOTE_PROCESS: this is SERVER B's script that will be executed after log files ship (MUST match what you've configured in step 4).
d) SERVER_B: username and server address to access remotely (MUST match what you've configured in step 3).

6. SERVER A - Manually run script from step 5 to see if everything is working

/var/lib/postgresql/bin/ship-logs-to-pgbadger.sh

After running, if everything is OK (it might take a while the first time) you can point your browser to:

http://server-b/pgbadger

And PGBADGER reports should be good to go.





7. SERVER A - Configure a cron task to execute the script every 10 minutes and run PGBADGER analysis tool 

*/10 * * * * /var/lib/postgresql/bin/ship-logs-to-pgbadger.sh


That is all. Enjoy!

Thursday, November 22, 2018

Using Apache 2.4 Reverse Proxy to some (but not all) Tomcat/JavaEE Applications

Usually if you have a couple of Tomcat WAR's (Java WEB applications) deployed on a Tomcat Servlet Container, you a couple of options when exposing those applications through an Apache (or NGINX) http server.

Server Setup is laid out in the following pic:

Server Layout


For the sake of this discussion, let's assume we have these WAR applications deployed in Tomcat server (besides ROOT and manager default applications):

* users.war     -> tomcat context /users
* webapp.war    -> tomcat context /webapp
* discovery.war -> tomcat context /discovery
* bingo.war     -> tomcat context /bingo
* clubs.war     -> tomcat context /clubs
  

Option 1)

Just do a full reverse proxy from the Apache Server to the Tomcat Server (you could either use AJP or HTTP connectors for that purpose).

Apache Configuration will be something like this:

    <Location /tomcat/>
        ProxyPass ajp://192.168.0.2:8080/
        ProxyPassReverse https://example.com/tomcat/
    </Location>

This is very easy to use and setup. It just takes to add these lines to a virtual host and done!

You could access the tomcat Applications to the following URLs:

* http://example.com/tomcat/users
http://example.com/tomcat/webapp
http://example.com/tomcat/discovery
http://example.com/tomcat/bingo
http://example.com/tomcat/clubs

The problem with this approach is:

a. You have access to ALL APPLICATIONS (even if you don't want to)
b. You have access to default applications (if they're not removed) such as Tomcat's ROOT and Manager.

Option 2)

Do one reverse proxy location for each application you want to expose. Let's say you want to expose `users`, `webapp` and `clubs`. Your configuration will be something like this:

    <Location /tomcat/users/>
        ProxyPass ajp://192.168.0.2:8080/users/
        ProxyPassReverse https://example.com/tomcat/users/
    </Location>
    <Location /tomcat/webapp/>
        ProxyPass ajp://192.168.0.2:8080/webapps/
        ProxyPassReverse https://example.com/tomcat/webapp/
    </Location>
    <Location /tomcat/clubs/>
        ProxyPass ajp://192.168.0.2:8080/clubs/
        ProxyPassReverse https://example.com/tomcat/clubs/
    </Location>

The problem with this approach is obvious:

a. If you deployed 25 WARs in your tomcat and want to expose 18 of them, your Apache configuration will grow, and will become harder to maintain.
b. COPY+PASTE error might occur more frequently when adding new applications
c. If your Location sections contains more configuration options (RequestHeader directives, Require, Auth Type) then your COPY+PASTE gets bigger every time, and if you need to change/add something, you will need to do it in every single configuration you have done before.


Option 3)

My favorite option nowadays.

If you want the three same applications exposed, you can use LocationMatch and ProxyPassMatch directives to get the best of both previous options:

    <LocationMatch "^/tomcat/(?<apiurl>(users|webapp|clubs)/.*)">
        ProxyPassMatch ajp://192.168.0.2:8009/$1
    </LocationMatch>

You use a regular expression to filter what domains will go through to tomcat server, and you keep it only in one configuration.