Compare commits

...

10 Commits
1.16.2 ... main

Author SHA1 Message Date
Owen Schwartz
cdf79edb00 Merge pull request #2570 from Fizza-Mukhtar/fix/mixed-target-failover-2448
fix: local targets ignored when newt site is unhealthy (mixed target failover)
2026-03-01 15:58:25 -08:00
Owen Schwartz
44e3eedffa Merge pull request #2567 from marcschaeferger/fix-kubernetes-install
feat(kubernetes): enable newtInstances by default and update installation instructions
2026-03-01 10:56:18 -08:00
Marc Schäfer
bb189874cb fix(newt-install): conditionally display Kubernetes installation info
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-03-01 10:55:58 -08:00
Marc Schäfer
34dadd0e16 feat(kubernetes): enable newtInstances by default and update installation instructions
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-03-01 10:55:58 -08:00
Owen Schwartz
87b5cd9988 Merge pull request #2573 from Fizza-Mukhtar/fix/container-search-excludes-labels-2228
fix: exclude labels from container search to prevent false positives
2026-03-01 10:52:50 -08:00
Marc Schäfer
6a537a23e8 fix(newt-install): conditionally display Kubernetes installation info
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-03-01 18:17:45 +01:00
Fizza-Mukhtar
e63a6e9b77 fix: treat local and wireguard sites as online for failover 2026-03-01 07:56:47 -08:00
Fizza-Mukhtar
7ce589c4f2 fix: exclude labels from container search to prevent false positives 2026-03-01 06:50:03 -08:00
Fizza-Mukhtar
f36cf06e26 fix: fallback to local targets when newt targets are unhealthy 2026-03-01 01:43:15 -08:00
Marc Schäfer
375211f184 feat(kubernetes): enable newtInstances by default and update installation instructions
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-02-28 23:56:28 +01:00
4 changed files with 82 additions and 57 deletions

View File

