Initial commit: Cloudflare DNS management with Pulumi

This commit is contained in:
Adam Jones 2026-01-06 12:14:47 +00:00 • committed by Adam Jones
commit d8d2f39c99
No known key found for this signature in database
4 changed files with 3748 additions and 0 deletions

61
src/config/records.ts Normal file
View file

@ -0,0 +1,61 @@
import type { RecordType } from './utils';
export const DNS_RECORDS: Record<string, DnsRecordConfig[]> = {
'modelcontextprotocol.io': [
// Root domain
{ subdomain: '@', type: 'A', content: '76.76.21.21', proxied: false },
// Spec subdomain
{ subdomain: 'spec', type: 'A', content: '76.76.21.21', proxied: false },
// Registry
{ subdomain: 'registry', type: 'CNAME', content: 'prod.registry.modelcontextprotocol.io', proxied: false },
{ subdomain: 'prod.registry', type: 'A', content: '34.61.200.254', proxied: false },
{ subdomain: 'staging.registry', type: 'A', content: '35.222.36.75', proxied: false },
{ subdomain: 'grafana.prod.registry', type: 'A', content: '34.61.200.254', proxied: false },
{ subdomain: 'grafana.staging.registry', type: 'A', content: '35.222.36.75', proxied: false },
// GitHub Pages sites
{ subdomain: 'blog', type: 'CNAME', content: 'modelcontextprotocol.github.io', proxied: false },
{ subdomain: 'example-client', type: 'CNAME', content: 'modelcontextprotocol.github.io', proxied: false },
{ subdomain: 'static', type: 'CNAME', content: 'modelcontextprotocol.github.io', proxied: false },
// Other subdomains
{ subdomain: 'example-server', type: 'CNAME', content: 'ghs.googlehosted.com', proxied: true },
{ subdomain: 'meet', type: 'CNAME', content: 'mcp.meetable.org', proxied: false },
// MX record for Google Workspace
{ subdomain: '@', type: 'MX', content: 'smtp.google.com', priority: 1, comment: 'ITOPS-9980' },
// SPF record
{ subdomain: '@', type: 'TXT', content: 'v=spf1 include:_spf.google.com ~all' },
// DKIM for Google Workspace
{
subdomain: 'google._domainkey',
type: 'TXT',
content:
'v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtwBNpASgdq3T9tXSFRh3tu9s6bLVBeGtug5Tv5f5D9K2G8n3Ov7KgR8IEyIgWaVuFf+z82NUBtXlDfKRxRu6s9ND+SqPkgVey2IVx4VuHHUJMAC1f4Wst7ZAUmyeo9lf6PpPb7xzr4nSVbN9jbIFDAajsCe+M9TYdkIU9PXdraYpIVc6b+vE7EaiaCdXNWHzIVjo4wFBz4UsNKG1UsO53GZNyXfnxFFPQppaNYEXOfblYtxgW4BhKpBQhT9fC07EKyoUApe2AC8rcX83HBOKKvISR6TbMruv5p82lz1veIcpixRkZfIFDlxMF66yzFs5qdfY8ztRHbri4kw4DVygmwIDAQAB',
comment: 'ITOPS-9980',
},
// Google site verifications
{ subdomain: '@', type: 'TXT', content: 'google-site-verification=0jJ1JQ6pdBjRe2r6UCzi2RJbsjvglJUmekPb5rpUQXQ' },
{ subdomain: '@', type: 'TXT', content: 'google-site-verification=UI0Tjq-ecUgNu3kFATkW87qcabX6kTljsbYjms2-FdQ' },
// Other TXT verifications
{ subdomain: '@', type: 'TXT', content: 'czyymtp25a' },
{ subdomain: '_gh-modelcontextprotocol-o', type: 'TXT', content: '8f29e697fc' },
{ subdomain: '_github-pages-challenge-modelcontextprotocol.blog', type: 'TXT', content: '1d4b431f4dc23d532fd33da4596bcf' },
],
};
interface DnsRecordConfig {
subdomain: string;
type: RecordType;
content: string;
ttl?: number;
proxied?: boolean;
priority?: number;
comment?: string;
}

20
src/config/utils.ts Normal file
View file

@ -0,0 +1,20 @@
export type RecordType =
| 'A'
| 'AAAA'
| 'CAA'
| 'CNAME'
| 'DNSKEY'
| 'DS'
| 'HTTPS'
| 'LOC'
| 'MX'
| 'NAPTR'
| 'NS'
| 'PTR'
| 'SMIMEA'
| 'SRV'
| 'SSHFP'
| 'SVCB'
| 'TLSA'
| 'TXT'
| 'URI';

38
src/dns.ts Normal file
View file

@ -0,0 +1,38 @@
import * as pulumi from '@pulumi/pulumi';
import * as cloudflare from '@pulumi/cloudflare';
import { DNS_RECORDS } from './config/records';
const config = new pulumi.Config();
const accountId = config.require('cloudflareAccountId');
for (const [domain, records] of Object.entries(DNS_RECORDS)) {
const zone = cloudflare.getZoneOutput({
filter: {
name: domain,
account: { id: accountId },
},
});
// Track counts for generating unique names when same subdomain+type appears multiple times
const nameCounts: Record<string, number> = {};
for (const record of records) {
const baseKey = `${record.subdomain}-${record.type}`;
const count = nameCounts[baseKey] ?? 0;
nameCounts[baseKey] = count + 1;
// e.g., "modelcontextprotocol.io-@-A" or "modelcontextprotocol.io-@-TXT-2" for duplicates
const resourceName = count === 0 ? `${domain}-${baseKey}` : `${domain}-${baseKey}-${count + 1}`;
new cloudflare.DnsRecord(resourceName, {
zoneId: zone.id,
name: record.subdomain,
type: record.type,
content: record.content,
ttl: record.ttl ?? 1,
proxied: record.proxied ?? false,
priority: record.priority,
comment: record.comment,
});
}
}

1
src/index.ts Normal file
View file

@ -0,0 +1 @@
export * from './dns';