Email sending is not using docker secrets
Describe the bug
The Python script behind ak test_email throws socket.gaierror when sending a test mail if docker secrets are used for the mail configuration. The test mail is sent and delivered successfully if the corresponding login information is saved directly in the environment variables.
I assume that this happens because the script takes the content of the environment variable literally and does not use the content behind it (e.g. /run/secrets/pass instead of the password itself, which is stored in the secret).
To Reproduce Steps to reproduce the behavior:
- Setup a working instance with docker compose
- Add environment variables for mail using docker secrets
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.0}
container_name: authentik_worker
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: /run/secrets/db_pass
AUTHENTIK_SECRET_KEY: /run/secrets/secret_key
AUTHENTIK_EMAIL__HOST: /run/secrets/mail_server
AUTHENTIK_EMAIL__PORT: 587
AUTHENTIK_EMAIL__USERNAME: /run/secrets/mail_user
AUTHENTIK_EMAIL__PASSWORD: /run/secrets/mail_pass
AUTHENTIK_EMAIL__USE_TLS: true
AUTHENTIK_EMAIL__USE_SSL: false
AUTHENTIK_EMAIL__TIMEOUT: 10
AUTHENTIK_EMAIL__FROM: /run/secrets/mail_user
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /srv/authentik/media:/media
- /srv/authentik/certs:/certs
- /srv/authentik/custom-templates:/templates
depends_on:
- postgresql
- redis
secrets:
- db_pass
- secret_key
- mail_user
- mail_pass
- mail_server
- (Re)create worker container
- Execute
ak test_email [my address]in worker container
Expected behavior An Email is delivered to [my address]
Logs
Traceback of ak test_email
Switching to schema 'public'
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/manage.py", line 52, in <module>
execute_from_command_line(sys.argv)
File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
utility.execute()
File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/base.py", line 413, in run_from_argv
self.execute(*args, **cmd_options)
File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/base.py", line 459, in execute
output = self.handle(*args, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/authentik/tenants/management/__init__.py", line 38, in handle
self.handle_per_tenant(*args, **options)
File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/base.py", line 107, in wrapper
res = handle_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/authentik/stages/email/management/commands/test_email.py", line 38, in handle_per_tenant
send_mail(message.__dict__, stage.pk)
File "/ak-root/venv/lib/python3.12/site-packages/celery/local.py", line 182, in __call__
return self._get_current_object()(*a, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ak-root/venv/lib/python3.12/site-packages/celery/app/task.py", line 411, in __call__
return self.run(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ak-root/venv/lib/python3.12/site-packages/celery/app/autoretry.py", line 60, in run
ret = task.retry(exc=exc, **retry_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ak-root/venv/lib/python3.12/site-packages/celery/app/task.py", line 720, in retry
raise_with_context(exc or Retry('Task can be retried', None))
File "/ak-root/venv/lib/python3.12/site-packages/celery/app/autoretry.py", line 38, in run
return task._orig_run(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/authentik/stages/email/tasks.py", line 105, in send_mail
raise exc
File "/authentik/stages/email/tasks.py", line 73, in send_mail
backend.open()
File "/ak-root/venv/lib/python3.12/site-packages/django/core/mail/backends/smtp.py", line 86, in open
self.connection = self.connection_class(
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/smtplib.py", line 255, in __init__
(code, msg) = self.connect(host, port)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/smtplib.py", line 341, in connect
self.sock = self._get_socket(host, port, self.timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/smtplib.py", line 312, in _get_socket
return socket.create_connection((host, port), timeout,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/socket.py", line 841, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/socket.py", line 976, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
socket.gaierror: [Errno -2] Name or service not known
Version and Deployment (please complete the following information):
- authentik version: 2024.8.0
- Deployment: docker compose
instead of just setting the environment variables to the file path, you need to tell authentik that it's a file path by prefixing it with file://
hi, i am having the same issue,
the secret file is of course also defined on a top-level 'secrets' element in the compose file
where are you suggesting we should put the "file://" part?
Tnx Koen
where are you suggesting we should put the "file://" part?
in front of the file path, e.g. AUTHENTIK_EMAIL__PASSWORD: file:///run/secrets/mail_pass
This is actually in the documentation under “Installation > Configuration”, perhaps I missed it when I first read it.
While the issue itself is solved, it might be useful to include a hint about secrets directly on the Docker Compose installation page
Mmm - yes, indeed. However, I'm still having issues due to file permissions. Since my secrets are saved in a folder for only root access, it seems that authentik cannot read the file...
You can change the permissions for the secrets files mounted here: https://docs.docker.com/reference/compose-file/services/#long-syntax-4, although the default mode is 0444 which should work just fine