Amppackager
Tool to improve AMP URLs via Signed Exchanges
Install / Use
/learn @ampproject/AmppackagerREADME
AMP Packager
AMP Packager is a tool to improve AMP URLs by serving AMP using Signed Exchanges. By running it in a proper configuration, web publishers enable origin URLs to appear in AMP search results.
The AMP Packager works by creating Signed HTTP
Exchanges (SXGs)
containing AMP documents, signed with a certificate associated with the origin,
with a maximum lifetime of 7 days. The Google AMP
Cache will fetch,
cache, and serve them, similar to what it does for normal AMP HTML documents.
When a user loads such an SXG, Chrome validates the signature and then displays
the certificate's domain in the URL bar instead of google.com, and treats the
web page as though it were on that domain.
The packager is an HTTP server that sits behind a frontend server; it fetches and signs AMP documents as requested by the AMP Cache.
As an alternative to running the packager, you can sign up for one of the SXG service providers.
Packager/Signer
How to use
In all the instructions below, replace amppackageexample.com with a domain you
own and can obtain certificates for.
Development server
Manual installation
-
Install Go version 1.13 or higher.
-
Get amppackager.
git clone https://github.com/ampproject/amppackager.git my-amp-directory cd my-amp-directory make build -
Optionally, move the built
amppkgwherever you like. -
Prepare a temporary certificate and private key pair to use for signing the exchange when testing your config. Follow WICG instructions to ensure compliance with the WICG certificate requirements.
-
Create a file
amppkg.toml. A minimal config looks like this:LocalOnly = true CertFile = 'path/to/fullchain.pem' KeyFile = 'path/to/privkey.pem' OCSPCache = '/tmp/amppkg-ocsp' [[URLSet]] [URLSet.Sign] Domain = "amppackageexample.com"More details can be found in amppkg.example.toml.
-
amppkg -developmentIf
amppkg.tomlis not in the current working directory, pass-config=/path/to/amppkg.toml.
Docker
Follow the instructions here on how to deploy a local Docker container.
Test your config
- Run Chrome with the following command line flags:
alias chrome = [FULL PATH TO CHROME BINARY] PATH_TO_FULLCHAIN_PEM = [FULL PATH TO fullchain.pem] chrome --user-data-dir=/tmp/udd\ --ignore-certificate-errors-spki-list=$(\ openssl x509 -pubkey -noout -in $PATH_TO_FULLCHAIN_PEM |\ openssl pkey -pubin -outform der |\ openssl dgst -sha256 -binary | base64)\ --enable-features=SignedHTTPExchange\ 'data:text/html,<a href="https://localhost:8080/priv/doc/https://amppackageexample.com/">click me' - Open DevTools. Check 'Preserve log'.
- Click the
click melink. - Watch the URL transmogrify! Verify it came from an SXG by switching
DevTools to the Network tab and looking in the
Sizecolumn for(from signed-exchange)and in theTypecolumn forsigned-exchange. Click on that row and then click on the Preview tab, to see if there are any errors.
Demonstrate privacy-preserving prefetch
This step is optional; just to show how privacy-preserving prefetch works with SXGs.
go get -u github.com/ampproject/amppackager/cmd/amppkg_dl_sxg.amppkg_dl_sxg https://localhost:8080/priv/doc/https://amppackageexample.com/- Stop
amppkgwith Ctrl-C. go get -u github.com/ampproject/amppackager/cmd/amppkg_test_cache.amppkg_test_cache- Open Chrome and DevTools, as above.
- Visit
https://localhost:8000/. Observe the prefetch of/test.sxg. - Click the link. Observe that the cached SXG is used.
Productionizing
For now, productionizing is a bit manual. The minimum steps are:
-
Don't pass
-developmentflag toamppkg. This causes it to serve HTTP rather than HTTPS, among other changes. -
Don't expose
amppkgto the outside world; keep it on your internal network. -
Configure your TLS-serving frontend server to conditionally proxy to
amppkg:-
If the URL starts with
/amppkg/, forward the request unmodified. -
If the URL points to an AMP page and the
AMP-Cache-Transformrequest header is present, rewrite the URL by prepending/priv/docand forward the request.NOTE: If using nginx, prefer using
proxy_passwith$request_uri, rather than usingrewrite, as in this PR, to avoid percent-encoding issues. -
If at all possible, don't send URLs of non-AMP pages to
amppkg; its transforms may break non-AMP HTML. -
DO NOT forward
/priv/docrequests; these URLs are meant to be generated by the frontend server only.
-
-
For HTTP compliance, ensure the
Varyheader set toAMP-Cache-Transform, Acceptfor all URLs that point to an AMP page, irrespective of whether the response is HTML or SXG. (SXG responses that come fromamppkgwill have the appropriateVaryheader set, so it may only be necessary to explicitly set theVaryheader for HTML responses.) -
Get an SXG cert from your CA. It must use an EC key with the prime256v1 algorithm, and it must have a CanSignHttpExchanges extension. One provider of SXG certs is DigiCert. You MUST use this in
amppkg.toml, and MUST NOT use it in your frontend. -
Every 90 days or sooner, renew your SXG cert (per WICG/webpackage#383) and restart amppkg (per #93).
-
Keep amppkg updated from
releases(the default branch, sogo getworks) about every ~2 months. The wg-caching team will release a new version approximately this often. Soon after each release, Googlebot will increment the version it requests withAMP-Cache-Transform. Googlebot will only allow the latest 2-3 versions (details are still TBD), so an update is necessary but not immediately. If amppkg doesn't support the requested version range, it will fall back to serving unsigned AMP.To keep subscribed to releases, you can select "Releases only" from the "Watch" dropdown in GitHub, or use various tools to subscribe to the
releasesbranch.
You may also want to:
- Launch
amppkgas a restricted user. - Save its stdout to a rotated log somewhere.
- Use the provided tools to verify that your published AMP documents are valid, for instance just before publication, or with a regular audit of a sample of documents. The transforms are designed to work on valid AMP pages, and may break invalid AMP in small ways.
- Setup
monitoring
of
amppackagerand related requests to AMP document server.
Once you've done the above, you should be able to test by launching Chrome
without any command line flags. To test by visiting the packager URL directly,
first add a Chrome extension to send an AMP-Cache-Transform: any request
header. Otherwise, follow the above "Demonstrate privacy-preserving prefetch"
instructions.
Security Considerations
Signed exchanges come with some security considerations that publishers should consider. A starting list of recommendations based on that:
- Use different keys for the signed exchange cert and the TLS cert.
- Only sign public content that's OK to be shared with crawlers.
- Don't sign personalized content. (It's OK to sign content that includes static JS that adds personalization at runtime.)
- Be careful when signing inline JS; if it includes a vulnerability, it may be possible for attackers to exploit it without intercepting the network path, for up to 7 days.
Testing productionization without a valid certificate
It is possible to test an otherwise fully production configuration without
obtaining a certificate with the CanSignHttpExchanges extension. amppkg
still needs to perform OCSP verification, so the Issuer CA must be valid (i.e.
no self-signed certificates). e.g. You can use a certificate from Let's
Encrypt.
Running amppkg with the -invalidcert flag will skip the check for
CanSignHttpExchanges. This flag is not necessary when using the
-development flag.
Chrome can be configured to allow these invalid certificates with the `--ignore-cert
