Tu propio StackOverflow con Apache Answer.

Answer te permite montar tu propia plataforma de preguntas y respuestas en tu servidor. Aprende con nosotros a alojarlo en casa o en la oficina con Podman.

Tu propio StackOverflow con Apache Answer.
💡
En la imagen del artículo aparece MariaDB. Pero no documenté los pasos en este tutorial. Solamente SQLite3 y PostgreSQL están disponibles en este artículo. Replicar los pasos de PostgreSQL para MySQL/MariaDB debería ser intuitivo.

Llevo eones prometiendo el artículo del servidor multimedia. Parece que subestimé la cantidad de información que uno da por sentada al momento de escribir un artículo en un blog.

Para no dejar este lugar muerto por meses como las veces anteriores, me decidí a sacar este mini-tutorial para ustedes de como desplegar Apache Answer en su servidor local o del trabajo.

Answer es una plataforma o herramienta de búsqueda y procesamiento de preguntas (y sus respuestas) para equipos pequeños de desarrollo o de TI. Como Answer se enfoca en la privacidad y seguridad, es ideal para implementaciones en servidores de nicho o en entornos empresariales donde las políticas de privacidad son más estrictas o donde no deseas compartir los detalles de tu infraestructura con el mundo.

Para no perder la práctica en Podman, te traigo este artículo. Trataré de incluir variaciones en el despliegue con podman y esta vez no limitaré el contenido 😄. Recursos gratis para todos.

¿Para qué querría esto? 🤔

VixDev on X: "@MarcoJurez19 Chido pero... Y eso en que afecta a ultralord  https://t.co/pzRr6pcWsa" / X

Existen distintas razones por las cuales querrías tener una instancia de Answer a tu disposición:

  • Si lideras o formas parte de una pequeña comunidad de desarrolladores: Answer es perfecto para comunidades pequeñas de varios desarrolladores que necesiten compartir conocimientos técnicos muy específicos. Por ejemplo, detalles o dudas de infraestructura, despliegues, prácticas de código. Etc.
  • Soporte técnico interno: Las empresas pueden implementar Answer para que los empleados compartan soluciones y respondan preguntas internas.
  • Educación y formación: Las instituciones educativas pueden utilizar Answer como una herramienta de colaboración para estudiantes y profesores.

¿Por qué no una wiki u otra forma de documentación interna? 🤓

Esta elección en tu entorno dependerá de varios factores. Una wiki interna puede ayudarte a documentar de forma extensiva procesos, infraestructura y detalles extensos de tu entorno, sin embargo, la información se presenta de forma general y podría no cubrir casos de desarrollo nuevos, preguntas de uso o la implementación completa.

Answer te será útil si buscas:

  • Interacción activa
    • El formato de preguntas y respuestas permite interacción activa entre usuarios. Con dichas preguntas y respuestas teniendo una respuesta más inmediata y más “al grano”. A diferencia de una Wiki, donde sería necesario estructurar la información para que sea más accesible.
  • Enfoque en problemas específicos
    • Answer se centra en resolver problemas específicos y proporcionar soluciones concretas.
    • Una wiki interna puede ser más general y no siempre abordar los problemas específicos que enfrentan los usuarios.
  • Privacidad y seguridad
    • Answer se preocupa por la privacidad y la seguridad de los datos. No rastrea ni comparte información personal.
    • En una wiki interna, la seguridad y la privacidad pueden ser más difíciles de garantizar. Especialmente si se trata de un SaaS/PaaS o de algún software antiguo que no recibe actualizaciones frecuentes.
  • Facilidad de uso
    • Sabes usar StackOverflow, sabes usar Answer.
    • Una wiki interna puede requerir más tiempo para navegar y encontrar la información deseada.

Usarlo o no dependerá de tu criterio y tus necesidades.

Requerimientos 🧑‍🏫

Para seguir este tutorial asumiré que cumples con los siguientes requisitos:

Un VPS o un servidor donde desplegar Answer 💻

Como alternativa, también podrías usar algún PaaS como Fly.io o alojarlo en tu computadora.

Podman 🦭

Puedes usar Docker y Docker Compose. Pero en este blog solo usamos Podman 😄

Opcional: Una base de datos PostgreSQL 🐘

