gps-license: GetPageSpeed license and update-telemetry module
Debian/Ubuntu installation
These docs apply to the APT package nginx-module-gps-license provided by the GetPageSpeed Extras repository.
- Configure the APT repository as described in APT repository setup.
- Install the module:
sudo apt-get update
sudo apt-get install nginx-module-gps-license
Warning
This module is not yet published as nginx-module-gps-license in the APT repositories. Stay tuned, or email [email protected] to request it.
GetPageSpeed License Module for nginx. Validates JWT-based license tokens, reports usage telemetry, and exposes license state via nginx variables.
Overview
This module provides license validation for nginx-mod packages distributed via GetPageSpeed. It supports:
- JWT token validation with RS256 signatures
- Shared memory caching of license state
- Grace period for expired licenses (90 days)
- Soft/footer/hard enforcement modes
- nginx variables for license status
Note: Usage telemetry reporting is planned for a future version.
Configuration
Directives
gps_license_zone
Syntax: gps_license_zone zone=name:size
Context: http
Default: —
Defines shared memory zone for caching license state.
http {
gps_license_zone zone=license:1m;
}
gps_license
Syntax: gps_license on | off
Context: http, server, location
Default: off
Enables license checking for requests.
gps_license_token
Syntax: gps_license_token path | env:VAR_NAME
Context: http
Default: —
Path to JWT token file or environment variable name.
gps_license_token /etc/nginx/license.jwt;
## OR
gps_license_token env:GPS_LICENSE_TOKEN;
gps_license_enforcement
Syntax: gps_license_enforcement soft | footer | hard
Context: http, server, location
Default: soft
Enforcement mode:
- soft: Log warnings, continue serving traffic
- footer: Continue serving traffic, but append a visible GetPageSpeed
notice to unlicensed text/html responses (free-trial watermark). The
footer disappears as soon as a valid license token is installed.
Responses that are pre-compressed upstream (Content-Encoding set),
non-HTML, non-200, or subrequests are never touched. Locally produced
gzip is fine — the filter runs before the gzip filter.
- hard: Return 503 with error details
The backend report response may override the configured mode (field
enforcement: "soft" | "footer" | "hard"); a backend-pushed value takes
precedence over local config until the next restart.
gps_license_report_endpoint
Syntax: gps_license_report_endpoint url
Context: http
Default: https://www.getpagespeed.com/wp-json/getpagespeed/v1/license/report
URL for usage reporting (not yet implemented).
gps_license_report_interval
Syntax: gps_license_report_interval time
Context: http
Default: 1h
Interval between usage reports (not yet implemented).
gps_license_grace_period
Syntax: gps_license_grace_period time
Context: http
Default: 90d
Grace period after license expiration.
Variables
| Variable | Description |
|---|---|
$gps_license_valid |
"1" if valid or in grace, "0" otherwise |
$gps_license_tier |
License tier ("ultra", "plus", "standard") |
$gps_license_expires |
Expiration timestamp |
$gps_license_grace |
"1" if in grace period, "0" otherwise |
$gps_license_enforcement |
Current enforcement mode |
Example Configuration
http {
gps_license_zone zone=license:1m;
server {
listen 80;
server_name example.com;
gps_license on;
gps_license_token /etc/nginx/license.jwt;
gps_license_enforcement soft;
# Log license state
log_format license '$remote_addr - $gps_license_tier [$gps_license_valid]';
location / {
root /var/www/html;
# Add license header for debugging
add_header X-License-Tier $gps_license_tier;
}
}
}
Error Responses
When gps_license_enforcement hard and license is invalid:
HTTP 503 with headers:
- X-GPS-License-Error: missing|invalid|expired|revoked
Response body:
GetPageSpeed License Error: expired
Your nginx-mod license is not valid.
Visit https://www.getpagespeed.com/repo-subscribe to get a license.
JWT Token Format
Tokens are signed with RS256 and contain:
{
"iss": "getpagespeed.com",
"aud": "nginx-mod",
"sub": "I-XXXXXXXXX",
"exp": 1234567890,
"tier": "ultra",
"jti": "uuid-v4",
"client_id": 12345,
"features": {
"reposync_allowed": true
}
}
Public Key
The RSA public key is embedded at compile time. Key rotation requires module rebuild.
Important Notes
nginx Request Phases
The license module runs in the ACCESS_PHASE. Some nginx directives run in earlier phases and will bypass license checking:
returnandrewrite ... lastrun in REWRITE_PHASE (before ACCESS_PHASE)error_pageredirects may bypass the check
For license enforcement to work, use content handlers like proxy_pass,
fastcgi_pass, try_files, or static file serving with root/alias.
## WRONG - return runs before license check
location / {
gps_license on;
gps_license_enforcement hard;
return 200 "OK"; # Bypasses license check!
}
## CORRECT - static files trigger ACCESS_PHASE
location / {
gps_license on;
gps_license_enforcement hard;
root /var/www/html;
}
## CORRECT - proxy_pass triggers ACCESS_PHASE
location / {
gps_license on;
gps_license_enforcement hard;
proxy_pass http://backend;
}
gps_license_token Location
The gps_license_token directive must be in the http {} block (not in
server or location blocks) because license validation happens once at
worker startup, not per-request.