symfony-docker
symfony-docker copied to clipboard
[DX] Automatically trust Caddy's internal CA locally
Hi!
I started using the docker-compose configuration provided by this repository in order to support Mercure in my app. After some tinkering, I got it to work within the dockerized environment.
After getting it to work, I ran into some issues regarding local development and testing. I eventually found the Mercure HubStub examples in the documentation and got local unit tests to work again.
I'm still running into an issue when running local commands that want to send real Mercure updates, because the dockerized Caddy generates a CA, and uses that CA to generate a certificate. This CA is automatically trusted in the docker container, but not in my local PHP installation. This ultimately leads to such issues:
❯ ./bin/console hautelook:fixtures:load
Careful, database will be purged. Do you want to continue y/N ?y
In Hub.php line 104:
Failed to send an update.
In CommonResponseTrait.php line 148:
SSL certificate problem: unable to get local issuer certificate for "https://localhost/.well-known/mercure".
In ErrorChunk.php line 65:
SSL certificate problem: unable to get local issuer certificate for "https://localhost/.well-known/mercure".
In CurlResponse.php line 338:
SSL certificate problem: unable to get local issuer certificate for "https://localhost/.well-known/mercure".
hautelook:fixtures:load [-b|--bundle [BUNDLE]] [--no-bundles] [-m|--manager MANAGER] [--append] [--shard SHARD] [--purge-with-truncate]
I am temporarily hacking around this by manually extracting the generated CA and inserting it into the trust store used by my local PHP installation as follows:
❯ docker compose exec caddy /bin/sh -c 'cat /data/caddy/pki/authorities/local/root.crt' >> /usr/local/etc/[email protected]/cert.pem
❯ ./bin/console hautelook:fixtures:load
Careful, database will be purged. Do you want to continue y/N ?y
However, this would be necessary each time Caddy generates a new CA.
This seems to be a DX issue users would run into when using the suggested default configuration. It could be overcome by supplying your own certificates using a static/unchanging CA, but it would be neat if we could somehow automatically trust the generated CA locally as well.
Why don't you run your PHP commands inside the PHP containers instead of on the host?
A work has already been started here: https://github.com/dunglas/symfony-docker/pull/106
Why don't you run your PHP commands inside the PHP containers instead of on the host?
Mostly because it is what I am used to. Running it in the docker containers is (slightly) more complicated but honestly it's just a preference. I want to work locally and use docker to abstract some services, without necessarily having to adopt a docker-first work method.
#106
Thanks, that looks like it should work. I didn't know about the /data/caddy/pki/authorities/local/root.crt
location -- that makes my 'solution' slightly less convoluted. (edited in original post). Perhaps this could be documented around here as well, as it is basically the same thing specifically for local PHP instead of the system trust store.
I will try the set-up with static certs created by mkcert
and report back on the PR.
ref https://github.com/dunglas/symfony-docker/pull/106#issuecomment-1011046380
TL;DR the proposed configuration allows Caddy to use the locally generated certificate (with the CA generated by mkcert
) but now that certificate isn't trusted by the docker PHP container, meaning the running app cannot send Mercure updates.
I will revert to using Caddy's internally generated CA for now, using the following commands to trust the CA within my local PHP set-up:
- Find the trust store used by PHP:
❯ grep "openssl.cafile.*=" $(php --ini | grep 'php.ini$' | awk '{ print $NF }') | awk '{ print $NF }'
- Add the CA generated by Caddy to your local PHP's trust store
❯ docker compose exec caddy /bin/sh -c 'cat /data/caddy/pki/authorities/local/root.crt' >> $trust_store_location
The generated CA seems to survive container reboots as well as rebuilds, and only seems to be re-generated if the docker volume is removed. Maybe we can document this somewhere.
I just realized the docker PHP container is, by default, configured to send Mercure updates over HTTP instead of HTTPS.
Adding 127.0.0.1 caddy
to /etc/hosts
allows me to configure MERCURE_URL=http://caddy/.well-known/mercure
and everything works out-of-the-box without needing to explicitly trust anything.
Close for https://github.com/dunglas/symfony-docker/pull/106