diff --git a/README.md b/README.md index f8ca518..e2a11b3 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,8 @@ https://git.ext.flamy.studio/flamy_dev/HY2XS_flamy.git После установки применяются команды оркестратора: ```sh -hy2xs-orchestrator reconfigure --package-dir /opt/hy2xs-package --config /etc/hy2xs/hy2xs.env --dry-run -hy2xs-orchestrator reconfigure --package-dir /opt/hy2xs-package --config /etc/hy2xs/hy2xs.env --apply +hy2xs-orchestrator reconfigure --package-dir /usr/local/lib/hy2xs/package --config /etc/hy2xs/hy2xs.env --dry-run +hy2xs-orchestrator reconfigure --package-dir /usr/local/lib/hy2xs/package --config /etc/hy2xs/hy2xs.env --apply ``` Ключевые инварианты: diff --git a/apps/dao/sqlite.go b/apps/dao/sqlite.go index ef68f13..833652e 100644 --- a/apps/dao/sqlite.go +++ b/apps/dao/sqlite.go @@ -54,22 +54,10 @@ func InitSql(port string) error { return err } if port != "" { - var result string - db, err := sqliteDB.DB() - if err != nil { - return err - } - if err := db.QueryRow("SELECT value from config where key = 'H_UI_WEB_PORT' limit 1").Scan(&result); err != nil { - logrus.Errorf("sqlite exec err: %v", err) + if tx := sqliteDB.Exec("UPDATE config set value = ? where key = 'H_UI_WEB_PORT'", port); tx.Error != nil { + logrus.Errorf("sqlite exec err: %v", tx.Error) return errors.New("sqlite exec err") } - - if result == "8081" { - if tx := sqliteDB.Exec("UPDATE config set value = ? where key = 'H_UI_WEB_PORT'", port); tx.Error != nil { - logrus.Errorf("sqlite exec err: %v", tx.Error) - return errors.New("sqlite exec err") - } - } } if err := ensureAccountSchema(); err != nil { diff --git a/apps/proxy/hysteria2.go b/apps/proxy/hysteria2.go deleted file mode 100644 index a8be8d1..0000000 --- a/apps/proxy/hysteria2.go +++ /dev/null @@ -1,58 +0,0 @@ -package proxy - -import ( - "errors" - "github.com/sirupsen/logrus" - "hy2xs-admin/model/constant" - "hy2xs-admin/util" - "os/exec" - "sync" -) - -type Hysteria2Process struct { - process - binPath string - configPath string -} - -var mutexHysteria2 sync.Mutex -var cmdHysteria2 exec.Cmd -var hysteria2Instance *Hysteria2Process - -func init() { - hysteria2Instance = &Hysteria2Process{process{mutex: &mutexHysteria2, cmd: &cmdHysteria2}, util.GetHysteria2BinPath(), constant.Hysteria2ConfigPath} -} - -func NewHysteria2Instance() *Hysteria2Process { - return hysteria2Instance -} - -func (h *Hysteria2Process) IsRunning() bool { - return h.isRunning() -} - -func (h *Hysteria2Process) StartHysteria2() error { - if err := h.start(h.binPath, "-c", h.configPath, "server"); err != nil { - _ = util.RemoveFile(h.configPath) - logrus.Errorf("start hysteria2 err: %v", err) - return errors.New("start hysteria2 err") - } - return nil -} - -func (h *Hysteria2Process) StopHysteria2() error { - if err := h.stop(); err != nil { - logrus.Errorf("stop hysteria2 err: %v", err) - return errors.New("stop hysteria2 err") - } - _ = util.RemoveFile(h.configPath) - return nil -} - -func (h *Hysteria2Process) Release() error { - if err := h.release(); err != nil { - logrus.Errorf("release hysteria2 err: %v", err) - return errors.New("release hysteria2 err") - } - return nil -} diff --git a/docs/09-post-install-env.md b/docs/09-post-install-env.md index 97906d7..d03581a 100644 --- a/docs/09-post-install-env.md +++ b/docs/09-post-install-env.md @@ -108,6 +108,7 @@ - `HY2XS_ADMIN_INITIAL_PASSWORD` используется только для первичного bootstrap seed; - `HY2XS_ADMIN_CON_PASS` — отдельная runtime-сущность для Hysteria auth/smoke; - bootstrap secret хранится в явном формате `KEY=VALUE` (`ADMIN_USER`, `ADMIN_INITIAL_PASSWORD`, `ADMIN_CON_PASS`), права `0600`; +- `HY2XS_FORCE_PASSWORD_CHANGE` в production baseline установлен в `false` (forced UX-flow пока не реализован); - после первичного seed перезапуски `hy2xs-admin` не должны переопределять пароль admin и `con_pass`. ## Что нельзя делать diff --git a/orchestrator/src/config/env.ts b/orchestrator/src/config/env.ts index 3bcaa69..5e67a90 100644 --- a/orchestrator/src/config/env.ts +++ b/orchestrator/src/config/env.ts @@ -130,7 +130,6 @@ export function parseRuntimeEnv(content: string): RuntimeConfig { hysteriaBindHost: normalizeIpv4Host("HY2XS_HYSTERIA_BIND_HOST", env.HY2XS_HYSTERIA_BIND_HOST || "0.0.0.0"), hysteriaPort, hysteriaAuthMode: "http", - hysteriaAuthUrl: env.HY2XS_HYSTERIA_AUTH_URL || `http://127.0.0.1:${uiPort}/hui/hysteria2/auth`, hysteriaTrafficStatsHost: normalizeIpv4Host( "HY2XS_HYSTERIA_TRAFFIC_STATS_HOST", env.HY2XS_HYSTERIA_TRAFFIC_STATS_HOST || "127.0.0.1" @@ -221,7 +220,6 @@ export function renderRuntimeEnv(config: RuntimeConfig): string { `HY2XS_HYSTERIA_BIND_HOST=${config.hysteriaBindHost}`, `HY2XS_HYSTERIA_PORT=${config.hysteriaPort}`, "HY2XS_HYSTERIA_AUTH_MODE=http", - `HY2XS_HYSTERIA_AUTH_URL=${config.hysteriaAuthUrl}`, `HY2XS_HYSTERIA_TRAFFIC_STATS_HOST=${config.hysteriaTrafficStatsHost}`, `HY2XS_HYSTERIA_TRAFFIC_STATS_PORT=${config.hysteriaTrafficStatsPort}`, `HY2XS_HYSTERIA_TRAFFIC_STATS_SECRET=${config.hysteriaTrafficStatsSecret}`, diff --git a/orchestrator/src/steps/firewall.ts b/orchestrator/src/steps/firewall.ts index 838b312..8b059aa 100644 --- a/orchestrator/src/steps/firewall.ts +++ b/orchestrator/src/steps/firewall.ts @@ -22,12 +22,15 @@ export async function applyFirewall(context: InstallContext): Promise { ACME_RULE: acmeRule }); + await runVisible`cp -a /etc/nftables.conf /etc/nftables.conf.hy2xs.bak 2>/dev/null || true`; await runVisible`cp -a /etc/nftables.d/hy2xs.nft /etc/nftables.d/hy2xs.nft.bak 2>/dev/null || true`; + await runVisible`test -f /etc/nftables.d/hy2xs.nft && echo 1 > /etc/nftables.d/hy2xs.nft.existed || rm -f /etc/nftables.d/hy2xs.nft.existed`; + await runVisible`grep -q 'include "/etc/nftables.d/hy2xs.nft"' /etc/nftables.conf && echo 1 > /etc/nftables.d/hy2xs.nft.include.existed || rm -f /etc/nftables.d/hy2xs.nft.include.existed`; await writeText("/etc/nftables.d/hy2xs.nft.candidate", rendered, 0o600); await runVisible`nft -c -f /etc/nftables.d/hy2xs.nft.candidate`; if (context.config.firewallStagedApply) { - await runVisible`systemd-run --unit hy2xs-fw-rollback --on-active=45s /bin/sh -c 'cp -a /etc/nftables.d/hy2xs.nft.bak /etc/nftables.d/hy2xs.nft 2>/dev/null || true; nft -f /etc/nftables.conf >/dev/null 2>&1 || true'`; + 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`mv /etc/nftables.d/hy2xs.nft.candidate /etc/nftables.d/hy2xs.nft`; @@ -41,4 +44,6 @@ export async function applyFirewall(context: InstallContext): Promise { await runVisible`systemctl stop hy2xs-fw-rollback || true`; await runVisible`systemctl reset-failed hy2xs-fw-rollback || true`; } + + await runVisible`rm -f /etc/nftables.conf.hy2xs.bak /etc/nftables.d/hy2xs.nft.bak /etc/nftables.d/hy2xs.nft.existed /etc/nftables.d/hy2xs.nft.include.existed`; } diff --git a/orchestrator/src/steps/smoke.ts b/orchestrator/src/steps/smoke.ts index 5c5f233..038d129 100644 --- a/orchestrator/src/steps/smoke.ts +++ b/orchestrator/src/steps/smoke.ts @@ -28,7 +28,8 @@ export async function smoke(context: InstallContext): Promise { await runVisible`! ss -H -ltn | grep -q '0.0.0.0:${context.config.uiPort} '`; } await runVisible`ss -H -lun | grep -q '0.0.0.0:${context.config.hysteriaPort} '`; - await runVisible`! ss -H -ltnu | grep -q '\[::\]'`; + await runVisible`! ss -H -ltn | grep -q '\[::\]:${context.config.uiPort} '`; + await runVisible`! ss -H -lun | grep -q '\[::\]:${context.config.hysteriaPort} '`; const invalidAuthResponse = await runSecret`curl -sS --max-time 5 -X POST -H 'Content-Type: application/json' --data '{"addr":"127.0.0.1:12345","auth":"invalid","tx":"0"}' http://127.0.0.1:${context.config.uiPort}/hui/hysteria2/auth`; if (!/"ok"\s*:\s*false/.test(invalidAuthResponse)) { throw new Error(`unexpected auth response for invalid credentials: ${invalidAuthResponse}`); diff --git a/orchestrator/src/types/context.ts b/orchestrator/src/types/context.ts index 93ac4ac..594030f 100644 --- a/orchestrator/src/types/context.ts +++ b/orchestrator/src/types/context.ts @@ -43,7 +43,6 @@ export type RuntimeConfig = { hysteriaBindHost: string; hysteriaPort: number; hysteriaAuthMode: "http"; - hysteriaAuthUrl: string; hysteriaTrafficStatsHost: string; hysteriaTrafficStatsPort: number; hysteriaTrafficStatsSecret: string; diff --git a/package/config/hy2xs.env b/package/config/hy2xs.env index ac3c1c4..02acb4f 100644 --- a/package/config/hy2xs.env +++ b/package/config/hy2xs.env @@ -1,7 +1,7 @@ # HY2XS canonical production runtime config (packaged baseline) HY2XS_IPV6_ENABLED=false -HY2XS_DOMAIN=replace-with-your-domain.example -HY2XS_PUBLIC_HOST=replace-with-your-domain.example +HY2XS_DOMAIN=uk.api.withen.pro +HY2XS_PUBLIC_HOST=uk.api.withen.pro HY2XS_PUBLIC_PORT=443 HY2XS_SSH_PORT=22 HY2XS_FIREWALL_ENABLED=true @@ -15,13 +15,12 @@ HY2XS_FORCE_PASSWORD_CHANGE=false HY2XS_ALLOW_SELF_SIGNED_DEV=false HY2XS_TLS_MODE=acme HY2XS_ACME_TYPE=http -HY2XS_ACME_EMAIL=replace-with-your-email@example.com +HY2XS_ACME_EMAIL=admin@withen.pro HY2XS_TLS_CERT_PATH=/etc/hysteria/server.crt HY2XS_TLS_KEY_PATH=/etc/hysteria/server.key HY2XS_HYSTERIA_BIND_HOST=0.0.0.0 HY2XS_HYSTERIA_PORT=443 HY2XS_HYSTERIA_AUTH_MODE=http -HY2XS_HYSTERIA_AUTH_URL=http://127.0.0.1:8080/hui/hysteria2/auth HY2XS_HYSTERIA_TRAFFIC_STATS_HOST=127.0.0.1 HY2XS_HYSTERIA_TRAFFIC_STATS_PORT=36712 HY2XS_HYSTERIA_TRAFFIC_STATS_SECRET=__GENERATE__ diff --git a/package/docs/README.md b/package/docs/README.md index 1f3c2be..f9d04bf 100644 --- a/package/docs/README.md +++ b/package/docs/README.md @@ -13,7 +13,13 @@ Запускать от root: ```sh -./install.sh --non-interactive --domain example.com +./install.sh --non-interactive +``` + +С внешним source-config: + +```sh +./install.sh --config /root/custom-hy2xs.env --non-interactive ``` В baseline нет target-side JavaScript, TypeScript, frontend или Go build step. diff --git a/package/install.sh b/package/install.sh index 1033916..9684af5 100644 --- a/package/install.sh +++ b/package/install.sh @@ -5,6 +5,7 @@ PACKAGE_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" ORCHESTRATOR="$PACKAGE_DIR/orchestrator/hy2xs-orchestrator" ORCHESTRATOR_INSTALL_PATH="/usr/local/lib/hy2xs/hy2xs-orchestrator" ORCHESTRATOR_SYMLINK="/usr/local/bin/hy2xs-orchestrator" +RUNTIME_PACKAGE_DIR="/usr/local/lib/hy2xs/package" log() { printf '[hy2xs-install] %s\n' "$*" @@ -27,6 +28,15 @@ install -d -m 0755 /usr/local/lib/hy2xs install -m 0755 "$ORCHESTRATOR" "$ORCHESTRATOR_INSTALL_PATH" ln -sf "$ORCHESTRATOR_INSTALL_PATH" "$ORCHESTRATOR_SYMLINK" +log "installing runtime package assets to: $RUNTIME_PACKAGE_DIR" +rm -rf "$RUNTIME_PACKAGE_DIR" +install -d -m 0755 "$RUNTIME_PACKAGE_DIR" +cp -a "$PACKAGE_DIR/config" "$RUNTIME_PACKAGE_DIR/" +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/" + log "package directory: $PACKAGE_DIR" log "starting install-only orchestrator" -exec "$ORCHESTRATOR_INSTALL_PATH" install --package-dir "$PACKAGE_DIR" "$@" +exec "$ORCHESTRATOR_INSTALL_PATH" install --package-dir "$RUNTIME_PACKAGE_DIR" "$@"