mirror of
https://github.com/partofmyid/register.git
synced 2026-06-05 18:46:50 +07:00
Compare commits
19 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68998df219 | ||
|
|
550ca5228c | ||
|
|
42f6c415b6 | ||
|
|
a1720f8400 | ||
|
|
f1c21760a5 | ||
|
|
de22d7bd14 | ||
|
|
be1ebe0d15 | ||
|
|
c5161c6471 |
||
|
|
4ca3912135 | ||
|
|
910447b90d |
||
|
|
3fac80dcfc |
||
|
|
1c04d92eb4 |
||
|
|
20ebb7da08 | ||
|
|
291bc39a7a | ||
|
|
08350def49 | ||
|
|
a97ad1b804 | ||
|
|
71102fabc8 | ||
|
|
e7d62df069 | ||
|
|
0015313795 |
45 changed files with 1037 additions and 104 deletions
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -8,7 +8,7 @@
|
|||
- Github Pull Requests
|
||||
- How DNS Works
|
||||
4. When in doubt, read the docs before asking in PR
|
||||
5. **PREVIEWS ARE REQUIRED FOR WEBSITES.** Must be a link. If it's not a website then please state the use of the subdomain.
|
||||
5. **PREVIEWS ARE REQUIRED FOR WEBSITES.** Can be a screenshot/link. If it's not a website then please state the use of the subdomain.
|
||||
-->
|
||||
|
||||
## Requirements
|
||||
|
|
@ -38,5 +38,5 @@ _None provided..._
|
|||
<!--
|
||||
^^^^^^ Remove the line above to provide a link/screenshot
|
||||
⚠️⚠️ ****REQUIRED IF ITS A WEBSITE**** ⚠️⚠️
|
||||
Please provide a link (required) and/or screenshot to your website below.
|
||||
Please provide a link/screenshot to your website below.
|
||||
-->
|
||||
|
|
|
|||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,2 +1,7 @@
|
|||
# DNSControl files
|
||||
creds.json
|
||||
types-dnscontrol.d.ts
|
||||
|
||||
# Zone files
|
||||
result*
|
||||
part-of.my.id.txt
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
> [!IMPORTANT]
|
||||
> We are currently rewriting our registration process, CI/CD pipeline, documentation, and website. Due to time constraints, **pull requests are still welcome** and will be migrated to the new syntax after the rewrite. We will document the new registration process in this repository once it's ready. In the meantime, you can join our [discord server](https://discord.gg/rFyRF3MMhc) to get updates and support.
|
||||
> We are currently rewriting our registration process, CI/CD pipeline, documentation, and website. Pull requests are temporarily paused until the new system is ready. We will document the new registration process in this repository once it's ready. In the meantime, you can join our [discord server](https://discord.gg/rFyRF3MMhc) to get updates and support.
|
||||
|
||||
> [!CAUTION]
|
||||
> We currently **DO NOT** support Vercel, Netlify, and other services that requires us to be on the [PSL](https://github.com/publicsuffix/list). _We will apply to be on the list [only if theres high demand](https://publicsuffix.org/submit/#:~:text=We%20will%20generally%20decline%20small%20projects)_, so be patient and invite some of your friends!
|
||||
|
|
|
|||
76
docs/example.nix
Normal file
76
docs/example.nix
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
description = "Example domain configuration for dns.nix"; # optional, description of use
|
||||
proxy = false; # optional, defaults to false. proxy through Cloudflare
|
||||
owner = { # add extra contacts if needed
|
||||
username = "satr14washere"; # required, github username
|
||||
email = "admin@satr14.my.id";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; { # full list of records supported: https://github.com/nix-community/dns.nix/tree/master/dns/types/records
|
||||
# dns.lib.combinators is optional but provides a lot of useful shortcuts:
|
||||
# https://github.com/nix-community/dns.nix/blob/master/dns/combinators.nix
|
||||
|
||||
A = [
|
||||
"203.0.113.50"
|
||||
"198.51.100.50"
|
||||
|
||||
# or:
|
||||
|
||||
{ address = "203.0.113.50"; ttl = 60 * 60; } # TTL is optional
|
||||
{ address = "198.51.100.50"; ttl = 60 * 60; }
|
||||
|
||||
# using dns.lib.combinators:
|
||||
|
||||
(ttl (60 * 60) (a "203.0.113.50")) # standalone A record
|
||||
(ttl (60 * 60) (a "2198.51.100.50")) # record with TTL
|
||||
];
|
||||
|
||||
AAAA = [ # mostly same as above
|
||||
"2001:db8::1"
|
||||
"2001:db8::2"
|
||||
|
||||
# or:
|
||||
|
||||
{ address = "2001:db8::1"; ttl = 60 * 60; }
|
||||
{ address = "2001:db8::2"; ttl = 60 * 60; }
|
||||
|
||||
# using dns.lib.combinators:
|
||||
|
||||
(ttl (60 * 60) (aaaa "2001:db8::1"))
|
||||
(ttl (60 * 60) (aaaa "2001:db8::2"))
|
||||
];
|
||||
|
||||
TXT = [
|
||||
"v=spf1 include:mailgun.org ~all"
|
||||
"dh=some-long-random-string"
|
||||
];
|
||||
|
||||
MX = [
|
||||
{
|
||||
preference = 10;
|
||||
exchange = "mail.protonmail.ch.";
|
||||
}
|
||||
{
|
||||
preference = 20;
|
||||
exchange = "mailsec.protonmail.ch.";
|
||||
}
|
||||
|
||||
# using dns.lib.combinators:
|
||||
|
||||
(mx.mx 10 "mail.protonmail.ch.")
|
||||
(mx.mx 20 "mailsec.protonmail.ch.")
|
||||
];
|
||||
|
||||
# a few notes about CNAME records:
|
||||
# - value must end with a dot (.)
|
||||
# - cannot coexist with other record types (e.g. A, AAAA, MX) for the same subdomain
|
||||
# - can only be one despite being a list (this example defined multiple only for demonstrating valid values)
|
||||
CNAME = [
|
||||
"edge.redirect.pizza."
|
||||
"username.github.io."
|
||||
"site.pages.dev."
|
||||
];
|
||||
|
||||
};
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"description": "dashboard and main website",
|
||||
"owner": {
|
||||
"username": "partofmyid"
|
||||
},
|
||||
"record": {
|
||||
"ALIAS": "website-e7n.pages.dev"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"owner": {
|
||||
"username": "LunarisXOffical"
|
||||
},
|
||||
"record": {
|
||||
"TXT": [ "vc-domain-verify=reallunarisx.part-of.my.id,eb89acab3adcd3ee3acd" ]
|
||||
},
|
||||
"proxy": false
|
||||
}
|
||||
12
domains/part-of.my.id/_discord.colin.nix
Normal file
12
domains/part-of.my.id/_discord.colin.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
description = "Discord verification";
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "ColinLeDev";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
TXT = [ "dh=279643a6f8677dedb1c5c63d007fc4516149679c" ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/_discord.cutedog5695.nix
Normal file
13
domains/part-of.my.id/_discord.cutedog5695.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "CuteDog5695";
|
||||
email = "cutedog5695@gmail.com";
|
||||
repo = "https://github.com/CuteDog5695/cutedog5695.github.io";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
TXT = [ "dh=a7c19efb0f6bc38b97a33760f6c1ee84df4151b1" ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/_discord.justdeveloper.nix
Normal file
13
domains/part-of.my.id/_discord.justdeveloper.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "justdeveloper@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustDeveloper1/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
TXT = [ "dh=6024027bc233825451e290ac37a4b4a1f838ee70" ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/_discord.nix
Normal file
11
domains/part-of.my.id/_discord.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "satr14washere";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
TXT = [ "dh=d509fc9014e196311ed887c2e410cdefa833436e" ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/_discord.roki.nix
Normal file
11
domains/part-of.my.id/_discord.roki.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
owner = {
|
||||
username = "Roki100";
|
||||
discord = "289479495444987904";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
TXT = [ "dh=5633078cd5bfd347a896ddb0f0de017c5423aa06" ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/batman.nix
Normal file
11
domains/part-of.my.id/batman.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = true;
|
||||
owner = {
|
||||
username = "shadowe1ite";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "shadowe1ite.github.io." ];
|
||||
};
|
||||
}
|
||||
12
domains/part-of.my.id/c.nix
Normal file
12
domains/part-of.my.id/c.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "orangci";
|
||||
email = "c@orangc.xyz";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
12
domains/part-of.my.id/colin.nix
Normal file
12
domains/part-of.my.id/colin.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
description = "My personal portfolio hosted on my server";
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "ColinLeDev";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "proxy.col1n.fr." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/cutedog5695.nix
Normal file
13
domains/part-of.my.id/cutedog5695.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "CuteDog5695";
|
||||
email = "cutedog5695@gmail.com";
|
||||
repo = "https://github.com/CuteDog5695/cutedog5695.github.io";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
10
domains/part-of.my.id/elkaff.nix
Normal file
10
domains/part-of.my.id/elkaff.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
owner = {
|
||||
username = "elkhaff";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "portofolio-pixel.pages.dev." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/j.nix
Normal file
13
domains/part-of.my.id/j.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "support@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustStudio7/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/jacob.nix
Normal file
11
domains/part-of.my.id/jacob.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "jacobrdale";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "hexon404.onrender.com." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/jd.nix
Normal file
13
domains/part-of.my.id/jd.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "justdeveloper@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustDeveloper1/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/job.nix
Normal file
11
domains/part-of.my.id/job.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "FWEEaaaa1";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
A = [ "128.204.223.115" ];
|
||||
};
|
||||
}
|
||||
19
domains/part-of.my.id/joel.nix
Normal file
19
domains/part-of.my.id/joel.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "joestr";
|
||||
email = "strasser999@gmail.com";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
A = [ "142.132.173.34" ];
|
||||
AAAA = [ "2a01:4f8:1c0c:6cc0::1" ];
|
||||
MX = [
|
||||
{
|
||||
preference = 10;
|
||||
exchange = "achlys.infra.joestr.at.";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/js.nix
Normal file
13
domains/part-of.my.id/js.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "support@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustStudio7/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/just.nix
Normal file
13
domains/part-of.my.id/just.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "justdeveloper@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustDeveloper1/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/justdev.nix
Normal file
13
domains/part-of.my.id/justdev.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "justdeveloper@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustDeveloper1/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/justdeveloper.nix
Normal file
13
domains/part-of.my.id/justdeveloper.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "justdeveloper@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustDeveloper1/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/juststudio.nix
Normal file
13
domains/part-of.my.id/juststudio.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "JustDeveloper1";
|
||||
email = "support@juststudio.is-a.dev";
|
||||
repo = "https://github.com/JustStudio7/Website";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/katz.nix
Normal file
11
domains/part-of.my.id/katz.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "Bananalolok";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
A = [ "69.197.135.205" ];
|
||||
};
|
||||
}
|
||||
12
domains/part-of.my.id/no-one-is.nix
Normal file
12
domains/part-of.my.id/no-one-is.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "EducatedSuddenBucket";
|
||||
email = "me@esb.is-a.dev";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "educatedsuddenbucket-github-io.onrender.com." ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/pxl.nix
Normal file
11
domains/part-of.my.id/pxl.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "heypxl";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "heypxl.github.io." ];
|
||||
};
|
||||
}
|
||||
11
domains/part-of.my.id/rchessauth.nix
Normal file
11
domains/part-of.my.id/rchessauth.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "vortexprime24";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "fire.hackclub.app." ];
|
||||
};
|
||||
}
|
||||
12
domains/part-of.my.id/roki.nix
Normal file
12
domains/part-of.my.id/roki.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "Roki100";
|
||||
discord = "289479495444987904";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "edge.redirect.pizza." ];
|
||||
};
|
||||
}
|
||||
10
domains/part-of.my.id/satr14.nix
Normal file
10
domains/part-of.my.id/satr14.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
owner = {
|
||||
username = "satr14washere";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "5th-site.pages.dev." ];
|
||||
};
|
||||
}
|
||||
12
domains/part-of.my.id/stef.nix
Normal file
12
domains/part-of.my.id/stef.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "Stef-00012";
|
||||
email = "admin@stefdp.lol";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "proxy.stefdp.lol." ];
|
||||
};
|
||||
}
|
||||
13
domains/part-of.my.id/ukriu.nix
Normal file
13
domains/part-of.my.id/ukriu.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
description = "my website";
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "ukriu";
|
||||
email = "partofmyid@ukriu.com";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "ukriu.pages.dev." ];
|
||||
};
|
||||
}
|
||||
12
domains/part-of.my.id/you-are.nix
Normal file
12
domains/part-of.my.id/you-are.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ dns, ... }: {
|
||||
metadata = {
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "Stef-00012";
|
||||
email = "admin@stefdp.com";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "proxy.stefdp.com." ];
|
||||
};
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"owner": {
|
||||
"username": "LunarisXOffical"
|
||||
},
|
||||
"record": {
|
||||
"CNAME": "3bdbf404a94a1470.vercel-dns-017.com"
|
||||
},
|
||||
"proxy": false
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"owner": {
|
||||
"email": "me@stefdp.com",
|
||||
"email": "admin@stefdp.lol",
|
||||
"username": "Stef-00012"
|
||||
},
|
||||
"record": {
|
||||
"CNAME": "proxy.stefdp.com"
|
||||
"CNAME": "proxy.stefdp.lol"
|
||||
},
|
||||
"proxied": false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"owner": {
|
||||
"email": "me@stefdp.com",
|
||||
"email": "admin@stefdp.com",
|
||||
"username": "Stef-00012"
|
||||
},
|
||||
"record": {
|
||||
|
|
|
|||
81
flake.nix
81
flake.nix
|
|
@ -1,32 +1,59 @@
|
|||
{
|
||||
description = "Zone File Generator For part-of.my.id";
|
||||
description = "Zone File Generator";
|
||||
inputs.dns.url = "github:nix-community/dns.nix";
|
||||
|
||||
outputs = { dns, ... }: let
|
||||
email = "admin@satr14.my.id";
|
||||
domains."0" = {
|
||||
domain = "part-of.my.id";
|
||||
nameservers = [
|
||||
"adele.ns.cloudflare.com"
|
||||
"fattouche.ns.cloudflare.com"
|
||||
outputs =
|
||||
{ dns, ... }:
|
||||
let
|
||||
email = "admin@satr14.my.id";
|
||||
domains = [
|
||||
"0" = {
|
||||
domain = "part-of.my.id";
|
||||
nameservers = [
|
||||
"adele.ns.cloudflare.com"
|
||||
"fattouche.ns.cloudflare.com"
|
||||
];
|
||||
};
|
||||
"1" = {
|
||||
domain = "is-my.id";
|
||||
nameservers = [
|
||||
"adele.ns.cloudflare.com"
|
||||
"fattouche.ns.cloudflare.com"
|
||||
];
|
||||
};
|
||||
];
|
||||
};
|
||||
in {
|
||||
packages.x86_64-linux = builtins.mapAttrs (_: domain:
|
||||
dns.util.x86_64-linux.writeZone domain.domain (
|
||||
with dns.lib.combinators; {
|
||||
SOA = {
|
||||
adminEmail = email;
|
||||
nameServer = builtins.head domain.nameservers;
|
||||
serial = builtins.currentTime;
|
||||
};
|
||||
NS = domain.nameservers;
|
||||
|
||||
# note: Cloudflare ignores SOA and NS records uploaded via Zone File, they are just so that dns.nix builds a valid zone file.
|
||||
|
||||
A = [ "1.1.1.1" ];
|
||||
inherit (import <nixpkgs> { }) lib;
|
||||
domainsFolder = builtins.readDir ./domains;
|
||||
domainFiles = lib.filterAttrs (
|
||||
name: type: type == "regular" && builtins.match ".*\\.nix" name != null
|
||||
) domainsFolder;
|
||||
subdomains = lib.mapAttrs' (
|
||||
name: _:
|
||||
let
|
||||
key = builtins.replaceStrings [ ".nix" ] [ "" ] name;
|
||||
in
|
||||
{
|
||||
name = key;
|
||||
value = (import (./domains + "/${name}") { inherit dns; }).records;
|
||||
}
|
||||
)
|
||||
) domains;
|
||||
};
|
||||
) domainFiles;
|
||||
in
|
||||
{
|
||||
packages.x86_64-linux = builtins.mapAttrs (
|
||||
_: domain:
|
||||
dns.util.x86_64-linux.writeZone domain.domain (
|
||||
with dns.lib.combinators;
|
||||
{
|
||||
SOA = {
|
||||
adminEmail = email;
|
||||
nameServer = builtins.head domain.nameservers;
|
||||
serial = builtins.currentTime;
|
||||
};
|
||||
NS = domain.nameservers;
|
||||
# note: Cloudflare ignores SOA and NS records uploaded via Zone File, they are included just so that dns.nix builds a valid zone file.
|
||||
CNAME = [ "website-e7n.pages.dev." ];
|
||||
inherit subdomains;
|
||||
}
|
||||
)
|
||||
) domains;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
72
is-my.id.txt
Normal file
72
is-my.id.txt
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
;;
|
||||
;; Domain: is-my.id.
|
||||
;; Exported: 2026-03-21 23:44:57
|
||||
;;
|
||||
;; This file is intended for use for informational and archival
|
||||
;; purposes ONLY and MUST be edited before use on a production
|
||||
;; DNS server. In particular, you must:
|
||||
;; -- update the SOA record with the correct authoritative name server
|
||||
;; -- update the SOA record with the contact e-mail address information
|
||||
;; -- update the NS record(s) with the authoritative name servers for this domain.
|
||||
;;
|
||||
;; For further information, please consult the BIND documentation
|
||||
;; located on the following website:
|
||||
;;
|
||||
;; http://www.isc.org/
|
||||
;;
|
||||
;; And RFC 1035:
|
||||
;;
|
||||
;; http://www.ietf.org/rfc/rfc1035.txt
|
||||
;;
|
||||
;; Please note that we do NOT offer technical support for any use
|
||||
;; of this zone data, the BIND name server, or any other third-party
|
||||
;; DNS software.
|
||||
;;
|
||||
;; Use at your own risk.
|
||||
;; SOA Record
|
||||
is-my.id 3600 IN SOA adele.ns.cloudflare.com. dns.cloudflare.com. 2052580329 10000 2400 604800 3600
|
||||
|
||||
;; NS Records
|
||||
is-my.id. 86400 IN NS adele.ns.cloudflare.com.
|
||||
is-my.id. 86400 IN NS fattouche.ns.cloudflare.com.
|
||||
|
||||
;; A Records
|
||||
job.is-my.id. 1 IN A 128.204.223.115 ; cf_tags=cf-proxied:false
|
||||
joel.is-my.id. 1 IN A 142.132.173.34 ; cf_tags=cf-proxied:false
|
||||
katz.is-my.id. 1 IN A 69.197.135.205 ; cf_tags=cf-proxied:false
|
||||
|
||||
;; AAAA Records
|
||||
joel.is-my.id. 1 IN AAAA 2a01:4f8:1c0c:6cc0::1 ; cf_tags=cf-proxied:false
|
||||
|
||||
;; CNAME Records
|
||||
batman.is-my.id. 1 IN CNAME shadowe1ite.github.io. ; cf_tags=cf-proxied:true
|
||||
colin.is-my.id. 1 IN CNAME proxy.col1n.fr. ; cf_tags=cf-proxied:false
|
||||
c.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
cutedog5695.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
elkaff.is-my.id. 1 IN CNAME portofolio-pixel.pages.dev. ; cf_tags=cf-proxied:false
|
||||
jacob.is-my.id. 1 IN CNAME hexon404.onrender.com. ; cf_tags=cf-proxied:false
|
||||
jd.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
j.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
js.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
justdeveloper.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
justdev.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
just.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
juststudio.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
no-one-is.is-my.id. 1 IN CNAME educatedsuddenbucket-github-io.onrender.com. ; cf_tags=cf-proxied:false
|
||||
is-my.id. 1 IN CNAME website-e7n.pages.dev. ; cf_tags=cf-proxied:false
|
||||
pxl.is-my.id. 1 IN CNAME heypxl.github.io. ; cf_tags=cf-proxied:false
|
||||
rchessauth.is-my.id. 1 IN CNAME fire.hackclub.app. ; cf_tags=cf-proxied:false
|
||||
roki.is-my.id. 1 IN CNAME edge.redirect.pizza. ; cf_tags=cf-proxied:false
|
||||
stef.is-my.id. 1 IN CNAME proxy.stefdp.lol. ; cf_tags=cf-proxied:false
|
||||
ukriu.is-my.id. 1 IN CNAME ukriu.pages.dev. ; cf_tags=cf-proxied:false
|
||||
you-are.is-my.id. 1 IN CNAME proxy.stefdp.com. ; cf_tags=cf-proxied:false
|
||||
|
||||
;; MX Records
|
||||
joel.is-my.id. 1 IN MX 10 achlys.infra.joestr.at.
|
||||
|
||||
;; TXT Records
|
||||
_discord.colin.is-my.id. 1 IN TXT "dh=279643a6f8677dedb1c5c63d007fc4516149679c"
|
||||
_discord.cutedog5695.is-my.id. 1 IN TXT "dh=a7c19efb0f6bc38b97a33760f6c1ee84df4151b1"
|
||||
_discord.justdeveloper.is-my.id. 1 IN TXT "dh=6024027bc233825451e290ac37a4b4a1f838ee70"
|
||||
_discord.is-my.id. 1 IN TXT "dh=d509fc9014e196311ed887c2e410cdefa833436e"
|
||||
_discord.roki.is-my.id. 1 IN TXT "dh=5633078cd5bfd347a896ddb0f0de017c5423aa06"
|
||||
200
scripts/compare-zones.sh
Executable file
200
scripts/compare-zones.sh
Executable file
|
|
@ -0,0 +1,200 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# compare-zones.sh — Compare two BIND-format zone files
|
||||
#
|
||||
# Normalizes both files (strips comments, TTLs, SOA records, and whitespace
|
||||
# differences) then performs a record-by-record comparison.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/compare-zones.sh <zone-file-a> <zone-file-b>
|
||||
#
|
||||
# Examples:
|
||||
# ./scripts/compare-zones.sh expected.zone generated.zone
|
||||
# ./scripts/compare-zones.sh part-of.my.id.txt result
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
RESET='\033[0m'
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 <zone-file-a> <zone-file-b>"
|
||||
echo ""
|
||||
echo "Compare two BIND-format zone files."
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " zone-file-a Path to the first zone file"
|
||||
echo " zone-file-b Path to the second zone file"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
FILE_A="$1"
|
||||
FILE_B="$2"
|
||||
|
||||
for f in "$FILE_A" "$FILE_B"; do
|
||||
resolved="$f"
|
||||
# Resolve symlinks (e.g. nix store results)
|
||||
if [[ -L "$resolved" ]]; then
|
||||
resolved="$(readlink -f "$resolved")"
|
||||
fi
|
||||
if [[ ! -f "$resolved" ]]; then
|
||||
echo -e "${RED}Error:${RESET} File not found: $f"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Resolve symlinks for display
|
||||
RESOLVED_A="$FILE_A"
|
||||
RESOLVED_B="$FILE_B"
|
||||
[[ -L "$FILE_A" ]] && RESOLVED_A="$(readlink -f "$FILE_A")"
|
||||
[[ -L "$FILE_B" ]] && RESOLVED_B="$(readlink -f "$FILE_B")"
|
||||
|
||||
TMPDIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
|
||||
# normalize_zone <input-file> <output-file>
|
||||
#
|
||||
# Extracts resource records, strips comments, normalizes whitespace and TTLs,
|
||||
# ensures FQDNs have trailing dots, skips SOA (which always differs), and sorts.
|
||||
normalize_zone() {
|
||||
local input="$1"
|
||||
local output="$2"
|
||||
|
||||
# Resolve symlinks
|
||||
if [[ -L "$input" ]]; then
|
||||
input="$(readlink -f "$input")"
|
||||
fi
|
||||
|
||||
grep -E '^\S+' "$input" \
|
||||
| grep -v '^\s*;' \
|
||||
| grep -v '^\s*$' \
|
||||
| grep -v '^\$' \
|
||||
| sed 's/\s*;.*$//' \
|
||||
| sed 's/\t\+/ /g; s/ \+/ /g' \
|
||||
| awk '
|
||||
{
|
||||
# Expected formats after cleanup:
|
||||
# name TTL IN TYPE rdata...
|
||||
# name IN TYPE rdata...
|
||||
#
|
||||
# We output: name TYPE rdata...
|
||||
|
||||
name = $1
|
||||
idx = 2
|
||||
|
||||
# Skip TTL if present (a number)
|
||||
if ($idx ~ /^[0-9]+$/) idx++
|
||||
|
||||
# Skip class (IN, CS, CH, HS)
|
||||
if (toupper($idx) == "IN" || toupper($idx) == "CS" || toupper($idx) == "CH" || toupper($idx) == "HS") idx++
|
||||
|
||||
rtype = toupper($idx)
|
||||
idx++
|
||||
|
||||
# Skip SOA — serial and timers will always differ
|
||||
if (rtype == "SOA") next
|
||||
|
||||
rdata = ""
|
||||
for (i = idx; i <= NF; i++) {
|
||||
val = $i
|
||||
# Ensure trailing dot on targets for NS, CNAME, MX
|
||||
if ((rtype == "NS" || rtype == "CNAME") && i == idx) {
|
||||
if (val !~ /\.$/) val = val "."
|
||||
}
|
||||
if (rtype == "MX" && i == NF) {
|
||||
if (val !~ /\.$/) val = val "."
|
||||
}
|
||||
if (rdata != "") rdata = rdata " "
|
||||
rdata = rdata val
|
||||
}
|
||||
|
||||
print name " " rtype " " rdata
|
||||
}
|
||||
' \
|
||||
| sort > "$output"
|
||||
}
|
||||
|
||||
LABEL_A="$(basename "$FILE_A")"
|
||||
LABEL_B="$(basename "$FILE_B")"
|
||||
|
||||
echo -e "${BOLD}Comparing zones${RESET}"
|
||||
echo -e " A: ${CYAN}${RESOLVED_A}${RESET}"
|
||||
echo -e " B: ${CYAN}${RESOLVED_B}${RESET}"
|
||||
echo ""
|
||||
|
||||
normalize_zone "$FILE_A" "$TMPDIR/a.norm"
|
||||
normalize_zone "$FILE_B" "$TMPDIR/b.norm"
|
||||
|
||||
COUNT_A=$(wc -l < "$TMPDIR/a.norm")
|
||||
COUNT_B=$(wc -l < "$TMPDIR/b.norm")
|
||||
|
||||
echo -e " A records: ${BOLD}$COUNT_A${RESET} (excluding SOA)"
|
||||
echo -e " B records: ${BOLD}$COUNT_B${RESET} (excluding SOA)"
|
||||
echo ""
|
||||
|
||||
# Compute differences
|
||||
comm -23 "$TMPDIR/a.norm" "$TMPDIR/b.norm" > "$TMPDIR/only-a.txt"
|
||||
comm -13 "$TMPDIR/a.norm" "$TMPDIR/b.norm" > "$TMPDIR/only-b.txt"
|
||||
comm -12 "$TMPDIR/a.norm" "$TMPDIR/b.norm" > "$TMPDIR/matching.txt"
|
||||
|
||||
MATCH_COUNT=$(wc -l < "$TMPDIR/matching.txt")
|
||||
ONLY_A_COUNT=$(wc -l < "$TMPDIR/only-a.txt")
|
||||
ONLY_B_COUNT=$(wc -l < "$TMPDIR/only-b.txt")
|
||||
|
||||
echo -e "${BOLD}Results${RESET}"
|
||||
echo -e " ${GREEN}✓ Matching:${RESET} $MATCH_COUNT"
|
||||
echo -e " ${RED}✗ Only in A:${RESET} $ONLY_A_COUNT"
|
||||
echo -e " ${YELLOW}+ Only in B:${RESET} $ONLY_B_COUNT"
|
||||
echo ""
|
||||
|
||||
if [[ "$ONLY_A_COUNT" -gt 0 ]]; then
|
||||
echo -e "${RED}${BOLD}Records only in A (${LABEL_A}):${RESET}"
|
||||
while IFS= read -r line; do
|
||||
echo -e " ${RED}-${RESET} $line"
|
||||
done < "$TMPDIR/only-a.txt"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ "$ONLY_B_COUNT" -gt 0 ]]; then
|
||||
echo -e "${YELLOW}${BOLD}Records only in B (${LABEL_B}):${RESET}"
|
||||
while IFS= read -r line; do
|
||||
echo -e " ${YELLOW}+${RESET} $line"
|
||||
done < "$TMPDIR/only-b.txt"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ "$ONLY_A_COUNT" -eq 0 && "$ONLY_B_COUNT" -eq 0 ]]; then
|
||||
echo -e "${GREEN}${BOLD}✓ Zones are identical!${RESET}"
|
||||
exit 0
|
||||
else
|
||||
# Unified diff
|
||||
echo -e "${BOLD}Diff (unified):${RESET}"
|
||||
diff -u \
|
||||
--label "$LABEL_A" "$TMPDIR/a.norm" \
|
||||
--label "$LABEL_B" "$TMPDIR/b.norm" \
|
||||
| head -80 || true
|
||||
echo ""
|
||||
|
||||
# Summary by record type
|
||||
echo -e "${BOLD}Summary by record type:${RESET}"
|
||||
echo -e " ${BOLD}Type A-only B-only Matching${RESET}"
|
||||
{
|
||||
cat "$TMPDIR/only-a.txt" "$TMPDIR/only-b.txt" "$TMPDIR/matching.txt"
|
||||
} | awk '{print $2}' | sort -u | while read -r rtype; do
|
||||
a_only=$(grep -c "^[^ ]* ${rtype} " "$TMPDIR/only-a.txt" || true)
|
||||
b_only=$(grep -c "^[^ ]* ${rtype} " "$TMPDIR/only-b.txt" || true)
|
||||
matching=$(grep -c "^[^ ]* ${rtype} " "$TMPDIR/matching.txt" || true)
|
||||
printf " %-6s %6d %6d %8d\n" "$rtype" "$a_only" "$b_only" "$matching"
|
||||
done
|
||||
echo ""
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# script to deploy the APEX domain to Cloudflare with CNAME flattening
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ZONE_ID="${CF_ZONE_ID:?}"
|
||||
TOKEN="${CF_API_TOKEN:?}"
|
||||
TARGET="website-e7n.pages.dev"
|
||||
|
||||
EXISTING=$(curl -s \
|
||||
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?type=CNAME&name=@" \
|
||||
-H "Authorization: Bearer ${TOKEN}" \
|
||||
| jq -r '.result[0] // empty')
|
||||
|
||||
EXISTING_CONTENT=$(echo "$EXISTING" | jq -r '.content // empty')
|
||||
EXISTING_ID=$(echo "$EXISTING" | jq -r '.id // empty')
|
||||
|
||||
if [[ "$EXISTING_CONTENT" == "$TARGET" ]]; then
|
||||
echo "Apex CNAME unchanged, skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "$EXISTING_ID" ]]; then
|
||||
echo "No apex CNAME found, creating..."
|
||||
METHOD="POST"
|
||||
URL="https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records"
|
||||
else
|
||||
echo "Apex CNAME changed ($EXISTING_CONTENT → $TARGET), updating..."
|
||||
METHOD="PUT"
|
||||
URL="https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${EXISTING_ID}"
|
||||
fi
|
||||
|
||||
curl -s -X "$METHOD" "$URL" \
|
||||
-H "Authorization: Bearer ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"type\": \"CNAME\",
|
||||
\"name\": \"@\",
|
||||
\"content\": \"${TARGET}\",
|
||||
\"proxied\": true
|
||||
}" | jq -e '.success'
|
||||
265
scripts/migrate-nix.py
Executable file
265
scripts/migrate-nix.py
Executable file
|
|
@ -0,0 +1,265 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Migrate domains/*.json to domains/*.nix
|
||||
|
||||
Converts each JSON domain config into a .nix file matching the format
|
||||
from docs/example.nix:
|
||||
|
||||
{ dns, ... }: {
|
||||
metadata = {
|
||||
description = "...";
|
||||
proxy = false;
|
||||
owner = {
|
||||
username = "...";
|
||||
};
|
||||
};
|
||||
records = with dns.lib.combinators; {
|
||||
CNAME = [ "example.com." ];
|
||||
};
|
||||
}
|
||||
|
||||
Usage:
|
||||
python3 scripts/migrate-nix.py [--dry-run] [--delete-json]
|
||||
|
||||
Options:
|
||||
--dry-run Print generated .nix to stdout without writing files
|
||||
--delete-json Delete the .json files after successful conversion
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
DOMAINS_DIR = Path(__file__).resolve().parent.parent / "domains"
|
||||
|
||||
|
||||
# --- Nix string helpers ---
|
||||
|
||||
def escape(s: str) -> str:
|
||||
"""Escape a string for use inside Nix double quotes."""
|
||||
return s.replace("\\", "\\\\").replace('"', '\\"').replace("${", "\\${")
|
||||
|
||||
|
||||
def fqdn(s: str) -> str:
|
||||
"""Ensure a domain string ends with a trailing dot."""
|
||||
return s if s.endswith(".") else s + "."
|
||||
|
||||
|
||||
# --- Block builders ---
|
||||
|
||||
def build_metadata(data: dict) -> list[str]:
|
||||
"""Build the metadata = { ... }; block."""
|
||||
owner = data.get("owner", {})
|
||||
description = data.get("description")
|
||||
proxy = data.get("proxied", data.get("proxy"))
|
||||
|
||||
lines = [" metadata = {"]
|
||||
|
||||
if description is not None:
|
||||
lines.append(f' description = "{escape(description)}";')
|
||||
|
||||
if proxy is not None:
|
||||
lines.append(f" proxy = {'true' if proxy else 'false'};")
|
||||
|
||||
owner_keys = ["username", "email", "discord", "repo"]
|
||||
owner_fields = [(k, owner[k]) for k in owner_keys if owner.get(k)]
|
||||
|
||||
if owner_fields:
|
||||
lines.append(" owner = {")
|
||||
for key, val in owner_fields:
|
||||
lines.append(f' {key} = "{escape(val)}";')
|
||||
lines.append(" };")
|
||||
|
||||
lines.append(" };")
|
||||
return lines
|
||||
|
||||
|
||||
def build_records(record: dict) -> list[str]:
|
||||
"""Build the records = with dns.lib.combinators; { ... }; block."""
|
||||
entries = []
|
||||
|
||||
# A records
|
||||
if "A" in record:
|
||||
entries.extend(string_list_record("A", as_list(record["A"])))
|
||||
|
||||
# AAAA records
|
||||
if "AAAA" in record:
|
||||
entries.extend(string_list_record("AAAA", as_list(record["AAAA"])))
|
||||
|
||||
# CNAME (also handles ALIAS → CNAME)
|
||||
cname = record.get("CNAME") or record.get("ALIAS")
|
||||
if cname is not None:
|
||||
val = cname[0] if isinstance(cname, list) else cname
|
||||
entries.append(f' CNAME = [ "{fqdn(val)}" ];')
|
||||
|
||||
# MX records
|
||||
if "MX" in record:
|
||||
entries.extend(build_mx(as_list(record["MX"])))
|
||||
|
||||
# TXT records
|
||||
if "TXT" in record:
|
||||
escaped = [escape(v) for v in as_list(record["TXT"])]
|
||||
entries.extend(string_list_record("TXT", escaped))
|
||||
|
||||
# NS records
|
||||
if "NS" in record:
|
||||
fqdns = [fqdn(v) for v in as_list(record["NS"])]
|
||||
entries.extend(string_list_record("NS", fqdns))
|
||||
|
||||
# SRV records
|
||||
if "SRV" in record:
|
||||
entries.extend(build_srv(as_list(record["SRV"])))
|
||||
|
||||
# CAA records
|
||||
if "CAA" in record:
|
||||
entries.extend(build_caa(as_list(record["CAA"])))
|
||||
|
||||
if not entries:
|
||||
return [" records = with dns.lib.combinators; {};"]
|
||||
|
||||
lines = [" records = with dns.lib.combinators; {"]
|
||||
lines.extend(entries)
|
||||
lines.append(" };")
|
||||
return lines
|
||||
|
||||
|
||||
# --- Record type formatters ---
|
||||
|
||||
def as_list(value) -> list:
|
||||
"""Wrap a scalar in a list if it isn't one already."""
|
||||
return value if isinstance(value, list) else [value]
|
||||
|
||||
|
||||
def string_list_record(rtype: str, values: list[str]) -> list[str]:
|
||||
"""Format a record type whose values are plain strings."""
|
||||
if len(values) == 1:
|
||||
return [f' {rtype} = [ "{values[0]}" ];']
|
||||
|
||||
lines = [f" {rtype} = ["]
|
||||
for v in values:
|
||||
lines.append(f' "{v}"')
|
||||
lines.append(" ];")
|
||||
return lines
|
||||
|
||||
|
||||
def build_mx(values: list) -> list[str]:
|
||||
"""Format MX records as attrsets with preference + exchange."""
|
||||
lines = [" MX = ["]
|
||||
for i, v in enumerate(values):
|
||||
pref = (i + 1) * 10
|
||||
lines.append(" {")
|
||||
lines.append(f" preference = {pref};")
|
||||
lines.append(f' exchange = "{fqdn(v)}";')
|
||||
lines.append(" }")
|
||||
lines.append(" ];")
|
||||
return lines
|
||||
|
||||
|
||||
def build_srv(values: list[dict]) -> list[str]:
|
||||
"""Format SRV records."""
|
||||
lines = [" SRV = ["]
|
||||
for srv in values:
|
||||
lines.append(" {")
|
||||
for key in ("service", "proto"):
|
||||
if key in srv:
|
||||
lines.append(f' {key} = "{srv[key]}";')
|
||||
for key in ("priority", "weight", "port"):
|
||||
if key in srv:
|
||||
lines.append(f" {key} = {srv[key]};")
|
||||
if "target" in srv:
|
||||
lines.append(f' target = "{fqdn(srv["target"])}";')
|
||||
lines.append(" }")
|
||||
lines.append(" ];")
|
||||
return lines
|
||||
|
||||
|
||||
def build_caa(values: list[dict]) -> list[str]:
|
||||
"""Format CAA records."""
|
||||
lines = [" CAA = ["]
|
||||
for caa in values:
|
||||
lines.append(" {")
|
||||
if "flags" in caa:
|
||||
lines.append(f" flags = {caa['flags']};")
|
||||
if "tag" in caa:
|
||||
lines.append(f' tag = "{caa["tag"]}";')
|
||||
if "value" in caa:
|
||||
lines.append(f' value = "{escape(caa["value"])}";')
|
||||
lines.append(" }")
|
||||
lines.append(" ];")
|
||||
return lines
|
||||
|
||||
|
||||
# --- Top-level conversion ---
|
||||
|
||||
def json_to_nix(data: dict) -> str:
|
||||
"""Convert a parsed JSON domain config to a complete .nix file string."""
|
||||
lines = ["{ dns, ... }: {"]
|
||||
lines.extend(build_metadata(data))
|
||||
lines.extend(build_records(data.get("record", {})))
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
# --- File operations ---
|
||||
|
||||
def migrate_file(path: Path, *, dry_run: bool, delete_json: bool) -> bool:
|
||||
"""Migrate a single .json file. Returns True on success."""
|
||||
try:
|
||||
data = json.loads(path.read_text())
|
||||
except json.JSONDecodeError as e:
|
||||
print(f" ERROR: {path.name}: {e}", file=sys.stderr)
|
||||
return False
|
||||
|
||||
nix = json_to_nix(data)
|
||||
nix_path = path.with_suffix(".nix")
|
||||
|
||||
if dry_run:
|
||||
print(f"--- {nix_path.name} ---")
|
||||
print(nix)
|
||||
return True
|
||||
|
||||
nix_path.write_text(nix)
|
||||
print(f" Created {nix_path.name}")
|
||||
|
||||
if delete_json:
|
||||
path.unlink()
|
||||
print(f" Deleted {path.name}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
dry_run = "--dry-run" in sys.argv
|
||||
delete_json = "--delete-json" in sys.argv
|
||||
|
||||
if not DOMAINS_DIR.exists():
|
||||
print(f"Error: {DOMAINS_DIR} not found", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
files = sorted(DOMAINS_DIR.glob("*.json"))
|
||||
if not files:
|
||||
print("No .json files found in domains/")
|
||||
sys.exit(0)
|
||||
|
||||
print(f"Found {len(files)} JSON file(s) to migrate")
|
||||
if dry_run:
|
||||
print("(dry run — no files will be written)\n")
|
||||
|
||||
success = 0
|
||||
failed = 0
|
||||
|
||||
for f in files:
|
||||
print(f"Migrating {f.name}...")
|
||||
if migrate_file(f, dry_run=dry_run, delete_json=delete_json):
|
||||
success += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\nDone: {success} succeeded, {failed} failed")
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
3
scripts/upload-zone.sh
Normal file
3
scripts/upload-zone.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
curl
|
||||
|
|
@ -1 +1 @@
|
|||
32
|
||||
31
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue