fix8: усилить rollback reconfigure, идемпотентность firewall и prod-hardening baseline
This commit is contained in:
@@ -43,6 +43,13 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-alert
|
||||||
|
title="Managed by hy2xs-orchestrator reconfigure"
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
style="margin-bottom: 12px"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<el-form
|
<el-form
|
||||||
ref="dataFormRef"
|
ref="dataFormRef"
|
||||||
@@ -54,6 +61,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="dataForm.huiWebPort"
|
v-model="dataForm.huiWebPort"
|
||||||
:placeholder="$t('config.huiWebPort')"
|
:placeholder="$t('config.huiWebPort')"
|
||||||
|
disabled
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -61,6 +69,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="dataForm.huiWebContext"
|
v-model="dataForm.huiWebContext"
|
||||||
:placeholder="$t('config.huiWebContext')"
|
:placeholder="$t('config.huiWebContext')"
|
||||||
|
disabled
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -75,7 +84,7 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('config.huiHttps')" prop="huiHttps">
|
<el-form-item :label="$t('config.huiHttps')" prop="huiHttps">
|
||||||
<el-select v-model="huiHttps" style="width: 50%" ref="huiHttpsRef">
|
<el-select v-model="huiHttps" style="width: 50%" ref="huiHttpsRef" disabled>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in huiHttpsList"
|
v-for="item in huiHttpsList"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
@@ -83,9 +92,6 @@
|
|||||||
:value="item.value"
|
:value="item.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-button v-if="huiHttps" @click="setCertPath"
|
|
||||||
>{{ t("config.useHysteria2Cert") }}
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="huiHttps"
|
v-if="huiHttps"
|
||||||
@@ -96,27 +102,9 @@
|
|||||||
v-model="dataForm.huiCrtPath"
|
v-model="dataForm.huiCrtPath"
|
||||||
:placeholder="$t('config.huiCrtPath')"
|
:placeholder="$t('config.huiCrtPath')"
|
||||||
style="width: 50%"
|
style="width: 50%"
|
||||||
|
disabled
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
<el-upload
|
|
||||||
style="height: 32px"
|
|
||||||
ref="uploadCrtFile"
|
|
||||||
action=""
|
|
||||||
:file-list="crtFileList"
|
|
||||||
:http-request="uploadCertFile"
|
|
||||||
accept=".crt"
|
|
||||||
:before-upload="
|
|
||||||
() => {
|
|
||||||
crtFileList = [];
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:show-file-list="false"
|
|
||||||
:limit="1"
|
|
||||||
>
|
|
||||||
<template #trigger>
|
|
||||||
<el-button>{{ t("config.uploadCrtFile") }}</el-button>
|
|
||||||
</template>
|
|
||||||
</el-upload>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="huiHttps"
|
v-if="huiHttps"
|
||||||
@@ -127,27 +115,9 @@
|
|||||||
v-model="dataForm.huiKeyPath"
|
v-model="dataForm.huiKeyPath"
|
||||||
:placeholder="$t('config.huiKeyPath')"
|
:placeholder="$t('config.huiKeyPath')"
|
||||||
style="width: 50%"
|
style="width: 50%"
|
||||||
|
disabled
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
<el-upload
|
|
||||||
style="height: 32px"
|
|
||||||
ref="uploadKeyFile"
|
|
||||||
action=""
|
|
||||||
:file-list="keyFileList"
|
|
||||||
:http-request="uploadCertFile"
|
|
||||||
accept=".key"
|
|
||||||
:before-upload="
|
|
||||||
() => {
|
|
||||||
keyFileList = [];
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:show-file-list="false"
|
|
||||||
:limit="1"
|
|
||||||
>
|
|
||||||
<template #trigger>
|
|
||||||
<el-button>{{ t("config.uploadKeyFile") }}</el-button>
|
|
||||||
</template>
|
|
||||||
</el-upload>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
:content="$t('config.resetTrafficCronTip')"
|
:content="$t('config.resetTrafficCronTip')"
|
||||||
@@ -189,12 +159,10 @@ export default {
|
|||||||
import { Select } from "@element-plus/icons-vue";
|
import { Select } from "@element-plus/icons-vue";
|
||||||
import {
|
import {
|
||||||
exportConfigApi,
|
exportConfigApi,
|
||||||
hysteria2AcmePathApi,
|
|
||||||
importConfigApi,
|
importConfigApi,
|
||||||
listConfigApi,
|
listConfigApi,
|
||||||
restartServerApi,
|
restartServerApi,
|
||||||
updateConfigsApi,
|
updateConfigsApi,
|
||||||
uploadCertFileApi,
|
|
||||||
} from "@/api/config";
|
} from "@/api/config";
|
||||||
import { ConfigsUpdateDto } from "@/api/config/types";
|
import { ConfigsUpdateDto } from "@/api/config/types";
|
||||||
import {
|
import {
|
||||||
@@ -204,7 +172,6 @@ import {
|
|||||||
} from "element-plus/lib/components";
|
} from "element-plus/lib/components";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { UploadUserFile } from "element-plus";
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -278,50 +245,19 @@ const state = reactive({
|
|||||||
resetTrafficCron: "",
|
resetTrafficCron: "",
|
||||||
},
|
},
|
||||||
huiHttps: 0,
|
huiHttps: 0,
|
||||||
fileList: [] as UploadUserFile[],
|
fileList: [] as UploadFile[],
|
||||||
crtFileList: [] as UploadUserFile[],
|
|
||||||
keyFileList: [] as UploadUserFile[],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { dataForm, huiHttps, fileList, crtFileList, keyFileList } =
|
const { dataForm, huiHttps, fileList } = toRefs(state);
|
||||||
toRefs(state);
|
|
||||||
|
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
dataFormRef.value.validate((valid: boolean) => {
|
dataFormRef.value.validate((valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (state.huiHttps) {
|
|
||||||
if (!state.dataForm.huiCrtPath || !state.dataForm.huiKeyPath) {
|
|
||||||
ElMessage.error("crt and key required");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state.huiHttps) {
|
|
||||||
state.dataForm.huiCrtPath = "";
|
|
||||||
state.dataForm.huiKeyPath = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
let configs: ConfigsUpdateDto[] = [
|
let configs: ConfigsUpdateDto[] = [
|
||||||
{
|
|
||||||
key: huiWebPortKey,
|
|
||||||
value: state.dataForm.huiWebPort,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: huiWebContext,
|
|
||||||
value: state.dataForm.huiWebContext,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: hysteria2TrafficTimeKey,
|
key: hysteria2TrafficTimeKey,
|
||||||
value: state.dataForm.hysteria2TrafficTime,
|
value: state.dataForm.hysteria2TrafficTime,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: huiCrtPathKey,
|
|
||||||
value: state.dataForm.huiCrtPath,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: huiKeyPathKey,
|
|
||||||
value: state.dataForm.huiKeyPath,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: resetTrafficCronKey,
|
key: resetTrafficCronKey,
|
||||||
value: state.dataForm.resetTrafficCron,
|
value: state.dataForm.resetTrafficCron,
|
||||||
@@ -415,41 +351,6 @@ const handleExport = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setCertPath = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await hysteria2AcmePathApi();
|
|
||||||
const { crtPath, keyPath } = data;
|
|
||||||
state.dataForm.huiCrtPath = crtPath;
|
|
||||||
state.dataForm.huiKeyPath = keyPath;
|
|
||||||
} catch (e) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const uploadCertFile = async (params: UploadRequestOptions) => {
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
!params.file.name.endsWith(".crt") &&
|
|
||||||
!params.file.name.endsWith(".key")
|
|
||||||
) {
|
|
||||||
ElMessage.error("file format not supported");
|
|
||||||
}
|
|
||||||
if (params.file.size > 1024 * 1024) {
|
|
||||||
ElMessage.error("the file is too big");
|
|
||||||
}
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append("file", params.file);
|
|
||||||
const { data } = await uploadCertFileApi(formData);
|
|
||||||
if (params.file.name.endsWith(".crt")) {
|
|
||||||
state.dataForm.huiCrtPath = data;
|
|
||||||
} else if (params.file.name.endsWith(".key")) {
|
|
||||||
state.dataForm.huiKeyPath = data;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRestartServer = async () => {
|
const handleRestartServer = async () => {
|
||||||
try {
|
try {
|
||||||
ElMessageBox.confirm("Are you sure to restart panel?", "Warning", {
|
ElMessageBox.confirm("Are you sure to restart panel?", "Warning", {
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ project/
|
|||||||
│ ├── branding/
|
│ ├── branding/
|
||||||
│ ├── patches/
|
│ ├── patches/
|
||||||
│ └── BUILD_NOTES.md
|
│ └── BUILD_NOTES.md
|
||||||
├── examples/
|
├── config/
|
||||||
│ └── post-install.env.example
|
│ └── hy2xs.env
|
||||||
└── dist/
|
└── dist/
|
||||||
└── hy2xs-install-<version>.tar.gz
|
└── hy2xs-install-<version>.tar.gz
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ HY2XS: runtime package layout
|
|||||||
- package.build_id
|
- package.build_id
|
||||||
- checksums.txt
|
- checksums.txt
|
||||||
|
|
||||||
7. docs/examples
|
7. docs/config
|
||||||
- короткий README по установке
|
- короткий README по установке
|
||||||
- post-install.env.example
|
- canonical runtime source config (hy2xs.env)
|
||||||
|
|
||||||
Что не должно быть в runtime package
|
Что не должно быть в runtime package
|
||||||
- builder/
|
- builder/
|
||||||
|
|||||||
@@ -15,14 +15,28 @@ async function backupCurrentState(): Promise<void> {
|
|||||||
await runVisible`cp -a /etc/hysteria/config.yaml /etc/hy2xs/backups/config.yaml.bak 2>/dev/null || true`;
|
await runVisible`cp -a /etc/hysteria/config.yaml /etc/hy2xs/backups/config.yaml.bak 2>/dev/null || true`;
|
||||||
await runVisible`cp -a /etc/systemd/system/hy2xs-admin.service /etc/hy2xs/backups/hy2xs-admin.service.bak 2>/dev/null || true`;
|
await runVisible`cp -a /etc/systemd/system/hy2xs-admin.service /etc/hy2xs/backups/hy2xs-admin.service.bak 2>/dev/null || true`;
|
||||||
await runVisible`cp -a /etc/systemd/system/hysteria-server.service /etc/hy2xs/backups/hysteria-server.service.bak 2>/dev/null || true`;
|
await runVisible`cp -a /etc/systemd/system/hysteria-server.service /etc/hy2xs/backups/hysteria-server.service.bak 2>/dev/null || true`;
|
||||||
|
await runVisible`cp -a /etc/hy2xs/hy2xs.env /etc/hy2xs/backups/hy2xs.env.bak 2>/dev/null || true`;
|
||||||
|
await runVisible`cp -a /etc/hysteria/post-install.env /etc/hy2xs/backups/post-install.env.bak 2>/dev/null || true`;
|
||||||
|
await runVisible`cp -a /etc/nftables.conf /etc/hy2xs/backups/nftables.conf.bak 2>/dev/null || true`;
|
||||||
await runVisible`cp -a /etc/nftables.d/hy2xs.nft /etc/hy2xs/backups/hy2xs.nft.bak 2>/dev/null || true`;
|
await runVisible`cp -a /etc/nftables.d/hy2xs.nft /etc/hy2xs/backups/hy2xs.nft.bak 2>/dev/null || true`;
|
||||||
|
|
||||||
|
await runVisible`test -f /etc/hy2xs/hy2xs.env && echo 1 > /etc/hy2xs/backups/hy2xs.env.existed || rm -f /etc/hy2xs/backups/hy2xs.env.existed`;
|
||||||
|
await runVisible`test -f /etc/hysteria/post-install.env && echo 1 > /etc/hy2xs/backups/post-install.env.existed || rm -f /etc/hy2xs/backups/post-install.env.existed`;
|
||||||
|
await runVisible`test -f /etc/nftables.conf && echo 1 > /etc/hy2xs/backups/nftables.conf.existed || rm -f /etc/hy2xs/backups/nftables.conf.existed`;
|
||||||
|
await runVisible`test -f /etc/nftables.d/hy2xs.nft && echo 1 > /etc/hy2xs/backups/hy2xs.nft.existed || rm -f /etc/hy2xs/backups/hy2xs.nft.existed`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function rollbackCurrentState(): Promise<void> {
|
async function rollbackCurrentState(): Promise<void> {
|
||||||
await runVisible`cp -a /etc/hy2xs/backups/config.yaml.bak /etc/hysteria/config.yaml 2>/dev/null || true`;
|
await runVisible`cp -a /etc/hy2xs/backups/config.yaml.bak /etc/hysteria/config.yaml 2>/dev/null || true`;
|
||||||
await runVisible`cp -a /etc/hy2xs/backups/hy2xs-admin.service.bak /etc/systemd/system/hy2xs-admin.service 2>/dev/null || true`;
|
await runVisible`cp -a /etc/hy2xs/backups/hy2xs-admin.service.bak /etc/systemd/system/hy2xs-admin.service 2>/dev/null || true`;
|
||||||
await runVisible`cp -a /etc/hy2xs/backups/hysteria-server.service.bak /etc/systemd/system/hysteria-server.service 2>/dev/null || true`;
|
await runVisible`cp -a /etc/hy2xs/backups/hysteria-server.service.bak /etc/systemd/system/hysteria-server.service 2>/dev/null || true`;
|
||||||
await runVisible`cp -a /etc/hy2xs/backups/hy2xs.nft.bak /etc/nftables.d/hy2xs.nft 2>/dev/null || true`;
|
|
||||||
|
await runVisible`if [ -f /etc/hy2xs/backups/hy2xs.env.existed ]; then cp -a /etc/hy2xs/backups/hy2xs.env.bak /etc/hy2xs/hy2xs.env 2>/dev/null || true; else rm -f /etc/hy2xs/hy2xs.env; fi`;
|
||||||
|
await runVisible`if [ -f /etc/hy2xs/backups/post-install.env.existed ]; then cp -a /etc/hy2xs/backups/post-install.env.bak /etc/hysteria/post-install.env 2>/dev/null || true; else rm -f /etc/hysteria/post-install.env; fi`;
|
||||||
|
await runVisible`if [ -f /etc/hy2xs/backups/nftables.conf.existed ]; then cp -a /etc/hy2xs/backups/nftables.conf.bak /etc/nftables.conf 2>/dev/null || true; fi`;
|
||||||
|
await runVisible`if [ -f /etc/hy2xs/backups/hy2xs.nft.existed ]; then cp -a /etc/hy2xs/backups/hy2xs.nft.bak /etc/nftables.d/hy2xs.nft 2>/dev/null || true; else rm -f /etc/nftables.d/hy2xs.nft; fi`;
|
||||||
|
|
||||||
|
await runVisible`nft -f /etc/nftables.conf >/dev/null 2>&1 || true`;
|
||||||
await runVisible`systemctl daemon-reload`;
|
await runVisible`systemctl daemon-reload`;
|
||||||
await runVisible`systemctl restart hysteria-server hy2xs-admin || true`;
|
await runVisible`systemctl restart hysteria-server hy2xs-admin || true`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,19 @@ export async function applyFirewall(context: InstallContext): Promise<void> {
|
|||||||
await writeText("/etc/nftables.d/hy2xs.nft.candidate", rendered, 0o600);
|
await writeText("/etc/nftables.d/hy2xs.nft.candidate", rendered, 0o600);
|
||||||
await runVisible`nft -c -f /etc/nftables.d/hy2xs.nft.candidate`;
|
await runVisible`nft -c -f /etc/nftables.d/hy2xs.nft.candidate`;
|
||||||
|
|
||||||
|
const nftablesConf = `#!/usr/sbin/nft -f
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
include "/etc/nftables.d/hy2xs.nft"
|
||||||
|
`;
|
||||||
|
await writeText("/etc/nftables.conf", nftablesConf, 0o644);
|
||||||
|
await runVisible`nft -c -f /etc/nftables.conf`;
|
||||||
|
|
||||||
if (context.config.firewallStagedApply) {
|
if (context.config.firewallStagedApply) {
|
||||||
await runVisible`systemd-run --unit hy2xs-fw-rollback --on-active=45s /bin/sh -c 'cp -a /etc/nftables.conf.hy2xs.bak /etc/nftables.conf 2>/dev/null || true; if [ -f /etc/nftables.d/hy2xs.nft.existed ]; then cp -a /etc/nftables.d/hy2xs.nft.bak /etc/nftables.d/hy2xs.nft 2>/dev/null || true; else rm -f /etc/nftables.d/hy2xs.nft; fi; nft -f /etc/nftables.conf >/dev/null 2>&1 || true'`;
|
await runVisible`systemd-run --unit hy2xs-fw-rollback --on-active=45s /bin/sh -c 'if [ -f /etc/nftables.conf.hy2xs.bak ]; then cp -a /etc/nftables.conf.hy2xs.bak /etc/nftables.conf 2>/dev/null || true; fi; if [ -f /etc/nftables.d/hy2xs.nft.existed ]; then cp -a /etc/nftables.d/hy2xs.nft.bak /etc/nftables.d/hy2xs.nft 2>/dev/null || true; else rm -f /etc/nftables.d/hy2xs.nft; fi; nft -f /etc/nftables.conf >/dev/null 2>&1 || true'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await runVisible`mv /etc/nftables.d/hy2xs.nft.candidate /etc/nftables.d/hy2xs.nft`;
|
await runVisible`mv /etc/nftables.d/hy2xs.nft.candidate /etc/nftables.d/hy2xs.nft`;
|
||||||
await runVisible`grep -q 'include "/etc/nftables.d/hy2xs.nft"' /etc/nftables.conf || printf '\ninclude "/etc/nftables.d/hy2xs.nft"\n' >> /etc/nftables.conf`;
|
|
||||||
await runVisible`nft -f /etc/nftables.conf`;
|
await runVisible`nft -f /etc/nftables.conf`;
|
||||||
await runVisible`systemctl enable --now nftables`;
|
await runVisible`systemctl enable --now nftables`;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ HY2XS_HYSTERIA_BANDWIDTH_UP=50 mbps
|
|||||||
HY2XS_HYSTERIA_BANDWIDTH_DOWN=50 mbps
|
HY2XS_HYSTERIA_BANDWIDTH_DOWN=50 mbps
|
||||||
HY2XS_HYSTERIA_IGNORE_CLIENT_BANDWIDTH=false
|
HY2XS_HYSTERIA_IGNORE_CLIENT_BANDWIDTH=false
|
||||||
HY2XS_HYSTERIA_CONFIG_PATH=/etc/hysteria/config.yaml
|
HY2XS_HYSTERIA_CONFIG_PATH=/etc/hysteria/config.yaml
|
||||||
HY2XS_HYSTERIA_VERSION=latest
|
HY2XS_HYSTERIA_VERSION=v2.6.0
|
||||||
HY2XS_INSTALL_DIR=/opt/hy2xs-admin
|
HY2XS_INSTALL_DIR=/opt/hy2xs-admin
|
||||||
HY2XS_DATA_DIR=/var/lib/hy2xs-admin
|
HY2XS_DATA_DIR=/var/lib/hy2xs-admin
|
||||||
HY2XS_LOG_DIR=/var/log/hy2xs
|
HY2XS_LOG_DIR=/var/log/hy2xs
|
||||||
|
|||||||
@@ -6,6 +6,25 @@ BUN_REQUIRED="${BUN_REQUIRED:-1.1.45}"
|
|||||||
NODE_REQUIRED="${NODE_REQUIRED:-20.19.0}"
|
NODE_REQUIRED="${NODE_REQUIRED:-20.19.0}"
|
||||||
PNPM_REQUIRED="${PNPM_REQUIRED:-9.15.9}"
|
PNPM_REQUIRED="${PNPM_REQUIRED:-9.15.9}"
|
||||||
TOOLCHAIN_DIR="${TOOLCHAIN_DIR:-$ROOT_DIR/.toolchain}"
|
TOOLCHAIN_DIR="${TOOLCHAIN_DIR:-$ROOT_DIR/.toolchain}"
|
||||||
|
VERIFY_TOOLCHAIN_CHECKSUMS="${VERIFY_TOOLCHAIN_CHECKSUMS:-false}"
|
||||||
|
GO_ARCHIVE_SHA256="${GO_ARCHIVE_SHA256:-}"
|
||||||
|
NODE_ARCHIVE_SHA256="${NODE_ARCHIVE_SHA256:-}"
|
||||||
|
BUN_ARCHIVE_SHA256="${BUN_ARCHIVE_SHA256:-}"
|
||||||
|
|
||||||
|
verify_archive_sha256() {
|
||||||
|
local archive="$1"
|
||||||
|
local expected="$2"
|
||||||
|
local label="$3"
|
||||||
|
|
||||||
|
if [ "$VERIFY_TOOLCHAIN_CHECKSUMS" != "true" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$expected" ] || fail "missing expected SHA256 for $label (set ${label}_SHA256 env)"
|
||||||
|
local actual
|
||||||
|
actual="$(sha256sum "$archive" | awk '{print $1}')"
|
||||||
|
[ "$actual" = "$expected" ] || fail "$label sha256 mismatch: expected $expected, got $actual"
|
||||||
|
}
|
||||||
|
|
||||||
require_linux_debian12_amd64() {
|
require_linux_debian12_amd64() {
|
||||||
[ "$(uname -s)" = "Linux" ] || fail "production builder supports only Linux Debian 12 amd64"
|
[ "$(uname -s)" = "Linux" ] || fail "production builder supports only Linux Debian 12 amd64"
|
||||||
@@ -79,6 +98,7 @@ ensure_go() {
|
|||||||
mkdir -p "$TOOLCHAIN_DIR/downloads"
|
mkdir -p "$TOOLCHAIN_DIR/downloads"
|
||||||
local archive="$TOOLCHAIN_DIR/downloads/go${GO_REQUIRED}.linux-amd64.tar.gz"
|
local archive="$TOOLCHAIN_DIR/downloads/go${GO_REQUIRED}.linux-amd64.tar.gz"
|
||||||
download_file "https://go.dev/dl/go${GO_REQUIRED}.linux-amd64.tar.gz" "$archive"
|
download_file "https://go.dev/dl/go${GO_REQUIRED}.linux-amd64.tar.gz" "$archive"
|
||||||
|
verify_archive_sha256 "$archive" "$GO_ARCHIVE_SHA256" "GO_ARCHIVE"
|
||||||
rm -rf "$TOOLCHAIN_DIR/go"
|
rm -rf "$TOOLCHAIN_DIR/go"
|
||||||
tar -C "$TOOLCHAIN_DIR" -xzf "$archive"
|
tar -C "$TOOLCHAIN_DIR" -xzf "$archive"
|
||||||
GO_BIN="$managed"
|
GO_BIN="$managed"
|
||||||
@@ -102,6 +122,7 @@ ensure_bun() {
|
|||||||
mkdir -p "$TOOLCHAIN_DIR/downloads" "$TOOLCHAIN_DIR/bun"
|
mkdir -p "$TOOLCHAIN_DIR/downloads" "$TOOLCHAIN_DIR/bun"
|
||||||
local archive="$TOOLCHAIN_DIR/downloads/bun-linux-x64-${BUN_REQUIRED}.zip"
|
local archive="$TOOLCHAIN_DIR/downloads/bun-linux-x64-${BUN_REQUIRED}.zip"
|
||||||
download_file "https://github.com/oven-sh/bun/releases/download/bun-v${BUN_REQUIRED}/bun-linux-x64.zip" "$archive"
|
download_file "https://github.com/oven-sh/bun/releases/download/bun-v${BUN_REQUIRED}/bun-linux-x64.zip" "$archive"
|
||||||
|
verify_archive_sha256 "$archive" "$BUN_ARCHIVE_SHA256" "BUN_ARCHIVE"
|
||||||
rm -rf "$TOOLCHAIN_DIR/bun-tmp" "$TOOLCHAIN_DIR/bun"
|
rm -rf "$TOOLCHAIN_DIR/bun-tmp" "$TOOLCHAIN_DIR/bun"
|
||||||
mkdir -p "$TOOLCHAIN_DIR/bun-tmp"
|
mkdir -p "$TOOLCHAIN_DIR/bun-tmp"
|
||||||
unzip -q "$archive" -d "$TOOLCHAIN_DIR/bun-tmp"
|
unzip -q "$archive" -d "$TOOLCHAIN_DIR/bun-tmp"
|
||||||
@@ -131,6 +152,7 @@ ensure_node() {
|
|||||||
mkdir -p "$TOOLCHAIN_DIR/downloads"
|
mkdir -p "$TOOLCHAIN_DIR/downloads"
|
||||||
local archive="$TOOLCHAIN_DIR/downloads/node-v${NODE_REQUIRED}-linux-x64.tar.xz"
|
local archive="$TOOLCHAIN_DIR/downloads/node-v${NODE_REQUIRED}-linux-x64.tar.xz"
|
||||||
download_file "https://nodejs.org/dist/v${NODE_REQUIRED}/node-v${NODE_REQUIRED}-linux-x64.tar.xz" "$archive"
|
download_file "https://nodejs.org/dist/v${NODE_REQUIRED}/node-v${NODE_REQUIRED}-linux-x64.tar.xz" "$archive"
|
||||||
|
verify_archive_sha256 "$archive" "$NODE_ARCHIVE_SHA256" "NODE_ARCHIVE"
|
||||||
rm -rf "$TOOLCHAIN_DIR/node" "$TOOLCHAIN_DIR/node-v${NODE_REQUIRED}-linux-x64"
|
rm -rf "$TOOLCHAIN_DIR/node" "$TOOLCHAIN_DIR/node-v${NODE_REQUIRED}-linux-x64"
|
||||||
tar -C "$TOOLCHAIN_DIR" -xJf "$archive"
|
tar -C "$TOOLCHAIN_DIR" -xJf "$archive"
|
||||||
mv "$TOOLCHAIN_DIR/node-v${NODE_REQUIRED}-linux-x64" "$TOOLCHAIN_DIR/node"
|
mv "$TOOLCHAIN_DIR/node-v${NODE_REQUIRED}-linux-x64" "$TOOLCHAIN_DIR/node"
|
||||||
|
|||||||
Reference in New Issue
Block a user