diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,24 @@
 
 ## [Unreleased]
 
+## [0.1.1.0] - 2026-09-08
+
+### Added
+- ALPN protocol advertisement. The server now offers `h2` and `http/1.1`, so
+  Warp can select HTTP/2 for clients that request it.
+
+### Changed
+- **HTTP/2 is now reachable, where previously it was not.** Warp chooses
+  between HTTP/1.1 and HTTP/2 from the ALPN protocol negotiated on the
+  `Transport`. No protocol preferences were ever set on the s2n config, so no
+  application protocol was negotiated, `tlsNegotiatedProtocol` was always
+  `Nothing`, and every connection fell through to HTTP/1.1 regardless of the
+  caller's Warp settings.
+
+  The advertised list is derived from Warp's own `settingsHTTP2Enabled`, so
+  `setHTTP2Disabled` withdraws `h2` from the offer and restores the previous
+  behaviour exactly. Callers that require HTTP/1.1 should set it.
+
 ## [0.1.0.0] - 2026-04-28
 
 ### Added
diff --git a/src/Network/Wai/Handler/WarpS2N.hs b/src/Network/Wai/Handler/WarpS2N.hs
--- a/src/Network/Wai/Handler/WarpS2N.hs
+++ b/src/Network/Wai/Handler/WarpS2N.hs
@@ -413,6 +413,16 @@
   -- Initialize s2n config
   config <- initS2nConfig tls tlsSet
 
+  -- Advertise ALPN protocols.  Warp selects HTTP/2 from the negotiated
+  -- protocol on the Transport, so without this it never sees "h2" and every
+  -- connection stays HTTP/1.1.  Deriving the list from the caller's Warp
+  -- settings keeps 'setHTTP2Disabled' working as the single kill switch
+  -- rather than adding a second, separately-configured one here.
+  tls.setProtocolPreferences config
+    $ if WarpI.settingsHTTP2Enabled settings
+      then ["h2", "http/1.1"]
+      else ["http/1.1"]
+
   -- Set up ticket key manager if configured, then run the server
   rotateAction <- case tlsTicketKeyManager of
     Nothing -> pure (pure ()) -- dummy rotation action
diff --git a/test/ProtocolTests.hs b/test/ProtocolTests.hs
--- a/test/ProtocolTests.hs
+++ b/test/ProtocolTests.hs
@@ -4,6 +4,7 @@
 
 import Control.Applicative
 import Control.Exception (SomeException, bracket, try)
+import Data.ByteString (ByteString)
 import Data.Default.Class (def)
 import Network.HTTP.Types (status200)
 import Network.Socket qualified as Socket
@@ -11,7 +12,12 @@
 import Network.TLS qualified as TLS
 import Network.TLS.Extra.Cipher qualified as TLS
 import Network.Wai (responseLBS)
-import Network.Wai.Handler.Warp (defaultSettings, setBeforeMainLoop)
+import Network.Wai.Handler.Warp (
+    Settings,
+    defaultSettings,
+    setBeforeMainLoop,
+    setHTTP2Disabled,
+ )
 import Network.Wai.Handler.WarpS2N (
     TLSSettings (..),
     runTLSSocketLib,
@@ -28,7 +34,34 @@
 protocolSpec = do
     describe "TLS version negotiation" versionNegotiationSpec
     describe "Cipher preferences" cipherPreferencesSpec
+    describe "ALPN" alpnSpec
 
+alpnSpec :: SpecWith S2nTls
+alpnSpec = do
+    it "negotiates h2 when the client offers it" $ \tls -> do
+        let serverSettings = tlsSettings testCertPath testKeyPath
+        proto <- withTestServerGetALPN tls serverSettings defaultSettings ["h2", "http/1.1"]
+        proto `shouldBe` Just "h2"
+
+    it "selects http/1.1 when the client does not offer h2" $ \tls -> do
+        let serverSettings = tlsSettings testCertPath testKeyPath
+        proto <- withTestServerGetALPN tls serverSettings defaultSettings ["http/1.1"]
+        proto `shouldBe` Just "http/1.1"
+
+    -- The advertised list is derived from Warp's own settingsHTTP2Enabled, so
+    -- setHTTP2Disabled has to withdraw h2 from the offer entirely.  Leaving it
+    -- advertised would let a client select a protocol Warp then refuses to
+    -- speak, which is worse than never offering it.
+    it "withdraws h2 when the Warp settings disable HTTP/2" $ \tls -> do
+        let serverSettings = tlsSettings testCertPath testKeyPath
+        proto <-
+            withTestServerGetALPN
+                tls
+                serverSettings
+                (setHTTP2Disabled defaultSettings)
+                ["h2", "http/1.1"]
+        proto `shouldBe` Just "http/1.1"
+
 versionNegotiationSpec :: SpecWith S2nTls
 versionNegotiationSpec = do
     it "negotiates TLS 1.3 with default settings" $ \tls -> do
@@ -99,6 +132,35 @@
             let version = TLS.infoVersion <$> info
             TLS.bye ctx
             pure version
+
+{- | Helper: Start server and report the ALPN protocol the client settles on.
+
+Takes the Warp 'Settings' explicitly, because the advertised protocol list is
+derived from them.
+-}
+withTestServerGetALPN :: S2nTls -> TLSSettings -> Settings -> [ByteString] -> IO (Maybe ByteString)
+withTestServerGetALPN tls tlsSet baseWarpSet clientProtos =
+    bracket bindFreePort (Socket.close . fst) $ \(sock, port) -> do
+        serverReady <- newEmptyTMVarIO
+        let app _ respond = respond $ responseLBS status200 [] "blarg!"
+            warpSet = setBeforeMainLoop (atomically $ putTMVar serverReady ()) baseWarpSet
+        withAsync (runTLSSocketLib tls tlsSet warpSet sock app) $ \as -> do
+            atomically $ waitSTM as <|> takeTMVar serverReady
+            threadDelay 10_000
+            backend <- makeClientSocket port
+            params <- makeClientParams [TLS.TLS13, TLS.TLS12]
+            let alpnParams =
+                    params
+                        { TLS.clientHooks =
+                            (TLS.clientHooks params)
+                                { TLS.onSuggestALPN = pure (Just clientProtos)
+                                }
+                        }
+            ctx <- TLS.contextNew backend alpnParams
+            TLS.handshake ctx
+            proto <- TLS.getNegotiatedProtocol ctx
+            TLS.bye ctx
+            pure proto
 
 -- | Helper: Start server and test if connection succeeds
 withTestServerConnect :: S2nTls -> TLSSettings -> IO Bool
diff --git a/warp-s2n-tls.cabal b/warp-s2n-tls.cabal
--- a/warp-s2n-tls.cabal
+++ b/warp-s2n-tls.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               warp-s2n-tls
-version:            0.1.0.0
+version:            0.1.1.0
 synopsis:           TLS support for Warp via s2n-tls
 description:
     This package provides TLS support for the Warp web server using
@@ -28,7 +28,7 @@
 source-repository this
     type:     git
     location: https://github.com/goertzenator/warp-s2n-tls.git
-    tag:      v0.1.0.0
+    tag:      v0.1.1.0
 
 library
     exposed-modules:    Network.Wai.Handler.WarpS2N
