# TLS 1.3 handshake fails for Erlang/OTP clients (Akkoma/Pleroma link previews) – missing ChangeCipherSpec in middlebox compatibility mode

**URL:** <https://forum.codefloe.com/t/tls-1-3-handshake-fails-for-erlang-otp-clients-akkoma-pleroma-link-previews-missing-changecipherspec-in-middlebox-compatibility-mode/218>\
**Category:** Pages\
**Created:** [October 20, 2026, 5:33pm UTC](https://forum.codefloe.com/t/tls-1-3-handshake-fails-for-erlang-otp-clients-akkoma-pleroma-link-previews-missing-changecipherspec-in-middlebox-compatibility-mode/218 "2026-10-20T17:33:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![juergen](https://forum.codefloe.com/user_avatar/forum.codefloe.com/juergen/32/323_2.png) [@juergen](https://forum.codefloe.com/u/juergen)\
**Post date:** [October 20, 2026, 5:33pm UTC](https://forum.codefloe.com/t/tls-1-3-handshake-fails-for-erlang-otp-clients-akkoma-pleroma-link-previews-missing-changecipherspec-in-middlebox-compatibility-mode/218/1 "2026-10-20T17:33:29Z")

</div>

Hi,

I host my blog on Codefloe Pages (`blog.jyrgi.de` → `juergen.codefloe.page`, server header `git-pages`). Browsers and curl connect fine, but Erlang/OTP-based clients cannot complete the TLS 1.3 handshake. As a result, Fediverse servers built on Erlang/Elixir (Akkoma, Pleroma) can’t fetch link previews for any page hosted on Codefloe Pages.

**Error on the client side (Akkoma log):**

```auto
Description: 'Failed to assert middlebox server message'
Reason: [missing: {change_cipher_spec, 1}]
TLS client: In state hello_middlebox_assert at ssl_gen_statem.erl:807
generated CLIENT ALERT: Fatal - Unexpected Message
{unexpected_msg, {internal, {encrypted_extensions, ...}}}

```

**What seems to happen:** The Erlang client uses TLS 1.3 middlebox compatibility mode (RFC 8446, Appendix D.4) and sends a non-empty `legacy_session_id`. It then expects the server to send a dummy `change_cipher_spec` record right after the ServerHello. The Pages server goes straight to EncryptedExtensions without that record, and Erlang’s TLS stack aborts the handshake. Other clients are more lenient, which is probably why this hasn’t come up before.

**Reproduce** (any machine with Erlang/OTP installed):

bash

```bash
# fails:
erl -noshell -eval 'ssl:start(), io:format("~p~n", [ssl:connect("blog.jyrgi.de", 443, [{verify,verify_none},{server_name_indication,"blog.jyrgi.de"}], 5000)]), halt().'

# works (middlebox compatibility disabled on the client):
erl -noshell -eval 'ssl:start(), io:format("~p~n", [ssl:connect("blog.jyrgi.de", 443, [{verify,verify_none},{server_name_indication,"blog.jyrgi.de"},{middlebox_comp_mode,false}], 5000)]), halt().'

```

I’ve patched my own Akkoma instance as a workaround, but other Pleroma/Akkoma instances on the Fediverse will still fail to generate previews for Codefloe-hosted pages. Would it be possible to have the server (or the TLS terminator in front of it) send the dummy ChangeCipherSpec when the client offers a session ID?

Thanks for the great service!

Jürgen

---

<div class="post-metadata">

**Author:** ![codefloe](https://forum.codefloe.com/user_avatar/forum.codefloe.com/codefloe/32/42_2.png) [@codefloe](https://forum.codefloe.com/u/codefloe)\
**Post date:** [October 21, 2026, 1:39am UTC](https://forum.codefloe.com/t/tls-1-3-handshake-fails-for-erlang-otp-clients-akkoma-pleroma-link-previews-missing-changecipherspec-in-middlebox-compatibility-mode/218/2 "2026-10-21T01:39:24Z")

</div>

Hi Jürgen,

Thanks for the detailed report.

CodeFloe Pages and [codefloe.com](http://codefloe.com) sit behind HAProxy built against wolfSSL. The wolfSSL version we were running only sends the dummy ChangeCipherSpec from RFC 8446 Appendix D.4 when it’s compiled with a specific option, and our build didn’t have it. Turn out newer wolfSSL releases always send it on the server side, so all we needed to do was to upgrade to the latest version.

The fix is live. The server now sends the `ChangeCipherSpec` right after the ServerHello, and we’ve confirmed it against [blog.jyrgi.de](http://blog.jyrgi.de). Your test should now succeed without `{middlebox_comp_mode,false}`:

```bash
erl -noshell -eval 'ssl:start(), io:format("~p~n", [ssl:connect("blog.jyrgi.de", 443, [{verify,verify_none},{server_name_indication,"blog.jyrgi.de"}], 5000)]), halt().'

```

You can drop the workaround on your Akkoma instance.

Thanks again, and let us know if anything still fails.

---

<div class="post-metadata">

**Author:** ![juergen](https://forum.codefloe.com/user_avatar/forum.codefloe.com/juergen/32/323_2.png) [@juergen](https://forum.codefloe.com/u/juergen)\
**Post date:** [October 21, 2026, 6:01am UTC](https://forum.codefloe.com/t/tls-1-3-handshake-fails-for-erlang-otp-clients-akkoma-pleroma-link-previews-missing-changecipherspec-in-middlebox-compatibility-mode/218/3 "2026-10-21T06:01:36Z")

</div>

Wow, that’s fast support. Thanks a lot 👍

---

<div class="post-metadata">

**Author:** ![system](https://forum.codefloe.com/user_avatar/forum.codefloe.com/system/32/1_2.png) [@system](https://forum.codefloe.com/u/system)\
**Post date:** [October 23, 2026, 6:01am UTC](https://forum.codefloe.com/t/tls-1-3-handshake-fails-for-erlang-otp-clients-akkoma-pleroma-link-previews-missing-changecipherspec-in-middlebox-compatibility-mode/218/4 "2026-10-23T06:01:46Z")

</div>

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.
