Skip to content

feat: support custom CA certificates from the data volume - #4841

Merged
nijel merged 4 commits into
WeblateOrg:mainfrom
tahodev:feat/custom-ca-certificates
Oct 24, 2026
Merged

nijel merged 4 commits into
WeblateOrg:mainfrom
tahodev:feat/custom-ca-certificates

Conversation

@tahodev

@tahodev tahodev commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds support for custom CA certificates without rebuilding the image: any *.crt files placed in /app/data/ssl/ca-certificates are combined with the system CA bundle at container start, and the runtime is pointed at the combined bundle.

Fixes #1525

Design

  • Follows the maintainer's suggested direction on the issue: a fixed location under /app/data/ssl, the same data-volume area already used for SAML certificates (saml.crt / saml.key). A dedicated ca-certificates subdirectory keeps the SAML files from being swept into the bundle.
  • The container runs as an unprivileged user (USER 1000), so the system trust store is not writable at runtime. Instead of installing into it, the start script generates a fresh combined bundle (system + custom CAs) at /tmp/custom-ca-certificates.crt on every start and exports REQUESTS_CA_BUNDLE, SSL_CERT_FILE, CURL_CA_BUNDLE and GIT_SSL_CAINFO pointing at it, so Python (requests), OpenSSL, libcurl and git all honor the custom certificates.
  • Rebuilding the bundle from scratch on each start means a certificate removed from the data volume is never left behind in a stale store.
  • No-op when the directory is absent or empty.

Testing

  • New tests/test-custom-ca-certificates (wired into tests/run) extracts the function verbatim from start and covers: missing directory (no-op), two certificates (combined bundle content, exports, file mode) and empty directory (no-op). 7/7 passing locally; shellcheck and shfmt clean.
  • No Docker daemon in my environment, so the image build and the CI script tests are left to the repo's workflows.

Notes

  • Docs for the docker environment live in the weblate repo (docs/admin/install/docker.rst); happy to follow up with a docs PR there if this lands.
  • Developed with AI assistance (various models); I verified the changes with the test suite above.

@nijel

nijel commented Oct 22, 2026

Copy link
Copy Markdown
Member

@codex review

@nijel nijel self-assigned this Oct 22, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T08:38:52.464816Z a0e038a Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e705938d89

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread start Outdated
Comment thread start
Comment thread tests/test-custom-ca-certificates Outdated
Any *.crt files placed in /app/data/ssl/ca-certificates are combined
with the system CA bundle into a runtime-writable bundle at container
start, and Python (requests), OpenSSL, libcurl and git are pointed at
it via REQUESTS_CA_BUNDLE, SSL_CERT_FILE, CURL_CA_BUNDLE and
GIT_SSL_CAINFO.

Generating a fresh bundle (instead of installing into the system trust
store) works with the image's unprivileged runtime user, where
/usr/local/share/ca-certificates and /etc/ssl/certs are not writable,
and it is rebuilt from scratch on every start so removed certificates
never linger.

No-op when the directory is absent or empty.

Fixes WeblateOrg#1525
@tahodev
tahodev force-pushed the feat/custom-ca-certificates branch from e705938 to 365062f Compare October 22, 2026 17:05
@tahodev

tahodev commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Reworked in 365062f:

  • Runtime UID (P1): the start script no longer installs into the system trust store. It generates a combined bundle (system + custom CAs) in a runtime-writable location (/tmp/custom-ca-certificates.crt) and exports REQUESTS_CA_BUNDLE, SSL_CERT_FILE, CURL_CA_BUNDLE and GIT_SSL_CAINFO, so the feature works with the image's unprivileged USER 1000.
  • Stale CAs (P1): the bundle is rebuilt from scratch on every start, so a certificate removed from the data volume cannot linger after a restart.
  • Test environment (P2): the test subprocess now strips inherited REQUESTS_CA_BUNDLE/SSL_CERT_FILE/CURL_CA_BUNDLE/GIT_SSL_CAINFO before asserting.

Also reworded the comment that tripped the pre-commit spell check.

@tahodev tahodev changed the title feat: install custom CA certificates from the data volume feat: support custom CA certificates from the data volume Oct 22, 2026
@nijel

