mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-16 09:56:36 +00:00
315 lines
11 KiB
TypeScript
315 lines
11 KiB
TypeScript
import { useTranslations } from "next-intl";
|
|
import CopyTextBox from "./CopyTextBox";
|
|
import {
|
|
SettingsSection,
|
|
SettingsSectionBody,
|
|
SettingsSectionDescription,
|
|
SettingsSectionHeader,
|
|
SettingsSectionTitle
|
|
} from "./Settings";
|
|
import { CheckboxWithLabel } from "./ui/checkbox";
|
|
import { Button } from "./ui/button";
|
|
import { useState } from "react";
|
|
import { FaCubes, FaDocker, FaWindows } from "react-icons/fa";
|
|
import { Terminal } from "lucide-react";
|
|
import { SiKubernetes, SiNixos } from "react-icons/si";
|
|
|
|
export type CommandItem = string | { title: string; command: string };
|
|
|
|
const PLATFORMS = [
|
|
"unix",
|
|
"windows",
|
|
"docker",
|
|
"kubernetes",
|
|
"podman",
|
|
"nixos"
|
|
] as const;
|
|
|
|
type Platform = (typeof PLATFORMS)[number];
|
|
|
|
export type NewtSiteInstallCommandsProps = {
|
|
id: string;
|
|
secret: string;
|
|
endpoint: string;
|
|
version?: string;
|
|
};
|
|
|
|
export function NewtSiteInstallCommands({
|
|
id,
|
|
secret,
|
|
endpoint,
|
|
version = "latest"
|
|
}: NewtSiteInstallCommandsProps) {
|
|
const t = useTranslations();
|
|
|
|
const [acceptClients, setAcceptClients] = useState(true);
|
|
const [platform, setPlatform] = useState<Platform>("unix");
|
|
const [architecture, setArchitecture] = useState(
|
|
() => getArchitectures(platform)[0]
|
|
);
|
|
|
|
const acceptClientsFlag = !acceptClients ? " --disable-clients" : "";
|
|
const acceptClientsEnv = !acceptClients
|
|
? "\n - DISABLE_CLIENTS=true"
|
|
: "";
|
|
|
|
const commandList: Record<Platform, Record<string, CommandItem[]>> = {
|
|
unix: {
|
|
All: [
|
|
{
|
|
title: t("install"),
|
|
command: `curl -fsSL https://static.pangolin.net/get-newt.sh | bash`
|
|
},
|
|
{
|
|
title: t("run"),
|
|
command: `newt --id ${id} --secret ${secret} --endpoint ${endpoint}${acceptClientsFlag}`
|
|
}
|
|
]
|
|
},
|
|
windows: {
|
|
x64: [
|
|
{
|
|
title: t("install"),
|
|
command: `curl -o newt.exe -L "https://github.com/fosrl/newt/releases/download/${version}/newt_windows_amd64.exe"`
|
|
},
|
|
{
|
|
title: t("run"),
|
|
command: `newt.exe --id ${id} --secret ${secret} --endpoint ${endpoint}${acceptClientsFlag}`
|
|
}
|
|
]
|
|
},
|
|
docker: {
|
|
"Docker Compose": [
|
|
`services:
|
|
newt:
|
|
image: fosrl/newt
|
|
container_name: newt
|
|
restart: unless-stopped
|
|
environment:
|
|
- PANGOLIN_ENDPOINT=${endpoint}
|
|
- NEWT_ID=${id}
|
|
- NEWT_SECRET=${secret}${acceptClientsEnv}`
|
|
],
|
|
"Docker Run": [
|
|
`docker run -dit fosrl/newt --id ${id} --secret ${secret} --endpoint ${endpoint}${acceptClientsFlag}`
|
|
]
|
|
},
|
|
kubernetes: {
|
|
"Helm Chart": [
|
|
`helm repo add fossorial https://charts.fossorial.io`,
|
|
`helm repo update fossorial`,
|
|
`helm install newt fossorial/newt \\
|
|
--create-namespace \\
|
|
--set newtInstances[0].name="main-tunnel" \\
|
|
--set-string newtInstances[0].auth.keys.endpointKey="${endpoint}" \\
|
|
--set-string newtInstances[0].auth.keys.idKey="${id}" \\
|
|
--set-string newtInstances[0].auth.keys.secretKey="${secret}"`
|
|
]
|
|
},
|
|
podman: {
|
|
"Podman Quadlet": [
|
|
`[Unit]
|
|
Description=Newt container
|
|
|
|
[Container]
|
|
ContainerName=newt
|
|
Image=docker.io/fosrl/newt
|
|
Environment=PANGOLIN_ENDPOINT=${endpoint}
|
|
Environment=NEWT_ID=${id}
|
|
Environment=NEWT_SECRET=${secret}${!acceptClients ? "\nEnvironment=DISABLE_CLIENTS=true" : ""}
|
|
# Secret=newt-secret,type=env,target=NEWT_SECRET
|
|
|
|
[Service]
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=default.target`
|
|
],
|
|
"Podman Run": [
|
|
`podman run -dit docker.io/fosrl/newt --id ${id} --secret ${secret} --endpoint ${endpoint}${acceptClientsFlag}`
|
|
]
|
|
},
|
|
nixos: {
|
|
All: [
|
|
`nix run 'nixpkgs#fosrl-newt' -- --id ${id} --secret ${secret} --endpoint ${endpoint}${acceptClientsFlag}`
|
|
]
|
|
}
|
|
};
|
|
|
|
const commands = commandList[platform][architecture];
|
|
|
|
return (
|
|
<SettingsSection>
|
|
<SettingsSectionHeader>
|
|
<SettingsSectionTitle>
|
|
{t("siteInstallNewt")}
|
|
</SettingsSectionTitle>
|
|
<SettingsSectionDescription>
|
|
{t("siteInstallNewtDescription")}
|
|
</SettingsSectionDescription>
|
|
</SettingsSectionHeader>
|
|
<SettingsSectionBody>
|
|
<div>
|
|
<p className="font-bold mb-3">{t("operatingSystem")}</p>
|
|
<div className="grid grid-cols-2 md:grid-cols-5 gap-2">
|
|
{PLATFORMS.map((os) => (
|
|
<Button
|
|
key={os}
|
|
variant={
|
|
platform === os
|
|
? "squareOutlinePrimary"
|
|
: "squareOutline"
|
|
}
|
|
className={`flex-1 min-w-30 ${platform === os ? "bg-primary/10" : ""} shadow-none`}
|
|
onClick={() => {
|
|
setPlatform(os);
|
|
const architectures = getArchitectures(os);
|
|
setArchitecture(architectures[0]);
|
|
}}
|
|
>
|
|
{getPlatformIcon(os)}
|
|
{getPlatformName(os)}
|
|
</Button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<p className="font-bold mb-3">
|
|
{["docker", "podman"].includes(platform)
|
|
? t("method")
|
|
: t("architecture")}
|
|
</p>
|
|
<div className="grid grid-cols-2 md:grid-cols-5 gap-2">
|
|
{getArchitectures(platform).map((arch) => (
|
|
<Button
|
|
key={arch}
|
|
variant={
|
|
architecture === arch
|
|
? "squareOutlinePrimary"
|
|
: "squareOutline"
|
|
}
|
|
className={`flex-1 min-w-30 ${architecture === arch ? "bg-primary/10" : ""} shadow-none`}
|
|
onClick={() => setArchitecture(arch)}
|
|
>
|
|
{arch}
|
|
</Button>
|
|
))}
|
|
</div>
|
|
|
|
<div className="pt-4">
|
|
<p className="font-bold mb-3">
|
|
{t("siteConfiguration")}
|
|
</p>
|
|
<div className="flex items-center space-x-2 mb-2">
|
|
<CheckboxWithLabel
|
|
id="acceptClients"
|
|
aria-describedby="acceptClients-desc"
|
|
checked={acceptClients}
|
|
onCheckedChange={(checked) => {
|
|
const value = checked as boolean;
|
|
setAcceptClients(value);
|
|
}}
|
|
label={t("siteAcceptClientConnections")}
|
|
/>
|
|
</div>
|
|
<p
|
|
id="acceptClients-desc"
|
|
className="text-sm text-muted-foreground"
|
|
>
|
|
{t("siteAcceptClientConnectionsDescription")}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="pt-4">
|
|
<p className="font-bold mb-3">{t("commands")}</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 (
|
|
<div key={index}>
|
|
{title && (
|
|
<p className="text-sm font-medium mb-1.5">
|
|
{title}
|
|
</p>
|
|
)}
|
|
<CopyTextBox
|
|
text={commandText}
|
|
outline={true}
|
|
/>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</SettingsSectionBody>
|
|
</SettingsSection>
|
|
);
|
|
}
|
|
|
|
function getPlatformIcon(platformName: Platform) {
|
|
switch (platformName) {
|
|
case "windows":
|
|
return <FaWindows className="h-4 w-4 mr-2" />;
|
|
case "unix":
|
|
return <Terminal className="h-4 w-4 mr-2" />;
|
|
case "docker":
|
|
return <FaDocker className="h-4 w-4 mr-2" />;
|
|
case "kubernetes":
|
|
return <SiKubernetes className="h-4 w-4 mr-2" />;
|
|
case "podman":
|
|
return <FaCubes className="h-4 w-4 mr-2" />;
|
|
case "nixos":
|
|
return <SiNixos className="h-4 w-4 mr-2" />;
|
|
default:
|
|
return <Terminal className="h-4 w-4 mr-2" />;
|
|
}
|
|
}
|
|
|
|
function getPlatformName(platformName: Platform) {
|
|
switch (platformName) {
|
|
case "windows":
|
|
return "Windows";
|
|
case "unix":
|
|
return "Unix & macOS";
|
|
case "docker":
|
|
return "Docker";
|
|
case "kubernetes":
|
|
return "Kubernetes";
|
|
case "podman":
|
|
return "Podman";
|
|
case "nixos":
|
|
return "NixOS";
|
|
default:
|
|
return "Unix / macOS";
|
|
}
|
|
}
|
|
|
|
function getArchitectures(platform: Platform) {
|
|
switch (platform) {
|
|
case "unix":
|
|
return ["All"];
|
|
case "windows":
|
|
return ["x64"];
|
|
case "docker":
|
|
return ["Docker Compose", "Docker Run"];
|
|
case "kubernetes":
|
|
return ["Helm Chart"];
|
|
case "podman":
|
|
return ["Podman Quadlet", "Podman Run"];
|
|
case "nixos":
|
|
return ["All"];
|
|
default:
|
|
return ["x64"];
|
|
}
|
|
}
|