2 Commits

Author SHA1 Message Date
mxmlndml
869d0d4e97 bump version 2023-08-28 19:12:52 +02:00
mxmlndml
027d499875 support multiple domains 2023-08-28 19:11:35 +02:00
5 changed files with 53 additions and 19 deletions

View File

@@ -5,6 +5,6 @@ services:
environment:
- API_KEY=123
- ZONE_ID=023e105f4ecef8ad9ca31a8372d0c353
- DOMAIN_NAME=dyndns.example.com
- DOMAIN_NAMES=dyndns.example.com,example.com
- INTERVAL=5
- LOG_LEVEL=INFO

View File

@@ -1,6 +1,6 @@
{
"name": "cloudflare-dynamic-dns",
"version": "0.1.0",
"version": "1.0.0-alpha",
"description": "",
"main": "dist/index.js",
"scripts": {

View File

@@ -17,7 +17,7 @@ const getDnsRecord = async (
name: string,
type: string,
apiKey: string,
): Promise<{ content: string; id: string }> => {
): Promise<{ content: string; name: string; id: string }> => {
const url =
`https://api.cloudflare.com/client/v4/zones/${zoneIdentifier}/dns_records?name=${name}&type=${type}`;
const headers = {
@@ -28,7 +28,7 @@ const getDnsRecord = async (
const json: CFResponse = await response.json();
if (json.success) {
return (({ content, id }) => ({ content, id }))(json.result[0]);
return (({ content, name, id }) => ({ content, name, id }))(json.result[0]);
}
const error = json.errors.reduce(
@@ -40,6 +40,16 @@ const getDnsRecord = async (
);
};
const getDnsRecords = async (
zoneIdentifier: string,
names: string[],
type: string,
apiKey: string,
): Promise<{ content: string; name: string; id: string }[]> =>
await Promise.all(
names.map(async (name) => getDnsRecord(zoneIdentifier, name, type, apiKey)),
);
const patchDnsRecord = async (
zoneIdentifier: string,
identifier: string,
@@ -77,4 +87,22 @@ const patchDnsRecord = async (
);
};
export { getDnsRecord, patchDnsRecord };
const patchDnsRecords = async (
dnsRecords: { content: string; name: string; id: string }[],
zoneIdentifier: string,
apiKey: string,
content: string,
type: string,
) =>
dnsRecords.forEach(async (dnsRecord) =>
await patchDnsRecord(
zoneIdentifier,
dnsRecord.id,
apiKey,
content,
dnsRecord.name,
type,
)
);
export { getDnsRecord, getDnsRecords, patchDnsRecord, patchDnsRecords };

View File

@@ -1,49 +1,55 @@
import { getDnsRecord, patchDnsRecord } from "./cloudflare";
import { getDnsRecords, patchDnsRecords } from "./cloudflare";
import getPublicIp from "./getPublicIp";
import * as log from "./log";
const { ZONE_ID, DOMAIN_NAME, API_KEY, INTERVAL } = process.env;
const { ZONE_ID, DOMAIN_NAMES, API_KEY, INTERVAL } = process.env;
if (ZONE_ID === undefined) {
log.error("could not access environment variable 'ZONE_ID'");
}
if (DOMAIN_NAME === undefined) {
log.error("could not access environment variable 'DOMAIN_NAME'");
if (DOMAIN_NAMES === undefined) {
log.error("could not access environment variable 'DOMAIN_NAMES'");
}
if (API_KEY === undefined) {
log.error("could not access environment variable 'API_KEY'");
}
if (
ZONE_ID === undefined || DOMAIN_NAME === undefined || API_KEY === undefined
ZONE_ID === undefined || DOMAIN_NAMES === undefined || API_KEY === undefined
) {
process.exit(1);
}
const dynamicDns = async () => {
const domainNames = DOMAIN_NAMES.split(",");
try {
const [publicIp, dnsRecord] = await Promise.all([
const [publicIp, dnsRecords] = await Promise.all([
getPublicIp(),
getDnsRecord(ZONE_ID, DOMAIN_NAME, "A", API_KEY),
getDnsRecords(ZONE_ID, domainNames, "A", API_KEY),
]);
if (publicIp === dnsRecord.content) {
const dnsRecordsToPatch = dnsRecords.filter((dnsRecord) => {
dnsRecord.content !== publicIp;
});
if (dnsRecordsToPatch.length === 0) {
log.info(`public ip address remained at '${publicIp}', no patch needed`);
log.info(`checking again in ${INTERVAL} minutes\n`);
return;
}
log.info(
`public ip address changed from '${dnsRecord.content}' to '${publicIp}'`,
`public ip address changed from '${
dnsRecordsToPatch[0].content
}' to '${publicIp}'`,
);
await patchDnsRecord(
await patchDnsRecords(
dnsRecordsToPatch,
ZONE_ID,
dnsRecord.id,
API_KEY,
publicIp,
DOMAIN_NAME,
"A",
);
log.info("patched dns entry");
log.info("patched dns entries");
log.info(`checking again in ${INTERVAL} minutes\n`);
} catch (error) {
log.error((error as Error).message);

View File

@@ -6,7 +6,7 @@ const STYLES = {
ERROR: "\x1b[31m",
};
let LOG_LEVEL = process.env.LOG_LEVEL || "INFO";
let LOG_LEVEL = process.env.LOG_LEVEL ?? "INFO";
if (!["DEBUG", "INFO", "WARN", "ERROR"].includes(LOG_LEVEL)) {
console.warn(