303 lines
12 KiB
HTML
303 lines
12 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="color-scheme" content="dark light" />
|
|
<link rel="icon" type="image/svg+xml" href="/Branding/favicon.svg?v=4" />
|
|
<!-- PNG fallback for browsers that don't support SVG favicons well -->
|
|
<link
|
|
rel="icon"
|
|
type="image/png"
|
|
sizes="32x32"
|
|
href="/Branding/favicon.png?v=4"
|
|
/>
|
|
<link
|
|
rel="shortcut icon"
|
|
type="image/png"
|
|
href="/Branding/app-icon.png?v=4"
|
|
/>
|
|
<link rel="mask-icon" href="/Branding/favicon.svg?v=4" color="#2563eb" />
|
|
<!-- iOS uses PNG for Home Screen icons -->
|
|
<link
|
|
rel="apple-touch-icon"
|
|
sizes="180x180"
|
|
href="/Branding/app-icon.png?v=4"
|
|
/>
|
|
<link rel="manifest" href="/manifest.json" />
|
|
<style>
|
|
:root {
|
|
--tt-blue: #2563eb;
|
|
--tt-navy: #1e40af;
|
|
--tt-google-blue: #3b82f6;
|
|
--tt-green: #16a34a;
|
|
--tt-orange: #f97316;
|
|
--tt-red: #dc2626;
|
|
--tt-grey: #64748b;
|
|
--tt-bg: #f8fafc;
|
|
--tt-neutral: #f1f5f9;
|
|
--font-ui: 'Montserrat', system-ui, sans-serif;
|
|
--font-mono: 'Roboto Mono', Menlo, monospace;
|
|
}
|
|
body {
|
|
font-family: 'Montserrat', 'Montserrat Fallback', system-ui, -apple-system, sans-serif;
|
|
}
|
|
h1,
|
|
h2,
|
|
h3 {
|
|
font-family: 'Archivo Black', 'Archivo Black Fallback', system-ui, sans-serif;
|
|
font-weight: 400;
|
|
}
|
|
.token-value,
|
|
.expiry-pill {
|
|
font-family: var(--font-mono);
|
|
font-size: 1em;
|
|
}
|
|
.expiry-pill {
|
|
border-radius: 8px;
|
|
padding: 2px 15px;
|
|
font-weight: 600;
|
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
|
display: inline-block;
|
|
}
|
|
html,
|
|
body,
|
|
#root {
|
|
height: 100%;
|
|
}
|
|
#root {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
/* Prevent theme class swap CLS */
|
|
body.chakra-ui-light,
|
|
body.chakra-ui-dark {
|
|
transition: none !important;
|
|
}
|
|
/* Background images for non-public pages, driven purely by CSS classes.
|
|
Chakra toggles chakra-ui-dark/light; JS toggles needs-bg on route change. */
|
|
body.needs-bg.chakra-ui-dark {
|
|
background-color: #171923;
|
|
background-image: url('/Branding/background-blue.avif'), url('/Branding/background-blue.png');
|
|
background-repeat: no-repeat;
|
|
background-attachment: fixed;
|
|
background-size: cover;
|
|
background-position: center center;
|
|
}
|
|
body.needs-bg.chakra-ui-light {
|
|
background-color: #ffffff;
|
|
background-image: url('/Branding/background-light.avif');
|
|
background-repeat: no-repeat;
|
|
background-attachment: fixed;
|
|
background-size: cover;
|
|
background-position: center center;
|
|
}
|
|
body:not(.needs-bg) {
|
|
background-image: none !important;
|
|
}
|
|
/* Reserve footer space to prevent CLS during hydration */
|
|
footer, [data-footer-placeholder] {
|
|
min-height: 110px;
|
|
contain: layout paint;
|
|
}
|
|
@media (max-width: 768px) {
|
|
footer, [data-footer-placeholder] {
|
|
min-height: 250px;
|
|
}
|
|
}
|
|
</style>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link rel="preconnect" href="https://eu.i.posthog.com" crossorigin />
|
|
<link
|
|
rel="preload"
|
|
as="style"
|
|
href="https://fonts.googleapis.com/css2?family=Archivo+Black&family=Archivo:wght@600;700&family=Montserrat:wght@400;500;600;700&family=Roboto+Mono:wght@400;500&display=swap"
|
|
onload="this.rel='stylesheet'"
|
|
/>
|
|
<noscript>
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://fonts.googleapis.com/css2?family=Archivo+Black&family=Archivo:wght@600;700&family=Montserrat:wght@400;500;600;700&family=Roboto+Mono:wght@400;500&display=swap"
|
|
/>
|
|
</noscript>
|
|
<style>
|
|
/* Prevent font swap shifting: use fallback metrics */
|
|
@font-face {
|
|
font-family: 'Montserrat Fallback';
|
|
src: local('Arial');
|
|
ascent-override: 90%;
|
|
descent-override: 22%;
|
|
line-gap-override: 0%;
|
|
size-adjust: 110%;
|
|
}
|
|
@font-face {
|
|
font-family: 'Archivo Black Fallback';
|
|
src: local('Arial Black');
|
|
ascent-override: 95%;
|
|
descent-override: 25%;
|
|
line-gap-override: 0%;
|
|
size-adjust: 105%;
|
|
}
|
|
@font-face {
|
|
font-family: 'Roboto Mono Fallback';
|
|
src: local('Courier New');
|
|
ascent-override: 85%;
|
|
descent-override: 20%;
|
|
line-gap-override: 0%;
|
|
size-adjust: 100%;
|
|
}
|
|
/* Apply fallbacks with system fonts */
|
|
body {
|
|
font-family: 'Montserrat', 'Montserrat Fallback', system-ui, -apple-system, sans-serif;
|
|
}
|
|
h1, h2, h3 {
|
|
font-family: 'Archivo Black', 'Archivo Black Fallback', system-ui, sans-serif;
|
|
}
|
|
</style>
|
|
<script>
|
|
// Set initial color mode class and needs-bg class early to avoid flash.
|
|
// Background styling is handled entirely via CSS rules above.
|
|
(function () {
|
|
try {
|
|
var m = localStorage.getItem('chakra-ui-color-mode');
|
|
var prefersDark = window.matchMedia(
|
|
'(prefers-color-scheme: dark)'
|
|
).matches;
|
|
var mode = m || (prefersDark ? 'dark' : 'light');
|
|
document.documentElement.style.colorScheme = mode;
|
|
// Scope theme at the root to prevent stale dark scoping on body
|
|
document.documentElement.setAttribute('data-theme', mode);
|
|
|
|
var applyToBody = function () {
|
|
try {
|
|
var b = document.body;
|
|
if (!b) return;
|
|
// Ensure body does not carry data-theme that could override root
|
|
b.removeAttribute('data-theme');
|
|
b.classList.remove('chakra-ui-light', 'chakra-ui-dark');
|
|
b.classList.add(
|
|
mode === 'dark' ? 'chakra-ui-dark' : 'chakra-ui-light'
|
|
);
|
|
|
|
var p = location.pathname.replace(/\/+$/, '') || '/';
|
|
var pub = ['/','/pricing','/privacy-policy','/terms-of-service','/solutions','/blog','/compare','/faq','/contact','/about','/security'];
|
|
var isPublic = pub.some(function(v){ return v === '/' ? p === '/' : p.indexOf(v) === 0; });
|
|
if (!isPublic) {
|
|
b.classList.add('needs-bg');
|
|
}
|
|
} catch (e) {}
|
|
};
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', applyToBody);
|
|
} else {
|
|
applyToBody();
|
|
}
|
|
} catch (e) {}
|
|
})();
|
|
</script>
|
|
<link
|
|
rel="preload"
|
|
as="image"
|
|
href="/Branding/logo.svg"
|
|
imagesrcset="/Branding/logo.svg 1x"
|
|
fetchpriority="high"
|
|
/>
|
|
<!-- Google Preferred Sources: lets readers add tokentimer.ch as a preferred source in Search/AI features -->
|
|
<script async src="https://news.google.com/swg/js/v1/publisher.js"></script>
|
|
<script type="module" crossorigin src="/assets/index-CrzAQ2t9.js"></script>
|
|
<link rel="modulepreload" crossorigin href="/assets/vendor-chakra-D4J0HJdd.js">
|
|
<link rel="modulepreload" crossorigin href="/assets/vendor-analytics-DZdTKst9.js">
|
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BtLk48lw.js">
|
|
<link rel="stylesheet" crossorigin href="/assets/index-PDkSgity.css">
|
|
|
|
<!-- Pre-rendered Open Graph tags for social media -->
|
|
<meta property="og:type" content="article" />
|
|
<meta property="og:url" content="https://tokentimer.ch/blog/tls-certificate-expiry-outages" />
|
|
<meta property="og:title" content="Certificate Expiry Is Still Taking Down Major Platforms" />
|
|
<meta property="og:description" content="Tailscale, jsDelivr, ServiceNow, and IPinfo went down after certificate renewals failed silently. Learn what monitoring missed and how CertOps closes the gap." />
|
|
<meta property="og:image" content="https://tokentimer.ch/Branding/social-share.png" />
|
|
<meta property="og:image:secure_url" content="https://tokentimer.ch/Branding/social-share.png" />
|
|
<meta property="og:image:width" content="1200" />
|
|
<meta property="og:image:height" content="627" />
|
|
<meta property="og:image:alt" content="TokenTimer" />
|
|
<meta property="og:site_name" content="TokenTimer" />
|
|
<meta property="og:locale" content="en_US" />
|
|
<meta property="article:author" content="Franz Alliod" />
|
|
<meta property="article:published_time" content="2026-08-12T00:00:00Z" />
|
|
<meta property="article:modified_time" content="2026-08-12T00:00:00Z" />
|
|
|
|
<!-- Pre-rendered Twitter Card tags -->
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta name="twitter:url" content="https://tokentimer.ch/blog/tls-certificate-expiry-outages" />
|
|
<meta name="twitter:title" content="Certificate Expiry Is Still Taking Down Major Platforms" />
|
|
<meta name="twitter:description" content="Tailscale, jsDelivr, ServiceNow, and IPinfo went down after certificate renewals failed silently. Learn what monitoring missed and how CertOps closes the gap." />
|
|
<meta name="twitter:image" content="https://tokentimer.ch/Branding/social-share.png" />
|
|
<meta name="twitter:site" content="@tokentimer" />
|
|
<meta name="twitter:creator" content="@tokentimer" />
|
|
|
|
<!-- Pre-rendered Page Info -->
|
|
<meta name="author" content="Franz Alliod" />
|
|
<title>Certificate Expiry Is Still Taking Down Major Platforms | TokenTimer</title>
|
|
<meta name="description" content="Tailscale, jsDelivr, ServiceNow, and IPinfo went down after certificate renewals failed silently. Learn what monitoring missed and how CertOps closes the gap." />
|
|
<link rel="canonical" href="https://tokentimer.ch/blog/tls-certificate-expiry-outages" />
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
<!-- Runtime env variables (tiny ~100 bytes, cached) - must load before module -->
|
|
<script src="/env.js"></script>
|
|
<!-- Google Analytics (optional, consent-gated via env.js if needed) -->
|
|
<script>
|
|
(function () {
|
|
try {
|
|
var env = window.__ENV__ || {};
|
|
if (!env.GA_MEASUREMENT_ID) return;
|
|
var s = document.createElement('script');
|
|
s.async = true;
|
|
s.src =
|
|
'https://www.googletagmanager.com/gtag/js?id=' +
|
|
encodeURIComponent(env.GA_MEASUREMENT_ID);
|
|
document.head.appendChild(s);
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag() {
|
|
dataLayer.push(arguments);
|
|
}
|
|
window.gtag = gtag;
|
|
gtag('js', new Date());
|
|
gtag('config', env.GA_MEASUREMENT_ID, { anonymize_ip: true });
|
|
} catch (e) {}
|
|
})();
|
|
</script>
|
|
<noscript>
|
|
<div
|
|
style="
|
|
padding: 16px;
|
|
font-family:
|
|
system-ui,
|
|
Segoe UI,
|
|
Roboto,
|
|
Helvetica,
|
|
Arial,
|
|
sans-serif;
|
|
"
|
|
>
|
|
<h2>
|
|
TokenTimer - Expiration monitoring for tokens, secrets, and credentials
|
|
</h2>
|
|
<p>
|
|
TokenTimer helps teams track expiring API keys, secrets, service
|
|
accounts, certificates, licenses, and subscriptions with ownership,
|
|
proactive alerts, and audit history.
|
|
</p>
|
|
<ul>
|
|
<li><a href="/pricing">Pricing</a></li>
|
|
<li><a href="/help">Help</a></li>
|
|
<li><a href="/privacy-policy">Privacy Policy</a></li>
|
|
<li><a href="/terms-of-service">Terms of Service</a></li>
|
|
</ul>
|
|
</div>
|
|
</noscript>
|
|
</body>
|
|
</html>
|