Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a00bd620a1 |
@@ -1,3 +1,7 @@
|
||||
# REFERENCE ONLY — install.sh GENERATES the real unit at install time,
|
||||
# substituting the actual PANEL_DIR/ports/user (see write_unit in install.sh).
|
||||
# This static copy assumes the /opt/panel defaults; edit it by hand if you wire
|
||||
# the units up yourself (e.g. via compose) instead of running install.sh.
|
||||
[Unit]
|
||||
Description=Panel agent (Docker runtime for game-server instances)
|
||||
Documentation=https://github.com/dbledeez/panel
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# REFERENCE ONLY — install.sh GENERATES the real unit at install time,
|
||||
# substituting the actual PANEL_DIR/ports/user (see write_unit in install.sh).
|
||||
# This static copy assumes the /opt/panel defaults; edit it by hand if you wire
|
||||
# the units up yourself (e.g. via compose) instead of running install.sh.
|
||||
[Unit]
|
||||
Description=Panel controller (HTTP dashboard :8080 + agent gRPC :8443)
|
||||
Documentation=https://github.com/dbledeez/panel
|
||||
|
||||
+2
-3
@@ -11,8 +11,6 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
@@ -21,7 +19,8 @@ golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeId
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||
google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 h1:GvESR9BIyHUahIb0NcTum6itIWtdoglGX+rnGxm2934=
|
||||
|
||||
+23
-7
@@ -18,7 +18,10 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$RepoUrl = $(if ($env:PANEL_REPO_URL) { $env:PANEL_REPO_URL } else { 'https://git.pdxtechs.com/dbledeez/panel' }),
|
||||
[string]$PrebuiltUrl = $env:PANEL_PREBUILT_URL,
|
||||
# Defaults to the published v0.9.0 windows/amd64 prebuilt zip so the installer
|
||||
# needs no Go toolchain. Pass -PrebuiltUrl '' (empty) to force a source build.
|
||||
# A local checkout (running install.ps1 from inside the repo) wins over this.
|
||||
[string]$PrebuiltUrl = $(if ($null -ne $env:PANEL_PREBUILT_URL) { $env:PANEL_PREBUILT_URL } else { 'https://git.pdxtechs.com/dbledeez/panel/releases/download/v0.9.0/panel-v0.9.0-windows-amd64.zip' }),
|
||||
[string]$Version = $env:PANEL_VERSION,
|
||||
[string]$InstallDir = $(if ($env:PANEL_DIR) { $env:PANEL_DIR } else { 'C:\Panel' }),
|
||||
[int] $HttpPort = $(if ($env:PANEL_HTTP_PORT) { [int]$env:PANEL_HTTP_PORT } else { 8080 }),
|
||||
@@ -26,10 +29,15 @@ param(
|
||||
[string]$AdminPassword = $env:PANEL_ADMIN_PASSWORD,
|
||||
[string]$DbUrl = $env:PANEL_DB_URL,
|
||||
[string]$DbPassword = $env:PANEL_DB_PASSWORD,
|
||||
[string]$DbContainer = $(if ($env:PANEL_DB_CONTAINER) { $env:PANEL_DB_CONTAINER } else { 'panel-postgres' }),
|
||||
[int] $DbPort = $(if ($env:PANEL_DB_PORT) { [int]$env:PANEL_DB_PORT } else { 5432 }),
|
||||
[string]$DbVolume = $(if ($env:PANEL_DB_VOLUME) { $env:PANEL_DB_VOLUME } else { 'panel_pgdata' }),
|
||||
[switch]$SkipAgent
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$PgContainer = 'panel-postgres'
|
||||
# Run two independent panels on one host by giving each install distinct
|
||||
# -InstallDir, -HttpPort, -GrpcPort, -DbContainer, -DbPort and -DbVolume.
|
||||
$PgContainer = $DbContainer
|
||||
|
||||
function Log($msg) { Write-Host "[panel] $msg" -ForegroundColor Green }
|
||||
function Warn($msg) { Write-Host "[panel] $msg" -ForegroundColor Yellow }
|
||||
@@ -65,15 +73,15 @@ if ($DbUrl) {
|
||||
if (-not $DbPassword) {
|
||||
$DbPassword = -join ((1..32) | ForEach-Object { '{0:x}' -f (Get-Random -Maximum 16) })
|
||||
}
|
||||
Log "starting postgres container '$PgContainer'"
|
||||
Log "starting postgres container '$PgContainer' on 127.0.0.1:$DbPort (volume $DbVolume)"
|
||||
docker run -d --name $PgContainer --restart unless-stopped `
|
||||
-e POSTGRES_USER=panel -e "POSTGRES_PASSWORD=$DbPassword" -e POSTGRES_DB=panel `
|
||||
-p 127.0.0.1:5432:5432 `
|
||||
-v panel_pgdata:/var/lib/postgresql/data `
|
||||
-p "127.0.0.1:${DbPort}:5432" `
|
||||
-v "${DbVolume}:/var/lib/postgresql/data" `
|
||||
postgres:17-alpine | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { Fail "docker run for postgres failed" }
|
||||
}
|
||||
$DbUrl = "postgres://panel:$DbPassword@127.0.0.1:5432/panel?sslmode=disable"
|
||||
$DbUrl = "postgres://panel:$DbPassword@127.0.0.1:$DbPort/panel?sslmode=disable"
|
||||
Log "waiting for postgres"
|
||||
$ready = $false
|
||||
foreach ($i in 1..30) {
|
||||
@@ -90,6 +98,13 @@ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
if ($ScriptDir -and (Test-Path (Join-Path $ScriptDir 'go.work')) -and (Test-Path (Join-Path $ScriptDir 'controller'))) {
|
||||
$Src = $ScriptDir
|
||||
Log "using local checkout at $Src"
|
||||
# Running from inside the repo means build THIS tree. Don't let the prebuilt
|
||||
# default override it. An explicit -PrebuiltUrl or $env:PANEL_PREBUILT_URL still
|
||||
# forces prebuilt (it won't equal the untouched default / the env is non-null).
|
||||
$prebuiltDefault = 'https://git.pdxtechs.com/dbledeez/panel/releases/download/v0.9.0/panel-v0.9.0-windows-amd64.zip'
|
||||
if (($null -eq $env:PANEL_PREBUILT_URL) -and ($PrebuiltUrl -eq $prebuiltDefault)) {
|
||||
$PrebuiltUrl = ''
|
||||
}
|
||||
}
|
||||
|
||||
if ($PrebuiltUrl) {
|
||||
@@ -167,7 +182,8 @@ foreach ($i in 1..60) {
|
||||
if (-not $up) { Fail "controller did not come up - see $ctrlLog" }
|
||||
|
||||
$adminEmail = 'admin@panel.local'
|
||||
$adminShown = '(set via -AdminPassword)'
|
||||
# BUG-5b: always give the operator a path to the password.
|
||||
$adminShown = "(the one you set via -AdminPassword; also in $EnvFile)"
|
||||
if (-not $AdminPassword) {
|
||||
if ($firstBoot) {
|
||||
$m = Select-String -Path $ctrlLog -Pattern 'password: ([a-f0-9]{16})' | Select-Object -First 1
|
||||
|
||||
+156
-18
@@ -6,6 +6,8 @@
|
||||
# Non-interactive knobs (env vars, all optional):
|
||||
# PANEL_REPO_URL git/https base of the panel source (default: placeholder, see below)
|
||||
# PANEL_PREBUILT_URL tarball with prebuilt bin/{controller,agent,panelctl} + modules/ (skips Go build)
|
||||
# (default: the published v0.9.0 linux/amd64 release — so
|
||||
# curl|bash needs no Go. Set it EMPTY to force a source build.)
|
||||
# PANEL_VERSION version string baked into the binaries (default: git describe || dev)
|
||||
# PANEL_DIR install prefix (default: /opt/panel)
|
||||
# PANEL_DATA_DIR data directory (default: $PANEL_DIR/data)
|
||||
@@ -13,15 +15,30 @@
|
||||
# PANEL_GRPC_PORT agent gRPC port (default: 8443)
|
||||
# PANEL_ADMIN_PASSWORD stable first-boot admin password (default: generated by the controller)
|
||||
# PANEL_DB_URL use an EXISTING Postgres instead of the managed container
|
||||
# PANEL_DB_PASSWORD password for the managed panel-postgres container (default: generated)
|
||||
# PANEL_DB_PASSWORD password for the managed Postgres container (default: generated)
|
||||
# PANEL_DB_CONTAINER name of the managed Postgres container (default: panel-postgres)
|
||||
# PANEL_DB_PORT host port to bind Postgres on (127.0.0.1) (default: 5432)
|
||||
# PANEL_DB_VOLUME docker volume for Postgres data (default: panel_pgdata)
|
||||
# PANEL_SKIP_AGENT=1 install controller only (add agents on other boxes later)
|
||||
#
|
||||
# Run TWO independent panels on one host by giving each install distinct
|
||||
# PANEL_DIR, PANEL_HTTP_PORT, PANEL_GRPC_PORT, PANEL_DB_CONTAINER,
|
||||
# PANEL_DB_PORT and PANEL_DB_VOLUME values so nothing collides.
|
||||
#
|
||||
# Idempotent: safe to re-run — existing containers, units, CA, DB and
|
||||
# passwords are kept; binaries and modules are refreshed.
|
||||
set -euo pipefail
|
||||
|
||||
PANEL_REPO_URL="${PANEL_REPO_URL:-https://git.pdxtechs.com/dbledeez/panel}"
|
||||
PANEL_PREBUILT_URL="${PANEL_PREBUILT_URL:-}"
|
||||
# Default to the published prebuilt release so `curl … | sudo bash` works with no
|
||||
# Go toolchain and no env. Explicitly set PANEL_PREBUILT_URL= (empty) to force the
|
||||
# git-clone + Go source-build fallback instead. A local checkout (running
|
||||
# ./install.sh from inside the repo) always wins over this default — see §4.
|
||||
PANEL_PREBUILT_DEFAULT="https://git.pdxtechs.com/dbledeez/panel/releases/download/v0.9.0/panel-v0.9.0-linux-amd64.tar.gz"
|
||||
# Was the var set in the environment at all (even to empty)? Distinguishes an
|
||||
# operator who explicitly wants prebuilt from the plain default.
|
||||
if [ "${PANEL_PREBUILT_URL+set}" = set ]; then PANEL_PREBUILT_URL_EXPLICIT=1; else PANEL_PREBUILT_URL_EXPLICIT=""; fi
|
||||
PANEL_PREBUILT_URL="${PANEL_PREBUILT_URL-$PANEL_PREBUILT_DEFAULT}"
|
||||
PANEL_DIR="${PANEL_DIR:-/opt/panel}"
|
||||
PANEL_DATA_DIR="${PANEL_DATA_DIR:-$PANEL_DIR/data}"
|
||||
PANEL_HTTP_PORT="${PANEL_HTTP_PORT:-8080}"
|
||||
@@ -29,9 +46,19 @@ PANEL_GRPC_PORT="${PANEL_GRPC_PORT:-8443}"
|
||||
PANEL_ADMIN_PASSWORD="${PANEL_ADMIN_PASSWORD:-}"
|
||||
PANEL_DB_URL="${PANEL_DB_URL:-}"
|
||||
PANEL_DB_PASSWORD="${PANEL_DB_PASSWORD:-}"
|
||||
PANEL_DB_CONTAINER="${PANEL_DB_CONTAINER:-panel-postgres}"
|
||||
PANEL_DB_PORT="${PANEL_DB_PORT:-5432}"
|
||||
PANEL_DB_VOLUME="${PANEL_DB_VOLUME:-panel_pgdata}"
|
||||
PANEL_SKIP_AGENT="${PANEL_SKIP_AGENT:-0}"
|
||||
PANEL_USER=panel
|
||||
PG_CONTAINER=panel-postgres
|
||||
PG_CONTAINER="$PANEL_DB_CONTAINER"
|
||||
|
||||
# Legacy escape hatch (kept for compatibility): a release asset tried only when
|
||||
# no prebuilt URL, no local checkout and no Go are available. Now that
|
||||
# PANEL_PREBUILT_URL defaults to the published release above, this is rarely hit —
|
||||
# it only matters if someone explicitly emptied PANEL_PREBUILT_URL but still has
|
||||
# no Go and no checkout.
|
||||
PANEL_RELEASE_TARBALL_URL="${PANEL_RELEASE_TARBALL_URL:-$PANEL_PREBUILT_DEFAULT}"
|
||||
|
||||
log() { printf '\033[1;32m[panel]\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m[panel]\033[0m %s\n' "$*" >&2; }
|
||||
@@ -86,14 +113,14 @@ else
|
||||
if [ -z "$PANEL_DB_PASSWORD" ]; then
|
||||
PANEL_DB_PASSWORD="$(head -c 24 /dev/urandom | od -An -tx1 | tr -d ' \n')"
|
||||
fi
|
||||
log "starting postgres container '$PG_CONTAINER'"
|
||||
log "starting postgres container '$PG_CONTAINER' on 127.0.0.1:$PANEL_DB_PORT (volume $PANEL_DB_VOLUME)"
|
||||
docker run -d --name "$PG_CONTAINER" --restart unless-stopped \
|
||||
-e POSTGRES_USER=panel -e POSTGRES_PASSWORD="$PANEL_DB_PASSWORD" -e POSTGRES_DB=panel \
|
||||
-p 127.0.0.1:5432:5432 \
|
||||
-v panel_pgdata:/var/lib/postgresql/data \
|
||||
-p "127.0.0.1:$PANEL_DB_PORT:5432" \
|
||||
-v "$PANEL_DB_VOLUME:/var/lib/postgresql/data" \
|
||||
postgres:17-alpine >/dev/null
|
||||
fi
|
||||
PANEL_DB_URL="postgres://panel:${PANEL_DB_PASSWORD}@127.0.0.1:5432/panel?sslmode=disable"
|
||||
PANEL_DB_URL="postgres://panel:${PANEL_DB_PASSWORD}@127.0.0.1:$PANEL_DB_PORT/panel?sslmode=disable"
|
||||
log "waiting for postgres to accept connections"
|
||||
for _ in $(seq 1 30); do
|
||||
if docker exec "$PG_CONTAINER" pg_isready -U panel -d panel >/dev/null 2>&1; then break; fi
|
||||
@@ -108,6 +135,20 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" >/dev/null 2>&1 && pwd ||
|
||||
if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/go.work" ] && [ -d "$SCRIPT_DIR/controller" ]; then
|
||||
SRC="$SCRIPT_DIR"
|
||||
log "using local checkout at $SRC"
|
||||
# A local checkout means the operator wants to build THIS tree. Don't silently
|
||||
# override it with the prebuilt release default. (An explicit PANEL_PREBUILT_URL
|
||||
# env still forces prebuilt — it survives because it was exported, not defaulted.)
|
||||
if [ -z "${PANEL_PREBUILT_URL_EXPLICIT:-}" ] && [ "$PANEL_PREBUILT_URL" = "$PANEL_PREBUILT_DEFAULT" ]; then
|
||||
PANEL_PREBUILT_URL=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# If no prebuilt URL, no local checkout and no Go, but a release tarball URL is
|
||||
# known, auto-fall-back to the published release so the one-liner still works.
|
||||
if [ -z "$PANEL_PREBUILT_URL" ] && [ -z "$SRC" ] \
|
||||
&& ! command -v go >/dev/null 2>&1 && [ -n "$PANEL_RELEASE_TARBALL_URL" ]; then
|
||||
log "no Go toolchain — falling back to the published release tarball"
|
||||
PANEL_PREBUILT_URL="$PANEL_RELEASE_TARBALL_URL"
|
||||
fi
|
||||
|
||||
if [ -n "$PANEL_PREBUILT_URL" ]; then
|
||||
@@ -121,6 +162,10 @@ else
|
||||
if [ -z "$SRC" ]; then
|
||||
command -v git >/dev/null || die "git is required to fetch sources (or set PANEL_PREBUILT_URL)"
|
||||
SRC="$PANEL_DIR/src"
|
||||
# BUG-4: the src tree is cloned as root then chowned to $PANEL_USER; on a
|
||||
# re-run git would refuse with "detected dubious ownership". Mark it safe
|
||||
# for whatever user runs git (root here) so re-runs are idempotent.
|
||||
git config --global --add safe.directory "$SRC" 2>/dev/null || true
|
||||
if [ -d "$SRC/.git" ]; then
|
||||
log "updating source checkout at $SRC"
|
||||
git -C "$SRC" pull --ff-only
|
||||
@@ -129,7 +174,12 @@ else
|
||||
git clone --depth 1 "$PANEL_REPO_URL" "$SRC"
|
||||
fi
|
||||
fi
|
||||
command -v go >/dev/null || die "Go toolchain not found. Install Go >= 1.26 (https://go.dev/dl/) or set PANEL_PREBUILT_URL."
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
die "Go toolchain not found. The one-line installer normally uses prebuilt
|
||||
binaries; falling back to a source build requires Go >= 1.26 (https://go.dev/dl/).
|
||||
Alternatively set PANEL_PREBUILT_URL to a prebuilt tarball, or
|
||||
PANEL_RELEASE_TARBALL_URL to a published release asset."
|
||||
fi
|
||||
VERSION="${PANEL_VERSION:-$(git -C "$SRC" describe --tags --always --dirty 2>/dev/null || echo dev)}"
|
||||
LDFLAGS="-s -w -X github.com/dbledeez/panel/pkg/version.Version=$VERSION"
|
||||
log "building panel $VERSION"
|
||||
@@ -162,15 +212,101 @@ umask 022
|
||||
chown -R "$PANEL_USER:$PANEL_USER" "$PANEL_DIR"
|
||||
chmod 600 "$ENV_FILE"
|
||||
|
||||
if [ -n "$SRC" ] && [ -d "$SRC/deploy/systemd" ]; then
|
||||
install -m 0644 "$SRC/deploy/systemd/panel-controller.service" \
|
||||
"$SRC/deploy/systemd/panel-agent.service" /etc/systemd/system/
|
||||
else
|
||||
# Prebuilt path: units are expected inside the tarball at deploy/systemd.
|
||||
[ -f "$PANEL_DIR/deploy/systemd/panel-controller.service" ] || die "no systemd units found (deploy/systemd missing)"
|
||||
install -m 0644 "$PANEL_DIR/deploy/systemd/panel-controller.service" \
|
||||
"$PANEL_DIR/deploy/systemd/panel-agent.service" /etc/systemd/system/
|
||||
fi
|
||||
# BUG-2/3/5: do NOT install deploy/systemd/*.service verbatim — those hardcode
|
||||
# /opt/panel, ProtectHome=true and stale :8080/:8443 in the Description. Instead
|
||||
# GENERATE both units here, substituting the REAL install parameters.
|
||||
#
|
||||
# BUG-3: systemd ProtectHome=true makes any binary under /home unreadable to the
|
||||
# service (203/EXEC). When PANEL_DIR is under /home we emit the unit WITHOUT
|
||||
# ProtectHome so it actually runs (reduced hardening, noted inline). The default
|
||||
# /opt/panel keeps ProtectHome=true.
|
||||
case "$PANEL_DIR/" in
|
||||
/home/*) PROTECT_HOME=""; log "PANEL_DIR is under /home — generating units without ProtectHome (reduced hardening)";;
|
||||
*) PROTECT_HOME="ProtectHome=true";;
|
||||
esac
|
||||
|
||||
write_unit() {
|
||||
# $1 = destination path
|
||||
cat > "$1"
|
||||
chmod 0644 "$1"
|
||||
}
|
||||
|
||||
write_unit /etc/systemd/system/panel-controller.service <<EOF
|
||||
[Unit]
|
||||
Description=Panel controller (HTTP dashboard :${PANEL_HTTP_PORT} + agent gRPC :${PANEL_GRPC_PORT})
|
||||
Documentation=https://github.com/dbledeez/panel
|
||||
After=network-online.target docker.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=${PANEL_USER}
|
||||
Group=${PANEL_USER}
|
||||
WorkingDirectory=${PANEL_DIR}
|
||||
Environment=PANEL_HTTP_PORT=${PANEL_HTTP_PORT}
|
||||
Environment=PANEL_GRPC_PORT=${PANEL_GRPC_PORT}
|
||||
EnvironmentFile=-${ENV_FILE}
|
||||
ExecStart=${PANEL_DIR}/bin/controller \\
|
||||
-http :\${PANEL_HTTP_PORT} \\
|
||||
-grpc :\${PANEL_GRPC_PORT} \\
|
||||
-ca-dir ./data/ca
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
# Hardening — the controller only needs its own tree + the network.
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
${PROTECT_HOME}
|
||||
ReadWritePaths=${PANEL_DIR}
|
||||
PrivateTmp=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictSUIDSGID=true
|
||||
LockPersonality=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
write_unit /etc/systemd/system/panel-agent.service <<EOF
|
||||
[Unit]
|
||||
Description=Panel agent (Docker runtime for game-server instances)
|
||||
Documentation=https://github.com/dbledeez/panel
|
||||
After=network-online.target docker.service panel-controller.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=${PANEL_USER}
|
||||
Group=${PANEL_USER}
|
||||
SupplementaryGroups=docker
|
||||
WorkingDirectory=${PANEL_DIR}
|
||||
Environment=PANEL_GRPC_PORT=${PANEL_GRPC_PORT}
|
||||
EnvironmentFile=-${ENV_FILE}
|
||||
ExecStart=${PANEL_DIR}/bin/agent \\
|
||||
--controller localhost:\${PANEL_GRPC_PORT} \\
|
||||
--modules-dir ./modules \\
|
||||
--data-root ./data/instances \\
|
||||
--meta-dir ./data/instance-meta \\
|
||||
--backup-dir ./data/backups \\
|
||||
--cert-dir ./data/certs
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
# Hardening is intentionally lighter than the controller's: the agent manages
|
||||
# Docker containers and bind-mounts instance data.
|
||||
NoNewPrivileges=true
|
||||
${PROTECT_HOME}
|
||||
ReadWritePaths=${PANEL_DIR}
|
||||
PrivateTmp=true
|
||||
LockPersonality=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
# ---- 6. Controller first boot (CA + admin bootstrap) ----------------------
|
||||
@@ -192,7 +328,9 @@ done
|
||||
curl -fsS "http://127.0.0.1:$PANEL_HTTP_PORT/login" >/dev/null 2>&1 || die "controller did not come up — check: journalctl -u panel-controller"
|
||||
|
||||
ADMIN_EMAIL="admin@panel.local"
|
||||
ADMIN_PW_SHOWN="(set via PANEL_ADMIN_PASSWORD)"
|
||||
# BUG-5b: always give the operator a path to the password. If they supplied one,
|
||||
# say so and point at the env file; otherwise scrape the generated one below.
|
||||
ADMIN_PW_SHOWN="(the one you set via PANEL_ADMIN_PASSWORD; also in $ENV_FILE)"
|
||||
if [ -z "$PANEL_ADMIN_PASSWORD" ]; then
|
||||
if [ "$FIRST_BOOT" = 1 ]; then
|
||||
# The controller prints the generated password once in its log.
|
||||
|
||||
Reference in New Issue
Block a user