Giter Site home page Giter Site logo

qdm12 / ddns-updater Goto Github PK

View Code? Open in Web Editor NEW
1.5K 15.0 147.0 6.95 MB

Container to update DNS records periodically with WebUI for many DNS providers

Home Page: https://hub.docker.com/r/qmcgaw/ddns-updater/

License: MIT License

Dockerfile 0.85% Go 98.10% HTML 0.44% CSS 0.60%
ddns-updater ddns-manager webui golang docker dynamic-dns ddns ddns-client gotify noip

ddns-updater's Introduction

Lightweight universal DDNS Updater program

Program to keep DNS A and/or AAAA records updated for multiple DNS providers

DDNS Updater logo

Build status

dockeri.co

Last release Last Docker tag Last release size GitHub last release date Commits since release

Latest size

GitHub last commit GitHub commit activity GitHub closed PRs GitHub issues GitHub closed issues

Lines of code Code size GitHub repo size Go version

MIT Visitors count

Versioned documentation

This readme and the docs/ directory are versioned to match the program version:

Version Readme link Docs link
Latest README docs/
v2.7.0 README docs/
v2.6.1 README docs/
v2.5.0 README docs/

Features

  • Available as a Docker image qmcgaw/ddns-updater and ghcr.io/qdm12/ddns-updater

  • ๐Ÿ†• Available as zero-dependency binaries for Linux, Windows and MacOS

  • Updates periodically A records for different DNS providers:

    • Aliyun
    • AllInkl
    • Changeip
    • Cloudflare
    • DD24
    • DDNSS.de
    • deSEC
    • DigitalOcean
    • DonDominio
    • DNSOMatic
    • DNSPod
    • Dreamhost
    • DuckDNS
    • DynDNS
    • Dynu
    • EasyDNS
    • FreeDNS
    • Gandi
    • GCP
    • GoDaddy
    • GoIP.de
    • He.net
    • Hetzner
    • Infomaniak
    • INWX
    • Ionos
    • Linode
    • LuaDNS
    • Name.com
    • Namecheap
    • Netcup
    • NoIP
    • Now-DNS
    • Njalla
    • OpenDNS
    • OVH
    • Porkbun
    • Route53
    • Selfhost.de
    • Servercow.de
    • Spdyn
    • Strato.de
    • Variomedia.de
    • Zoneedit
    • Want more? Create an issue for it!
  • Web user interface (Desktop)

    Web UI

  • Web user interface (Mobile)

    Mobile Web UI

  • Send notifications with Shoutrrr using SHOUTRRR_ADDRESSES

  • Container (Docker/K8s) specific features:

    • Lightweight 12MB Docker image based on the Scratch Docker image
    • Docker healthcheck verifying the DNS resolution of your domains
    • Images compatible with amd64, 386, arm64, armv7, armv6, s390x, ppc64le, riscv64 CPU architectures
  • Persistence with a JSON file updates.json to store old IP addresses with change times for each record

Setup

Binary programs

  1. Download the pre-built program for your platform from the assets of a release in the releases page. You can alternatively download, build and install the latest version of the program by installing Go and then run go install github.com/qdm12/ddns-updater/cmd/ddns-updater@latest.

  2. For Linux and MacOS, make the program executable with chmod +x ddns-updater.

  3. In the directory where the program is saved, create a directory data.

  4. Write a JSON configuration in data/config.json, for example:

    {
        "settings": [
            {
                "provider": "namecheap",
                "domain": "sub.example.com",
                "password": "e5322165c1d74692bfa6d807100c0310"
            }
        ]
    }

    You can find more information in the configuration section to customize it.

  5. Run the program with ./ddns-updater (./ddns-updater.exe on Windows) or by double-clicking on it.

  6. The following is optional.

    • You can customize the program behavior using either environment variables or flags. For flags, there is a flag corresponding to each environment variable, where it's all lowercase and underscores are replaced with dashes. For example the environment variable LOG_LEVEL translates into --log-level.

Container

โžก๏ธ Qnap guide by @Araminta

  1. Create a directory, for example, data which is:

    • owned by user id 1000, which is the built-in user ID of the ddns-updater container
    • has user read+write+execute permissions
    mkdir data
    chown 1000 data
    chmod u+r+w+x data

    If you want to use another user ID, build the image yourself with --build-arg UID=<your-uid>. You could also just run the container as root with --user="0" but this is not advised security wise.

  2. Similarly, create a data/config.json file which is:

    • owned by user id 1000
    • has user read permissions
    touch data/config.json
    chmod u+r data/config.json
  3. Edit data/config.json, for example:

    {
        "settings": [
            {
                "provider": "namecheap",
                "domain": "sub.example.com",
                "password": "e5322165c1d74692bfa6d807100c0310"
            }
        ]
    }

    You can find more information in the configuration section to customize it.

  4. Run the container with

    docker run -d -p 8000:8000/tcp -v "$(pwd)"/data:/updater/data qmcgaw/ddns-updater
  5. The following is optional.

    • You can customize the program behavior using environment variables
    • You can use docker-compose.yml with docker-compose up -d
    • Kubernetes: check out the k8s directory for an installation guide and examples.
    • Other Docker image tags are available
    • You can update the image with docker pull qmcgaw/ddns-updater
    • You can set your JSON configuration as a single environment variable line (i.e. {"settings": [{"provider": "namecheap", ...}]}), which takes precedence over config.json. Note however that if you don't bind mount the /updater/data directory, there won't be a persistent database file /updater/updates.json but it will still work.

