<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Hiroki Kumazaki on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Hiroki Kumazaki</name>
  </author>
  <link href="https://web.dev/authors/kumagi/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/Y780bmlJiHhk6UwxgOFF.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Our latest news, updates, and stories by Hiroki Kumazaki.</subtitle>
  
  
  <entry>
    <title>How to distribute Signed HTTP Exchanges (SXG) using nginx</title>
    <link href="https://web.dev/how-to-distribute-signed-http-exchanges/"/>
    <updated>2020-03-11T00:00:00Z</updated>
    <id>https://web.dev/how-to-distribute-signed-http-exchanges/</id>
    <content type="html" mode="escaped">&lt;p&gt;As a &lt;a href=&quot;https://developer.chrome.com/blog/signed-exchanges&quot; rel=&quot;noopener&quot;&gt;Signed HTTP Exchanges (SXG)&lt;/a&gt; distributor, you can deliver SXG files on behalf of the original content creators. Web browsers that support SXG will display such SXG files as if they were delivered from the original content creators. This enables you to implement cross-site preloading without violating privacy. This guide shows you how to distribute SXG properly.&lt;/p&gt;
&lt;h2 id=&quot;cross-browser-support&quot;&gt;Cross-browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-distribute-signed-http-exchanges/#cross-browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chrome is currently the only browser that supports SXG. See the Consensus &amp;amp; Standardization section of &lt;a href=&quot;https://www.chromestatus.com/feature/5745285984681984&quot; rel=&quot;noopener&quot;&gt;Origin-Signed HTTP Exchanges&lt;/a&gt; for more up-to-date information.&lt;/p&gt;
&lt;h2 id=&quot;get-sxg-files&quot;&gt;Get SXG files &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-distribute-signed-http-exchanges/#get-sxg-files&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Specify in your &lt;code&gt;Accept&lt;/code&gt; request header that you want the server to return an SXG file along with the request:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Accept: application/signed-exchange&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;b3,*/*&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.8&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This guide assumes that you put your SXG files in &lt;code&gt;/var/www/sxg&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;serve-a-simple-sxg-file&quot;&gt;Serve a simple SXG file &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-distribute-signed-http-exchanges/#serve-a-simple-sxg-file&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Attach the following headers to distribute a single SXG file:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Content-Type: application/signed-exchange;v=v3&lt;br /&gt;X-Content-Type-Options: nosniff&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Configure &lt;code&gt;nginx&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;http&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    ...&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;types&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;application/signed-exchange&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;v=b3  &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;add_header&lt;/span&gt; X-Content-Type-Options nosniff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;location&lt;/span&gt; /&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;more_set_headers&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type: application/signed-exchange;v=b3&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;alias&lt;/span&gt; /var/www/sxg/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try_files&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$uri&lt;/span&gt;.sxg &lt;span class=&quot;token variable&quot;&gt;$uri&lt;/span&gt; =404&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;autoindex&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;off&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Load the new configuration into &lt;code&gt;nginx&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl restart nginx.service&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;nginx&lt;/code&gt; will start serving SXG files.
When Chrome accesses your server, the address of the original content publisher will appear in the bar!&lt;/p&gt;
&lt;h2 id=&quot;prefetch-subresources&quot;&gt;Prefetch subresources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-distribute-signed-http-exchanges/#prefetch-subresources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most web pages consist of multiple subresources, such as CSS, JavaScript, fonts, and images.
The content of SXG cannot be changed without the content creator&#39;s private key.
This causes problems when the browser tries to resolve subresources.&lt;/p&gt;
&lt;p&gt;For example, suppose &lt;code&gt;index.html.sxg&lt;/code&gt; from &lt;code&gt;https://website.test/index.html&lt;/code&gt; has a link to &lt;code&gt;https://website.test/app.js&lt;/code&gt;. When a user&#39;s browser receives the SXG file from &lt;code&gt;https://distributor.test/example.com/index.html.sxg&lt;/code&gt;, it will find the link to &lt;code&gt;https://website.test/app.js&lt;/code&gt;.
The browser can fetch &lt;code&gt;https://website.test/app.js&lt;/code&gt; directly on actual access, but it should not be done in the preload phase to preserve privacy.
If the resource was fetched during the preload phase, it would be possible for the content creator (&lt;code&gt;website.test&lt;/code&gt;) to be able to detect which content distributor (&lt;code&gt;distributor.test&lt;/code&gt;) is requesting the resource.&lt;/p&gt;
&lt;img alt=&quot;The link to app.js in distributor.test/index.html.sxg points to website.test/app.js.&quot; decoding=&quot;async&quot; height=&quot;214&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/1wbVnJkocJ9cv3lR2wZv.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;If the distributor wants to serve &lt;code&gt;app.js.sxg&lt;/code&gt; from their own service and tries to modify &lt;code&gt;https://website.test/app.js&lt;/code&gt; to be the distributor&#39;s version of that subresource (such as &lt;code&gt;https://distributor.test/website.test/app.js.sxg&lt;/code&gt;), it will cause a signature mismatch and make the SXG invalid.&lt;/p&gt;
&lt;img alt=&quot;An attempt to link the reference to app.js in distributor.test/index.html.sxg to distributor.test/app.js causes a signature mismatch.&quot; decoding=&quot;async&quot; height=&quot;258&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 592px) 592px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/IRRFoXyhnmwVXwiDgeny.png?auto=format&amp;w=1184 1184w&quot; width=&quot;592&quot; /&gt;
&lt;p&gt;To solve this problem, there&#39;s an experimental SXG subresource prefetching feature in Chrome now.
You can enable it at: &lt;code&gt;about://flags/#enable-sxg-subresource-prefetching&lt;/code&gt;.
To use subresource prefetching the following conditions must be met:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The publisher must embed a response header entry in SXG, such as: &lt;code&gt;link: &amp;lt;https://website.test/app.js&amp;gt;;rel=&amp;quot;preload&amp;quot;;as=&amp;quot;script&amp;quot;,&amp;lt;https://website.test/app.js&amp;gt;;rel=&amp;quot;allowed-alt-sxg&amp;quot;;header-integrity=&amp;quot;sha256-h6GuCtTXe2nITIHHpJM+xCxcKrYDpOFcIXjihE4asxk=&amp;quot;&lt;/code&gt;. This specifies the subresource that can be substituted with the SXG&#39;s specific integrity hash.&lt;/li&gt;
&lt;li&gt;The distributor must attach a response header when serving the SXG, such as: &lt;code&gt;link: &amp;lt;https://distributor.test/website.test/app.js.sxg&amp;gt;;rel=&amp;quot;alternate&amp;quot;;type=&amp;quot;application/signed-exchange;v=b3&amp;quot;;anchor=&amp;quot;https://website.test/app.js&amp;quot;&lt;/code&gt;. This specifies the path of &lt;code&gt;app.js&lt;/code&gt; and corresponds to the subresource.&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt=&quot;anchor&quot; decoding=&quot;async&quot; height=&quot;244&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/zsSl4DBys5jv8i5bQ6AT.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The first one is relatively easy because &lt;a href=&quot;https://github.com/google/nginx-sxg-module&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;nginx-sxg-module&lt;/code&gt;&lt;/a&gt; can calculate integrity hashes and embed them into link headers from upstream responses. But the second one is more difficult because the content distributor must be aware of the specified subresources in the SXG.&lt;/p&gt;
&lt;p&gt;If there are no subresources other than &lt;code&gt;https://website.test/app.js&lt;/code&gt;, then all you need to append in your nginx config is:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;add_header&lt;/span&gt; link &amp;lt;https://distributor.test/website.test/app.js.sxg&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;rel=&quot;alter...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;But such cases are rare because typical websites consist of a lot of subresources. Additionally, the distributor must attach the proper anchor link header when serving an SXG file. Currently, there is no easy way to resolve this issue, so stay tuned for updates!&lt;/p&gt;
&lt;h2 id=&quot;send-feedback&quot;&gt;Send feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-distribute-signed-http-exchanges/#send-feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chromium engineers are keen to hear your feedback on distributing SXG at &lt;a href=&quot;mailto:webpackage-dev@chromium.org&quot; rel=&quot;noopener&quot;&gt;webpackage-dev@chromium.org&lt;/a&gt;.
You can also join &lt;a href=&quot;https://github.com/WICG/webpackage/issues&quot; rel=&quot;noopener&quot;&gt;the spec discussion&lt;/a&gt;, or &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/entry?status=untriaged&amp;amp;components=Blink%3ELoader&amp;amp;labels=Type-Bug,Hotlist-SignedExchange&quot; rel=&quot;noopener&quot;&gt;report a bug&lt;/a&gt; to the team.
Your feedback will greatly help the standardization process and also help address implementation issues.
Thank you!&lt;/p&gt;
</content>
    <author>
      <name>Hiroki Kumazaki</name>
    </author>
  </entry>
  
  <entry>
    <title>How to set up Signed HTTP Exchanges (SXG) using nginx</title>
    <link href="https://web.dev/how-to-set-up-signed-http-exchanges/"/>
    <updated>2020-03-11T00:00:00Z</updated>
    <id>https://web.dev/how-to-set-up-signed-http-exchanges/</id>
    <content type="html" mode="escaped">&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/blog/signed-exchanges/&quot; rel=&quot;noopener&quot;&gt;Signed HTTP Exchanges (SXG)&lt;/a&gt; is a new web technology that makes it easier for users to tell content creators apart from content distributors. This guide shows you how to set up SXG.&lt;/p&gt;
