mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-22 21:05:48 +08:00
feat(provider): new acme dns-01 provider: technitiumdns
This commit is contained in:
parent
34ca09a7fc
commit
1f6ef6dcb3
31
internal/certapply/applicators/sp_technitiumdns.go
Normal file
31
internal/certapply/applicators/sp_technitiumdns.go
Normal file
@ -0,0 +1,31 @@
|
||||
package applicators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/technitiumdns"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := ACMEDns01Registries.Register(domain.ACMEDns01ProviderTypeTechnitiumDNS, func(options *ProviderFactoryOptions) (challenge.Provider, error) {
|
||||
credentials := domain.AccessConfigForTechnitiumDNS{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := technitiumdns.NewChallengeProvider(&technitiumdns.ChallengeProviderConfig{
|
||||
ServerUrl: credentials.ServerUrl,
|
||||
ApiToken: credentials.ApiToken,
|
||||
AllowInsecureConnections: credentials.AllowInsecureConnections,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return provider, err
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -379,6 +379,12 @@ type AccessConfigForSSLCom struct {
|
||||
AccessConfigForACMEExternalAccountBinding
|
||||
}
|
||||
|
||||
type AccessConfigForTechnitiumDNS struct {
|
||||
ServerUrl string `json:"serverUrl"`
|
||||
ApiToken string `json:"apiToken"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForTelegramBot struct {
|
||||
BotToken string `json:"botToken"`
|
||||
ChatId int64 `json:"chatId,omitempty"`
|
||||
|
||||
@ -23,8 +23,9 @@ const (
|
||||
AccessProviderTypeBaishan = AccessProviderType("baishan")
|
||||
AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel")
|
||||
AccessProviderTypeBaotaWAF = AccessProviderType("baotawaf")
|
||||
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
|
||||
AccessProviderTypeBookMyName = AccessProviderType("bookmyname") // BookMyName(预留)
|
||||
AccessProviderTypeBunny = AccessProviderType("bunny")
|
||||
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
|
||||
AccessProviderTypeCacheFly = AccessProviderType("cachefly")
|
||||
AccessProviderTypeCdnfly = AccessProviderType("cdnfly")
|
||||
AccessProviderTypeCloudflare = AccessProviderType("cloudflare")
|
||||
@ -52,14 +53,17 @@ const (
|
||||
AccessProviderTypeGlobalSignAtlas = AccessProviderType("globalsignatlas")
|
||||
AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices")
|
||||
AccessProviderTypeHetzner = AccessProviderType("hetzner")
|
||||
AccessProviderTypeHostinger = AccessProviderType("hostinger") // Hostinger(预留)
|
||||
AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud")
|
||||
AccessProviderTypeJDCloud = AccessProviderType("jdcloud")
|
||||
AccessProviderTypeKong = AccessProviderType("kong")
|
||||
AccessProviderTypeKsyun = AccessProviderType("ksyun") // 金山云(预留)
|
||||
AccessProviderTypeKubernetes = AccessProviderType("k8s")
|
||||
AccessProviderTypeLarkBot = AccessProviderType("larkbot")
|
||||
AccessProviderTypeLetsEncrypt = AccessProviderType("letsencrypt")
|
||||
AccessProviderTypeLetsEncryptStaging = AccessProviderType("letsencryptstaging")
|
||||
AccessProviderTypeLeCDN = AccessProviderType("lecdn")
|
||||
AccessProviderTypeLinode = AccessProviderType("linode") // Linode(预留)
|
||||
AccessProviderTypeLocal = AccessProviderType("local")
|
||||
AccessProviderTypeMattermost = AccessProviderType("mattermost")
|
||||
AccessProviderTypeNamecheap = AccessProviderType("namecheap")
|
||||
@ -75,12 +79,14 @@ const (
|
||||
AccessProviderTypeQingCloud = AccessProviderType("qingcloud") // 青云(预留)
|
||||
AccessProviderTypeRainYun = AccessProviderType("rainyun")
|
||||
AccessProviderTypeRatPanel = AccessProviderType("ratpanel")
|
||||
AccessProviderTypeRFC2136 = AccessProviderType("rfc2136") // RFC2136(预留)
|
||||
AccessProviderTypeSafeLine = AccessProviderType("safeline")
|
||||
AccessProviderTypeSectigo = AccessProviderType("sectigo")
|
||||
AccessProviderTypeSlackBot = AccessProviderType("slackbot")
|
||||
AccessProviderTypeSpaceship = AccessProviderType("spaceship")
|
||||
AccessProviderTypeSSH = AccessProviderType("ssh")
|
||||
AccessProviderTypeSSLCOM = AccessProviderType("sslcom")
|
||||
AccessProviderTypeTechnitiumDNS = AccessProviderType("technitiumdns")
|
||||
AccessProviderTypeTelegramBot = AccessProviderType("telegrambot")
|
||||
AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud")
|
||||
AccessProviderTypeUCloud = AccessProviderType("ucloud")
|
||||
@ -169,6 +175,7 @@ const (
|
||||
ACMEDns01ProviderTypePowerDNS = ACMEDns01ProviderType(AccessProviderTypePowerDNS)
|
||||
ACMEDns01ProviderTypeRainYun = ACMEDns01ProviderType(AccessProviderTypeRainYun)
|
||||
ACMEDns01ProviderTypeSpaceship = ACMEDns01ProviderType(AccessProviderTypeSpaceship)
|
||||
ACMEDns01ProviderTypeTechnitiumDNS = ACMEDns01ProviderType(AccessProviderTypeTechnitiumDNS)
|
||||
ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS]
|
||||
ACMEDns01ProviderTypeTencentCloudDNS = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-dns")
|
||||
ACMEDns01ProviderTypeTencentCloudEO = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-eo")
|
||||
|
||||
@ -3,13 +3,13 @@ package powerdns
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/providers/dns/pdns"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xhttp "github.com/certimate-go/certimate/pkg/utils/http"
|
||||
)
|
||||
|
||||
type ChallengeProviderConfig struct {
|
||||
@ -30,12 +30,9 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (core.ACMEChallenger,
|
||||
providerConfig.Host = serverUrl
|
||||
providerConfig.APIKey = config.ApiKey
|
||||
if config.AllowInsecureConnections {
|
||||
providerConfig.HTTPClient.Transport = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
transport := xhttp.NewDefaultTransport()
|
||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
providerConfig.HTTPClient.Transport = transport
|
||||
}
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package technitiumdns
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/providers/dns/technitium"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xhttp "github.com/certimate-go/certimate/pkg/utils/http"
|
||||
)
|
||||
|
||||
type ChallengeProviderConfig struct {
|
||||
ServerUrl string `json:"serverUrl"`
|
||||
ApiToken string `json:"apiToken"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int32 `json:"dnsTTL,omitempty"`
|
||||
}
|
||||
|
||||
func NewChallengeProvider(config *ChallengeProviderConfig) (core.ACMEChallenger, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("the configuration of the acme challenge provider is nil")
|
||||
}
|
||||
|
||||
providerConfig := technitium.NewDefaultConfig()
|
||||
providerConfig.BaseURL = config.ServerUrl
|
||||
providerConfig.APIToken = config.ApiToken
|
||||
if config.AllowInsecureConnections {
|
||||
transport := xhttp.NewDefaultTransport()
|
||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
providerConfig.HTTPClient.Transport = transport
|
||||
}
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
if config.DnsTTL != 0 {
|
||||
providerConfig.TTL = int(config.DnsTTL)
|
||||
}
|
||||
|
||||
provider, err := technitium.NewDNSProviderConfig(providerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
BIN
ui/public/imgs/providers/technitiumdns.png
Normal file
BIN
ui/public/imgs/providers/technitiumdns.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 259 B |
@ -76,6 +76,7 @@ import AccessConfigFieldsProviderSlackBot from "./forms/AccessConfigFieldsProvid
|
||||
import AccessConfigFieldsProviderSpaceship from "./forms/AccessConfigFieldsProviderSpaceship";
|
||||
import AccessConfigFieldsProviderSSH from "./forms/AccessConfigFieldsProviderSSH";
|
||||
import AccessConfigFieldsProviderSSLCom from "./forms/AccessConfigFieldsProviderSSLCom";
|
||||
import AccessConfigFieldsProviderTechnitiumDNS from "./forms/AccessConfigFieldsProviderTechnitiumDNS";
|
||||
import AccessConfigFieldsProviderTelegramBot from "./forms/AccessConfigFieldsProviderTelegramBot";
|
||||
import AccessConfigFieldsProviderTencentCloud from "./forms/AccessConfigFieldsProviderTencentCloud";
|
||||
import AccessConfigFieldsProviderUCloud from "./forms/AccessConfigFieldsProviderUCloud";
|
||||
@ -322,15 +323,18 @@ const AccessForm = ({ className, style, disabled, initialValues, mode, usage, on
|
||||
case ACCESS_PROVIDERS.SPACESHIP: {
|
||||
return <AccessConfigFieldsProviderSpaceship />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.SSLCOM: {
|
||||
return <AccessConfigFieldsProviderSSLCom />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.SSH: {
|
||||
return <AccessConfigFieldsProviderSSH disabled={disabled} />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.TECHNITIUMDNS: {
|
||||
return <AccessConfigFieldsProviderTechnitiumDNS />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.TELEGRAMBOT: {
|
||||
return <AccessConfigFieldsProviderTelegramBot />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.SSLCOM: {
|
||||
return <AccessConfigFieldsProviderSSLCom />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.TENCENTCLOUD: {
|
||||
return <AccessConfigFieldsProviderTencentCloud />;
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const AccessConfigFormFieldsProviderTechnitiumDNS = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "serverUrl"]}
|
||||
initialValue={initialValues.serverUrl}
|
||||
label={t("access.form.technitiumdns_server_url.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input placeholder={t("access.form.technitiumdns_server_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "apiToken"]}
|
||||
initialValue={initialValues.apiToken}
|
||||
label={t("access.form.technitiumdns_api_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.technitiumdns_api_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.technitiumdns_api_token.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "allowInsecureConnections"]}
|
||||
initialValue={initialValues.allowInsecureConnections}
|
||||
label={t("access.form.shared_allow_insecure_conns.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.shared_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.shared_allow_insecure_conns.switch.off")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
serverUrl: "http://<your-host-addr>:5380/",
|
||||
apiToken: "",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z.object({
|
||||
serverUrl: z.url(t("common.errmsg.url_invalid")),
|
||||
apiToken: z.string().nonempty(t("access.form.technitiumdns_api_token.placeholder")),
|
||||
allowInsecureConnections: z.boolean().nullish(),
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(AccessConfigFormFieldsProviderTechnitiumDNS, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@ -83,6 +83,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
SPACESHIP: "spaceship",
|
||||
SSH: "ssh",
|
||||
SSLCOM: "sslcom",
|
||||
TECHNITIUMDNS: "technitiumdns",
|
||||
TELEGRAMBOT: "telegrambot",
|
||||
TENCENTCLOUD: "tencentcloud",
|
||||
UCLOUD: "ucloud",
|
||||
@ -185,6 +186,7 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.CMCCCLOUD, "provider.cmcccloud", "/imgs/providers/cmcccloud.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.WESTCN, "provider.westcn", "/imgs/providers/westcn.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.POWERDNS, "provider.powerdns", "/imgs/providers/powerdns.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.TECHNITIUMDNS, "provider.technitiumdns", "/imgs/providers/technitiumdns.png", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.ACMEDNS, "provider.acmedns", "/imgs/providers/acmedns.png", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.ACMEHTTPREQ, "provider.acmehttpreq", "/imgs/providers/acmehttpreq.svg", [ACCESS_USAGES.DNS]],
|
||||
|
||||
@ -320,6 +322,7 @@ export const ACME_DNS01_PROVIDERS = Object.freeze({
|
||||
RAINYUN: `${ACCESS_PROVIDERS.RAINYUN}`,
|
||||
SPACESHIP: `${ACCESS_PROVIDERS.SPACESHIP}`,
|
||||
UCLOUD_UDNR: `${ACCESS_PROVIDERS.UCLOUD}-udnr`,
|
||||
TECHNITIUMDNS: `${ACCESS_PROVIDERS.TECHNITIUMDNS}`,
|
||||
TENCENTCLOUD: `${ACCESS_PROVIDERS.TENCENTCLOUD}`, // 兼容旧值,等同于 `TENCENTCLOUD_DNS`
|
||||
TENCENTCLOUD_DNS: `${ACCESS_PROVIDERS.TENCENTCLOUD}-dns`,
|
||||
TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`,
|
||||
@ -380,6 +383,7 @@ export const acmeDns01ProvidersMap: Map<ACMEDns01Provider["type"] | string, ACME
|
||||
[ACME_DNS01_PROVIDERS.UCLOUD_UDNR, "provider.ucloud.udnr"],
|
||||
[ACME_DNS01_PROVIDERS.WESTCN, "provider.westcn"],
|
||||
[ACME_DNS01_PROVIDERS.POWERDNS, "provider.powerdns"],
|
||||
[ACME_DNS01_PROVIDERS.TECHNITIUMDNS, "provider.technitiumdns"],
|
||||
[ACME_DNS01_PROVIDERS.ACMEDNS, "provider.acmedns"],
|
||||
[ACME_DNS01_PROVIDERS.ACMEHTTPREQ, "provider.acmehttpreq"],
|
||||
] satisfies Array<[ACMEDns01ProviderType, string]>
|
||||
|
||||
@ -122,9 +122,6 @@
|
||||
"access.form.baiducloud_secret_access_key.label": "Baidu Cloud SecretAccessKey",
|
||||
"access.form.baiducloud_secret_access_key.placeholder": "Please enter Baidu Cloud SecretAccessKey",
|
||||
"access.form.baiducloud_secret_access_key.tooltip": "For more information, see <a href=\"https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en\" target=\"_blank\">https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en</a>",
|
||||
"access.form.bunny_api_key.label": "Bunny API key",
|
||||
"access.form.bunny_api_key.placeholder": "Please enter Bunny API key",
|
||||
"access.form.bunny_api_key.tooltip": "For more information, see <a href=\"https://docs.bunny.net/reference/bunnynet-api-overview\" target=\"_blank\">https://docs.bunny.net/reference/bunnynet-api-overview</a>",
|
||||
"access.form.baishan_api_token.label": "Baishan Cloud API token",
|
||||
"access.form.baishan_api_token.placeholder": "Please enter Baishan Cloud API token",
|
||||
"access.form.baotapanel_server_url.label": "aaPanel server URL",
|
||||
@ -139,6 +136,9 @@
|
||||
"access.form.baotawaf_api_key.label": "aaWAF API key",
|
||||
"access.form.baotawaf_api_key.placeholder": "Please enter aaWAF API key",
|
||||
"access.form.baotawaf_api_key.tooltip": "For more information, see <a href=\"https://github.com/aaPanel/aaWAF/blob/main/API.md\" target=\"_blank\">https://github.com/aaPanel/aaWAF/blob/main/API.md</a>",
|
||||
"access.form.bunny_api_key.label": "Bunny API key",
|
||||
"access.form.bunny_api_key.placeholder": "Please enter Bunny API key",
|
||||
"access.form.bunny_api_key.tooltip": "For more information, see <a href=\"https://docs.bunny.net/reference/bunnynet-api-overview\" target=\"_blank\">https://docs.bunny.net/reference/bunnynet-api-overview</a>",
|
||||
"access.form.byteplus_access_key.label": "BytePlus AccessKey",
|
||||
"access.form.byteplus_access_key.placeholder": "Please enter BytePlus AccessKey",
|
||||
"access.form.byteplus_access_key.tooltip": "For more information, see <a href=\"https://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys\" target=\"_blank\">https://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys</a>",
|
||||
@ -454,6 +454,11 @@
|
||||
"access.form.telegrambot_token.label": "Telegram bot token",
|
||||
"access.form.telegrambot_token.placeholder": "Please enter Telegram bot token",
|
||||
"access.form.telegrambot_token.tooltip": "How to get it? Please refer to <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.technitiumdns_server_url.label": "Technitium DNS server URL",
|
||||
"access.form.technitiumdns_server_url.placeholder": "Please enter Technitium DNS server URL",
|
||||
"access.form.technitiumdns_api_token.label": "Technitium DNS API token",
|
||||
"access.form.technitiumdns_api_token.placeholder": "Please enter Technitium DNS API token",
|
||||
"access.form.technitiumdns_api_token.tooltip": "For more information, see <a href=\"https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md\" target=\"_blank\">https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md</a>",
|
||||
"access.form.telegrambot_chat_id.label": "Telegram chat ID (Optional)",
|
||||
"access.form.telegrambot_chat_id.placeholder": "Please enter the default Telegram chat ID",
|
||||
"access.form.telegrambot_chat_id.help": "Notes: It can be overrided in the workflows.",
|
||||
|
||||
@ -138,6 +138,7 @@
|
||||
"provider.spaceship": "Spaceship",
|
||||
"provider.ssh": "Remote host (SSH)",
|
||||
"provider.sslcom": "SSL.com",
|
||||
"provider.technitiumdns": "Technitium DNS",
|
||||
"provider.telegrambot": "Telegram Bot",
|
||||
"provider.tencentcloud": "Tencent Cloud",
|
||||
"provider.tencentcloud.cdn": "Tencent Cloud - CDN (Content Delivery Network)",
|
||||
|
||||
@ -450,6 +450,11 @@
|
||||
"access.form.ssh_jump_servers.item.label": "跳板机",
|
||||
"access.form.ssh_jump_servers.add": "添加跳板机",
|
||||
"access.form.sslcom_eab.guide": "点击下方链接了解如何获取 SSL.com EAB:<br><a href=\"https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/#ftoc-heading-6\" target=\"_blank\">https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/</a>",
|
||||
"access.form.technitiumdns_server_url.label": "Technitium DNS 服务地址",
|
||||
"access.form.technitiumdns_server_url.placeholder": "请输入 Technitium DNS 服务地址",
|
||||
"access.form.technitiumdns_api_token.label": "Technitium DNS API Token",
|
||||
"access.form.technitiumdns_api_token.placeholder": "请输入 Technitium DNS API Token",
|
||||
"access.form.technitiumdns_api_token.tooltip": "这是什么?请参阅 <a href=\"https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md\" target=\"_blank\">https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md</a>",
|
||||
"access.form.telegrambot_token.label": "Telegram 机器人 API Token",
|
||||
"access.form.telegrambot_token.placeholder": "请输入 Telegram 机器人 API Token",
|
||||
"access.form.telegrambot_token.tooltip": "如何获取此参数?请参阅 <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
|
||||
@ -138,6 +138,7 @@
|
||||
"provider.spaceship": "Spaceship",
|
||||
"provider.ssh": "远程主机(SSH)",
|
||||
"provider.sslcom": "SSL.com",
|
||||
"provider.technitiumdns": "Technitium DNS",
|
||||
"provider.telegrambot": "Telegram 机器人",
|
||||
"provider.tencentcloud": "腾讯云",
|
||||
"provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user