Configuration

Start by having the following content in config.json, or in your CONFIG environment variable:

{
    "settings": [
        {
            "provider": "",
        },
        {
            "provider": "",
        }
    ]
}

For each setting, you need to fill in parameters. Check the documentation for your DNS provider:

Note that:

  • you can specify multiple owners/hosts for the same domain using a comma separated list. For example with "domain": "example.com,sub.example.com,sub2.example.com",.

Environment variables

๐Ÿ†• There are now flags equivalent for each variable below, for example --log-level.

Environment variable Default Description
CONFIG One line JSON object containing the entire config (takes precedence over config.json file) if specified
PERIOD 5m Default period of IP address check, following this format
PUBLICIP_FETCHERS all Comma separated fetcher types to obtain the public IP address from http and dns
PUBLICIP_HTTP_PROVIDERS all Comma separated providers to obtain the public IP address (ipv4 or ipv6). See the Public IP section
PUBLICIPV4_HTTP_PROVIDERS all Comma separated providers to obtain the public IPv4 address only. See the Public IP section
PUBLICIPV6_HTTP_PROVIDERS all Comma separated providers to obtain the public IPv6 address only. See the Public IP section
PUBLICIP_DNS_PROVIDERS all Comma separated providers to obtain the public IP address (IPv4 and/or IPv6). See the Public IP section
PUBLICIP_DNS_TIMEOUT 3s Public IP DNS query timeout
UPDATE_COOLDOWN_PERIOD 5m Duration to cooldown between updates for each record. This is useful to avoid being rate limited or banned.
HTTP_TIMEOUT 10s Timeout for all HTTP requests
SERVER_ENABLED yes Enable the web server and web UI
LISTENING_ADDRESS :8000 Internal TCP listening port for the web UI
ROOT_URL / URL path to append to all paths to the webUI (i.e. /ddns for accessing https://example.com/ddns through a proxy)
HEALTH_SERVER_ADDRESS 127.0.0.1:9999 Health server listening address
HEALTH_HEALTHCHECKSIO_BASE_URL https://hc-ping.com Base URL for the healthchecks.io server
HEALTH_HEALTHCHECKSIO_UUID UUID to idenfity with the healthchecks.io server
DATADIR /updater/data Directory to read and write data files from internally
CONFIG_FILEPATH /updater/data/config.json Path to the JSON configuration file
BACKUP_PERIOD 0 Set to a period (i.e. 72h15m) to enable zip backups of data/config.json and data/updates.json in a zip file
BACKUP_DIRECTORY /updater/data Directory to write backup zip files to if BACKUP_PERIOD is not 0.
RESOLVER_ADDRESS Your network DNS A plaintext DNS address to use to resolve your domain names defined in your settings only. For example it can be 1.1.1.1:53. This is useful for split dns, see #389
LOG_LEVEL info Level of logging, debug, info, warning or error
LOG_CALLER hidden Show caller per log line, hidden or short
SHOUTRRR_ADDRESSES (optional) Comma separated list of Shoutrrr addresses (notification services)
SHOUTRRR_DEFAULT_TITLE DDNS Updater Default title for Shoutrrr notifications
TZ Timezone to have accurate times, i.e. America/Montreal

Public IP

By default, all public IP fetching types are used and cycled (over DNS and over HTTPs).

On top of that, for each fetching method, all echo services available are cycled on each request.

This allows you not to be blocked for making too many requests.

You can otherwise customize it with the following:

Host firewall

If you have a host firewall in place, this container needs the following ports:

  • TCP 443 outbound for outbound HTTPS
  • UDP 53 outbound for outbound DNS resolution
  • TCP 8000 inbound (or other) for the WebUI

Architecture

At program start and every period (5 minutes by default):

  1. Fetch your public IP address
  2. For each record:
    1. DNS resolve it to obtain its current IP address(es)
      • If the resolution fails, update the record with your public IP address by calling the DNS provider API and finish
    2. Check if your public IP address is within the resolved IP addresses
      • Yes: skip the update
      • No: update the record with your public IP address by calling the DNS provider API

๐Ÿ’ก We do DNS resolution every period so it detects a change made to the record manually, for example on the DNS provider web UI ๐Ÿ’ก As DNS resolutions are essentially free and without rate limiting, these are great to avoid getting banned for too many requests.

Special case: Cloudflare

For Cloudflare records with the proxied option, the following is done.

At program start and every period (5 minutes by default), for each record:

  1. Fetch your public IP address
  2. For each record:
    1. Check the last IP address (persisted in updates.json) for that record
      • If it doesn't exist, update the record with your public IP address by calling the DNS provider API and finish
    2. Check if your public IP address matches the last IP address you updated the record with
      • Yes: skip the update
      • No: update the record with your public IP address by calling the DNS provider API

This is the only way as doing a DNS resolution on the record will give the IP address of a Cloudflare server instead of your server.

โš ๏ธ This has the disadvantage that if the record is changed manually, the program will not detect it. We could do an API call to get the record IP address every period, but that would get you banned especially with a low period duration.

Testing

  • The automated healthcheck verifies all your records are up to date using DNS lookups
  • You can also manually check, by:
    1. Going to your DNS management webpage
    2. Setting your record to 127.0.0.1
    3. Run the container
    4. Refresh the DNS management webpage and verify the update happened

Build the image

You can build the image yourself with:

docker build -t qmcgaw/ddns-updater https://github.com/qdm12/ddns-updater.git

You can use optional build arguments with --build-arg KEY=VALUE from the table below:

Build argument Default Description
UID 1000 User ID running the container
GID 1000 User group ID running the container
VERSION unknown Version of the program and Docker image
CREATED an unknown date Build date of the program and Docker image
COMMIT unknown Commit hash of the program and Docker image

Development and contributing

License

This repository is under an MIT license

Used in external projects

Support

Sponsor me on Github or donate to paypal.me/qmcgaw

Many thanks to J. Famiglietti for supporting me financially ๐Ÿฅ‡๐Ÿ‘

ddns-updater's People

Contributors

3deep5me avatar arturpragacz avatar azorimor avatar baswag avatar blackdark avatar cyberaustin avatar dennisgaida avatar dependabot[bot] avatar diamondprecisioncomputing avatar edaubert avatar felixwrt avatar fredericrous avatar fuse314 avatar jdiekhoff avatar jhotmann avatar lieblinger avatar marcelohpf avatar mchill avatar michaelmiklis avatar mikefero avatar msxdan avatar nu50218 avatar orbatschow avatar profiles avatar qdm12 avatar raman325 avatar ryankupk avatar sipnol avatar stavros-k avatar stumpylog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ddns-updater's Issues

Google Domains Support?

Hey, would it be possible to get Google Domains support? I have heard its incredibly similar to NO-IP. Thank you very much!

"no valid settings was found in the environment variables" w/Docker Compose?

Docker Compose file contents:

version: "3.7"
services:
ddns:
container_name: ddns
image: qmcgaw/ddns-updater
restart: unless-stopped
ports:
- 8000:8000
volumes:
- ./ddns:/updater/data
environment:
- DELAY=60
- LISTENINGPORT=8000
- LOGGING=human
- NODEID=0

When deploying this, I receive the following two error messages regardless of what variations I try:

ddns | {"level":"Warning","message":"The RECORDn environment variables will be removed and replaced by the config.json file in the coming months. Please update your container configuration as soon as possible to avoid problems once the retrocompatibility is removed. See more information on github.com/qdm12/ddns-updater","time":"2019-05-16T00:25:15.882564592Z","node":0}
ddns | {"level":"Warning","message":"no valid settings was found in the environment variables","time":"2019-05-16T00:25:15.882772979Z","node":0}

Is this just a logging logic issue, or is DDNS Updater really unable to read these variables? If so, why not?

Using 1 provider "Cloudflare". When ran, it registers as provider "Dreamhost

TLDR: Describe your issue in a one liner here

  1. Is this urgent?

    • Yes
    • No
  2. What DNS service provider(s) are you using?

    • Cloudflare
    • DDNSS.de
    • DNSPod
    • Dreamhost
    • DuckDNS
    • GoDaddy
    • Google
    • Infomaniak
    • Namecheap
    • NoIP
  3. What's the version of the program?

    See the line at the top of your logs

    Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)

  4. What are you using to run the container?

    • Docker run
    • Docker Compose
    • Kubernetes
    • Docker stack
    • Docker swarm
    • Podman
    • Other:
  5. Extra information

