Add HTTPS support via cpp-httplib's mbedtls backend#1011
Conversation
llamafile built cpp-httplib without any TLS backend, so every https:// operation failed: -hf/--model-url downloads from Hugging Face, https clients in server-models, and --ssl-cert-file/--ssl-key-file serving. llama.cpp gets TLS from cpp-httplib's OpenSSL backend (system OpenSSL or vendored BoringSSL/LibreSSL at cmake time), none of which fit the cosmocc make build. The vendored cpp-httplib is multi-backend though: enable its native Mbed TLS backend (CPPHTTPLIB_MBEDTLS_SUPPORT) against the mbedtls fork already vendored in third_party/mbedtls -- the same TLS stack llamafile <= 0.9.3 used -- so no new third-party code is vendored. - third_party/mbedtls/include: shims mapping <mbedtls/*.h> onto the fork - BUILD.mk: define the macro on every TU that reaches httplib.h (it changes httplib class layouts); link mbedtls.a into llama-server and llamafile - llama.cpp guards: CPPHTTPLIB_OPENSSL_SUPPORT -> CPPHTTPLIB_SSL_ENABLED in common/http.h, server-http.cpp, server-models.cpp (candidates for upstreaming; upstream's guards predate httplib's multi-backend split) - httplib.cpp: under __COSMOPOLITAN__, fall back to the Mozilla roots zipped into the APE (/zip/third_party/mbedtls/sslroot) when the host has no system CA store (e.g. Windows), keeping host stores preferred - llamafile main: accept -hf/--hf-repo/-mu/--model-url in place of -m Verified: HF downloads (hf.co -> CDN redirect) from llama-server and llamafile --server; self-signed/wrong-host/expired certs rejected; TLS serving works; make check and the clean patch round-trip pass. LibreSSL 4.3.2 was probed as the "same library as llama.cpp" option and does build under cosmocc (2-line arc4random.h patch, TLS 1.3 handshake verified) but was not chosen: it would vendor a second TLS stack for no gain on this path. Documented as plan-B if TLS 1.3 is ever required. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code reviewFound 1 issue:
Macro added for server.cpp only (the invariant comment): Lines 293 to 307 in 6015c53 Pattern rule that compiles the chatbot objects without the macro: Lines 364 to 367 in 6015c53
llamafile/llamafile/chatbot_api.cpp Lines 125 to 127 in 6015c53 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
chatbot_api.cpp and chatbot_main.cpp include httplib.h but were compiled without CPPHTTPLIB_MBEDTLS_SUPPORT while linking into the same binary as httplib.cpp, which is compiled with it. The macro enlarges httplib class layouts (Result grows ssl_error_/ssl_backend_error_, Client grows is_ssl_), so the TUI receiving Result by value from Get/Post would have the callee writing fields the caller never allocated. Factor the flags into LLAMAFILE_HTTPLIB_TLS_FLAGS and apply them to the chatbot objects alongside server.cpp.o, with a comment telling future httplib includers to do the same. Verified with a probe TU compiled with the chatbot flag set, linked against the same httplib.cpp.o + mbedtls.a, exchanging Result by value with a live server; make check passes. Reported-by: code review on #1011 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Fixed in 96436d5 — good catch, and it violated the invariant this PR itself documented.
Verified beyond the flag audit: a probe TU compiled with the chatbot flag set and linked against the same 🤖 Generated with Claude Code |
Four tests behind a new pytest 'ssl' marker (toggle with -m ssl / -m "not ssl"): - serve over TLS via --ssl-cert-file/--ssl-key-file and connect with a verifying client (self-signed cert generated with openssl, SAN for localhost/127.0.0.1) - plain-HTTP request to the TLS port is refused - download a tiny model (ggml-org/models stories260K, ~1 MiB) from Hugging Face over HTTPS into a fresh cache and serve it; the only test needing network access - offline negative test: --model-url against our own self-signed HTTPS server must fail with nothing written to the cache, proving the downloader enforces certificate verification (the rogue endpoint would otherwise happily serve a body) Also fixes a duplicate-row typo in the README marker table. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Allows running the suite offline with -m "not online" while keeping the rest of the ssl tests selectable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
Adds HTTPS/TLS support to llamafile, enabling:
-hf ggml-org/models,--hf-repo/--hf-file,--model-url https://...now work in llamafile and llama-server (previously threwHTTPS is not supported, so downloading from Hugging Face only worked in upstream llama.cpp, not here)--ssl-cert-file/--ssl-key-filenow start an HTTPS serverserver_http_proxy)How
llama.cpp gets TLS from cpp-httplib's OpenSSL backend (system OpenSSL, or vendored BoringSSL/LibreSSL at cmake time), none of which fit the cosmocc make build. But the cpp-httplib version vendored by our llama.cpp pin is multi-backend: it has a native Mbed TLS backend (
CPPHTTPLIB_MBEDTLS_SUPPORT, umbrella macroCPPHTTPLIB_SSL_ENABLED).So we keep the exact HTTP library llama.cpp uses and enable that backend against the Mbed TLS fork already vendored in
third_party/mbedtls— the same TLS stack llamafile ≤ 0.9.3 used for its HTTPS (llamafile/curl.cpp, localscore). Zero new vendored code.third_party/mbedtls/include/mbedtls/*.h(new): 12 one-line shims mapping the canonical<mbedtls/x.h>include paths onto the fork'sthird_party/mbedtls/x.hheaders.llama.cpp/BUILD.mk+llamafile/BUILD.mk: setCPPHTTPLIB_MBEDTLS_SUPPORTon every object that can reachhttplib.h(the macro changes httplib class layouts, so all TUs must agree — includingllamafile/server.cpp.o, which reaches it viaserver-cors-proxy.h); linkmbedtls.aintollama-serverandllamafile.common/http.h,tools/server/server-http.cpp,tools/server/server-models.cpp):#ifdef CPPHTTPLIB_OPENSSL_SUPPORT→#ifdef CPPHTTPLIB_SSL_ENABLED. These look upstreamable — upstream's guards predate httplib's multi-backend refactor.vendor/cpp-httplib/httplib.cpppatch, under__COSMOPOLITAN__: append/zip/third_party/mbedtls/sslrootto httplib's system-CA-dir fallback list, and__static_yoink("ssl_root_support")so the Mozilla root PEMs (already in-tree, bundled bythird_party/mbedtls/BUILD.mk) land in the APE zip. Host trust stores are preferred when present (/etc/ssl/..., so corporate CAs keep working); the bundled roots are the fallback — essential on Windows, where the_WIN32cert-store branches aren't compiled into an APE.llamafile/{args,main}.cpp: the main binary's "missing required-m" gate now also accepts-hf/-hfr/--hf-repo/-mu/--model-url(a remote model to download is a model); TUI banner falls back to the repo/URL string.Certificate verification is on (
MBEDTLS_SSL_VERIFY_REQUIREDpath via httplib defaults): TLS 1.2, SNI, hostname verification, entropy from cosmogetrandom.Why not the same TLS library as llama.cpp (BoringSSL/LibreSSL/OpenSSL)?
We probed it: LibreSSL 4.3.2 does build under cosmocc 4.0.2 — one 2-line patch (
crypto/compat/arc4random.hneeds a__COSMOPOLITAN__case) plus configure overrides; verified with a live TLS 1.3 handshake to google.com from an APE test binary. ahgamut/superconfigure also builds OpenSSL proper with cosmocc. So it's feasible, but it means vendoring and maintaining a second ~470-file TLS stack (~16 MB of fat static archives) for no functional gain on the download path. The cpp-httplib mbedtls backend gets us the same HTTP library as upstream with the TLS stack we already ship. LibreSSL stays documented as plan-B if TLS 1.3 or bit-exact upstream parity is ever needed.Testing
llama-server --hf-repo ggml-org/models --hf-file tinyllamas/stories260K.gguf: downloads over HTTPS (hf.co → CDN cross-host redirect exercised), loads,/healthok — same via the mainllamafile --serverbinary with a cold cache,/v1/completionsreturns tokensself-signed.badssl.com,wrong.host.badssl.com,expired.badssl.comall rejected withSSL server verification failed;huggingface.co→ HTTP 200--ssl-cert-file/--ssl-key-filewith a self-signed cert serveshttps://.../health= okmake checkpasses; clean round-trip (reset-repo→setup→ clean build →check) passes with the regenerated patches🤖 Generated with Claude Code