&lt;h2 id=&quot;cross-browser-support&quot;&gt;Cross-browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#cross-browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Several Chromium-based browsers support SXG, including Google Chrome, Samsung
Internet, and Microsoft Edge. See the Consensus and Standardization section of
&lt;a href=&quot;https://www.chromestatus.com/feature/5745285984681984&quot; rel=&quot;noopener&quot;&gt;Origin-Signed HTTP Exchanges&lt;/a&gt;
for more up-to-date information.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To implement SXG on your website, you must:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have control over your domain, including DNS entries.&lt;/li&gt;
&lt;li&gt;Get certificates. SXG requires the issuance of a dedicated certificate. In particular, you cannot reuse your TLS key or certificate.&lt;/li&gt;
&lt;li&gt;Have an HTTP server that can generate and serve SXG over HTTPS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;assumptions&quot;&gt;Assumptions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#assumptions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This guide assumes that you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have an OpenSSL 1.1.1 environment. This guide was written with Ubuntu 18.04 LTS on amd64 ISA.&lt;/li&gt;
&lt;li&gt;Have the ability to run &lt;code&gt;sudo&lt;/code&gt; to install executables.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;nginx&lt;/code&gt; as an HTTP server.&lt;/li&gt;
&lt;li&gt;Are using DigiCert to generate certificates that include SXG-related extensions, because it currently appears to be the only provider that supports these extensions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, the example commands in this article assume your domain is &lt;code&gt;website.test&lt;/code&gt;, so you&#39;ll need to replace &lt;code&gt;website.test&lt;/code&gt; with your actual domain.&lt;/p&gt;
&lt;h2 id=&quot;step-1&quot;&gt;Step 1: Get your certificate for SXG &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-1&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To generate SXG, you need a TLS certificate with the &lt;code&gt;CanSignHttpExchanges&lt;/code&gt; extension, as well as a particular key type.
DigiCert provides certificates with this extension.
You need a CSR file for issuance of a certificate, so generate it with the following commands:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl ecparam -genkey -name prime256v1 -out mySxg.key&lt;br /&gt;openssl req -new -key mySxg.key -nodes -out mySxg.csr -subj &lt;span class=&quot;token string&quot;&gt;&quot;/O=Test/C=US/CN=website.test&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You will get a CSR file that looks like the following:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;-----BEGIN CERTIFICATE REQUEST-----&lt;br /&gt;MIHuMIGVAgEAMDMxDTALBgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMRUwEwYDVQQD&lt;br /&gt;DAx3ZWJzaXRlLnRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS7IVaeMvid&lt;br /&gt;S5UO7BspzSe5eqT5Qk6X6dCggUiV/vyqQaFDjA/ALyTofgXpbCaksorPaDhdA+f9&lt;br /&gt;APdHWkTbbdv1oAAwCgYIKoZIzj0EAwIDSAAwRQIhAIb7n7Kcc6Y6pU3vFr8SDNkB&lt;br /&gt;kEadlVKNA24SVZ/hn3fjAiAS2tWXhYdJX6xjf2+DL/smB36MKbXg7VWy0K1tWmFi&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;Sg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;br /&gt;-----END CERTIFICATE REQUEST-----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Make sure that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The validity period does not exceed 90 days.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Include the CanSignHttpExchanges extension in the certificate&lt;/strong&gt; checkbox is enabled,
which is found under Additional Certificate Options.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;img alt=&quot;&quot; decoding=&quot;async&quot; height=&quot;133&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 718px) 718px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kFWTZFXNvwkHnwRu7y8Q.png?auto=format&amp;w=1436 1436w&quot; width=&quot;718&quot; /&gt;
  &lt;figcaption&gt;
    The &lt;b&gt;Include the CanSignHttpExchanges extension in the certificate&lt;/b&gt; checkbox.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If your certificate does not match these conditions, browsers and distributors will reject your SXG for security reasons.