Logs:


Configuration file (remove your credentials!):

Host OS:

cloudflare api changed

Hello,
Cloudflare API was changed, now on script we need to speciy ttl value, otherwise we get an error :

--data '{"type":"A","name":"*","content":"1.2.3.4" = got error code 9021

--data '{"type":"A","name":"*","content":"1.2.3.4","ttl":1 = got "success": true

Thank you
Andrea

IP method ddnss6 is only for IPv6 addresses

Hi, am I correct, that ddns-update cannot update IPV6 addresses for Cloudflare?

The following piece of code implies that, along with the error that I mentioned in the subject area of this issue:

cloudflarePutBody{ Type: "A", Name: host, Content: ip.String(), Proxied: proxied, TTL: ttl, },
Regards,
Thomas.

Use Cloudflare List DNS Records API For Retrieving Record Identifier

It was great if you could enhance your ddns-updater so that it calls the Cloudflare "List DNS Records" API for retrieving the record identifier, which is required for updating the record with the new IP address.
For sure I would create a pull request for that, if I was a more experienced Go developer. I played a bit with the following snippet, but was not able to see the response body:

func main() {
	token := "my-zone.dns-token"
	userServiceKey := ""
	email := ""
	key := ""
	zoneIdentifier := "1befa8a15f56bf0f04abbd3851fe95e0"
	URL := CloudflareURL + "/zones/" + zoneIdentifier + "/dns_records" + "?type=A&name=wiki.example.com"
	req, _ := http.NewRequest(http.MethodGet, URL, nil)
	switch {
	case len(token) > 0:
		req.Header.Set("Authorization", "Bearer "+token)
	case len(userServiceKey) > 0:
		req.Header.Set("X-Auth-User-Service-Key", userServiceKey)
	case len(email) > 0 && len(key) > 0:
		req.Header.Set("X-Auth-Email", email)
		req.Header.Set("X-Auth-Key", key)
	default:
		fmt.Println(fmt.Errorf("email and key are both unset and user service key is not set and no token was provided"))
		return
	}
	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	fmt.Println(resp.Body)
	fmt.Println("** Executed **")
}

