feat: add support for external dns plugins

This commit is contained in:
Johan Siebens
2025-05-24 11:01:05 +02:00
committed by GitHub
parent f8b0eceae7
commit 57e8eb3a25
8 changed files with 427 additions and 37 deletions
+16 -9
View File
@@ -16,8 +16,11 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.2
github.com/hashicorp/go-bexpr v0.1.14
github.com/hashicorp/go-getter v1.7.8
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-plugin v1.6.3
github.com/jsiebens/go-edit v0.1.0
github.com/jsiebens/libdns-plugin v0.1.0
github.com/jsiebens/mockoidc v0.1.0-rc2
github.com/klauspost/compress v1.18.0
github.com/labstack/echo-contrib v0.17.3
@@ -26,7 +29,7 @@ require (
github.com/libdns/cloudflare v0.1.1
github.com/libdns/digitalocean v0.0.0-20230728223659-4f9064657aea
github.com/libdns/googleclouddns v1.1.0
github.com/libdns/libdns v0.2.2
github.com/libdns/libdns v0.2.3
github.com/libdns/route53 v1.3.3
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/pointerstructure v1.2.1
@@ -43,10 +46,10 @@ require (
github.com/travisjeffery/certmagic-sqlstorage v1.1.1
github.com/xhit/go-str2duration/v2 v2.1.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.37.0
golang.org/x/net v0.39.0
golang.org/x/crypto v0.38.0
golang.org/x/net v0.40.0
golang.org/x/oauth2 v0.29.0
golang.org/x/sync v0.13.0
golang.org/x/sync v0.14.0
google.golang.org/protobuf v1.36.6
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
@@ -121,6 +124,7 @@ require (
github.com/dvsekhvalnov/jose2go v1.7.0 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gaissmai/bart v0.11.1 // indirect
@@ -137,6 +141,7 @@ require (
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@@ -154,6 +159,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/illarion/gonotify/v2 v2.0.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -187,6 +193,7 @@ require (
github.com/mtibben/percent v0.2.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runc v1.2.3 // indirect
@@ -240,9 +247,9 @@ require (
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/term v0.31.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.29.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
@@ -250,8 +257,8 @@ require (
google.golang.org/api v0.230.0 // indirect
google.golang.org/genproto v0.0.0-20250425173222-7b384671a197 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250425173222-7b384671a197 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197 // indirect
google.golang.org/grpc v1.72.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect
google.golang.org/grpc v1.72.1 // indirect
gvisor.dev/gvisor v0.0.0-20240722211153-64c016c92987 // indirect
modernc.org/libc v1.50.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
+36 -18
View File
@@ -743,6 +743,8 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg=
github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/caddyserver/certmagic v0.17.2/go.mod h1:ouWUuC490GOLJzkyN35eXfV8bSbwMwSf4bdhkIxtdQE=
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
@@ -851,6 +853,7 @@ github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6Ni
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
@@ -1075,6 +1078,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg=
github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
@@ -1084,6 +1089,8 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU=
github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
@@ -1108,6 +1115,8 @@ github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jellydator/ttlcache/v3 v3.1.0 h1:0gPFG0IHHP6xyUyXq+JaD8fwkDCqgqwohXNJBcYE71g=
github.com/jellydator/ttlcache/v3 v3.1.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@@ -1119,6 +1128,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jsiebens/go-edit v0.1.0 h1:62SSGW8Qc2zoBcJx7gV86ImPHmQzlU/DQhwCOR4uilE=
github.com/jsiebens/go-edit v0.1.0/go.mod h1:m/wuWMv8sNhSl+M2qA35gP/K5jX2J7Aa+g16VwyfxrI=
github.com/jsiebens/libdns-plugin v0.1.0 h1:ccZBGZi5HYnPRvKO5w/1wM8Aup6ukYwCAtFFgmRwz0A=
github.com/jsiebens/libdns-plugin v0.1.0/go.mod h1:38JU+yXbgU8Nb3PUWpoyTS59isnbJqEjfzx11MtgSzQ=
github.com/jsiebens/mockoidc v0.1.0-rc2 h1:ifKYhKxfYQMmglcBKkRX9EUuTYmOMnrrOrB6r1zW/gs=
github.com/jsiebens/mockoidc v0.1.0-rc2/go.mod h1:ym8B5bmE8RQAyxuC3lzqtNvxXyJomwxZZG5CIJGXCtk=
github.com/jsimonetti/rtnetlink v1.4.1 h1:JfD4jthWBqZMEffc5RjgmlzpYttAVw1sdnmiNaPO3hE=
@@ -1182,17 +1193,20 @@ github.com/libdns/digitalocean v0.0.0-20230728223659-4f9064657aea/go.mod h1:B2TC
github.com/libdns/googleclouddns v1.1.0 h1:murPR1LfTZZObLV2OLxUVmymWH25glkMFKpDjkk2m0E=
github.com/libdns/googleclouddns v1.1.0/go.mod h1:3tzd056dfqKlf71V8Oy19En4WjJ3ybyuWx6P9bQSCIw=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/libdns/libdns v0.2.3 h1:ba30K4ObwMGB/QTmqUxf3H4/GmUrCAIkMWejeGl12v8=
github.com/libdns/libdns v0.2.3/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/libdns/route53 v1.3.3 h1:16sTxbbRGm0zODz0p0aVHHIyTqtHzEn3j0s4dGzQvNI=
github.com/libdns/route53 v1.3.3/go.mod h1:n1Xy55lpfdxMIx4CVWAM16GQac+/OZcnm1xBjMyhZAo=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
@@ -1255,6 +1269,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nleeper/goment v1.4.4 h1:GlMTpxvhueljArSunzYjN9Ri4SOmpn0Vh2hg2z/IIl8=
github.com/nleeper/goment v1.4.4/go.mod h1:zDl5bAyDhqxwQKAvkSXMRLOdCowrdZz53ofRJc4VhTo=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
@@ -1377,6 +1393,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@@ -1529,8 +1546,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1669,8 +1686,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1724,8 +1741,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1787,6 +1804,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1826,8 +1844,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1843,8 +1861,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1865,8 +1883,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2166,8 +2184,8 @@ google.golang.org/genproto v0.0.0-20250425173222-7b384671a197 h1:qWb9n6MA4nHA/g2
google.golang.org/genproto v0.0.0-20250425173222-7b384671a197/go.mod h1:Cej/8iHf9mPl71o/a+R1rrvSFrAAVCUFX9s/sbNttBc=
google.golang.org/genproto/googleapis/api v0.0.0-20250425173222-7b384671a197 h1:9DuBh3k1jUho2DHdxH+kbJwthIAq02vGvZNrD2ggF+Y=
google.golang.org/genproto/googleapis/api v0.0.0-20250425173222-7b384671a197/go.mod h1:Cd8IzgPo5Akum2c9R6FsXNaZbH3Jpa2gpHlW89FqlyQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197 h1:29cjnHVylHwTzH66WfFZqgSQgnxzvWE+jvBwpZCLRxY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 h1:IkAfh6J/yllPtpYFU0zZN1hUPYdT0ogkBT/9hMxHjvg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -2209,8 +2227,8 @@ google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+1
View File
@@ -219,6 +219,7 @@ type DNS struct {
type DNSProvider struct {
Name string `json:"name"`
PluginPath string `json:"plugin_path"`
Zone string `json:"zone"`
Configuration json.RawMessage `json:"config"`
}
+124
View File
@@ -0,0 +1,124 @@
package dns
import (
"context"
"encoding/json"
"fmt"
"github.com/hashicorp/go-plugin"
"github.com/jsiebens/ionscale/internal/util"
dnsplugin "github.com/jsiebens/libdns-plugin"
"github.com/libdns/libdns"
"go.uber.org/zap"
"os/exec"
"sync"
"time"
)
// pluginManager handles plugin lifecycle and resilience
type pluginManager struct {
pluginPath string
client *plugin.Client
instance dnsplugin.Provider
lock sync.RWMutex
logger *zap.Logger
zone string
config json.RawMessage
}
// NewPluginManager creates a new plugin manager
func newPluginManager(pluginPath string, zone string, config json.RawMessage) (*pluginManager, error) {
logger := zap.L().Named("dns").With(zap.String("plugin_path", pluginPath))
p := &pluginManager{
pluginPath: pluginPath,
logger: logger,
zone: zone,
config: config,
}
if err := p.ensureRunning(true); err != nil {
return nil, err
}
return p, nil
}
// ensureRunning makes sure the plugin is running
func (pm *pluginManager) ensureRunning(start bool) error {
pm.lock.RLock()
running := pm.client != nil && !pm.client.Exited()
instance := pm.instance
pm.lock.RUnlock()
if running && instance != nil {
return nil
}
// Need to restart
pm.lock.Lock()
defer pm.lock.Unlock()
if !start {
pm.logger.Info("Restarting DNS plugin")
}
if pm.client != nil {
pm.client.Kill()
}
// Create a new client
cmd := exec.Command(pm.pluginPath)
pm.client = plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: dnsplugin.Handshake,
Plugins: dnsplugin.PluginMap,
Cmd: cmd,
AllowedProtocols: []plugin.Protocol{
plugin.ProtocolNetRPC,
plugin.ProtocolGRPC,
},
Managed: true,
Logger: util.NewZapAdapter(pm.logger, "dns"),
})
// Connect via RPC
rpcClient, err := pm.client.Client()
if err != nil {
return fmt.Errorf("error creating plugin client: %w", err)
}
// Request the plugin
raw, err := rpcClient.Dispense(dnsplugin.ProviderPluginName)
if err != nil {
return fmt.Errorf("error dispensing plugin: %w", err)
}
// Convert to the interface
pm.instance = raw.(dnsplugin.Provider)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
if err := pm.instance.Configure(ctx, pm.config); err != nil {
return fmt.Errorf("error configuring plugin: %w", err)
}
pm.logger.Info("DNS plugin started")
return nil
}
func (pm *pluginManager) SetRecord(ctx context.Context, recordType, recordName, value string) error {
if err := pm.ensureRunning(false); err != nil {
return err
}
_, err := pm.instance.SetRecords(ctx, pm.zone, []libdns.Record{{
Type: recordType,
Name: libdns.RelativeName(recordName, pm.zone),
Value: value,
TTL: 1 * time.Minute,
}})
return err
}
+17 -3
View File
@@ -11,6 +11,7 @@ import (
"github.com/libdns/googleclouddns"
"github.com/libdns/libdns"
"github.com/libdns/route53"
"go.uber.org/zap"
"strings"
"time"
)
@@ -33,16 +34,24 @@ func NewProvider(config config.DNS) (Provider, error) {
return nil, nil
}
if p.Name == "" && p.PluginPath == "" {
return nil, fmt.Errorf("invalid dns provider configuration, either name or plugin_path should be set")
}
if p.Name != "" && p.PluginPath != "" {
return nil, fmt.Errorf("invalid dns provider configuration, only one of name or plugin_path should be set")
}
if !strings.HasSuffix(config.MagicDNSSuffix, p.Zone) {
return nil, fmt.Errorf("invalid MagicDNS suffix [%s], not part of zone [%s]", config.MagicDNSSuffix, p.Zone)
}
factory, ok := factories[p.Name]
if !ok {
return nil, fmt.Errorf("unknown dns provider: %s", p.Name)
if ok {
return newProvider(p.Zone, p.Configuration, factory)
}
return newProvider(p.Zone, p.Configuration, factory)
return newPluginManager(p.PluginPath, fqdn(p.Zone), p.Configuration)
}
func newProvider(zone string, values json.RawMessage, factory func() libdns.RecordSetter) (Provider, error) {
@@ -54,22 +63,27 @@ func newProvider(zone string, values json.RawMessage, factory func() libdns.Reco
}
func azureProvider() libdns.RecordSetter {
zap.L().Warn("Builtin azure DNS plugin is deprecated and will be removed in a future release.")
return &azure.Provider{}
}
func cloudflareProvider() libdns.RecordSetter {
zap.L().Warn("Builtin cloudflare DNS plugin is deprecated and will be removed in a future release.")
return &cloudflare.Provider{}
}
func digitalOceanProvider() libdns.RecordSetter {
zap.L().Warn("Builtin digitalocean DNS plugin is deprecated and will be removed in a future release.")
return &digitalocean.Provider{}
}
func googleCloudDNSProvider() libdns.RecordSetter {
zap.L().Warn("Builtin googleclouddns DNS plugin is deprecated and will be removed in a future release.")
return &googleclouddns.Provider{}
}
func route53Provider() libdns.RecordSetter {
zap.L().Warn("Builtin route53 DNS plugin is deprecated and will be removed in a future release.")
return &route53.Provider{}
}
+2
View File
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"github.com/caddyserver/certmagic"
"github.com/hashicorp/go-plugin"
"github.com/jsiebens/ionscale/internal/auth"
"github.com/jsiebens/ionscale/internal/config"
"github.com/jsiebens/ionscale/internal/core"
@@ -221,6 +222,7 @@ func Start(ctx context.Context, c *config.Config) error {
go func() {
<-gCtx.Done()
logger.Sugar().Infow("Shutting down ionscale server")
plugin.CleanupClients()
shutdownHttpServer(metricsServer)
shutdownHttpServer(webServer)
_ = stunServer.Shutdown()
+152
View File
@@ -0,0 +1,152 @@
package util
import (
"fmt"
"io"
"log"
"strings"
"github.com/hashicorp/go-hclog"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type ZapHCLogAdapter struct {
zapLogger *zap.Logger
name string
}
func NewZapAdapter(zapLogger *zap.Logger, name string) *ZapHCLogAdapter {
return &ZapHCLogAdapter{
zapLogger: zapLogger.WithOptions(zap.AddCallerSkip(2)),
name: name,
}
}
func (z *ZapHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
fields := make([]zap.Field, 0, len(args)/2)
for i := 0; i < len(args); i += 2 {
if i+1 < len(args) {
key, ok := args[i].(string)
if !ok {
key = fmt.Sprintf("%v", args[i])
}
fields = append(fields, zap.Any(key, args[i+1]))
}
}
switch level {
case hclog.Trace:
z.zapLogger.Debug(msg, fields...)
case hclog.Debug:
z.zapLogger.Debug(msg, fields...)
case hclog.Info:
z.zapLogger.Info(msg, fields...)
case hclog.Warn:
z.zapLogger.Warn(msg, fields...)
case hclog.Error:
z.zapLogger.Error(msg, fields...)
}
}
func (z *ZapHCLogAdapter) Trace(msg string, args ...interface{}) {
z.Log(hclog.Trace, msg, args...)
}
func (z *ZapHCLogAdapter) Debug(msg string, args ...interface{}) {
z.Log(hclog.Debug, msg, args...)
}
func (z *ZapHCLogAdapter) Info(msg string, args ...interface{}) {
z.Log(hclog.Info, msg, args...)
}
func (z *ZapHCLogAdapter) Warn(msg string, args ...interface{}) {
z.Log(hclog.Warn, msg, args...)
}
func (z *ZapHCLogAdapter) Error(msg string, args ...interface{}) {
z.Log(hclog.Error, msg, args...)
}
func (z *ZapHCLogAdapter) IsTrace() bool {
return z.zapLogger.Core().Enabled(zapcore.DebugLevel)
}
func (z *ZapHCLogAdapter) IsDebug() bool {
return z.zapLogger.Core().Enabled(zapcore.DebugLevel)
}
func (z *ZapHCLogAdapter) IsInfo() bool {
return z.zapLogger.Core().Enabled(zapcore.InfoLevel)
}
func (z *ZapHCLogAdapter) IsWarn() bool {
return z.zapLogger.Core().Enabled(zapcore.WarnLevel)
}
func (z *ZapHCLogAdapter) IsError() bool {
return z.zapLogger.Core().Enabled(zapcore.ErrorLevel)
}
func (z *ZapHCLogAdapter) ImpliedArgs() []interface{} {
return nil
}
func (z *ZapHCLogAdapter) With(args ...interface{}) hclog.Logger {
if len(args) == 0 {
return z
}
fields := make([]zap.Field, 0, len(args)/2)
for i := 0; i < len(args); i += 2 {
if i+1 < len(args) {
key, ok := args[i].(string)
if !ok {
key = fmt.Sprintf("%v", args[i])
}
fields = append(fields, zap.Any(key, args[i+1]))
}
}
newLogger := z.zapLogger.With(fields...)
return &ZapHCLogAdapter{
zapLogger: newLogger,
}
}
func (z *ZapHCLogAdapter) Name() string {
return z.name
}
func (z *ZapHCLogAdapter) Named(name string) hclog.Logger {
return &ZapHCLogAdapter{zapLogger: z.zapLogger.Named(name), name: name}
}
func (z *ZapHCLogAdapter) ResetNamed(name string) hclog.Logger {
return &ZapHCLogAdapter{
zapLogger: z.zapLogger,
name: name,
}
}
func (z *ZapHCLogAdapter) SetLevel(level hclog.Level) {
}
func (z *ZapHCLogAdapter) GetLevel() hclog.Level {
return hclog.LevelFromString(z.zapLogger.Level().String())
}
func (z *ZapHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
return log.New(z, "", log.LstdFlags)
}
func (z *ZapHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
return z
}
func (z *ZapHCLogAdapter) Write(p []byte) (n int, err error) {
s := strings.TrimSpace(string(p))
z.Info(s)
return len(p), nil
}
+79 -7
View File
@@ -13,7 +13,11 @@ Without a configured DNS provider, these features will not be available to your
## Supported DNS providers
ionscale uses the [libdns](https://github.com/libdns) libraries to support the following DNS providers:
ionscale supports DNS providers through two methods:
### Built-in providers (deprecated)
ionscale includes built-in support for the following DNS providers using [libdns](https://github.com/libdns) libraries:
- [Azure DNS](https://github.com/libdns/azure)
- [Cloudflare](https://github.com/libdns/cloudflare)
@@ -21,18 +25,26 @@ ionscale uses the [libdns](https://github.com/libdns) libraries to support the f
- [Google Cloud DNS](https://github.com/libdns/googleclouddns)
- [Amazon Route 53](https://github.com/libdns/route53)
!!! info "Provider availability"
These are the DNS providers supported at the time of this writing. Since ionscale uses the libdns ecosystem, additional providers may be added in future releases as the ecosystem expands.
If you need support for a different DNS provider, check the [libdns GitHub organization](https://github.com/libdns) for newly available providers or consider contributing an implementation for your provider.
!!! warning "Built-in providers are deprecated"
The built-in DNS providers are deprecated and will be removed in a future release. Please migrate to external DNS plugins for continued support.
!!! note "Future plugin system"
A plugin system for DNS providers is currently in the ideation phase. This would make it significantly easier to add and configure additional DNS providers without modifying the core ionscale code. Stay tuned for updates on this feature in future releases.
### External DNS plugins (recommended)
ionscale now supports external DNS plugins through a plugin system. This allows for:
- **Extensibility**: Add support for any DNS provider without modifying ionscale
- **Maintainability**: Plugins are maintained independently
- **Flexibility**: Plugin configuration specific to each provider's needs
!!! info "Plugin availability"
External DNS plugins implement the [libdns-plugin](https://github.com/libdns/libdns-plugin) interface. Official plugin implementations can be found in the [ionscale GitHub organization](https://github.com/ionscale) with repositories named `ionscale-<provider>-dns`. You can also create your own following the plugin specification.
## DNS provider configuration
To configure a DNS provider, add the appropriate settings to your ionscale configuration file (`config.yaml`):
### Built-in provider configuration
```yaml
dns:
# The base domain for MagicDNS FQDN hostnames
@@ -50,11 +62,31 @@ dns:
# See provider-specific examples below
```
### External plugin configuration
```yaml
dns:
# The base domain for MagicDNS FQDN hostnames
magic_dns_suffix: "ionscale.net"
# DNS provider configuration for HTTPS certificates
provider:
# Path to your DNS plugin executable
plugin_path: "/path/to/your/dns-plugin"
# The DNS zone to use (typically your domain name)
zone: "example.com"
# Plugin-specific configuration (varies by plugin)
config:
# Plugin-specific credentials and settings go here
# See plugin documentation for configuration options
```
### Important requirements
1. The `magic_dns_suffix` must be a subdomain of the provider's zone (or the zone itself).
2. MagicDNS must be enabled for the tailnet to use HTTPS certificates.
3. You must have administrative access to the DNS zone to configure the provider.
4. For external plugins, the plugin executable must be accessible and executable by the ionscale process.
## Provider-specific examples
@@ -142,6 +174,38 @@ dns:
For DigitalOcean, create an API token with read and write access.
## External DNS plugin examples
### Using a hypothetical Cloudflare plugin
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
plugin_path: "/usr/local/bin/libdns-cloudflare-plugin"
zone: "example.com"
config:
api_token: "your-cloudflare-api-token"
```
### Using a custom DNS plugin
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
plugin_path: "/opt/dns-plugins/my-custom-provider"
zone: "example.com"
config:
# Configuration specific to your custom plugin
endpoint: "https://api.mydnsprovider.com"
api_key: "your-api-key"
custom_setting: "value"
```
!!! tip "Plugin development"
To create your own DNS plugin, implement the [libdns-plugin](https://github.com/libdns/libdns-plugin) interface. The plugin system uses HashiCorp's go-plugin framework for communication between ionscale and your plugin.
## Enabling HTTPS certificates for a tailnet
After configuring a DNS provider in your ionscale server, you can enable HTTPS certificates for a tailnet:
@@ -168,9 +232,17 @@ To verify that your DNS provider is correctly configured:
If you encounter issues with DNS provider integration:
### General troubleshooting
1. **Check DNS Provider Credentials**: Ensure the credentials in your configuration have sufficient permissions.
2. **Verify Zone Configuration**: Make sure the zone in your configuration matches your actual DNS zone.
3. **Check MagicDNS Settings**: Confirm that `magic_dns_suffix` is properly configured as a subdomain of your zone.
4. **Review Server Logs**: The ionscale server logs may contain error messages related to DNS provider integration.
5. **Test DNS Record Creation**: Some providers offer tools to test API access for creating and updating DNS records.
### External plugin troubleshooting
1. **Plugin Executable**: Ensure the plugin path is correct and the executable has proper permissions.
2. **Plugin Logs**: Check both ionscale logs and any plugin-specific logs for error messages.
3. **Plugin Health**: ionscale automatically restarts failed plugins, but persistent failures may indicate configuration issues.