Ejecutar PostgreSQL en Docker es una excelente manera de realizar pruebas rápidas, pero ¿qué sucede cuando necesitas que se comporte como una configuración adecuada y lista para producción, incluyendo cifrado SSL, autenticación basada en certificados, volúmenes persistentes y configuraciones personalizadas? Abordaremos todos estos aspectos, prestando especial atención a la propiedad y los permisos de los archivos, cruciales para la seguridad.
La Necesidad de SSL en Entornos de Docker
Si bien la imagen predeterminada de Docker para PostgreSQL es suficiente para la experimentación, las aplicaciones en producción requieren un nivel de seguridad más elevado. PostgreSQL soporta SSL, pero esta funcionalidad no está habilitada por defecto en la imagen de Docker. La implementación de SSL es fundamental para proteger la confidencialidad e integridad de los datos transmitidos entre el cliente y el servidor de base de datos, especialmente en entornos donde la información sensible es manejada.

La autenticación basada en certificados ofrece una alternativa robusta a la autenticación por contraseña. A diferencia de las contraseñas, que pueden ser olvidadas, interceptadas o adivinadas, los certificados proporcionan un mecanismo de autenticación más seguro y conveniente para la comunicación entre servicios. Las aplicaciones no pueden "olvidar" certificados, lo que reduce el riesgo de fallos de autenticación debido a errores humanos o de gestión de contraseñas. Esto es particularmente valioso en escenarios de comunicación de servicio a servicio, donde la automatización y la seguridad son primordiales.
Generación de Certificados Autogenerados con OpenSSL
El primer paso para habilitar SSL es generar los certificados necesarios. Esto se puede lograr utilizando la herramienta de línea de comandos OpenSSL.
Creación de la Clave Privada de la CA:Se genera una clave privada RSA mediante el comando
openssl genrsa -des3 -out ca-key.pem 4096. Esta clave será el corazón de nuestra Autoridad Certificadora (CA) autogenerada.Creación del Certificado de la CA:A continuación, se crea una CA autofirmada utilizando su clave privada. El comando
openssl req -new -x509 -days 365 -key ca-key.pem -out ca-cert.pemgenera tanto la clave privada como el certificado autofirmado. La validez del certificado se establece en 365 días y se guarda enca-cert.pem. Si se omite la bandera-subj, OpenSSL solicitará interactiva mente los metadatos para su CA, como el país, la organización y el nombre común.Generación de la Clave y Solicitud de Firma del Servidor:Para el servidor PostgreSQL, necesitamos una clave privada y una solicitud de firma de certificado (CSR).
openssl genrsa -out server-key.pem 4096genera la clave privada del servidor.openssl req -new -key server-key.pem -out server-req.pemcrea la solicitud de firma de certificado. De nuevo, se puede usar-subjpara proporcionar metadatos o responder a las preguntas interactivas.
Firma de la Solicitud del Servidor con la CA:Finalmente, la CA autofirmada firma la solicitud del servidor para crear el certificado del servidor.
openssl x509 -req -days 365 -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pemEste comando utiliza el certificado y la clave de la CA para firmar la solicitud del servidor, produciendoserver-cert.pem. El archivoca-cert.pemservirá como el certificado de la CA para que los clientes puedan verificar la autenticidad del servidor.
Con estos pasos, disponemos de los certificados necesarios. Sin embargo, PostgreSQL no los utilizará a menos que se lo indiquemos explícitamente a través de sus archivos de configuración.
Configuración de PostgreSQL para SSL
Para que PostgreSQL utilice los certificados generados, es necesario modificar su archivo de configuración principal, postgresql.conf.
ssl = on: Esta directiva habilita explícitamente el soporte SSL para el servidor PostgreSQL.ssl_cert_file = 'server-cert.pem': Especifica la ruta al archivo del certificado del servidor.ssl_key_file = 'server-key.pem': Especifica la ruta al archivo de la clave privada del servidor.ssl_ca_file = 'ca-cert.pem': Especifica la ruta al archivo del certificado de la CA, utilizado para la autenticación mutua (si se configura) y para que los clientes verifiquen el certificado del servidor.
Estos archivos de certificado y clave deben ser accesibles para el proceso de PostgreSQL dentro del contenedor.
Gestión de Datos Persistentes con Volúmenes Docker
PostgreSQL necesita un lugar para almacenar bases de datos, tablas, registros, etc.; sin esta capacidad, simplemente no funcionará. Por defecto, utiliza /var/lib/postgresql/data. Sin embargo, para un entorno de producción, es crucial tener datos persistentes que sobrevivan a la eliminación o recreación del contenedor. Esto se logra utilizando volúmenes de Docker.
Definimos un volumen personalizado, por ejemplo, /pgdata, que se montará en el contenedor. Este volumen se encargará de almacenar todos los datos de PostgreSQL.
version: '3.8'services: postgres: image: postgres:latest container_name: postgres environment: POSTGRES_DB: mydatabase POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword volumes: - pgdata:/var/lib/postgresql/data # Volumen persistente para los datos - ./postgres-conf:/etc/postgresql/conf.d # Montar configuración personalizada ports: - "5432:5432" restart: unless-stoppedvolumes: pgdata:En este ejemplo, pgdata es un volumen gestionado por Docker que se montará en /var/lib/postgresql/data dentro del contenedor. Esto asegura que los datos de la base de datos se conserven incluso si el contenedor postgres se elimina y se vuelve a crear.
Configuración de Red y Autenticación
Para permitir conexiones desde otras aplicaciones o contenedores dentro de un entorno Docker, es esencial configurar la red adecuadamente.
listen_addresses = '*': Esta directiva enpostgresql.confpermite las conexiones desde cualquier dirección IP. Esto es útil en desarrollo o si otros contenedores necesitan conectarse a PostgreSQL. En producción, se recomienda restringir esto a direcciones IP específicas o a la red interna de Docker.- Docker Network: Utilizar redes de Docker permite una comunicación segura y aislada entre contenedores. Los contenedores dentro de la misma red de Docker pueden comunicarse entre sí utilizando sus nombres de servicio como nombres de host.
Autenticación Basada en Certificados para Usuarios
Además de habilitar SSL para el transporte, podemos configurar PostgreSQL para utilizar certificados para la autenticación de usuarios. Esto va más allá de la autenticación por contraseña, proporcionando una capa adicional de seguridad.
- Usuarios para Conexiones Automatizadas: El usuario
pguser(o similar) es ideal para conexiones automatizadas donde las contraseñas son inconvenientes y menos seguras. Los certificados proporcionan una autenticación más fuerte para la comunicación de servicio a servicio. pg_hba.conf: Este archivo controla la autenticación de clientes. Para habilitar la autenticación basada en certificados, se pueden agregar entradas como:hostssl all all 0.0.0.0/0 cert clientcert=verify-fullEsta configuración requiere que el cliente presente un certificado válido y que la CA que firmó ese certificado sea confiable para el servidor PostgreSQL.clientcert=verify-fullasegura que el certificado del cliente sea verificado contra la CA configurada enssl_ca_file.
Uso de Certificados de Let's Encrypt en Producción
Si bien los certificados autofirmados son adecuados para el desarrollo y las pruebas, los entornos de producción deben utilizar certificados de confianza emitidos por una Autoridad Certificadora (CA) reconocida, como Let's Encrypt.
Generar certificado SSL con letsencriypt - Tutorial
El proceso para obtener y utilizar certificados de Let's Encrypt con PostgreSQL en Docker puede involucrar herramientas como Traefik y traefik-certs-dumper.
- Configuración de Traefik: Traefik puede actuar como un proxy inverso y gestionar automáticamente la obtención y renovación de certificados SSL para dominios. Configurando Traefik con las etiquetas adecuadas en un archivo
docker-compose.yml, se pueden obtener certificados para un nombre de dominio específico (ej.side-project.mydomain.org). traefik-certs-dumper: Dado que Traefik almacena los certificados generados en su propio volumen, se necesita una herramienta comotraefik-certs-dumperpara copiar estos certificados a una ubicación accesible por el contenedor de PostgreSQL. Este contenedor se ejecuta junto con Traefik y monta el volumen de certificados de Traefik, copiando los archivoscertificate.crtyprivatekey.keya un directorio compartido.- Montaje de Certificados en PostgreSQL: El contenedor de PostgreSQL luego monta este directorio compartido que contiene los certificados. Las directivas
ssl_cert_fileyssl_key_fileen la configuración de PostgreSQL apuntarán a estos archivos montados. - DNS y Reenvío de Puertos: Para que Let's Encrypt pueda generar un certificado, el nombre de dominio debe ser resoluble a la dirección IP pública del servidor donde se ejecutan los contenedores. Esto implica actualizar la configuración DNS del dominio. Además, los puertos necesarios (5432 para PostgreSQL, 443 y 80 para Traefik) deben ser reenviados desde el router a la máquina que aloja los contenedores Docker.
Consideraciones Adicionales y Desafíos
- Propiedad y Permisos de Archivos: PostgreSQL se ejecuta dentro del contenedor como el usuario
postgres(UID 999). Por lo tanto, este usuario debe poseer los archivos de configuración y los datos almacenados en el volumen. Al montar directorios desde el host, es crucial asegurarse de que los permisos de archivo y la propiedad sean correctos para que el usuariopostgresdentro del contenedor pueda leer y escribir en ellos. Si los archivos de configuración o los datos no son propiedad del usuariopostgres, el servidor PostgreSQL podría no iniciarse o fallar al acceder a ellos. - Recarga de Certificados en Tiempo de Ejecución: Un desafío recurrente es cómo hacer que PostgreSQL recargue automáticamente los certificados SSL sin necesidad de reiniciar el servicio o el contenedor. Si bien reiniciar el contenedor funciona, existe la posibilidad de instruir a un servidor PostgreSQL en ejecución para que recargue sus certificados SSL sin interrupción del servicio. Esto generalmente se logra enviando una señal específica al proceso de PostgreSQL o utilizando comandos de administración de PostgreSQL. En muchos casos, las actualizaciones del sistema operativo del host que provocan un reinicio del servicio pueden capturar los certificados más recientes.
Conclusión Parcial
Al seguir estos pasos, se construye una configuración de PostgreSQL mucho más cercana a un entorno de producción real, incorporando SSL, autenticación basada en certificados y datos persistentes, todo ello manteniendo la conveniencia y flexibilidad que ofrece Docker. La combinación de estas prácticas resulta en una base de datos más segura, confiable y robusta para aplicaciones críticas.