Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/dns.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ name: dns
on:
pull_request:
paths:
- "dns/**"
- "dns/rubyci.org/**"
- ".github/workflows/dns.yml"
push:
branches:
- master
paths:
- "dns/**"
- "dns/rubyci.org/**"
- ".github/workflows/dns.yml"

permissions:
Expand All @@ -19,13 +19,14 @@ env:
DNSCONTROL_VERSION: 4.44.1

jobs:
# Only rubyci.org is applied from CI. ruby-lang.org is pushed by hand; see dns/README.md.
dns:
# Secrets are unavailable to fork PRs, so run only for same-repo events
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
defaults:
run:
working-directory: dns
working-directory: dns/rubyci.org
steps:
- uses: actions/checkout@v5
- name: Install dnscontrol
Expand All @@ -36,9 +37,9 @@ jobs:
if: github.event_name == 'pull_request'
run: dnscontrol preview --creds creds.json
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_API_TOKEN_RUBYCI: ${{ secrets.CLOUDFLARE_API_TOKEN_RUBYCI }}
- name: Push
if: github.event_name == 'push'
run: dnscontrol push --creds creds.json
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_API_TOKEN_RUBYCI: ${{ secrets.CLOUDFLARE_API_TOKEN_RUBYCI }}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Prepare environment for hocho apply

After launching a VM and assigning the Elastic IP (DNS records are managed under `dns/`), bootstrap the host with the cloud image's default user:
After launching a VM and assigning the Elastic IP (DNS records are managed under `dns/rubyci.org/`, see `dns/README.md`), bootstrap the host with the cloud image's default user:

```bash
bin/bootstrap -i ~/.ssh/aws-keypair.pem fedora@fedora44-arm.rubyci.org
Expand Down
2 changes: 1 addition & 1 deletion cdn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The `ftp` service has been dormant since 2018 and is kept with `activate = false

The `logs.rubyci.org` service fronts the public `rubyci` S3 bucket (chkbuild logs). Switching rubyci.org log links over to it happens in the ruby/rubyci repository.

Bootstrapping a domain on a new TLS subscription takes three steps, because the ACME challenge has to resolve before Fastly will issue: `terraform apply`, then add the challenge CNAME from `terraform output logs_rubyci_managed_dns_challenges` to `dns/dnsconfig.js` and push it, then add the domain CNAME once the subscription reaches `issued`. The challenge record stays in `dnsconfig.js` afterwards, since renewal reuses it.
Bootstrapping a domain on a new TLS subscription takes three steps, because the ACME challenge has to resolve before Fastly will issue: `terraform apply`, then add the challenge CNAME from `terraform output logs_rubyci_managed_dns_challenges` to `dns/rubyci.org/dnsconfig.js` and push it, then add the domain CNAME once the subscription reaches `issued`. The challenge record stays in `dnsconfig.js` afterwards, since renewal reuses it.

Two things about the Fastly API token. It needs the TLS management permission, which is only settable when the automation token is created; without it `fastly_tls_subscription` fails with a bare `403 - Forbidden`. And this account has no default TLS configuration, so `configuration_id` is required, which also decides the CNAME target the domain points at.

Expand Down
31 changes: 31 additions & 0 deletions dns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# dns

DNSControl configuration for the Cloudflare zones. One directory per zone, each holding its own `dnsconfig.js` and `creds.json`.

- `rubyci.org/` — the CI hosts. Every rubyci host is resolved through DNS rather than `~/.ssh/config`, so a new host needs its record here before `bin/hocho apply`. The apex uses Cloudflare's CNAME flattening, which DNSControl expresses as `ALIAS`.
- `ruby-lang.org/` — the project zone.

The API tokens are zone-scoped and therefore different per zone, so each `creds.json` reads an environment variable named after its zone. `rubyci.org/creds.json` reads `CLOUDFLARE_API_TOKEN_RUBYCI` and `ruby-lang.org/creds.json` reads `CLOUDFLARE_API_TOKEN_RUBY_LANG_ORG`.

## rubyci.org