nijel commented Oct 23, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 365062f925

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread start Outdated
tahodev and others added 2 commits October 23, 2026 16:05
cat-ing the system bundle and user .crt files together glued PEM blocks
whenever an input lacked a trailing newline (END CERTIFICATE---BEGIN
CERTIFICATE---), producing a bundle that OpenSSL/Python reject. Write
each input followed by an explicit newline instead. Extend the test
with a no-trailing-newline case and verify the old and new behavior
against openssl with real self-signed certificates (old: "error
reading the file"; new: bundle parses).
@tahodev

tahodev commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 3f00080. Good catch — I reproduced it with real self-signed certificates before changing anything: a .crt without a trailing newline glues -----END CERTIFICATE----- onto the next -----BEGIN CERTIFICATE-----, and openssl crl2pkcs7 -nocrl -certfile then fails with "error reading the file" on the combined bundle.

The bundle is now built with an explicit newline after each input (system bundle and every .crt), so PEM blocks can never glue. tests/test-custom-ca-certificates gains a no-trailing-newline case (all 10 checks pass locally), and the openssl repro above passes on the new bundle.

@nijel

nijel commented Oct 23, 2026

Copy link
Copy Markdown
Member

I think this looks good to merge now, but let's do one more AI review round. Can you please create a documentation PR against https://github.com/WeblateOrg/weblate/?

@codex review

@tahodev

tahodev commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Documentation PR is up: WeblateOrg/weblate#22322. It adds a "Trusting custom CA certificates" section to the Docker install docs (placed right after "Using own SSL certificates"), covering the ssl/ca-certificates/ volume directory, the combined-bundle behavior on every start, and the .crt-only note.

@nijel

nijel commented Oct 23, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Unknown error
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0e038a3f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread start
export REQUESTS_CA_BUNDLE="$CUSTOM_CA_BUNDLE"
export SSL_CERT_FILE="$CUSTOM_CA_BUNDLE"
export CURL_CA_BUNDLE="$CUSTOM_CA_BUNDLE"
export GIT_SSL_CAINFO="$CUSTOM_CA_BUNDLE"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Export the bundle through PGSSLROOTCERT

When POSTGRES_SSL_MODE is verify-ca or verify-full, the database-version check is enabled, and PostgreSQL is signed only by a CA mounted here, this export list does not configure libpq. The libpq environment-variable documentation states that PGSSLROOTCERT behaves like the sslrootcert parameter, whose documented default is ~/.postgresql/root.crt; SSL_CERT_FILE is not its CA setting. The psql invocation in check_postgres_version therefore rejects the server before startup despite the mounted CA, so export this bundle as PGSSLROOTCERT as well.

Useful? React with 👍 / 👎.

libpq does not honor SSL_CERT_FILE; psql looks up the CA through
sslrootcert (default ~/.postgresql/root.crt). With POSTGRES_SSL_MODE
set to verify-ca or verify-full and PostgreSQL signed only by a
mounted custom CA, check_postgres_version would reject the server
before startup. Point PGSSLROOTCERT at the combined bundle too.
@tahodev
tahodev force-pushed the feat/custom-ca-certificates branch from 79cb8a4 to 10518dc Compare October 23, 2026 14:06
@tahodev

tahodev commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 10518dc: PGSSLROOTCERT now points at the combined bundle alongside the other exports, so the check_postgres_version psql probe validates servers signed by a mounted custom CA when POSTGRES_SSL_MODE=verify-ca/verify-full. The export assertions in tests/test-custom-ca-certificates cover the new variable (all cases pass).

@nijel
nijel enabled auto-merge (squash) October 24, 2026 07:36
@nijel

nijel commented Oct 24, 2026

Copy link
Copy Markdown
Member

Scheduled for merge, thanks for your contribution!

@nijel
nijel merged commit ce1e455 into WeblateOrg:main Oct 24, 2026
52 checks passed
nijel added a commit to WeblateOrg/weblate that referenced this pull request Oct 24, 2026
…#22322)

get_clean_env() scrubs the environment for repository operations, which
dropped the custom CA configuration before it could reach Git. Pass the
standard CA certificate variables through so that HTTPS Git remotes
secured by a private CA work out of the box, and simplify the Docker
custom CA documentation accordingly.

Documents the container start script support for combining user-provided
CA certificates in ssl/ca-certificates/ with the system CA bundle
(WeblateOrg/docker#4841).

Co-authored-by: Michal Čihař <michal@weblate.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Easy method to add trusted CA Certificate in containerized installation

2 participants