Change host to 0.0.0.0
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
# =============================================================================
|
||||
# PenguinHarness systemd unit (for hosts with a real systemd)
|
||||
#
|
||||
# The unit delegates to scripts/penguin-service.sh in "run" (foreground) mode,
|
||||
# so node discovery, .env loading and the entry path are handled by the script
|
||||
# and only ONE path needs adjusting below: /path/to/penguin-harness
|
||||
#
|
||||
# Install:
|
||||
# sudo cp scripts/penguin-harness.service /etc/systemd/system/
|
||||
# # sửa ExecStart nếu repo không nằm ở /home/<user>/penguin-harness
|
||||
# sudo systemctl daemon-reload
|
||||
# sudo systemctl enable --now penguin-harness
|
||||
#
|
||||
# The one-time seeded admin password is printed to the journal on first start
|
||||
# with an empty data root:
|
||||
# journalctl -u penguin-harness | grep "initial password"
|
||||
# =============================================================================
|
||||
[Unit]
|
||||
Description=PenguinHarness web service (agent builder)
|
||||
Documentation=https://penguin.ooo/docs
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
# Run as the user that owns the repo and the data root (~/.penguin/data).
|
||||
User=locpham
|
||||
WorkingDirectory=/home/locpham/penguin-harness
|
||||
ExecStart=/home/locpham/penguin-harness/scripts/penguin-service.sh run
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
TimeoutStopSec=15
|
||||
# Console = journald: `journalctl -u penguin-harness -f`
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
# Hardening (safe for this service)
|
||||
NoNewPrivileges=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Executable
+171
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# PenguinHarness service script (portable)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Starts / stops / restarts the penguin-harness web server as a background
|
||||
# daemon. Works anywhere: the repo location, node binary and .env are
|
||||
# auto-detected (no hardcoded /workspace paths).
|
||||
#
|
||||
# scripts/penguin-service.sh start|stop|status|restart|run
|
||||
#
|
||||
# run = foreground mode (for systemd Type=simple, ExecStart=.../run)
|
||||
#
|
||||
# Console output (including the one-time seeded admin password) goes to:
|
||||
# ~/.penguin/penguin-service.log
|
||||
#
|
||||
# Configuration comes from .env at the repo root (HOST / PORT / PENGUIN_WEB_DIST).
|
||||
# =============================================================================
|
||||
set -u
|
||||
|
||||
# --- Self-locating paths: BASE = repo root (parent of scripts/) ---------------
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BASE="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# --- Node discovery: $PENGUIN_NODE > known nvm paths > PATH -------------------
|
||||
if [ -n "${PENGUIN_NODE:-}" ]; then
|
||||
NODE="$PENGUIN_NODE"
|
||||
elif [ -x /workspace/.nvm/versions/node/v24.18.0/bin/node ]; then
|
||||
NODE=/workspace/.nvm/versions/node/v24.18.0/bin/node
|
||||
elif [ -x "$HOME/.nvm/versions/node/v24.18.0/bin/node" ]; then
|
||||
NODE="$HOME/.nvm/versions/node/v24.18.0/bin/node"
|
||||
elif command -v node >/dev/null 2>&1; then
|
||||
NODE="$(command -v node)"
|
||||
else
|
||||
echo "Không tìm thấy node. Cài Node >= 24 hoặc đặt biến PENGUIN_NODE." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ENTRY="$BASE/packages/server/dist/index.js"
|
||||
ENVFILE="$BASE/.env"
|
||||
|
||||
PENGUIN_HOME="${PENGUIN_HOME:-$HOME/.penguin/data}"
|
||||
LOG="${PENGUIN_SERVICE_LOG:-$HOME/.penguin/penguin-service.log}"
|
||||
PIDFILE="${PENGUIN_SERVICE_PID:-$HOME/.penguin/penguin-service.pid}"
|
||||
|
||||
# --- Sanity checks ------------------------------------------------------------
|
||||
if [ ! -f "$ENTRY" ]; then
|
||||
echo "Không thấy bản build: $ENTRY" >&2
|
||||
echo "Chạy trước: cd \"$BASE\" && pnpm install && pnpm build" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$ENVFILE" ]; then
|
||||
echo "Lưu ý: không có $ENVFILE — server sẽ nghe trên HOST=127.0.0.1." >&2
|
||||
echo "Tạo .env với nội dung 'HOST=0.0.0.0' để mở mọi interface." >&2
|
||||
fi
|
||||
|
||||
# --- Load .env (HOST / PORT / PENGUIN_WEB_DIST ...) and export -----------------
|
||||
if [ -f "$ENVFILE" ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
. "$ENVFILE"
|
||||
set +a
|
||||
fi
|
||||
export PENGUIN_HOME
|
||||
|
||||
PORT="${PORT:-7364}"
|
||||
|
||||
# True only while the process is really alive: `kill -0` alone would also
|
||||
# succeed on a zombie (exited but not yet reaped). A zombie (state Z in
|
||||
# /proc/<pid>/stat) counts as dead.
|
||||
proc_alive() {
|
||||
local pid="$1"
|
||||
kill -0 "$pid" 2>/dev/null || return 1
|
||||
[ "$(awk '{print $3}' "/proc/$pid/stat" 2>/dev/null)" != "Z" ]
|
||||
}
|
||||
|
||||
is_running() {
|
||||
[ -f "$PIDFILE" ] || return 1
|
||||
local pid
|
||||
pid="$(cat "$PIDFILE" 2>/dev/null)" || return 1
|
||||
[ -n "$pid" ] && proc_alive "$pid"
|
||||
}
|
||||
|
||||
start() {
|
||||
if is_running; then
|
||||
echo "PenguinHarness đang chạy (pid $(cat "$PIDFILE"))."
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$LOG")" "$(dirname "$PIDFILE")"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] starting penguin-server (HOST=${HOST:-127.0.0.1} PORT=$PORT PENGUIN_HOME=$PENGUIN_HOME)" >>"$LOG"
|
||||
|
||||
# setsid detaches from the controlling terminal; all fds go to the log file.
|
||||
setsid "$NODE" "$ENTRY" >>"$LOG" 2>&1 </dev/null &
|
||||
echo $! >"$PIDFILE"
|
||||
|
||||
# Wait for readiness (up to 30s) — any HTTP answer counts.
|
||||
local i
|
||||
for i in $(seq 1 30); do
|
||||
if curl -s -o /dev/null --max-time 2 "http://127.0.0.1:$PORT/"; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if is_running; then
|
||||
echo "PenguinHarness đã khởi động: http://0.0.0.0:$PORT (pid $(cat "$PIDFILE"))"
|
||||
echo "Log (console): $LOG"
|
||||
# In mật khẩu admin khởi tạo ra console nếu có (chỉ in 1 lần khi seed).
|
||||
grep -h "initial password" "$LOG" 2>/dev/null | tail -1
|
||||
else
|
||||
echo "Khởi động THẤT BẠI — xem log: $LOG" >&2
|
||||
tail -20 "$LOG" >&2
|
||||
rm -f "$PIDFILE"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
if ! is_running; then
|
||||
echo "PenguinHarness không đang chạy."
|
||||
rm -f "$PIDFILE"
|
||||
return 0
|
||||
fi
|
||||
local pid
|
||||
pid="$(cat "$PIDFILE")"
|
||||
echo "Đang dừng penguin-server (pid $pid)..."
|
||||
kill -TERM "$pid" 2>/dev/null
|
||||
local i
|
||||
for i in $(seq 1 10); do
|
||||
proc_alive "$pid" || break
|
||||
sleep 1
|
||||
done
|
||||
if proc_alive "$pid"; then
|
||||
echo "Không dừng được trong 10s, buộc dừng (SIGKILL)." >&2
|
||||
kill -KILL "$pid" 2>/dev/null
|
||||
fi
|
||||
# Reap any zombie so it cannot linger in the process table.
|
||||
wait "$pid" 2>/dev/null
|
||||
rm -f "$PIDFILE"
|
||||
echo "Đã dừng."
|
||||
}
|
||||
|
||||
status() {
|
||||
if is_running; then
|
||||
echo "PenguinHarness: ĐANG CHẠY (pid $(cat "$PIDFILE"))"
|
||||
echo " URL: http://0.0.0.0:$PORT"
|
||||
echo " Log: $LOG"
|
||||
if grep -h "initial password" "$LOG" 2>/dev/null | tail -1 | grep -q .; then
|
||||
echo " Admin khởi tạo: $(grep -h 'initial password' "$LOG" | tail -1)"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
echo "PenguinHarness: KHÔNG chạy."
|
||||
return 1
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
start) start ;;
|
||||
stop) stop ;;
|
||||
restart) stop; start ;;
|
||||
status) status ;;
|
||||
run)
|
||||
# Foreground mode for systemd (Type=simple): exec replaces the shell so
|
||||
# systemd tracks the real server process and Restart= works.
|
||||
exec "$NODE" "$ENTRY"
|
||||
;;
|
||||
*)
|
||||
echo "Sử dụng: $0 {start|stop|status|restart|run}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user