-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5e09530
commit 2137860
Showing
10 changed files
with
528 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules | ||
npm-debug.log | ||
.env | ||
.github |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Docker Image CI | ||
|
||
on: | ||
push: | ||
branches: [ "master" ] | ||
|
||
jobs: | ||
docker: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- | ||
name: Set up QEMU | ||
uses: docker/setup-qemu-action@v2 | ||
- | ||
name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v2 | ||
- | ||
name: Login to Docker Hub | ||
uses: docker/login-action@v2 | ||
with: | ||
username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
- | ||
name: Build and push | ||
uses: docker/build-push-action@v4 | ||
with: | ||
push: true | ||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/cloudflare-ddns:latest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
FROM node:19-alpine | ||
|
||
# Create app directory | ||
WORKDIR /usr/src/app | ||
|
||
ENV NODE_ENV=production | ||
|
||
# Install app dependencies | ||
# A wildcard is used to ensure both package.json AND package-lock.json are copied | ||
# where available (npm@5+) | ||
COPY package*.json ./ | ||
|
||
RUN npm install | ||
# If you are building your code for production | ||
# RUN npm ci --only=production | ||
|
||
# Bundle app source | ||
COPY . . | ||
|
||
CMD [ "npm", "run", "start" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
version: '3' | ||
services: | ||
log-tailer: | ||
container_name: cloudflare-ddns | ||
build: | ||
dockerfile: Dockerfile | ||
environment: | ||
- CLOUDFLARE_API_KEY= | ||
- DNS_URL= | ||
- CRON_SCHEDULE= | ||
volumes: | ||
- /var/run/docker.sock:/var/run/docker.sock | ||
labels: | ||
- disableLogging=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "cloudflare-ddns", | ||
"version": "0.0.1", | ||
"description": "Auto update a cloudflare DNS record with your public IP", | ||
"main": "index.js", | ||
"type": "module", | ||
"scripts": { | ||
"start": "node ./src/index", | ||
"dev": "node -r dotenv/config ./src/index" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com-personal:realshaunoneill/cloudflare-ddns.git" | ||
}, | ||
"keywords": [ | ||
"cloudflare" | ||
], | ||
"author": "Shaun O'Neill", | ||
"license": "ISC", | ||
"dependencies": { | ||
"cron": "^2.3.1", | ||
"node-fetch": "^3.3.1" | ||
}, | ||
"devDependencies": { | ||
"dotenv": "^16.3.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
import fetch from "node-fetch"; | ||
import { | ||
VERIFY_CLOUDFLARE_TOKEN_URL, | ||
GET_ZONES_URL, | ||
GET_ZONE_RECORDS_URL, | ||
UPDATE_ZONE_RECORD_URL, | ||
CREATE_ZONE_RECORD_URL, | ||
} from "./constants.js"; | ||
|
||
const WEBHOOK_URL = process.env.WEBHOOK_URL; | ||
const WEBHOOK_METHOD = process.env.WEBHOOK_METHOD; | ||
|
||
const defaultHeaders = { | ||
'Authorization': `Bearer ${process.env.CLOUDFLARE_API_KEY}`, | ||
} | ||
|
||
export const verifyCloudflareToken = async () => { | ||
try { | ||
const response = await fetch(VERIFY_CLOUDFLARE_TOKEN_URL, { | ||
method: 'GET', | ||
headers: defaultHeaders, | ||
}); | ||
|
||
if (response.ok) { | ||
const json = await response.json(); | ||
if (json.result && json.result.status === 'active') { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
return false; | ||
} | ||
}; | ||
|
||
export const getPublicIpAddress = async () => { | ||
try { | ||
const response = await fetch('https://api.ipify.org?format=json', { | ||
method: 'GET', | ||
}); | ||
|
||
if (response.ok) { | ||
const json = await response.json(); | ||
return json; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
export const getCloudflareZones = async () => { | ||
try { | ||
const response = await fetch(GET_ZONES_URL, { | ||
method: 'GET', | ||
headers: defaultHeaders, | ||
}); | ||
|
||
if (response.ok) { | ||
const json = await response.json(); | ||
return json; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
export const getCloudflareZoneRecords = async (zoneId) => { | ||
try { | ||
const response = await fetch(GET_ZONE_RECORDS_URL(zoneId), { | ||
method: 'GET', | ||
headers: defaultHeaders, | ||
}); | ||
if (response.ok) { | ||
const json = await response.json(); | ||
return json; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
export const updateCloudflareZoneRecord = async (zoneId, recordId, data) => { | ||
try { | ||
const response = await fetch(UPDATE_ZONE_RECORD_URL(zoneId, recordId), { | ||
method: 'PUT', | ||
headers: { | ||
...defaultHeaders, | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(data), | ||
}); | ||
|
||
if (response.ok) { | ||
const json = await response.json(); | ||
return json; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
export const createCloudflareZoneRecord = async (zoneId, data) => { | ||
try { | ||
const response = await fetch(CREATE_ZONE_RECORD_URL(zoneId), { | ||
method: 'POST', | ||
headers: { | ||
...defaultHeaders, | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(data), | ||
}); | ||
if (response.ok) { | ||
const json = await response.json(); | ||
return json; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
export const sendWebhookRequest = async (data) => { | ||
if (!WEBHOOK_URL || !WEBHOOK_METHOD) return; | ||
|
||
try { | ||
const response = await fetch(WEBHOOK_URL, { | ||
method: WEBHOOK_METHOD, | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(data), | ||
}); | ||
|
||
if (response.ok) { | ||
return response.status; | ||
} | ||
|
||
// Check if the response code is 429 (too many requests) | ||
if (response.status === 429) { | ||
throw new Error('Too many requests'); | ||
} | ||
|
||
// If the response code is not 429, throw an error | ||
throw new Error(response.status); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const VERIFY_CLOUDFLARE_TOKEN_URL = 'https://api.cloudflare.com/client/v4/user/tokens/verify'; | ||
export const GET_ZONES_URL = 'https://api.cloudflare.com/client/v4/zones'; | ||
export const GET_ZONE_RECORDS_URL = (zoneId) => `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`; | ||
export const UPDATE_ZONE_RECORD_URL = (zoneId, recordId) => `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`; | ||
export const CREATE_ZONE_RECORD_URL = (zoneId) => `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`; |
Oops, something went wrong.