Applied from CI by `.github/workflows/dns.yml`: a pull request runs `dnscontrol preview`, and merging to `master` runs `dnscontrol push`. The token comes from the repository secret `CLOUDFLARE_API_TOKEN_RUBYCI`.

To preview locally:

```
source ~/.config/cloudflare/rubyci.org/token.sh
cd dns/rubyci.org
dnscontrol preview --creds creds.json
```

## ruby-lang.org

Not applied from CI. The zone is shared with other maintainers, so `push` is run by hand after the change is reviewed:

```
source ~/.config/cloudflare/ruby-lang.org/token.sh
cd dns/ruby-lang.org
dnscontrol preview --creds creds.json
dnscontrol push --creds creds.json
```
6 changes: 6 additions & 0 deletions dns/ruby-lang.org/creds.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cloudflare": {
"TYPE": "CLOUDFLAREAPI",
"apitoken": "$CLOUDFLARE_API_TOKEN_RUBY_LANG_ORG"
}
}
59 changes: 59 additions & 0 deletions dns/ruby-lang.org/dnsconfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
var DSP_CLOUDFLARE = NewDnsProvider("cloudflare");
var REG_NONE = NewRegistrar("none");

D("ruby-lang.org", REG_NONE,
DnsProvider(DSP_CLOUDFLARE),
DefaultTTL(1),
A("doc", "18.178.72.192"),
A("docs-2020", "18.178.72.192"),
A("docs-origin", "18.178.72.192"),
A("gem-codesearch.dev", "18.180.198.97"),
A("git", "52.192.80.219"),
A("mame.dev", "18.180.198.97"),
A("ml", "94.130.110.93"),
// GitHub Pages apex addresses for www.ruby-lang.org.
A("@", "185.199.111.153"),
A("@", "185.199.110.153"),
A("@", "185.199.109.153"),
A("@", "185.199.108.153"),
AAAA("ml", "2a01:4f8:1c0c:6b10::1"),
CNAME("_acme-challenge", "rxvnnzqvc8fpc7ws1w.fastly-validations.com."),
CNAME("archive", "dualstack.m.shared.global.fastly.net."),
CNAME("blade", "infinite-mayflower-abjfcuhrpvgf9g7g8a4rmwq8.herokudns.com."),
CNAME("bugs", "bugs.ruby-lang.org.herokudns.com."),
CNAME("cache", "dualstack.m.shared.global.fastly.net."),
CNAME("ci", "git.ruby-lang.org."),
CNAME("cvs", "git.ruby-lang.org."),
CNAME("docs", "dualstack.m.shared.global.fastly.net."),
CNAME("em5188", "u313651.wl152.sendgrid.net."),
CNAME("ftp", "dualstack.m.shared.global.fastly.net."),
CNAME("lists", "ext-sq.squarespace.com."),
CNAME("redmine", "bugs.ruby-lang.org.herokudns.com."),
CNAME("s1._domainkey", "s1.domainkey.u313651.wl152.sendgrid.net."),
CNAME("s2._domainkey", "s2.domainkey.u313651.wl152.sendgrid.net."),
CNAME("speed", "rubybench.github.io."),
CNAME("svn", "git.ruby-lang.org."),
CNAME("try", "ruby.github.io."),
CNAME("www", "ruby.github.io."),
MX("git", 10, "git.ruby-lang.org."),
MX("g", 10, "alt4.aspmx.l.google.com."),
MX("g", 10, "alt3.aspmx.l.google.com."),
MX("g", 5, "alt2.aspmx.l.google.com."),
MX("g", 5, "alt1.aspmx.l.google.com."),
MX("g", 1, "aspmx.l.google.com."),
MX("ml", 10, "nue.mailmanlists.eu."),
TXT("_dmarc.ml", "v=DMARC1; p=quarantine; rua=mailto:dmarc@nue.mailmanlists.eu; ruf=mailto:dmarc@nue.mailmanlists.eu"),
TXT("_dmarc", "v=DMARC1;p=none"),
TXT("_github-challenge-ruby", "d1d1ebcf87"),
TXT("_github-challenge-ruby.www", "130b9370c3"),
TXT("_github-pages-challenge-rubybench.speed", "bb3aa7c4fca5a93c67c29e37e31a28"),
TXT("_github-pages-challenge-ruby", "7945b3c0777b14c533ce1a058058ea"),
TXT("_github-pages-challenge-ruby.try", "0c8a06ccf14e008aa2120723c94bd3"),
TXT("google._domainkey.g", "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnQOXdwH6epkMSB4stgVaQpx+Hx+pcvNkot5b+14uEjN0aueiGzN+ut78QNqWzE8zdJH+oIaV2CPf4MKP5dzwS/wexm50ZUGGcMnMEMXqihTBnxKEOLz0M9Z3XZ1r059dLCtDizFNvVDKlDrFiS0UTqgJxHQ98T+Kh6gwEnaNvktoz2riEXlvVET8tet0FDCXQN+re4MaJkhGgiezezZpfW0Rpjn9WrS60i2YlUYf7qEhS6mqdF7f0GxO6wVz7sfNDfb70m8S+KLV3C5LoiiKhKGk+pBByV2ybVmYx4WaCVnvrYGVf8yLLoxxG3pLGx+/qeTkbRTyY9dn1mfh/6KDuQIDAQAB"),
TXT("google._domainkey", "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAooSJ0AtdVuBRVrS7D+I9nYTppJFeRgtAlpbJufWZLPNg9lu1k5PZnbIvxxP/KcMcTtxch2X2Lfg+JCdn3NSJRx9Tx9DM0p9/1odOxotNiED1g6bDrUwjPKhMqkUgx+jJ/W8NmJGGItYe50Nr2ADgsUczd7YWVnnNEU2EZTglD1/tE5eQsA0/9XEFi8mugbTN2Bme/VVu81X1r04xd6D3a95b3bTXRBEX8S/4T3O2d4MoVmEyBBzfMJ4CQmcgxTFLgMKqoKwT4OzOu2JFbTeisAMox89XtX11jnyYa2M2gSH15ovgWM+pow6eGOgHUWBbTNKB/ssLhKVrbJbeedGPBQIDAQAB"),
TXT("mail._domainkey.ml", "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDa9srBE8/dR7UT1VuXn7RD/MrtShhXQVBugaw8vpD0BJYQ3zsq7O+pF7EVMKwIAoPZeXFLA1eLpihhFExGrOFit+XEz54Le1Fvsnw3Blcc8Ul4UXjpb7NJfS8CcMUXiJFEZVanjs3A1d8BCedFRYN1kCXNqTtQ7LK/2xBJNCyKDwIDAQAB"),
TXT("ml", "v=spf1 a mx ip4:94.130.110.93 ip6:2a01:4f8:1c0c:6b10::1 ~all"),
TXT("@", "TICKET-9336"),
TXT("@", "twufyqeoih"),
TXT("@", "v=spf1 include:_spf.mx.cloudflare.net include:_spf.google.com ~all"),
);
2 changes: 1 addition & 1 deletion dns/creds.json → dns/rubyci.org/creds.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"cloudflare": {
"TYPE": "CLOUDFLAREAPI",
"apitoken": "$CLOUDFLARE_API_TOKEN"
"apitoken": "$CLOUDFLARE_API_TOKEN_RUBYCI"
}
}
8 changes: 3 additions & 5 deletions dns/dnsconfig.js → dns/rubyci.org/dnsconfig.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// generated by get-zones. This is 'a decent first draft' and requires editing.
var DSP_CLOUDFLARE = NewDnsProvider("cloudflare");
var REG_NONE = NewRegistrar("none");

var DSP_CLOUDFLARE = NewDnsProvider("cloudflare", "CLOUDFLAREAPI");
var REG_CHANGEME = NewRegistrar("none");

D("rubyci.org", REG_CHANGEME,
D("rubyci.org", REG_NONE,
DnsProvider(DSP_CLOUDFLARE),
DefaultTTL(1),
A("amazon2023", "35.72.97.116"),
Expand Down