diff --git a/apps/frontend/src/types/components.d.ts b/apps/frontend/src/types/components.d.ts
index 1412768..f048e95 100644
--- a/apps/frontend/src/types/components.d.ts
+++ b/apps/frontend/src/types/components.d.ts
@@ -7,6 +7,7 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
+ ElAlert: typeof import('element-plus/es')['ElAlert']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCol: typeof import('element-plus/es')['ElCol']
diff --git a/apps/frontend/src/views/hysteria/list/index.vue b/apps/frontend/src/views/hysteria/list/index.vue
index 48acaab..3bf6320 100644
--- a/apps/frontend/src/views/hysteria/list/index.vue
+++ b/apps/frontend/src/views/hysteria/list/index.vue
@@ -2,28 +2,6 @@
-
-
- {{ $t("common.save") }}
-
-
-
-
-
-
-
-
- {{ $t("common.import") }}
-
-
-
@@ -32,53 +10,18 @@
{{ $t("common.export") }}
-
-
-
-
-
- {{ $t("common.reset") }}
-
-
+
+
-
-
-
-
-
-
-
-
-
- {{ $t("hysteria.addConfigItem") }}
-
-
-
- {{ item.desc }}
-
-
-
-
-
+
{{ $t("hysteria.hysteria2Version") }}:
@@ -100,17 +43,16 @@
-
(["tcp", "udp", "tls", "https"]);
const masqueradeTypes = ref(["file", "proxy", "string"]);
const state = reactive({
- enableForm: {
- enable: "0",
- },
configForm: {
remark: "",
clashExtension: "",
@@ -1140,7 +1073,6 @@ const state = reactive({
acl: false,
outbounds: false,
masquerade: false,
- fileList: [] as UploadFile[],
hysteria2Monitor: {
version: "",
running: false,
@@ -1150,7 +1082,6 @@ const state = reactive({
});
const {
- enableForm,
configForm,
activeName,
dataForm,
@@ -1166,7 +1097,6 @@ const {
acl,
outbounds,
masquerade,
- fileList,
hysteria2Monitor,
crtFileList,
keyFileList,
@@ -1237,28 +1167,6 @@ const tabs = computed(() => {
return tabs;
});
-const handleImport = (params: UploadRequestOptions) => {
- if (state.fileList.length > 0) {
- let formData = new FormData();
- formData.append("file", params.file);
- importHysteria2ConfigApi(formData).then(() => {
- ElMessage.success(t("common.success"));
- });
- state.fileList = [];
- }
-};
-
-const beforeImport = (file: UploadRawFile) => {
- if (!file.name.endsWith(".yaml")) {
- ElMessage.error("file format not supported");
- return false;
- }
- if (file.size / 1024 / 1024 > 2) {
- ElMessage.error("the file is too big, less than 2 MB");
- return false;
- }
-};
-
const handleExport = async () => {
let response = await exportHysteria2ConfigApi();
try {
@@ -1279,199 +1187,13 @@ const handleExport = async () => {
}
};
-const handleReset = () => {
- state.configForm = {
- remark: "",
- clashExtension: "",
- };
- state.dataForm = deepCopy(defaultHysteria2ServerConfig);
- state.activeName = "extension";
- state.tlsType = "acme";
- state.aclType = "inline";
- state.obfs = false;
- state.quic = false;
- state.bandwidth = false;
- state.speedTest = false;
- state.udp = false;
- state.resolver = false;
- state.sniff = false;
- state.acl = false;
- state.outbounds = false;
- state.masquerade = false;
- state.fileList = [];
-};
-
-const handleChangeEnable = async () => {
- const enable = state.enableForm.enable === "1" ? "0" : "1";
- try {
- await updateConfigsApi({
- configUpdateDtos: [
- { key: hysteria2EnableKey, value: state.enableForm.enable },
- ],
- });
- if (state.enableForm.enable === "1") {
- ElMessage.success(t("common.enableSuccess"));
- } else {
- ElMessage.error(t("common.disableSuccess"));
- }
- } catch (e) {
- state.enableForm.enable = enable;
- }
- await setHysteria2Monitor();
-};
-
-const submitForm = () => {
- dataFormRef.value.validate((valid: any) => {
- if (valid) {
- let configs: ConfigsUpdateDto[] = [
- {
- key: hysteria2Remark,
- value: state.configForm.remark,
- },
- {
- key: clashExtension,
- value: state.configForm.clashExtension,
- },
- ];
- updateConfigsApi({ configUpdateDtos: configs });
-
- if (state.tlsType == "tls") {
- state.dataForm.acme = undefined;
- } else if (state.tlsType == "acme") {
- state.dataForm.tls = undefined;
- if (state.dataForm.acme?.type == "http") {
- state.dataForm.acme.tls = undefined;
- state.dataForm.acme.dns = undefined;
- } else if (state.dataForm.acme?.type == "tls") {
- state.dataForm.acme.http = undefined;
- state.dataForm.acme.dns = undefined;
- } else if (state.dataForm.acme?.type == "dns") {
- state.dataForm.acme.http = undefined;
- state.dataForm.acme.tls = undefined;
- } else if (state.dataForm.acme?.type == "") {
- state.dataForm.acme.http = undefined;
- state.dataForm.acme.tls = undefined;
- state.dataForm.acme.dns = undefined;
- }
- }
-
- if (state.dataForm.acl) {
- if (state.aclType == "inline") {
- state.dataForm.acl.file = undefined;
- } else if (state.aclType == "file") {
- state.dataForm.acl.inline = undefined;
- }
- }
-
- if (state.dataForm.resolver?.type == "tcp") {
- state.dataForm.resolver.udp = undefined;
- state.dataForm.resolver.tls = undefined;
- state.dataForm.resolver.https = undefined;
- } else if (state.dataForm.resolver?.type == "udp") {
- state.dataForm.resolver.tcp = undefined;
- state.dataForm.resolver.tls = undefined;
- state.dataForm.resolver.https = undefined;
- } else if (state.dataForm.resolver?.type == "tls") {
- state.dataForm.resolver.tcp = undefined;
- state.dataForm.resolver.udp = undefined;
- state.dataForm.resolver.https = undefined;
- } else if (state.dataForm.resolver?.type == "https") {
- state.dataForm.resolver.tcp = undefined;
- state.dataForm.resolver.udp = undefined;
- state.dataForm.resolver.tls = undefined;
- }
-
- if (state.dataForm.masquerade?.type == "file") {
- state.dataForm.masquerade.proxy = undefined;
- state.dataForm.masquerade.string = undefined;
- } else if (state.dataForm.masquerade?.type == "proxy") {
- state.dataForm.masquerade.file = undefined;
- state.dataForm.masquerade.string = undefined;
- } else if (state.dataForm.masquerade?.type == "string") {
- state.dataForm.masquerade.file = undefined;
- state.dataForm.masquerade.proxy = undefined;
- }
-
- if (!state.obfs) {
- state.dataForm.obfs = undefined;
- }
- if (!state.quic) {
- state.dataForm.quic = undefined;
- }
- if (!state.bandwidth) {
- state.dataForm.bandwidth = undefined;
- state.dataForm.ignoreClientBandwidth = undefined;
- }
- if (!state.speedTest) {
- state.dataForm.speedTest = undefined;
- }
- if (!state.udp) {
- state.dataForm.disableUDP = undefined;
- state.dataForm.udpIdleTimeout = undefined;
- }
- if (!state.resolver) {
- state.dataForm.resolver = undefined;
- }
- if (!state.sniff) {
- state.dataForm.sniff = undefined;
- }
- if (!state.acl) {
- state.dataForm.acl = undefined;
- }
- if (!state.outbounds) {
- state.dataForm.outbounds = undefined;
- }
- if (!state.masquerade) {
- state.dataForm.masquerade = undefined;
- }
-
- if (state.dataForm?.udpIdleTimeout === "") {
- state.dataForm!.udpIdleTimeout = "60s";
- }
- if (state.dataForm?.quic?.maxIdleTimeout === "") {
- state.dataForm!.quic!.maxIdleTimeout = "30s";
- }
- if (state.dataForm?.resolver?.tcp?.timeout === "") {
- state.dataForm!.resolver!.tcp!.timeout = "4s";
- }
- if (state.dataForm?.resolver?.udp?.timeout === "") {
- state.dataForm!.resolver!.udp!.timeout = "4s";
- }
- if (state.dataForm?.resolver?.tls?.timeout === "") {
- state.dataForm!.resolver!.tls!.timeout = "10s";
- }
- if (state.dataForm?.resolver?.https?.timeout === "") {
- state.dataForm!.resolver!.https!.timeout = "10s";
- }
- if (state.dataForm?.sniff?.timeout === "") {
- state.dataForm!.sniff!.timeout = "2s";
- }
- if (state.dataForm?.acl?.geoUpdateInterval === "") {
- state.dataForm!.acl!.geoUpdateInterval = "168h";
- }
-
- const params = { ...state.dataForm };
- updateHysteria2ConfigApi(params).then(() => {
- ElMessage.success(t("common.success"));
- setConfig();
- });
- }
- });
-};
-
const setConfig = () => {
listConfigApi({
- keys: [
- hysteria2EnableKey,
- hysteria2Remark,
- clashExtension,
- ],
+ keys: [hysteria2Remark, clashExtension],
}).then((response) => {
const data = response.data;
data.forEach((configVo) => {
- if (configVo.key === hysteria2EnableKey) {
- state.enableForm.enable = configVo.value;
- } else if (configVo.key === hysteria2Remark) {
+ if (configVo.key === hysteria2Remark) {
state.configForm.remark = configVo.value;
} else if (configVo.key === clashExtension) {
state.configForm.clashExtension = configVo.value;
@@ -1502,66 +1224,6 @@ const setConfig = () => {
});
};
-const closeTabPane = (tabPaneName: string) => {
- if (
- tabPaneName === "extension" ||
- tabPaneName === "listen" ||
- tabPaneName === "tls" ||
- tabPaneName === "http"
- ) {
- ElMessage.error("This tab is required");
- return;
- }
-
- if (tabPaneName === "obfs") {
- state.obfs = false;
- } else if (tabPaneName === "quic") {
- state.quic = false;
- } else if (tabPaneName === "bandwidth") {
- state.bandwidth = false;
- } else if (tabPaneName === "speedTest") {
- state.speedTest = false;
- } else if (tabPaneName === "udp") {
- state.udp = false;
- } else if (tabPaneName === "resolver") {
- state.resolver = false;
- } else if (tabPaneName === "sniff") {
- state.sniff = false;
- } else if (tabPaneName === "acl") {
- state.acl = false;
- } else if (tabPaneName === "outbounds") {
- state.outbounds = false;
- } else if (tabPaneName === "masquerade") {
- state.masquerade = false;
- }
- state.activeName = "listen";
-};
-
-const handleDropdownClick = (command: string) => {
- if (command === "obfs") {
- state.obfs = true;
- } else if (command === "quic") {
- state.quic = true;
- } else if (command === "bandwidth") {
- state.bandwidth = true;
- } else if (command === "speedTest") {
- state.speedTest = true;
- } else if (command === "udp") {
- state.udp = true;
- } else if (command === "resolver") {
- state.resolver = true;
- } else if (command === "sniff") {
- state.sniff = true;
- } else if (command === "acl") {
- state.acl = true;
- } else if (command === "outbounds") {
- state.outbounds = true;
- } else if (command === "masquerade") {
- state.masquerade = true;
- }
- state.activeName = command;
-};
-
const setHysteria2Monitor = async () => {
const { data } = await monitorHysteria2Api();
Object.assign(state.hysteria2Monitor, data);
diff --git a/docs/08-orchestrator-spec.md b/docs/08-orchestrator-spec.md
index b7e4c2f..3a04691 100644
--- a/docs/08-orchestrator-spec.md
+++ b/docs/08-orchestrator-spec.md
@@ -114,7 +114,7 @@
## CLI baseline
Команды:
-- `install --package-dir [--config /etc/hy2xs/hy2xs.env]`
+- `install --package-dir [--config ]`
- `reconfigure --package-dir --config /etc/hy2xs/hy2xs.env --dry-run`
- `reconfigure --package-dir --config /etc/hy2xs/hy2xs.env --apply`
diff --git a/hy2xs_implementation_plan-no_git/05-orchestrator-install-flow.txt b/hy2xs_implementation_plan-no_git/05-orchestrator-install-flow.txt
index 830c1dc..d411dee 100644
--- a/hy2xs_implementation_plan-no_git/05-orchestrator-install-flow.txt
+++ b/hy2xs_implementation_plan-no_git/05-orchestrator-install-flow.txt
@@ -71,7 +71,6 @@ Install-only orchestrator ставит систему на чистый Debian 1
CLI baseline
Допустимые флаги:
- --non-interactive
-- --domain
- --port
- --ssh-port
- --skip-firewall
diff --git a/orchestrator/src/steps/preflight.ts b/orchestrator/src/steps/preflight.ts
index c5a638a..e66cc87 100644
--- a/orchestrator/src/steps/preflight.ts
+++ b/orchestrator/src/steps/preflight.ts
@@ -66,6 +66,13 @@ export async function preflight(context: InstallContext): Promise {
fail("acme mode requires HY2XS_DOMAIN and HY2XS_ACME_EMAIL");
}
+ if (!isReconfigure && context.config.tlsMode === "acme") {
+ const acmeChallengePort = context.config.acmeType === "http" ? 80 : 443;
+ if (await isPortBusy(acmeChallengePort)) {
+ fail(`ACME ${context.config.acmeType}-challenge port is already in use: ${acmeChallengePort}`);
+ }
+ }
+
if (context.config.domain) {
try {
const a = await run`getent ahostsv4 ${context.config.domain}`;
diff --git a/package/install.sh b/package/install.sh
index 9684af5..2a0f81c 100644
--- a/package/install.sh
+++ b/package/install.sh
@@ -36,6 +36,8 @@ cp -a "$PACKAGE_DIR/docs" "$RUNTIME_PACKAGE_DIR/"
cp -a "$PACKAGE_DIR/systemd" "$RUNTIME_PACKAGE_DIR/"
cp -a "$PACKAGE_DIR/templates" "$RUNTIME_PACKAGE_DIR/"
cp -a "$PACKAGE_DIR/metadata" "$RUNTIME_PACKAGE_DIR/"
+cp -a "$PACKAGE_DIR/ui" "$RUNTIME_PACKAGE_DIR/"
+cp -a "$PACKAGE_DIR/install.sh" "$RUNTIME_PACKAGE_DIR/"
log "package directory: $PACKAGE_DIR"
log "starting install-only orchestrator"
diff --git a/tools/build/lib/deps.sh b/tools/build/lib/deps.sh
index 7227c91..6bf72bc 100644
--- a/tools/build/lib/deps.sh
+++ b/tools/build/lib/deps.sh
@@ -144,6 +144,7 @@ ensure_node() {
ensure_pnpm() {
local managed="$TOOLCHAIN_DIR/pnpm/bin/pnpm"
+ export PATH="$TOOLCHAIN_DIR/pnpm/bin:$PATH"
if [ -x "$managed" ] && [ "$($managed --version)" = "$PNPM_REQUIRED" ]; then
PNPM_BIN="$managed"
else
@@ -151,11 +152,8 @@ ensure_pnpm() {
mkdir -p "$TOOLCHAIN_DIR/pnpm/bin"
corepack enable --install-directory "$TOOLCHAIN_DIR/pnpm/bin"
corepack prepare "pnpm@$PNPM_REQUIRED" --activate
- if command -v pnpm >/dev/null 2>&1; then
- cp "$(command -v pnpm)" "$managed"
- chmod 0755 "$managed"
- fi
- PNPM_BIN="$(command -v pnpm)"
+ [ -x "$managed" ] || fail "pnpm binary was not installed into $managed"
+ PNPM_BIN="$managed"
fi
export PNPM_BIN