You could raise an error in case that more than one record is found.

Thanks,

Thomas.

Index out of range error

I have been continually getting the following error since the most recent image update a few days ago. Seems to be triggered by the addition of a Gotify notification trigger for a new IP address assignment.

panic: runtime error: index out of range [0] with length 0
goroutine 51 [running]:
ddns-updater/pkg/update.update(0xc0005994d0, 0xc0005960c0, 0xc0006c4180, 0xc000373780)
/tmp/gobuild/pkg/update/update.go:148 +0x12a0
created by ddns-updater/pkg/update.periodicServer
/tmp/gobuild/pkg/update/trigger.go:76 +0x1b8

lookup domain on ip: no such host

Hey there I've setup my domain with cloudflare and your ddns-updater in docker. Everything seems to work perfectly fine. it's updating my wildcard subdomain just fine but the docker container itself seems to "unhealthy" all the time and I get this log:

2020-01-04T18:47:48.976Z	WARN	Unhealthy	{"node_id": 0, "error": "lookup CENSORED_DOMAIN on CENSORED_IP:53: no such host"}

Any idea why this is happening ?

my config.json looks like this:

{
  "settings": [
    {
        "provider": "cloudflare",
        "domain": "CENSORED",
        "host": "*",
        "ip_method": "opendns",
        "zone_identifier": "CENSORED",
        "identifier": "CENSORED",
        "email": "[email protected]",
        "key": "CENSORED"
    }
  ]
}

Wildcard Entries for Dreamhost

When trying to update *.exampledomain.com, I the following error message:

