Add an opt-in insecure-TLS mode for the agent, for self-signed certs
Installing the agent against a Homelab Manager instance with a self-signed cert failed: curl verifies TLS by default on the install download, the report-tasks.sh fetch inside install.sh, and every periodic check-in — not just the outer one-liner, so passing -k to only that first curl wasn't enough. Mirrors the existing Proxmox/Synology "insecure" toggle pattern already in this app. - install.sh and report-tasks.sh accept API_INSECURE=true, adding -k to their own curl calls; install.sh persists it into the agent's env file so the periodic systemd timer picks it up too. - The Servers & Tasks page has a new checkbox next to the generated install/uninstall commands that adds -k and API_INSECURE=true for you, so the outer one-liner (which install.sh's own logic can't touch) also skips verification. Off by default — only for a trusted LAN. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f5d3c25c89
commit
130212baec
3 files changed
+56
-11
No files matched your search
+21
-2
@@ -6,16 +6,30 @@
|
||||
# curl -fsSL https://homelab.example.lan/agent/linux/install.sh | \
|
||||
# sudo API_URL=https://homelab.example.lan API_TOKEN=hlm_xxx bash
|
||||
#
|
||||
# If Homelab Manager is served with a self-signed certificate, also pass
|
||||
# API_INSECURE=true (skips TLS verification for every request this agent
|
||||
# makes — only do this on a trusted LAN) AND add -k to the outer curl
|
||||
# above, since that first fetch of this very script also hits the
|
||||
# self-signed endpoint before any of this script's logic can run:
|
||||
# curl -fsSL -k https://homelab.example.lan/agent/linux/install.sh | \
|
||||
# sudo API_URL=https://homelab.example.lan API_TOKEN=hlm_xxx API_INSECURE=true bash
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
: "${API_URL:?Set API_URL to your Homelab Manager URL, e.g. https://homelab.example.lan}"
|
||||
: "${API_TOKEN:?Set API_TOKEN to the per-server token generated on the Servers & Tasks page}"
|
||||
API_INSECURE="${API_INSECURE:-false}"
|
||||
|
||||
INSTALL_DIR="/usr/local/bin"
|
||||
CONFIG_DIR="/etc"
|
||||
SYSTEMD_DIR="/etc/systemd/system"
|
||||
INTERVAL_MINUTES="${INTERVAL_MINUTES:-15}"
|
||||
|
||||
CURL_INSECURE_FLAG=()
|
||||
case "${API_INSECURE,,}" in
|
||||
1|true|yes) CURL_INSECURE_FLAG=(-k) ;;
|
||||
esac
|
||||
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
echo "This installer must be run as root (it installs a systemd timer)." >&2
|
||||
echo "If you're piping from curl, put sudo right after the pipe so it elevates bash, not curl:" >&2
|
||||
@@ -55,13 +69,14 @@ fi
|
||||
|
||||
echo "Installing Homelab Manager agent from $API_URL ..."
|
||||
|
||||
curl -fsSL "$API_URL/agent/linux/report-tasks.sh" -o "$INSTALL_DIR/homelab-manager-agent.sh"
|
||||
curl -fsSL "${CURL_INSECURE_FLAG[@]}" "$API_URL/agent/linux/report-tasks.sh" -o "$INSTALL_DIR/homelab-manager-agent.sh"
|
||||
chmod 755 "$INSTALL_DIR/homelab-manager-agent.sh"
|
||||
|
||||
umask 077
|
||||
cat > "$CONFIG_DIR/homelab-manager-agent.env" <<EOF
|
||||
API_URL=$API_URL
|
||||
API_TOKEN=$API_TOKEN
|
||||
API_INSECURE=$API_INSECURE
|
||||
EOF
|
||||
chmod 600 "$CONFIG_DIR/homelab-manager-agent.env"
|
||||
|
||||
@@ -95,4 +110,8 @@ echo "Installed. Running an initial report now..."
|
||||
"$INSTALL_DIR/homelab-manager-agent.sh"
|
||||
|
||||
echo "Done. The agent reports every ${INTERVAL_MINUTES} minute(s) via the 'homelab-manager-agent.timer' systemd timer."
|
||||
echo "To remove it later: curl -fsSL $API_URL/agent/linux/uninstall.sh | sudo bash"
|
||||
if [[ ${#CURL_INSECURE_FLAG[@]} -gt 0 ]]; then
|
||||
echo "To remove it later: curl -fsSL -k $API_URL/agent/linux/uninstall.sh | sudo bash"
|
||||
else
|
||||
echo "To remove it later: curl -fsSL $API_URL/agent/linux/uninstall.sh | sudo bash"
|
||||
fi
|
||||
@@ -5,6 +5,9 @@
|
||||
#
|
||||
# API_URL=https://homelab.example.lan API_TOKEN=hlm_xxx ./report-tasks.sh --dry-run
|
||||
#
|
||||
# Set API_INSECURE=true (also written to the env file by install.sh when
|
||||
# passed there) if Homelab Manager uses a self-signed certificate.
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
ENV_FILE="${ENV_FILE:-/etc/homelab-manager-agent.env}"
|
||||
@@ -15,6 +18,7 @@ fi
|
||||
|
||||
API_URL="${API_URL:-}"
|
||||
API_TOKEN="${API_TOKEN:-}"
|
||||
API_INSECURE="${API_INSECURE:-false}"
|
||||
DRY_RUN=0
|
||||
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=1
|
||||
|
||||
@@ -23,6 +27,11 @@ if [[ -z "$API_URL" || -z "$API_TOKEN" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURL_INSECURE_FLAG=()
|
||||
case "${API_INSECURE,,}" in
|
||||
1|true|yes) CURL_INSECURE_FLAG=(-k) ;;
|
||||
esac
|
||||
|
||||
suggest_package_install() {
|
||||
local pkg="$1"
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
@@ -240,7 +249,7 @@ if [[ "$DRY_RUN" == "1" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
response=$(curl -sS -o /tmp/hlm-agent-response.json -w "%{http_code}" \
|
||||
response=$(curl -sS "${CURL_INSECURE_FLAG[@]}" -o /tmp/hlm-agent-response.json -w "%{http_code}" \
|
||||
-X POST "$API_URL/api/agent/report" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
|
||||
@@ -22,12 +22,17 @@ const SCHEDULE_TYPE_OPTIONS: { value: ScheduleType; label: string }[] = [
|
||||
{ value: "manual", label: "Other / manual" },
|
||||
];
|
||||
|
||||
function installCommand(token: string): string {
|
||||
return `curl -fsSL ${window.location.origin}/agent/linux/install.sh | sudo API_URL=${window.location.origin} API_TOKEN=${token} bash`;
|
||||
function installCommand(token: string, insecure: boolean): string {
|
||||
const curlFlags = insecure ? "-fsSL -k" : "-fsSL";
|
||||
const envVars = insecure
|
||||
? `API_URL=${window.location.origin} API_TOKEN=${token} API_INSECURE=true`
|
||||
: `API_URL=${window.location.origin} API_TOKEN=${token}`;
|
||||
return `curl ${curlFlags} ${window.location.origin}/agent/linux/install.sh | sudo ${envVars} bash`;
|
||||
}
|
||||
|
||||
function uninstallCommand(): string {
|
||||
return `curl -fsSL ${window.location.origin}/agent/linux/uninstall.sh | sudo bash`;
|
||||
function uninstallCommand(insecure: boolean): string {
|
||||
const curlFlags = insecure ? "-fsSL -k" : "-fsSL";
|
||||
return `curl ${curlFlags} ${window.location.origin}/agent/linux/uninstall.sh | sudo bash`;
|
||||
}
|
||||
|
||||
const emptyTaskForm = {
|
||||
@@ -64,6 +69,7 @@ export default function ServersTasks({ user }: { user: CurrentUser }) {
|
||||
const [serverDescription, setServerDescription] = useState("");
|
||||
const [newToken, setNewToken] = useState<{ server: ServerRecord; token: string } | null>(null);
|
||||
const [uninstallFor, setUninstallFor] = useState<ServerRecord | null>(null);
|
||||
const [insecureAgent, setInsecureAgent] = useState(false);
|
||||
|
||||
const loadServers = useCallback(() => {
|
||||
return api.servers
|
||||
@@ -266,12 +272,23 @@ export default function ServersTasks({ user }: { user: CurrentUser }) {
|
||||
<code className="form-control">{newToken.token}</code>
|
||||
<CopyButton text={newToken.token} />
|
||||
</div>
|
||||
<label className="form-check mb-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
checked={insecureAgent}
|
||||
onChange={(e) => setInsecureAgent(e.target.checked)}
|
||||
/>
|
||||
<span className="form-check-label">
|
||||
This Homelab Manager instance uses a self-signed certificate (skip TLS verification on the agent)
|
||||
</span>
|
||||
</label>
|
||||
<p className="text-secondary">
|
||||
Install the agent on the server (run as root — put sudo right after the pipe, not before curl):
|
||||
</p>
|
||||
<div className="input-group">
|
||||
<pre className="form-control text-wrap mb-0">{installCommand(newToken.token)}</pre>
|
||||
<CopyButton text={installCommand(newToken.token)} />
|
||||
<pre className="form-control text-wrap mb-0">{installCommand(newToken.token, insecureAgent)}</pre>
|
||||
<CopyButton text={installCommand(newToken.token, insecureAgent)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-footer">
|
||||
@@ -290,8 +307,8 @@ export default function ServersTasks({ user }: { user: CurrentUser }) {
|
||||
<div className="card-body">
|
||||
<p className="text-secondary">Run this on the server as root to stop and remove the agent (its entry here is kept):</p>
|
||||
<div className="input-group">
|
||||
<pre className="form-control text-wrap mb-0">{uninstallCommand()}</pre>
|
||||
<CopyButton text={uninstallCommand()} />
|
||||
<pre className="form-control text-wrap mb-0">{uninstallCommand(insecureAgent)}</pre>
|
||||
<CopyButton text={uninstallCommand(insecureAgent)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-footer">
|
||||
|
||||
Reference in new issue
Block a user