This guide assumes that the filename of the certificate you got from DigiCert is &lt;code&gt;mySxg.pem&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;step-2-install-libsxg&quot;&gt;Step 2: Install &lt;code&gt;libsxg&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-2-install-libsxg&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The SXG format is complex and hard to generate without using tools.
You can use one of the following options to generate SXG:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/WICG/webpackage/tree/main/go/signedexchange&quot; rel=&quot;noopener&quot;&gt;gen-signedexchange&lt;/a&gt; tool written in Go.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/google/libsxg&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;libsxg&lt;/code&gt; library&lt;/a&gt; written in C.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This guide uses &lt;code&gt;libsxg&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;option-1-install-libsxg-from-a-debian-package&quot;&gt;Option 1: Install &lt;code&gt;libsxg&lt;/code&gt; from a Debian package &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#option-1-install-libsxg-from-a-debian-package&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can install the package in the usual Debian way, as long as the OpenSSL (&lt;code&gt;libssl-dev&lt;/code&gt;) version matches.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -y libssl-dev&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; https://github.com/google/libsxg/releases/download/v0.2/libsxg0_0.2-1_amd64.deb&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; https://github.com/google/libsxg/releases/download/v0.2/libsxg-dev_0.2-1_amd64.deb&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; dpkg -i libsxg0_0.2-1_amd64.deb&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; dpkg -i libsxg-dev_0.2-1_amd64.deb&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;option-2-build-libsxg-manually&quot;&gt;Option 2: Build &lt;code&gt;libsxg&lt;/code&gt; manually &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#option-2-build-libsxg-manually&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you are not using an environment compatible with &lt;code&gt;.deb&lt;/code&gt; files, you can build &lt;code&gt;libsxg&lt;/code&gt; yourself.
As a precondition, you need to install &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;cmake&lt;/code&gt;, &lt;code&gt;openssl&lt;/code&gt;, and &lt;code&gt;gcc&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/google/libsxg&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; libsxg/build&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; libsxg/build&lt;br /&gt;cmake &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt; -DRUN_TEST&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;false -DCMAKE_BUILD_TYPE&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;Release&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-3-install-nginx-plugin&quot;&gt;Step 3: Install &lt;code&gt;nginx&lt;/code&gt; plugin &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-3-install-nginx-plugin&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;nginx&lt;/code&gt; plugin allows you to generate SXG dynamically instead of statically generating them prior to serving.&lt;/p&gt;
&lt;h3 id=&quot;step-3-option-1&quot;&gt;Option 1: Install the plugin from a Debian package &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-3-option-1&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/google/nginx-sxg-module&quot; rel=&quot;noopener&quot;&gt;SXG module for &lt;code&gt;nginx&lt;/code&gt;&lt;/a&gt; is distributed on GitHub.
On Debian-based systems, you can install it as a binary package:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -y &lt;span class=&quot;token assign-left variable&quot;&gt;nginx&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.15&lt;/span&gt;.9-0&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; https://github.com/google/nginx-sxg-module/releases/download/v0.1/libnginx-mod-http-sxg-filter_1.15.9-0ubuntu1.1_amd64.deb&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; dpkg -i libnginx-mod-http-sxg-filter_1.15.9-0ubuntu1.1_amd64.deb&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;step-3-option-2&quot;&gt;Option 2: Build plugin manually &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-3-option-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Building the &lt;code&gt;nginx&lt;/code&gt; module requires the &lt;code&gt;nginx&lt;/code&gt; source code.
You can get the tarball and build it along with the SXG dynamic module using the commands below:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/google/nginx-sxg-module&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; https://nginx.org/download/nginx-1.17.5.tar.gz&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;tar&lt;/span&gt; xvf nginx-1.17.5.tar.gz&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; nginx-1.17.5&lt;br /&gt;./configure --prefix&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/opt/nginx --add-dynamic-module&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/nginx-sxg-module --without-http_rewrite_module --with-http_ssl_module&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;nginx&lt;/code&gt; configuration has great flexibility.
Install &lt;code&gt;nginx&lt;/code&gt; anywhere in your system, then specify a respective path of &lt;code&gt;module/config/log/pidfile&lt;/code&gt;.
This guide assumes that you install it to &lt;code&gt;/opt/nginx&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;step-4-configure-the-nginx-plugin-to-work-with-sxg&quot;&gt;Step 4: Configure the &lt;code&gt;nginx&lt;/code&gt; plugin to work with SXG &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-4-configure-the-nginx-plugin-to-work-with-sxg&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;option-1-configure-an-installed-from-debian-nginx-module&quot;&gt;Option 1: Configure an installed-from-Debian &lt;code&gt;nginx&lt;/code&gt; module &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#option-1-configure-an-installed-from-debian-nginx-module&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Follow these instructions if you used &lt;a href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-3-option-1&quot;&gt;Step 3, Option 1&lt;/a&gt; earlier.&lt;/p&gt;
&lt;p&gt;Delivering SXG content requires HTTPS. You can get an SSL/TLS certificate from DigiCert, Let&#39;s Encrypt, and other services. Note that you CANNOT use an SXG certificate for SSL or vice versa, therefore you will need two certificates. The configuration file in &lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt; should look similar to the following, assuming that you put the SSL key/certificate pair in &lt;code&gt;/path/to/ssl/&lt;/code&gt; and the SXG key/certificate pair in &lt;code&gt;/path/to/sxg/&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;user&lt;/span&gt; www-data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt; /etc/nginx/modules-enabled/*.conf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;events&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;worker_connections&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;768&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;http&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;       mime.types&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;default_type&lt;/span&gt;  application/octet-stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;add_header&lt;/span&gt;  X-Content-Type-Options nosniff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt; ssl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl_certificate&lt;/span&gt;     /path/to/ssl/fullchain.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl_certificate_key&lt;/span&gt; /path/to/ssl/privkey.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server_name&lt;/span&gt;  website.test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;on&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_certificate&lt;/span&gt;     /path/to/sxg/mySxg.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_certificate_key&lt;/span&gt; /path/to/sxg/mySxg.key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_cert_url&lt;/span&gt;        https://website.test/certs/cert.cbor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_validity_url&lt;/span&gt;    https://website.test/validity/resource.msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_cert_path&lt;/span&gt;       /certs/cert.cbor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;root&lt;/span&gt; /var/www/html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sxg_cert_url&lt;/code&gt; is essential for browsers to load SXG properly because it locates the certificate chain. The certificate chain contains certificate and OCSP stapling information with cbor format. Note that you do not have to serve the &lt;code&gt;cert.cbor&lt;/code&gt; file from the same origin. You can serve it via any CDNs or other static file serving services as long as it supports HTTPS.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sxg_validitiy_url&lt;/code&gt; is planned to serve SXG-signature-header-related information. If a page has not been modified since the last SXG, downloading the entire SXG file is not required technically. So updating signature header information alone is expected to reduce network traffic. But the details are not implemented yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Start &lt;code&gt;nginx&lt;/code&gt; and you are ready to serve SXG!&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl start nginx.service&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -H&lt;span class=&quot;token string&quot;&gt;&quot;Accept: application/signed-exchange;v=b3&quot;&lt;/span&gt; https://website.test/ &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; index.html.sxg&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; index.html.sxg&lt;br /&gt;sxg1-b3&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.https://website.test/&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;omit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;option-2-configure-a-built-from-source-nginx-module&quot;&gt;Option 2: Configure a built-from-source &lt;code&gt;nginx&lt;/code&gt; module &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#option-2-configure-a-built-from-source-nginx-module&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Follow these instructions if you used &lt;a href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-3-option-2&quot;&gt;Step 3, Option 2&lt;/a&gt; earlier.&lt;/p&gt;
&lt;p&gt;Configure your &lt;code&gt;nginx&lt;/code&gt; system installed under &lt;code&gt;/opt/nginx&lt;/code&gt; to look similar to the following example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;load_module&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/opt/nginx/modules/ngx_http_sxg_filter_module.so&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;events&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;worker_connections&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;768&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;http&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;       mime.types&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;default_type&lt;/span&gt;  application/octet-stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;add_header&lt;/span&gt; X-Content-Type-Options nosniff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt; ssl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl_certificate&lt;/span&gt;     /path/to/ssl/fullchain.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl_certificate_key&lt;/span&gt; /path/to/ssl/privkey.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server_name&lt;/span&gt;  example.com&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;on&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_certificate&lt;/span&gt;     /path/to/sxg/mySxg.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_certificate_key&lt;/span&gt; /path/to/sxg/mySxg.key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_cert_url&lt;/span&gt;        https://website.test/certs/cert.cbor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_validity_url&lt;/span&gt;    https://website.test/validity/resource.msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sxg_cert_path&lt;/span&gt;       /certs/cert.cbor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;root&lt;/span&gt; /opt/nginx/html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then start &lt;code&gt;nginx&lt;/code&gt;. Now you can get your SXG!&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /opt/nginx/sbin&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; ./nginx&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -H &lt;span class=&quot;token string&quot;&gt;&quot;Accept: application/signed-exchange;v=b3&quot;&lt;/span&gt; https://website.test/ &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; index.html.sxg&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;less&lt;/span&gt; index.html.sxg&lt;br /&gt;sxg1-b3&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.https://website.test/&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;omit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-5-serve-your-application-backend&quot;&gt;Step 5: Serve your application backend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-5-serve-your-application-backend&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the above examples, &lt;code&gt;nginx&lt;/code&gt; serves static files in the root directory, but you can use upstream directives for your applications to make SXG for arbitrary web application backends (such as Ruby on Rails, Django, or Express) as long as your &lt;code&gt;nginx&lt;/code&gt; works as a front HTTP(S) server.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;upstream&lt;/span&gt; app&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt; 127.0.0.1:8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;location&lt;/span&gt; /&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_pass&lt;/span&gt; http://app&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-6-test&quot;&gt;Step 6: Test &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#step-6-test&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use the &lt;a href=&quot;https://github.com/WICG/webpackage/tree/main/go/signedexchange&quot; rel=&quot;noopener&quot;&gt;dump-signedexchange tool&lt;/a&gt;
to test that the SXGs being served are correct, ensure that no errors are reported, and verify that the headers
and body are as expected.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;go get -u github.com/WICG/webpackage/go/signedexchange/cmd/dump-signedexchange&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;PATH&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token environment constant&quot;&gt;$PATH&lt;/span&gt;:~/go/bin&lt;br /&gt;dump-signedexchange -verify -uri https://website.test/ &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;less&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;send-feedback&quot;&gt;Send feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-to-set-up-signed-http-exchanges/#send-feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Chromium engineers working on SXG are keen to hear your feedback at &lt;a href=&quot;mailto:webpackage-dev@chromium.org&quot; rel=&quot;noopener&quot;&gt;webpackage-dev@chromium.org&lt;/a&gt;.
You can also join the &lt;a href=&quot;https://github.com/WICG/webpackage/issues&quot; rel=&quot;noopener&quot;&gt;spec discussion&lt;/a&gt;, or &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/entry?status=untriaged&amp;amp;components=Blink%3ELoader&amp;amp;labels=Type-Bug,Hotlist-SignedExchange&quot; rel=&quot;noopener&quot;&gt;report a bug&lt;/a&gt; to the team.
Your feedback will greatly help the standardization process and also help address implementation issues.
Thank you!&lt;/p&gt;
</content>
    <author>
      <name>Hiroki Kumazaki</name>
    </author>
  </entry>
</feed>