{"level":"WARN","ts":"2019-10-29T00:32:30.973Z","msg":"invalid domain name format for settings {"domain":"*.exampledomain.com","host":"@","provider":"dreamhost"}","node_id":0}`

Config:

{
"provider": "dreamhost",
"domain": "*.exampledomain.com",
"ip_method": "duckduckgo",
"key": "XXXXXXX"
}

Current workaround: CNAME *.exampledomain.com > exampledomain.com

Custom ip_method provider

Linked to the thoughts on the ip method, would it be possible to add a "custom" ip_method provider ?

Assuming that the user provides an URL, which would just return the IP ? You could provide the PHP file to be self-hosted by the user as well.

Any though on that one ?

Thanks !

Cloudflare Update removes "Proxied" setting.

When this tool updates the IP address of a cloudflare DNS entry, the fact that the domain is being proxied (or passed through the cloudflare CDN) is cancelled, exposing the target IP address directly to the internet.

I have tried this a few different ways, but this always seems to be the case.

FEATURE REQUEST: read environment variables for setup

It would be absolutely positively greatly beneficially (I'm in a "lee" mood) enhance ddns-updater to alternatively read all (config.json) setup variables from environment variables. This would add the ability to completely script an install without having to manually create or modify any files.

Gotify env variables problem. (Upgrade docker image)

Hi, in the last version I have this error.

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x8e781b] goroutine 1 [running]: main.setupGotify(0xbc4060, 0xc00049ed20, 0x0, 0x1, 0x1, 0xb2d05e00) /tmp/gobuild/main.go:120 +0xeb main.main() /tmp/gobuild/main.go:53 +0x604

It seems an error whit Gotify, Adding env variables for gotify solve the issue.
I have a Gotify server so is no problem, but this may be a problem for other people.


Rollback to version Nov 28, 2019, everything is fine here.

Web UI Typo

In the web UI the last (far right) column header reads "Previous IPs (achronologically)" which appears to be a simple typo, as it appears it should be "chronologically" (omitting the leading 'a').

Issues getting DDNS to work.

I have discovered while doing a docker-compose up it will hang on

Reading history from database: domain URL.X host @

This happens when I do not have the correct HOME IP set within namecheap on my A record before DDNS-Updater boots up. Occasionally it will come up with the IP being off and will successfully change it.

After its running, I can get to the web interface and see that it successfully changed it. If my IP changes however, it doesn't look like its being recorded over on namecheap. All I get is:

 2020-05-31T04:35:17.344Z	WARN	unhealthy: lookup IP address of msrl.cc is 73.169.x.x instead of 73.169.x.x
ddns    | 2020-05-31T04:36:17.670Z	WARN	unhealthy: lookup IP address of msrl.cc is 73.169.x.x  instead of 73.169.x.x
ddns    | 2020-05-31T04:37:18.059Z	WARN	unhealthy: lookup IP address of msrl.cc is 73.169.x.x instead of 73.169.x.x

It gives me the warning but it doesn't update it. I can then do a docker-compose and it either goes through and changes it or hangs. I have no idea at this point.

Request: No-IP

Any chance of getting No-IP's service added? They have a Linux based app, but I'm not able to get it working and it would be awesome to add it to the docker environment.

The app and some support is available here: https://www.noip.com/download

Feature request: Better error logging

  1. What's the feature?

Add more information to DNS API update errors such as the provider name and domain name

  1. Why do you need this feature?

For now it's unclear what record is causing a problem if there is a problem.

  1. Extra information?

Backup config.json periodically

Hi, I always run a backup for the ddns-updater configuration. But in the last version the shell /bin/sh is not found in the docker image. Is there any change that broke the sh shell in the latest release?

oc rsh ddns-updater-x-xxx /bin/sh -i -c 'tar -zcvf /backup/ddns-updater.apps.xxx.com.ar/ddns-updater.20200501.tar.gz /updater/data'

rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:235: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory"

Thanks!!

No IP not working

Hi,

it seems like NoIp changed something in their http request.

I get badauth response.
When i try with curl it works if i use a base64 encoded password

curl --header "Authorization: Basic plain_username:base64_password" --header "User-Agent: DDNS-Updater [email protected]" https://dynupdate.no-ip.com/nic/update?hostname=domain

curl --header "Authorization: Basic base64-encoded-auth-string plain_username:base64_password" --header "User-Agent: DDNS-Updater [email protected]" https://dynupdate.no-ip.com/nic/update?hostname=domain
works as well

If i try any other combination it is not working and i get badauth.

I tried setting my password as base64 in the settings file but this will not work either unfortunately.

Regards,
Marcus

Cloudflare ttl error

Hello,

After using ddns-updater for a while with godaddy i wanted to change nameservers and use cloudflare.

I configured it as shown below:

         "provider": "cloudflare",
         "zone_identifier": "***********",
         "identifier": "***********",
         "host": "***********",
         "ttl": "1s",
         "email": "***********",
         "ip_method": "cycle",
         "key": "***********"

and i receive the following error:

2020-05-21T17:48:16.453Z WARN The value for the duration period of the updater does not have a time unit, you might want to set it to "300s" instead of "300" {"node_id": 0}

2020-05-21T17:48:16.455Z ERROR json: cannot unmarshal string into Go struct field settingsType.settings.ttl of type uint {"node_id": 0}

Feature request: Record events log

  1. What's the feature?

Record all events in the database, such as ip address changes, failed updates, etc.

  1. Why do you need this feature?

That would be interesting for the future web frontend

  1. Extra information?

[Feature Request] Support multiple namecheap host in one line

Instead of define each host in each block, it is better to define all hosts in one line seperate by comma. For example:

{
            "provider": "namecheap",
            "domain": "example.com",
            "host": "@, www, hello, world",
            "ip_method": "provider",
            "delay": 86400,
            "password": "123456EXAMPLEPASSWORD"
        },

When I write this issue, if I define host use this method, error appeared:


2020-05-17T21:48:25.448Z	INFO	Reading history from database: domain example.com host @, www, hello, world	{"node_id": 0},
2020-05-17T21:48:25.449Z	INFO	Web UI listening at address 0.0.0.0:8001 with root URL 	{"node_id": 0},
2020-05-17T21:48:25.199Z	INFO	Found single setting to update records	{"node_id": 0},
2020-05-17T21:48:25.449Z	INFO	backup: disabled	{"node_id": 0},
2020-05-17T21:48:26.081Z	ERROR	No Records updated. A record not Found;	{"node_id": 0},
2020-05-17T21:48:49.686Z	WARN	Stopping program: caught OS signal "terminated"	{"node_id": 0}

I used ddclient before and it can update namecheap record without define multiple block.

(All domain changed for security)

The command '/bin/sh -c apk --update add git build-base' returned a non-zero code: 1

Trying to build on a raspberry pi. Cloned the repo to a local directory and ran the arm64 build command from you documentation. This is usally the error I see when the architecture is not right but I am pretty sure Raspberry Pi3 is Arm8 64. Output is below.

docker build -t qmcgaw/ddns-updater \
--build-arg BASE_IMAGE_BUILDER=arm64v8/golang \
--build-arg BASE_IMAGE=arm64v8/alpine \
--build-arg GOARCH=arm64 \
.

Sending build context to Docker daemon   98.3kB
Step 1/26 : ARG BASE_IMAGE_BUILDER=golang
Step 2/26 : ARG BASE_IMAGE=alpine
Step 3/26 : ARG ALPINE_VERSION=3.10
Step 4/26 : ARG GO_VERSION=1.13
Step 5/26 : FROM ${BASE_IMAGE_BUILDER}:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder
1.13-alpine3.10: Pulling from arm64v8/golang
8bfa91304040: Pull complete
d523c651118b: Pull complete
a46c40489613: Pull complete
ce81c8f18008: Pull complete
232d38dd15d6: Pull complete
Digest: sha256:9244aa9c3b34272a57bb0e1cbacc571c7eb3c9113813e81fe430a372f308c2f2
Status: Downloaded newer image for arm64v8/golang:1.13-alpine3.10
 ---> 51f17d606bde
Step 6/26 : ARG GOARCH=amd64
 ---> Running in 00dfac987b27
Removing intermediate container 00dfac987b27
 ---> e17e30f89543
Step 7/26 : ARG GOARM=
 ---> Running in fce99676fed6
Removing intermediate container fce99676fed6
 ---> a975b179c146
Step 8/26 : RUN apk --update add git build-base
 ---> Running in dc2ad1bf6d48
standard_init_linux.go:211: exec user process caused "exec format error"
The command '/bin/sh -c apk --update add git build-base' returned a non-zero code: 1

Error on ip method

As it seems duckduckgo doesnt return the ip anymore, also google and opendns return this error:
In godaddy you cant use provider so no option to get the ip. Although both google and opendns return results.
Google
{"level":"WARN","ts":"2020-01-06T16:45:39.954Z","msg":"IP method google not recognized","node_id":0}
{"level":"FATAL","ts":"2020-01-06T16:45:39.954Z","msg":"no settings found in config.json","node_id":0}

OpenDNS
{"level":"WARN","ts":"2020-01-06T16:46:53.008Z","msg":"IP method opendns no longer supported","node_id":0}
{"level":"FATAL","ts":"2020-01-06T16:46:53.008Z","msg":"no settings found in config.json","node_id":0}

Using 1 provider "Cloudflare". When ran, it registers as provider "Dreamhost" and doesnt upgrade the record on cloudflare

I still dont think that it is still updating records and is registering as Dreamhost.

  1. Is this urgent?

    • Yes
    • No
  2. What DNS service provider(s) are you using?

    • Cloudflare
    • DDNSS.de
    • DNSPod
    • Dreamhost
    • DuckDNS
    • GoDaddy
    • Google
    • Infomaniak
    • Namecheap
    • NoIP
  3. What are you using to run the container?

    • Docker run
    • Docker Compose
    • Kubernetes
    • Docker stack
    • Docker swarm
    • Podman
    • Other:
  4. Extra information

Logs:

ddns    | 2020-06-01T20:52:37.072Z	INFO	Reading history from database: domain URL host @
ddns    | 2020-06-01T20:52:37.072Z	INFO	Reading history from database: domain URL host filebot
ddns    | 2020-06-01T20:52:37.072Z	INFO	Reading history from database: domain URL host files
ddns    | 2020-06-01T20:52:37.072Z	INFO	Reading history from database: domain URL host nginx
ddns    | 2020-06-01T20:52:37.072Z	INFO	Reading history from database: domain URL host portainer
ddns    | 2020-06-01T20:52:37.072Z	INFO	Reading history from database: domain URL host rss
ddns    | 2020-06-01T20:52:37.073Z	INFO	Reading history from database: domain URL host shlink
ddns    | 2020-06-01T20:52:37.073Z	INFO	Reading history from database: domain URL host shlink-server
ddns    | 2020-06-01T20:52:37.073Z	INFO	Reading history from database: domain URL host sonarr
ddns    | 2020-06-01T20:52:37.073Z	INFO	Web UI listening at address 0.0.0.0:8000 with root URL ""
ddns    | 2020-06-01T20:52:37.073Z	INFO	backup: disabled
ddns    | 2020-06-01T20:52:37.305Z	INFO	IP address changed from 172.67.190.152 to  
ddns    | 2020-06-01T20:52:37.350Z	INFO	IP address changed from 104.27.158.141 to  
ddns    | 2020-06-01T20:52:37.392Z	INFO	IP address changed from 172.67.190.152 to  
ddns    | 2020-06-01T20:52:37.431Z	INFO	IP address changed from 104.27.159.141 to  
ddns    | 2020-06-01T20:52:37.472Z	INFO	IP address changed from 172.67.190.152 to  
ddns    | 2020-06-01T20:52:37.511Z	INFO	IP address changed from 104.27.158.141 to  
ddns    | 2020-06-01T20:52:37.552Z	INFO	IP address changed from 172.67.190.152 to  
ddns    | 2020-06-01T20:52:37.590Z	INFO	IP address changed from 104.27.159.141 to  
ddns    | 2020-06-01T20:52:37.631Z	INFO	IP address changed from 104.27.158.141 to  
ddns    | 2020-06-01T20:52:37.631Z	INFO	Updating record [domain: URL | host: @ | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:37.631Z	INFO	Updating record [domain: URL | host: nginx | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:37.631Z	INFO	Updating record [domain: URL | host: shlink-server | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:37.852Z	ERROR	error 9006: Content for AAAA record is invalid. Must be a valid IPv6 address; 
ddns    | 2020-06-01T20:52:37.852Z	INFO	Updating record [domain: URL | host: rss | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:37.852Z	INFO	Updating record [domain: URL | host: shlink | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:37.852Z	INFO	Updating record [domain: URL | host: sonarr | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:38.002Z	ERROR	error 9006: Content for AAAA record is invalid. Must be a valid IPv6 address; 
ddns    | 2020-06-01T20:52:38.002Z	INFO	Updating record [domain: URL | host: filebot | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:38.002Z	INFO	Updating record [domain: URL | host: files | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:38.002Z	INFO	Updating record [domain: URL | host: portainer | provider: dreamhost | ip: ipv4 or ipv6]
ddns    | 2020-06-01T20:52:38.148Z	ERROR	error 9006: Content for AAAA record is invalid. Must be a valid IPv6 address; 


Configuration file (remove your credentials!):

   "settings":[
      {
         "provider":"cloudflare",
         "zone_identifier":"ZONE",
         "identifier":"IDENTIFIER",
         "domain":"URL;.com",
         "host":"@,filebot,files,nginx,portainer,rss,shlink,shlink-server,sonarr",
         "ttl":1,
         "proxied":true,
         "email":"EMAIL",
         "key":"KEY",
         "no_dns_lookup":false
      }
   ]
}

Host OS: Ubuntu 20.04

Feature request: DNS lookup before DNS API call

  1. What's the feature?

For each record, run a DNS lookup to obtain the A and AAAA records values to verify if the IP address matches the one fetched. Only call the DNS API if it's different.

  1. Why do you need this feature?

To avoid calling the DNS API when the container starts, especially when there is no historical data for a particular record.

  1. Extra information?

FEATURE REQUEST: allowing setting PUID/GUID

Of course I did NOT follow the instructions for setting up the config.json...

After initial install and run I instantly received:
image

If we could set PUID/GUID in the environment variables, setup would be simpler. (HINT: Look at all the linuxserver containers.)

Not sure of the setup, but running as root would also solve the problem!

opendns something wrong

~ curl https://diagnostic.opendns.com/myip
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

change https to http is ok

~ curl http://diagnostic.opendns.com/myip
xxx.xxx.xxx

Unable to open database file.....

2019/04/29 15:36:32 Info: Node 0: Found 1 records to update
#################################
##### DDNS Universal Updater ####
######## by Quentin McGaw #######
######## Give some โค at #########
# github.com/qdm12/ddns-updater #
#################################
2019/04/29 15:36:32 Info: Node 0: unable to open database file

Docker on Raspberry Pi 3

Hi,
i'm trying to run the container over a raspberry pi 3b, but i'm getting this error when i start the container.

standard_init_linux.go:207: exec user process caused "exec format error"

Googling i read that seems to be a architecture error, do you provide a container builded for arm devices?

Thanks!

Feature request: React user interface

  1. What's the feature?

Reactjs Flutter based web user interface

  1. Why do you need this feature?

See updates status and insert and modify settings to update the records.

  1. Extra information?
  • Create a new icon
  • Have live update (poll every second)

Feature request: AAAA records update for IPv6

  1. What's the feature?

    For now, only DDNSS.de and Infomaniak support IPv6 AAAA records update. This should be extended to all other DNS providers

  2. Why do you need this feature?

    If you ipv6 (or ipv4 and ipv6)

  3. Extra information?

    Refers to #50

Infomaniak.com support

Hi,

Thanks for the great work !

Would it be possible to add Infomaniak.com as a provider ? It gives the following HTTPS url to call with specific parameters to update a domain:

https://[USERNAME]:[PASSWORD]@[infomaniak.com/nic/update?hostname=[DOMAIN]&myip=[IP]

Reference

Thanks !

ERROR unexpected end of JSON input {"node_id": 0}

I'm getting the error: unexpected end of JSON input {"node_id": 0}

When trying to use dens-updater for the first time via this entry in the docker compose file:

  ddns-updater:
    image: qmcgaw/ddns-updater
    container_name: ddns-updater
    networks:
      - default
    ports:
      - 8000:8000/tcp
    volumes:
      - $USERDIR/docker/ddns-updater/data:/updater/data
    environment:
      - DELAY=300s
      - ROOT_URL=/
      - LISTENING_PORT=8000
      - LOG_ENCODING=console
      - LOG_LEVEL=info
      - NODE_ID=0
      - HTTP_TIMEOUT=10s
      - GOTIFY_URL=
      - GOTIFY_TOKEN=
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    restart: always

If the URL is within updates.json than it will not update the record.

Hey, I think I discovered an issue that when the record is within updates.json it will no longer update the record if the IP changes. This is repeatable because as long as the updates.json exists it will not update the record. Delete the file and boot up the container and it will update the record.

  1. Is this urgent?

    • Yes
    • No
  2. What DNS service provider(s) are you using?

    • Cloudflare
    • DDNSS.de
    • DNSPod
    • Dreamhost
    • DuckDNS
    • GoDaddy
    • Google
    • Infomaniak
    • Namecheap
    • NoIP
  3. What's the version of the program?

    See the line at the top of your logs

    Running version latest built on 2020-06-01T21:16:36Z (commit 9ccdbbd)

  4. What are you using to run the container?

    • Docker run
    • Docker Compose
    • Kubernetes
    • Docker stack
    • Docker swarm
    • Podman
    • Other:
  5. Extra information

Logs:


plex@LMS:~/utilities/ddns$ docker-compose up
Starting ddns ... done
Attaching to ddns
ddns    | =========================================
ddns    | =========================================
ddns    | ========= DDNS Universal Updater ========
ddns    | =========================================
ddns    | === Made with โค๏ธ  by github.com/qdm12 ====
ddns    | =========================================
ddns    | 
ddns    | Running version latest built on 2020-06-01T21:16:36Z (commit 9ccdbbd)
ddns    | 
ddns    | 
ddns    | ๐Ÿ”ง  Need help? https://github.com/qdm12/ddns-updater/issues/new
ddns    | ๐Ÿ’ป  Email? [email protected]
ddns    | โ˜•  Slack? Join from the Slack button on Github
ddns    | ๐Ÿ’ธ  Help me? https://github.com/sponsors/qdm12
ddns    | 2020-06-03T03:48:15.502Z	INFO	Found 11 settings to update records
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host @
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL2 host @
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host filebot
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host netdata
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host files
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host nginx
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host portainer
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host rss
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host shlink
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host shlink-server
ddns    | 2020-06-03T03:48:15.751Z	INFO	Reading history from database: domain URL host sonarr
ddns    | 2020-06-03T03:48:15.751Z	INFO	Web UI listening at address 0.0.0.0:8000 with root URL ""
ddns    | 2020-06-03T03:48:15.751Z	INFO	backup: disabled
ddns    | 2020-06-03T03:48:16.020Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:48:16.057Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:48:16.096Z	WARN	lookup netdata.URL on 127.0.0.11:53: no such host
ddns    | 2020-06-03T03:48:16.096Z	INFO	IP address changed from <nil> to IP
ddns    | 2020-06-03T03:48:16.135Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:48:16.174Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:48:16.213Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:48:16.251Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:48:16.328Z	WARN	lookup shlink-server.URL on 127.0.0.11:53: no such host
ddns    | 2020-06-03T03:48:16.328Z	INFO	IP address changed from <nil> to IP
ddns    | 2020-06-03T03:48:16.366Z	INFO	IP address changed from 104.27.158.141 to IP
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: sonarr | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: @ | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: files | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: nginx | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: rss | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: shlink-server | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.366Z	INFO	Updating record [domain: URL | host: filebot | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.367Z	INFO	Updating record [domain: URL | host: netdata | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:48:16.645Z	INFO	Updating record [domain: URL | host: portainer | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.032Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.071Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.110Z	WARN	lookup netdata.URL on 127.0.0.11:53: no such host
ddns    | 2020-06-03T03:49:16.110Z	INFO	IP address changed from <nil> to IP
ddns    | 2020-06-03T03:49:16.146Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.181Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.218Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.254Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.331Z	WARN	lookup shlink-server.URL on 127.0.0.11:53: no such host
ddns    | 2020-06-03T03:49:16.331Z	INFO	IP address changed from <nil> to IP
ddns    | 2020-06-03T03:49:16.372Z	INFO	IP address changed from X to IP
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: portainer | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: rss | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: filebot | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: files | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: nginx | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: shlink-server | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: sonarr | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: @ | provider: cloudflare | ip: ipv4 or ipv6]
ddns    | 2020-06-03T03:49:16.372Z	INFO	Updating record [domain: URL | host: netdata | provider: cloudflare | ip: ipv4 or ipv6]



Configuration file (remove your credentials!):

Host OS:

UBUNTU

open /updater/data/config.json: no such file or directory

I am trying to get this container to run with no success.

I have other containers running with volume mounts which work fine.

I have made sure to set the permissions correctly on the data folder and config.json file.

Here is the error message:

{"level":"FATAL","ts":"2019-11-06T09:16:10.375Z","msg":"open /updater/data/config.json: no such file or directory","node_id":0}

Here is the docker-compose.yml:

https://gist.github.com/Clownfused/9985b3dcc49ddfef67e167ab6089c5be

Any idea why this is happening?

Thanks

Issue with Cloudflare Tokens containing a dash/hyphen `-`

I have faced this myself. I have Cloudflare which I am able to use via the curl CLI but the same token is returned as invalid when used via the docker image. Upon diagnosis, I found that the regex being used to check for token validity did not contain a dash/hyphen whereas my token had one. I have created PR #86 that fixes this.

Please merge and update the docker image.

  1. Is this urgent?

    • Yes
    • No
  2. What DNS service provider(s) are you using?

    • Cloudflare
    • DDNSS.de
    • DNSPod
    • Dreamhost
    • DuckDNS
    • GoDaddy
    • Google
    • Infomaniak
    • Namecheap
    • NoIP
  3. What's the version of the program?

    Latest docker image

  4. What are you using to run the container?

    • Docker run
    • Docker Compose
    • Kubernetes
    • Docker stack
    • Docker swarm
    • Podman
    • Other:

Configuration file (remove your credentials!):

{
    "settings": [
        {
            "provider":"cloudflare",
            "no_dns_lookup":false,
            "zone_identifier":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "domain":"example.com",
            "host":"@",
            "ttl":1,
            "token":"xxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxx_xxx",
            "proxied":true,
            "ip_version":"ipv4"
        }
    ]
}

Host OS: Docker Image on Ubuntu 20.04 aarch64

ERROR: no settings found in config.json

Using docker-compose; have properly formatted config.json via jsonlint, however when I start the container & run docker logs ddns-updater I receive the error 'no settings found in config.json'
getting the same result both with a specific volumes line pointing to the config file: './ddns/data:/config.json' & without that volume line.

permissions for directory & config.json are set as per configuration instructions.

Best I can tell I've got config.json placed incorrectly, or at least placed where ddns-updater isn't seeing it; can you provide some guidance on either properly mapping the volume line in docker-compose.yml or placement of the config file?

Thanks for this tool, not only does it serve a much-needed purpose but I'm learning about several things in the process of getting it up & running which I really appreciate.

Healthcheck Error

Configured using namecheap, and looks like the IP was updated successfully. I can access the UI, and all looks well. However, healthceck is failing?

{"level":"Warning","message":"Responded with error to healthcheck: lookup IP address of MYDOMAIN is 127.0.0.1, not MYIP","time":"2019-08-23T12:01:45.865150724Z","node":0}

Any thoughts?

Thanks for writing this btw ๐Ÿ‘

Feature request: API HTTP server

  1. What's the feature?

Setup a simple HTTP server to serve information and modify settings

  1. Why do you need this feature?

Such that it can be used as an API consumed by the web ui react frontend

  1. Extra information?

Unhealthy IP Lookup for Cloudflare proxied domains.

When utilizing an A record for dynamic DNS on a proxied CloudFlare domain, the following is seen constantly in the console log.

WARN unhealthy: lookup IP address of MyDomain.com is 104.18.55.237 instead of W.X.Y.Z {"node_id": 0}
Note that 104.18.55.237 is the CloudFlare proxy IP and W.X.Y.Z is my current Public IP.

I'm utilizing OpenDNS for the IP lookup.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.