@@ -477,7 +477,10 @@ export async function getTraefikConfig(
// TODO: HOW TO HANDLE ^^^^^^ BETTER // TODO: HOW TO HANDLE ^^^^^^ BETTER
const anySitesOnline = targets.some( const anySitesOnline = targets.some(
(target) => target.site.online (target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
); );
return ( return (
@@ -490,7 +493,7 @@ export async function getTraefikConfig(
if (target.health == "unhealthy") { if (target.health == "unhealthy") {
return false; return false;
} }
// If any sites are online, exclude offline sites // If any sites are online, exclude offline sites
if (anySitesOnline && !target.site.online) { if (anySitesOnline && !target.site.online) {
return false; return false;
@@ -605,7 +608,10 @@ export async function getTraefikConfig(
servers: (() => { servers: (() => {
// Check if any sites are online // Check if any sites are online
const anySitesOnline = targets.some( const anySitesOnline = targets.some(
(target) => target.site.online (target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
); );
return targets return targets
@@ -613,7 +619,7 @@ export async function getTraefikConfig(
if (!target.enabled) { if (!target.enabled) {
return false; return false;
} }
// If any sites are online, exclude offline sites // If any sites are online, exclude offline sites
if (anySitesOnline && !target.site.online) { if (anySitesOnline && !target.site.online) {
return false; return false;

View File

@@ -665,7 +665,10 @@ export async function getTraefikConfig(
// TODO: HOW TO HANDLE ^^^^^^ BETTER // TODO: HOW TO HANDLE ^^^^^^ BETTER
const anySitesOnline = targets.some( const anySitesOnline = targets.some(
(target) => target.site.online (target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
); );
return ( return (
@@ -793,7 +796,10 @@ export async function getTraefikConfig(
servers: (() => { servers: (() => {
// Check if any sites are online // Check if any sites are online
const anySitesOnline = targets.some( const anySitesOnline = targets.some(
(target) => target.site.online (target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
); );
return targets return targets

View File

@@ -171,8 +171,7 @@ const DockerContainersTable: FC<{
...Object.values(container.networks) ...Object.values(container.networks)
.map((n) => n.ipAddress) .map((n) => n.ipAddress)
.filter(Boolean), .filter(Boolean),
...getExposedPorts(container).map((p) => p.toString()), ...getExposedPorts(container).map((p) => p.toString())
...Object.entries(container.labels).flat()
]; ];
return searchableFields.some((field) => return searchableFields.some((field) =>

View File

@@ -101,6 +101,7 @@ export function NewtSiteInstallCommands({
`helm install newt fossorial/newt \\ `helm install newt fossorial/newt \\
--create-namespace \\ --create-namespace \\
--set newtInstances[0].name="main-tunnel" \\ --set newtInstances[0].name="main-tunnel" \\
--set newtInstances[0].enabled=true \\
--set-string newtInstances[0].auth.keys.endpointKey="${endpoint}" \\ --set-string newtInstances[0].auth.keys.endpointKey="${endpoint}" \\
--set-string newtInstances[0].auth.keys.idKey="${id}" \\ --set-string newtInstances[0].auth.keys.idKey="${id}" \\
--set-string newtInstances[0].auth.keys.secretKey="${secret}"` --set-string newtInstances[0].auth.keys.secretKey="${secret}"`
@@ -185,59 +186,72 @@ WantedBy=default.target`
className="mt-4" className="mt-4"
/> />
<div className="pt-4"> <div className="pt-4">
<p className="font-bold mb-3"> <p className="font-bold mb-3">{t("siteConfiguration")}</p>
{t("siteConfiguration")} <div className="flex items-center space-x-2 mb-2">
</p> <CheckboxWithLabel
<div className="flex items-center space-x-2 mb-2"> id="acceptClients"
<CheckboxWithLabel aria-describedby="acceptClients-desc"
id="acceptClients" checked={acceptClients}
aria-describedby="acceptClients-desc" onCheckedChange={(checked) => {
checked={acceptClients} const value = checked as boolean;
onCheckedChange={(checked) => { setAcceptClients(value);
const value = checked as boolean; }}
setAcceptClients(value); label={t("siteAcceptClientConnections")}
}} />
label={t("siteAcceptClientConnections")}
/>
</div>
<p
id="acceptClients-desc"
className="text-sm text-muted-foreground"
>
{t("siteAcceptClientConnectionsDescription")}
</p>
</div> </div>
<p
id="acceptClients-desc"
className="text-sm text-muted-foreground"
>
{t("siteAcceptClientConnectionsDescription")}
</p>
</div>
<div className="pt-4"> <div className="pt-4">
<p className="font-bold mb-3">{t("commands")}</p> <p className="font-bold mb-3">{t("commands")}</p>
<div className="mt-2 space-y-3"> {platform === "kubernetes" && (
{commands.map((item, index) => { <p className="text-sm text-muted-foreground mb-3">
const commandText = For more and up to date Kubernetes installation
typeof item === "string" information, see{" "}
? item <a
: item.command; href="https://docs.pangolin.net/manage/sites/install-kubernetes"
const title = target="_blank"
typeof item === "string" rel="noreferrer"
? undefined className="underline"
: item.title; >
docs.pangolin.net/manage/sites/install-kubernetes
</a>
.
</p>
)}
<div className="mt-2 space-y-3">
{commands.map((item, index) => {
const commandText =
typeof item === "string" ? item : item.command;
const title =
typeof item === "string"
? undefined
: item.title;
return ( const key = `${title ?? ""}::${commandText}`;
<div key={index}>
{title && ( return (
<p className="text-sm font-medium mb-1.5"> <div key={key}>
{title} {title && (
</p> <p className="text-sm font-medium mb-1.5">
)} {title}
<CopyTextBox </p>
text={commandText} )}
outline={true} <CopyTextBox
/> text={commandText}
</div> outline={true}
); />
})} </div>
</div> );
})}
</div> </div>
</div>
</SettingsSectionBody> </SettingsSectionBody>
</SettingsSection> </SettingsSection>
); );