Necesitarás de una base de datos adicional en caso de que desees desplegar de forma distinta Answer. Si no la tienes, no te preocupes. Aquí aprenderás como levantar Answer con PostgreSQL.

Un usuario sin privilegios en Gnu/Linux para el despliegue 🤖

Si pretendes usar este contenedor de forma rootless. Deberás crear un usuario para el mismo, te recomiendo algo como adduser answer o adduser localoverflow para tu servidor. No te olvides de configurar los permisos de los directorios que necesitarás montar como volúmenes.

Conocimientos básicos de SQL 🧠

No soy experto en bases de datos. Aun así, asumiré que ya has desplegado una BD en el pasado y conoces suficiente de consultas SQL para crear una mísera base de datos.

Despliegue con Podman 🦭

Antes de desplegar nada utilizando Podman debemos preparar nuestro entorno de despliegue. Para esto vamos a descargar las imágenes necesarias y configurar los directorios correspondientes.

Descargar imagenes de Podman/Docker ⬇️

Revisa en Docker Hub primero las versiones disponibles de las bases de datos en cuestión. Este tutorial podría estar desactualizado luego de publicarse.

Si ya tienes Docker Hub configurado como registro en podman simplemente puedes ejecutar la siguiente orden:

podman pull postgres:alpine apache/answer:latest

En la terminal del servidor donde planeas desplegar Answer.

En caso de que no tengas (y no quieras configurar Docker Hub) como registro en Podman, puedes escribir el “nombre completo” de la imagen, es decir, incluyendo el registro:

podman pull docker.io/postgres:alpine docker.io/apache/answer:latest

En la terminal del servidor donde planeas desplegar Answer

  • Para descargar Answer solamente (SQLite): podman pull docker.io/apache/answer:latest
  • Para descargar PostgreSQL en su última versión en Alpine Linux: podman pull docker.io/postgres:alpine
    • Si deseas utilizar PostgreSQL con Debian en su lugar puedes ejecutar: podman pull docker.io/postgres:bookworm
¿Puedes hacer algo que me ahorre esos pasos?
Pin de HELL BB en MM | Imágenes divertidas, Imágenes graciosas, Imagenes  para reirse
jsjsjs

No, mentira 😆. Aquí hay un pequeño script que hice tratando de ahorrarme los pasos de este tutorial, esto que diré se pasa todo el propósito de podman por el arco del triunfo, pero en mi máquina funciona. Puedes utilizar este script como guía o como “instalador” no oficial de las imagenes.

Para comprobar que descargaste las imagenes correctas, puedes ejecutar podman images si seguiste bien los pasos o todo te salió bien, deberías ver una salida en tu terminal similar a esta:

$ podman images

REPOSITORY                  TAG         IMAGE ID      CREATED       SIZE
docker.io/apache/answer     latest      44b4219f13fa  9 days ago    115 MB
docker.io/library/postgres  alpine      9a510ccf1de4  2 months ago  246 MB

Las versiones podrían cambiar en el futuro

Si estás usando Podman Desktop, en la pestaña de “images” podrás ver tus imagenes descargadas:

Las versiones podrían cambiar en el futuro

Crear directorios de datos 📁

Ahora, necesitarás crear los directorios donde se almacenen los datos. Lamentablemente, mi flojera no me dio para hacer un script separado o incluirlo en el script original. Además de que no sé en qué directorio del sistema de archivos deseas hacer esto. En mi caso trabajaré sobre /home/localoverflow, pero tú puedes utilizar el directorio que más te guste.

Para Answer 💭

Answer solo requiere de un directorio para almacenar la información. Este directorio en la imagen es /data, aquí te presento algunas rutas que podrías utilizar, asegúrate de que tienes permisos de lectura y escritura en el directorio que vayas a elegir:

  • /opt/answer/data
  • /home/localoverflow/answer/data
  • /home/localoverflow/.answer/data
  • /home/localoverflow/.local/share/answer/answer-data

Realmente puedes utilizar tu directorio favorito.

Para PostgreSQL 🐘

PostgreSQL maneja un caso similar, solo que, en esta ocasión, el directorio dentro de la imagen es /var/lib/postgresql/data. Espero no tener que repetir lo mismo una tercera vez:

  • /opt/answer/postgres/data
  • /home/localoverflow/answer/postgres/data
  • /home/localoverflow/.answer/postgres/data
  • /home/localoverflow/.local/share/postgres/data

💡
Para los tres casos usaré la tercera estructura de directorios: /home/localoverflow/.answer. Ajusta los pods y los comandos a los directorios que deseas usar.

Desplegar con contenedor standalone + SQLite3 👨‍💻

El despliegue standalone es el más sencillo de todos, solo debemos montar el directorio de datos para Answer que creamos anteriormente desde el comando de podman.

Vamos a ejecutar nuestro despliegue standalone con el siguiente comando:

podman run -d \
-p 9080:80 \
-v /home/localoverflow/.answer/data:/data \
--name="answer-standalone" \
--restart=always \
--label io.containers.autoupdate=registry docker.io/apache/answer:latest 

En la terminal de tu servidor

Si tu contenedor se creó correctamente, verás en la salida de la consola el identificador del contenedor:

podman run -d \
-p 9080:80 \
-v /home/localoverflow/.answer/data:/data \
--name="answer-standalone" \
--restart=always \
--label io.containers.autoupdate=registry docker.io/apache/answer:latest 

0ff0903ded67cf0711f5f0ce71bdb2f044d6605919c6c22fcc5bb96f0b1a51f7

Puedes comprobar que tu contenedor se está ejecutando con el comando podman ps:

podman ps

CONTAINER ID  IMAGE                           COMMAND     CREATED        STATUS        PORTS                 NAMES
0ff0903ded67  docker.io/apache/answer:latest              2 minutes ago  Up 2 minutes  0.0.0.0:9080->80/tcp  answer-standalone

Si estás usando Podman Desktop podrás ver tu contenedor en ejecución en la pestaña “containers”:

Answer standalone ejecutandose en Podman Desktop

Vamos a ingresar a la dirección que le colocamos a Answer para configurarlo

  1. Ingresa a localhost:9080, 127.0.0.1:9080 o al 0.0.0.0:9080. Si ves la siguiente pantalla en tu navegador, felicidades, lo lograste:
Configuración de Answer
  1. Selecciona el idioma que más te guste o el que prefieras. El número que indica la lista es el porcentaje de texto traducido a ese idioma presente en Answer.
  2. Selecciona en la lista de bases de datos la opción SQLite y deja la opción Database file con su valor por defecto:
Usar SQLite como base de datos de Answer
  1. Si todo salió bien, el instalador te reportará que pudo crear el archivo config.yaml de manera satisfactoria:
Archivo config.yaml creado correctamente.
  1. Configura los detalles de tu instancia de Answer:

Las opciones que te presentará Answer son las siguientes:

  • Site Name: El título del sitio que se mostrará en el navegador.
  • Site URL: La URL del sitio. Si vas a desplegar esto bajo un dominio
  • Contact email: La dirección de correo electrónico de contacto en caso de que tus usuarios necesiten asistencia técnica con el sitio.
  • Private: Si los visitantes del sitio necesitan estar registrados para explorar las preguntas y respuestas del mismo.
  • Admin Account
    • Name: Username del administrador
    • Password: Contraseña del administrador (Te recomiendo generarla con un gestor de contraseñas como KeePassXC o Bitwarden)
    • Email: Correo electrónico para iniciar sesión con la cuenta de administrador.
  1. Si configuraste correctamente tu instancia de Answer podrás ver la siguiente pantalla:

Cuando presiones el botón azul con el texto “Done” serás redirigido al sitio de Login:

Ingresa con las credenciales que acabas de configurar. Y listo. Disfruta de tu nueva instancia de Answer.

Desplegar con contenedor standalone + PostgreSQL 🦭🐘

🦭
La información proporcionada aquí deja las contraseñas expuestas en la línea de comandos. Si deseas guardar la contraseña de la base de datos de forma segura, te sugiero que hagas uso de podman secrets.

Los pasos para desplegar Answer junto con PostgreSQL en contenedores son muy similares. La creación del contenedor de Answer es exactamente igual:

podman run -d \
-p 9080:80 \
-v /home/localoverflow/.answer/data:/data \
--name="answer-pgsql" \
--restart=always \
--label io.containers.autoupdate=registry docker.io/apache/answer:latest 

Recuerda que la salida del comando debería ser el ID del contenedor

Toca levantar el contenedor de PostgreSQL, si ya tienes la imagen de Podman descargada, puedes ejecutar el siguiente comando:

podman run -d \
--name="pgsql-db" \
-p 5432:5432 \
-e POSTGRES_USER=laesquinagris \
-e POSTGRES_PASSWORD=supersecurepassword \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v /home/localoverflow/.answer/postgres/data:/var/lib/postgresql/data postgres:alpine

Recuerda que la salida del comando debería ser el ID del contenedor

🐘
Puedes personalizar y mejorar tu despliegue de PostgreSQL siguiendo la documentación oficial de la imagen en DockerHub.
Probar la conexión a la base de datos 📚

Puedes revisar si tu contenedor está vivo usando el comando podman ps, revisar en podman desktop o si tienes un cliente gráfico de bases de datos puedes utilizarlo para revisar la conexión a la misma.

Si deseas cambiar el nombre de la base de datos creada por defecto, añade la variable de entorno POSTGRES_DB. De no hacerlo el valor de POSTGRES_USER será utilizado para esa base de datos.
Probando la conexión a la BD en Beekeeper Studio

Una vez comprobada la conexión a nuesta base de datos, es momento de configurar Answer. Los pasos de configuración son exactamente iguales, con la diferencia en la configuración de la BD. Omitiré la serie de pasos antes y después de la BD.

En mi caso hice una nueva base de datos para el despliegue con el nombre answer:

SELECT 'CREATE DATABASE answer'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'answer')\gexec
Yo mismo no soy experto en SQL (o en bases de datos en general). Toma los consejos que te dé referente a este tema con un granito de sal.
  • En la sección de configuración de base de datos, deberás colocar los detalles de la DB PGSQL que acabas de crear en podman:

En mi caso quedó así:

💡
Puse la dirección IP del host y no usé algo como localhost porque estoy idiota para las redes y olvidé que podía usar la IP de Docker.

Si tu conexión a la BD es correcta, el resto de pantallas será el mismo:

No hay más pasos que modificar de aquí en adelante, es un despropósito repetir las instrucciones si no cambia algo en el proceso.

Despliegue con Podman en un Pod 🦭📦

En caso de que necesites orquestar tus contenedores de Answer y su respectiva base de datos o que, en un futuro, necesites migrarlo a Kubernetes, podemos desplegarlo directamente en un pod.

Antes de usar cualquiera de las variaciones presentadas aquí, deberás crear un pod primero:

  • Comando para Pod de Answer Standalone: podman pod create --name AnswerStandalone -p 9080:80
  • Comando para Pod de Answer + PostgreSQL: podman pod create --name AnswerPostgres -p 5432:5432 -p 9080:80

Para revisar tu configuración de Pods o que se hayan creado correctamente puedes ejecutar el comando podman pod ps:

podman pod ps
POD ID        NAME              STATUS      CREATED        INFRA ID      # OF CONTAINERS
f5fbb64a5164  AnswerStandalone  Created     2 minutes ago  d0f8e296d69f  1

Si estás usando Podman Desktop puedes verlo en esta pestaña:

Pods en ejecución dentro de Podman

Pod Standalone 🧑‍🔧

Los pasos son similares al despliegue con podman standalone, solo que, ahora, la orden de creación del contenedor no necesita que le digamos qué puertos exponer:

podman run -d \
--pod AnswerStandalone \
-v /home/localoverflow/.answer/data:/data \
--name="answer-standalone" \
--restart=always \
--label io.containers.autoupdate=registry docker.io/apache/answer:latest

Podemos ver si nuestro contenedor se agregó correctamente con el comando podman pod stats AnswerStandalone:

POD           CID           NAME                CPU %       MEM USAGE/ LIMIT   MEM %       NET IO       BLOCK IO    PIDS
f5fbb64a5164  1866beae3871  answer-standalone   0.45%       100.9MB / 16.52GB  0.61%       268B / 430B  -- / --     10
f5fbb64a5164  d0f8e296d69f  f5fbb64a5164-infra  0.01%       40.96kB / 16.52GB  0.00%       268B / 430B  -- / --     1

