mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-29 06:10:47 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e986def78 | ||
|
|
d16a05959d | ||
|
|
7e58e0b490 | ||
|
|
9b01aecf3c | ||
|
|
86043fd5f8 | ||
|
|
372a1758e9 | ||
|
|
0a2b1d9e53 | ||
|
|
e562946308 | ||
|
|
398e15b3c6 |
@@ -16,7 +16,7 @@ _Pangolin tunnels your services to the internet so you can access anything from
|
||||
|
||||
<div align="center">
|
||||
<h5>
|
||||
<a href="https://fossorial.io">
|
||||
<a href="https://digpangolin.com">
|
||||
Website
|
||||
</a>
|
||||
<span> | </span>
|
||||
@@ -111,7 +111,7 @@ Host the full application on your own server or on the cloud with a VPS. Take a
|
||||
|
||||
### Pangolin Cloud
|
||||
|
||||
Easy to use with simple [pay as you go pricing](https://fossorial.io/pricing). [Check it out here](https://pangolin.fossorial.io/auth/signup).
|
||||
Easy to use with simple [pay as you go pricing](https://digpangolin.io/pricing). [Check it out here](https://pangolin.fossorial.io/auth/signup).
|
||||
|
||||
- Everything you get with self hosted Pangolin, but fully managed for you.
|
||||
|
||||
|
||||
@@ -1266,6 +1266,7 @@
|
||||
"createDomainName": "Name:",
|
||||
"createDomainValue": "Value:",
|
||||
"createDomainCnameRecords": "CNAME Records",
|
||||
"createDomainARecords": "A Records",
|
||||
"createDomainRecordNumber": "Record {number}",
|
||||
"createDomainTxtRecords": "TXT Records",
|
||||
"createDomainSaveTheseRecords": "Save These Records",
|
||||
|
||||
@@ -128,7 +128,9 @@ export const configSchema = z
|
||||
.object({
|
||||
http_entrypoint: z.string().optional().default("web"),
|
||||
https_entrypoint: z.string().optional().default("websecure"),
|
||||
additional_middlewares: z.array(z.string()).optional()
|
||||
additional_middlewares: z.array(z.string()).optional(),
|
||||
cert_resolver: z.string().optional().default("letsencrypt"),
|
||||
prefer_wildcard_cert: z.boolean().optional().default(false)
|
||||
})
|
||||
.optional()
|
||||
.default({}),
|
||||
@@ -157,13 +159,16 @@ export const configSchema = z
|
||||
})
|
||||
.optional()
|
||||
.default({}),
|
||||
orgs: z.object({
|
||||
block_size: z.number().positive().gt(0).optional().default(24),
|
||||
subnet_group: z.string().optional().default("100.90.128.0/24")
|
||||
}).optional().default({
|
||||
block_size: 24,
|
||||
subnet_group: "100.90.128.0/24"
|
||||
}),
|
||||
orgs: z
|
||||
.object({
|
||||
block_size: z.number().positive().gt(0).optional().default(24),
|
||||
subnet_group: z.string().optional().default("100.90.128.0/24")
|
||||
})
|
||||
.optional()
|
||||
.default({
|
||||
block_size: 24,
|
||||
subnet_group: "100.90.128.0/24"
|
||||
}),
|
||||
rate_limits: z
|
||||
.object({
|
||||
global: z
|
||||
@@ -242,7 +247,7 @@ export const configSchema = z
|
||||
{
|
||||
message: "At least one domain must be defined"
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
export function readConfigFile() {
|
||||
const loadConfig = (configPath: string) => {
|
||||
|
||||
@@ -29,6 +29,7 @@ export type CreateDomainResponse = {
|
||||
domainId: string;
|
||||
nsRecords?: string[];
|
||||
cnameRecords?: { baseDomain: string; value: string }[];
|
||||
aRecords?: { baseDomain: string; value: string }[];
|
||||
txtRecords?: { baseDomain: string; value: string }[];
|
||||
};
|
||||
|
||||
@@ -97,6 +98,7 @@ export async function createOrgDomain(
|
||||
}
|
||||
|
||||
let numOrgDomains: OrgDomains[] | undefined;
|
||||
let aRecords: CreateDomainResponse["aRecords"];
|
||||
let cnameRecords: CreateDomainResponse["cnameRecords"];
|
||||
let txtRecords: CreateDomainResponse["txtRecords"];
|
||||
let nsRecords: CreateDomainResponse["nsRecords"];
|
||||
@@ -239,7 +241,7 @@ export async function createOrgDomain(
|
||||
}
|
||||
];
|
||||
} else if (type === "wildcard") {
|
||||
cnameRecords = [
|
||||
aRecords = [
|
||||
{
|
||||
value: `Server IP Address`,
|
||||
baseDomain: `*.${baseDomain}`
|
||||
@@ -271,7 +273,8 @@ export async function createOrgDomain(
|
||||
domainId: returned.domainId,
|
||||
cnameRecords,
|
||||
txtRecords,
|
||||
nsRecords
|
||||
nsRecords,
|
||||
aRecords
|
||||
},
|
||||
success: true,
|
||||
error: false,
|
||||
|
||||
@@ -214,22 +214,29 @@ export async function traefikConfigProvider(
|
||||
|
||||
const configDomain = config.getDomain(resource.domainId);
|
||||
|
||||
let tls = {};
|
||||
if (configDomain) {
|
||||
tls = {
|
||||
certResolver: configDomain.cert_resolver,
|
||||
...(configDomain.prefer_wildcard_cert
|
||||
? {
|
||||
domains: [
|
||||
{
|
||||
main: wildCard
|
||||
}
|
||||
]
|
||||
}
|
||||
: {})
|
||||
};
|
||||
let certResolver: string, preferWildcardCert: boolean;
|
||||
if (!configDomain) {
|
||||
certResolver = config.getRawConfig().traefik.cert_resolver;
|
||||
preferWildcardCert =
|
||||
config.getRawConfig().traefik.prefer_wildcard_cert;
|
||||
} else {
|
||||
certResolver = configDomain.cert_resolver;
|
||||
preferWildcardCert = configDomain.prefer_wildcard_cert;
|
||||
}
|
||||
|
||||
const tls = {
|
||||
certResolver: certResolver,
|
||||
...(preferWildcardCert
|
||||
? {
|
||||
domains: [
|
||||
{
|
||||
main: wildCard
|
||||
}
|
||||
]
|
||||
}
|
||||
: {})
|
||||
};
|
||||
|
||||
const additionalMiddlewares =
|
||||
config.getRawConfig().traefik.additional_middlewares || [];
|
||||
|
||||
|
||||
@@ -205,188 +205,267 @@ export default function CreateDomainForm({
|
||||
</Alert>
|
||||
|
||||
<div className="space-y-4">
|
||||
{domainType === "ns" &&
|
||||
createdDomain.nsRecords && (
|
||||
{createdDomain.nsRecords &&
|
||||
createdDomain.nsRecords.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-medium mb-3">
|
||||
{t("createDomainNsRecords")}
|
||||
</h3>
|
||||
<InfoSections cols={1}>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
{t("createDomainRecord")}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainType"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
NS
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainName"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{baseDomain}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainValue"
|
||||
)}
|
||||
</span>
|
||||
{createdDomain.nsRecords.map(
|
||||
(
|
||||
nsRecord,
|
||||
index
|
||||
) => (
|
||||
<div
|
||||
className="flex justify-between items-center"
|
||||
key={index}
|
||||
>
|
||||
<CopyToClipboard
|
||||
text={
|
||||
nsRecord
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
</InfoSections>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{createdDomain.cnameRecords &&
|
||||
createdDomain.cnameRecords.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-medium mb-3">
|
||||
{t("createDomainNsRecords")}
|
||||
{t("createDomainCnameRecords")}
|
||||
</h3>
|
||||
<InfoSections cols={1}>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
{t("createDomainRecord")}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainType")}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
NS
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainName")}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{baseDomain}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainValue")}
|
||||
</span>
|
||||
{createdDomain.nsRecords.map(
|
||||
(
|
||||
nsRecord,
|
||||
index
|
||||
) => (
|
||||
<div
|
||||
className="flex justify-between items-center"
|
||||
key={
|
||||
index
|
||||
}
|
||||
>
|
||||
{createdDomain.cnameRecords.map(
|
||||
(cnameRecord, index) => (
|
||||
<InfoSection
|
||||
key={index}
|
||||
>
|
||||
<InfoSectionTitle>
|
||||
{t(
|
||||
"createDomainRecordNumber",
|
||||
{
|
||||
number:
|
||||
index +
|
||||
1
|
||||
}
|
||||
)}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainType"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
CNAME
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainName"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{
|
||||
cnameRecord.baseDomain
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainValue"
|
||||
)}
|
||||
</span>
|
||||
<CopyToClipboard
|
||||
text={
|
||||
nsRecord
|
||||
cnameRecord.value
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
)
|
||||
)}
|
||||
</InfoSections>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{domainType === "cname" ||
|
||||
(domainType == "wildcard" && (
|
||||
<>
|
||||
{createdDomain.cnameRecords &&
|
||||
createdDomain.cnameRecords
|
||||
.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-medium mb-3">
|
||||
{t("createDomainCnameRecords")}
|
||||
</h3>
|
||||
<InfoSections cols={1}>
|
||||
{createdDomain.cnameRecords.map(
|
||||
(
|
||||
cnameRecord,
|
||||
index
|
||||
) => (
|
||||
<InfoSection
|
||||
key={
|
||||
index
|
||||
}
|
||||
>
|
||||
<InfoSectionTitle>
|
||||
{t("createDomainRecordNumber", { number: index + 1 })}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainType")}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
CNAME
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainName")}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{
|
||||
cnameRecord.baseDomain
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainValue")}
|
||||
</span>
|
||||
<CopyToClipboard
|
||||
text={
|
||||
cnameRecord.value
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
)
|
||||
)}
|
||||
</InfoSections>
|
||||
</div>
|
||||
{createdDomain.aRecords &&
|
||||
createdDomain.aRecords.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-medium mb-3">
|
||||
{t("createDomainARecords")}
|
||||
</h3>
|
||||
<InfoSections cols={1}>
|
||||
{createdDomain.aRecords.map(
|
||||
(aRecord, index) => (
|
||||
<InfoSection
|
||||
key={index}
|
||||
>
|
||||
<InfoSectionTitle>
|
||||
{t(
|
||||
"createDomainRecordNumber",
|
||||
{
|
||||
number:
|
||||
index +
|
||||
1
|
||||
}
|
||||
)}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainType"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
A
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainName"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{
|
||||
aRecord.baseDomain
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainValue"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{
|
||||
aRecord.value
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
)
|
||||
)}
|
||||
|
||||
{createdDomain.txtRecords &&
|
||||
createdDomain.txtRecords
|
||||
.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-medium mb-3">
|
||||
{t("createDomainTxtRecords")}
|
||||
</h3>
|
||||
<InfoSections cols={1}>
|
||||
{createdDomain.txtRecords.map(
|
||||
(
|
||||
txtRecord,
|
||||
index
|
||||
) => (
|
||||
<InfoSection
|
||||
key={
|
||||
index
|
||||
}
|
||||
>
|
||||
<InfoSectionTitle>
|
||||
{t("createDomainRecordNumber", { number: index + 1 })}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainType")}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
TXT
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainName")}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{
|
||||
txtRecord.baseDomain
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t("createDomainValue")}
|
||||
</span>
|
||||
<CopyToClipboard
|
||||
text={
|
||||
txtRecord.value
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
)
|
||||
)}
|
||||
</InfoSections>
|
||||
</div>
|
||||
</InfoSections>
|
||||
</div>
|
||||
)}
|
||||
{createdDomain.txtRecords &&
|
||||
createdDomain.txtRecords.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-medium mb-3">
|
||||
{t("createDomainTxtRecords")}
|
||||
</h3>
|
||||
<InfoSections cols={1}>
|
||||
{createdDomain.txtRecords.map(
|
||||
(txtRecord, index) => (
|
||||
<InfoSection
|
||||
key={index}
|
||||
>
|
||||
<InfoSectionTitle>
|
||||
{t(
|
||||
"createDomainRecordNumber",
|
||||
{
|
||||
number:
|
||||
index +
|
||||
1
|
||||
}
|
||||
)}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainType"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
TXT
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainName"
|
||||
)}
|
||||
</span>
|
||||
<span className="text-sm font-mono">
|
||||
{
|
||||
txtRecord.baseDomain
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium">
|
||||
{t(
|
||||
"createDomainValue"
|
||||
)}
|
||||
</span>
|
||||
<CopyToClipboard
|
||||
text={
|
||||
txtRecord.value
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</InfoSectionContent>
|
||||
</InfoSection>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</InfoSections>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{build == "saas" ||
|
||||
@@ -397,7 +476,9 @@ export default function CreateDomainForm({
|
||||
{t("createDomainSaveTheseRecords")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t("createDomainSaveTheseRecordsDescription")}
|
||||
{t(
|
||||
"createDomainSaveTheseRecordsDescription"
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user