O desde Podman Desktop:

Pods en ejecución dentro de Podman Desktop

Vamos a generar un .yml para este pod de Kubernetes con podman generate kube AnswerStandalone > answer-standalone-pod.yml.

Puedes descargarlo aquí:

Puede que necesites modificar este archivo antes de ejecutarlo en tu servidor.

Para ejecutar el pod solo ve al directorio donde se encuentra el archivo .yml y ejecuta el comando:

~$ podman play kube ./answer-standalone-pod.yml

Pod PostgreSQL 📦🐘

Similar al pod de Answer Standalone, podemos generar un pod de Podman con Answer y PostgreSQL para "llevarnos" nuestro despliegue a donde queramos. Vamos a repetir el comando para crear el pod que necesitamos:

~$ podman pod create --name AnswerPostgres -p 5432:5432 -p 9080:80

f1157d0cfdc442423dbea69ea7bdf5dcf3233a570223f53f245bff000c803e05

Recuerda que si el comando se ejecutó correctamente, podrás ver el ID del pod en la salida del comando.

Vamos a comprobarlo:

Con podman pod ps:

~$ podman pod ps
POD ID        NAME            STATUS      CREATED             INFRA ID      # OF CONTAINERS
f1157d0cfdc4  AnswerPostgres  Created     About a minute ago  b0826ce0dc76  1

O desde podman desktop:

Aunque la imagen se vea diferente a la anterior, no te preocupes, la diferencia es que este pod está vacío y todos sus contenedores detenidos. Arreglaremos eso pronto. Por el momento es suficiente saber que nuestro pod de creó correctamente.

Vamos a agregar el contenedor de Answer al pod que acabamos de crear:

~$ podman run -d \
--pod AnswerPostgres \
-v /home/localoverflow/.answer/data:/data \
--name="answer-standalone" \
--restart=always \
--label io.containers.autoupdate=registry docker.io/apache/answer:latest


2d351afdd02ac9c51f066bce4588c2b56666af2aa71688c4d0cb1c304a170a59

Recuerda que si el comando se ejecutó correctamente, podrás ver el ID del contenedor en la salida del comando.

Ahora hacemos lo mismo con PostgreSQL:

~$ podman run -d \
--pod AnswerPostgres \
--name="pgsql-pod" \
-e POSTGRES_USER=laesquinagris \
-e POSTGRES_PASSWORD=supersecurepassword \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v /home/localoverflow/.answer/postgres/data:/var/lib/postgresql/data postgres:alpine

56d3655878fb86e9997bbe1580d040da499a4c6f3eb367e150483c20a2009b88

Recuerda que si el comando se ejecutó correctamente, podrás ver el ID del contenedor en la salida del comando.

Comprobamos que los contenedores se encuentran en ejecución con podman pod stats AnswerPostgres

~$ POD           CID           NAME                CPU %       MEM USAGE/ LIMIT   MEM %       NET IO       BLOCK IO    PIDS
f1157d0cfdc4  b0826ce0dc76  f1157d0cfdc4-infra  0.01%       36.86kB / 16.52GB  0.00%       134B / 430B  -- / --     1
f1157d0cfdc4  2d351afdd02a  answer-standalone   0.57%       98.88MB / 16.52GB  0.60%       134B / 430B  -- / --     8
f1157d0cfdc4  56d3655878fb  pgsql-pod           0.36%       3.887MB / 16.52GB  0.02%       134B / 430B  -- / --     6

Y en Podman Desktop ahora podemos ver esto:

El pod y sus contenedores

Puedes repetir los pasos de PostgreSQL en este tipo de despliegue. En la configuración de base de datos podrás usar ahora si la dirección 0.0.0.0 para conectar Answer a la base de datos.

Podemos generar un archivo de kubernetes con un Pod también, el comando es igual al de un contenedor standalone: podman generate kube AnswerPostgres > answer-postgres-pod.yml

Puedes descargarlo aquí:

Puede que necesites modificar este archivo antes de ejecutarlo en tu servidor.

Integrar con systemd + actualizaciones ⚙️⬆️

Contenedor standalone

Para generar un servicio de systemd en nuestro usuario localoverflow con el contenedor answer-standalone generado (pero no en ejecución), ejecuta los siguientes comandos:

mkdir -p ~/.config/systemd/user/
podman generate systemd --new answer-standalone > ~/.config/systemd/user/answer-container.service

Entra al directorio a explorar tu unidad de systemd generada por Podman. Debería verse similar a esto:

# container-4fe6da067758a81050bb9e2c515d767d47cb4dfce7b0ca129c52d99ac8bb313e.service
# autogenerated by Podman 4.5.1

[Unit]
Description=Podman container-4fe6da067758a81050bb9e2c515d767d47cb4dfce7b0ca129c52d99ac8bb313e.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
TimeoutStopSec=70
ExecStart=/usr/bin/podman run \
	--cidfile=%t/%n.ctr-id \
	--cgroups=no-conmon \
	--rm \
	--sdnotify=conmon \
	--replace \
	-d \
	-p 9080:80 \
	-v /home/localoverflow/.answer/data:/data \
	--name=answer-standalone \
	--label io.containers.autoupdate=registry docker.io/apache/answer:latest
ExecStop=/usr/bin/podman stop \
	--ignore -t 10 \
	--cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm \
	-f \
	--ignore -t 10 \
	--cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target

El contenedor al estar configurado con la opción: --label io.containers.autoupdate=registry es fácilmente actualizable ejecutando el siguiente comando:

podman auto-update

Trying to pull docker.io/apache/answer:latest...
Getting image source signatures
Copying blob 4fe6da067758 done   
Copying config e2c515d767d4 done   
Writing manifest to image destination
Storing signatures
UNIT                    CONTAINER                       IMAGE                               POLICY      UPDATED
answer-container.service  dfce7b0ca129 (enable-sysadmin)  docker.io/apache/answer:latest  registry true

Pod (de cualquier tipo)

Me sorprende que hayas llegado hasta aquí sin amar a Podman, similar al artículo anterior, podemos usar sus poderes para generar los servicios de systemd necesarios para nuestro usuario rootless de Podman, si no recuerdas el comando, es:

~$ cd ~/.config/systemd/user/ && podman generate systemd --files --name AnswerPostgres

La salida de este comando (en mi caso) se ve así:

/home/localoverflow/.config/systemd/user/pod-AnswerPostgres.service
/home/localoverflow/.config/systemd/user/container-answer-standalone.service
/home/localoverflow/.config/systemd/user/container-pgsql-pod.service

Detén los contenedores que tengas en ejecución o detén todo el pod que creaste con podman pod stop AnswerPostgres (PERO NO LO ELIMINES).

Una vez hecho eso podrás ejecutar systemctl enable --now pod-AnswerPostgres

Conclusión ✍️

Vómito con memes on X: "ajajaj no manches https://t.co/JPhSrbeIY7" / X

Maldita sea, qué rico es Podman para levantar aplicaciones a lo desgraciado en servidores.

Yo mismo tengo una instancia de Answer personal, para aquellos problemas que no vale la pena documentar en este blog y que, estoy seguro, me voy a topar más de una vez con ellos:

Las capacidades de Podman no se limitan a aplicaciones profesionales, puedes comenzar a utilizarlo como parte de tus procesos de desarrollo y deploy en producción. Solo debes perder el miedo a experimentar por tu cuenta. Dime ¿qué opinas de todo esto? ¿más tutoriales así te animarían a usar Podman en tu trabajo o en tu vida diaria como informático?

Siéntete libre de dejarme tu feedback en las redes sociales de La Esquina Gris, apreciaré mucho tus comentarios 👍

¿No hay una versión con MariaDB?
Pin de HELL BB en MM | Imágenes divertidas, Imágenes graciosas, Imagenes  para reirse

Mentira de nuevo 😆. Me pareció innecesario crear un apartado con MySQL/MariaDB ya que las instrucciones son 99.98% parecidas a las de PostgreSQL y las únicas diferencias son el puerto y la imagen de Docker. Puedes replicar los pasos de MariaDB intuyendo las instrucciones de PGSQL.

Canción triste del día

Do you wanna know why I keep avoiding your eyes?