Init
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# Telemt Panel + Traefik (production).
|
||||
# Docs: docs/install.md
|
||||
#
|
||||
# On server:
|
||||
# mkdir -p /opt/telemt-panel/data
|
||||
# cp deploy/docker-compose.traefik.yml /opt/telemt-panel/docker-compose.yml
|
||||
# cp deploy/env.traefik.example /opt/telemt-panel/.env
|
||||
# docker login git.shts.su
|
||||
# cd /opt/telemt-panel && docker compose pull && docker compose up -d
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:${TRAEFIK_IMAGE_TAG:-v3.7}
|
||||
container_name: telemt-panel-traefik
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
ports:
|
||||
- "${TRAEFIK_HTTP_PORT:-80}:80"
|
||||
- "${TRAEFIK_HTTPS_PORT:-443}:443"
|
||||
environment:
|
||||
CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN:?set CF_DNS_API_TOKEN in .env}
|
||||
command:
|
||||
- --log.level=${TRAEFIK_LOG_LEVEL:-INFO}
|
||||
- --api.dashboard=false
|
||||
- --providers.docker=true
|
||||
- --providers.docker.exposedbydefault=false
|
||||
- --providers.docker.network=telemt-panel
|
||||
- --entrypoints.web.address=:80
|
||||
- --entrypoints.websecure.address=:443
|
||||
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
||||
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
||||
- --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL:?set LETSENCRYPT_EMAIL in .env}
|
||||
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
|
||||
- --certificatesresolvers.letsencrypt.acme.dnschallenge=true
|
||||
- --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
|
||||
- --certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=15
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- traefik_letsencrypt:/letsencrypt
|
||||
networks:
|
||||
- telemt-panel
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
app:
|
||||
image: git.shts.su/denozord/telemtPanel:${PANEL_IMAGE_TAG:-latest}
|
||||
pull_policy: always
|
||||
container_name: telemt-panel
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- traefik
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
DATABASE_URL: sqlite:/data/app.db
|
||||
STATIC_DIR: /app/static
|
||||
NODE_ENV: production
|
||||
SERVER_PORT: 8080
|
||||
PANEL_MODE: ${PANEL_MODE:-fleet}
|
||||
JWT_SECRET: ${JWT_SECRET:?set JWT_SECRET in .env}
|
||||
PANEL_ENCRYPTION_KEY: ${PANEL_ENCRYPTION_KEY:?set PANEL_ENCRYPTION_KEY in .env}
|
||||
PANEL_PUBLIC_URL: ${PANEL_PUBLIC_URL:?set PANEL_PUBLIC_URL in .env}
|
||||
TELEMT_API_URL: ${TELEMT_API_URL:-http://127.0.0.1:9091}
|
||||
BOOTSTRAP_USERNAME: ${BOOTSTRAP_USERNAME:-admin}
|
||||
BOOTSTRAP_PASSWORD: ${BOOTSTRAP_PASSWORD:-}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
volumes:
|
||||
- ./data:/data
|
||||
networks:
|
||||
- telemt-panel
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=telemt-panel
|
||||
- traefik.http.routers.telemt-panel.rule=Host(`${PANEL_DOMAIN:-panel.example.com}`)
|
||||
- traefik.http.routers.telemt-panel.entrypoints=websecure
|
||||
- traefik.http.routers.telemt-panel.tls=true
|
||||
- traefik.http.routers.telemt-panel.tls.certresolver=letsencrypt
|
||||
- traefik.http.services.telemt-panel.loadbalancer.server.port=8080
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"node",
|
||||
"-e",
|
||||
"fetch('http://127.0.0.1:8080/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
||||
]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
volumes:
|
||||
traefik_letsencrypt:
|
||||
name: telemt_panel_traefik_letsencrypt
|
||||
|
||||
networks:
|
||||
telemt-panel:
|
||||
name: telemt-panel
|
||||
@@ -0,0 +1,15 @@
|
||||
# Traefik stack secrets for /opt/telemt-panel/.env
|
||||
PANEL_IMAGE_TAG=latest
|
||||
PANEL_DOMAIN=panel.example.com
|
||||
PANEL_MODE=fleet
|
||||
PANEL_PUBLIC_URL=https://panel.example.com
|
||||
|
||||
JWT_SECRET=change-me-long-random
|
||||
PANEL_ENCRYPTION_KEY=change-me-32chars-minimum!!!!!!
|
||||
BOOTSTRAP_USERNAME=admin
|
||||
BOOTSTRAP_PASSWORD=change-me
|
||||
|
||||
[email protected]
|
||||
CF_DNS_API_TOKEN=
|
||||
TRAEFIK_IMAGE_TAG=v3.7
|
||||
LOG_LEVEL=info
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PANEL_URL=""
|
||||
TOKEN=""
|
||||
TELEMT_URL="${TELEMT_API_URL:-http://127.0.0.1:9091}"
|
||||
STATE_DIR="/var/lib/telemt-panel-agent"
|
||||
BIN_PATH="/usr/local/bin/telemt-panel-agent"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--panel-url) PANEL_URL="$2"; shift 2 ;;
|
||||
--token) TOKEN="$2"; shift 2 ;;
|
||||
--telemt-url) TELEMT_URL="$2"; shift 2 ;;
|
||||
*) echo "Unknown arg: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$PANEL_URL" || -z "$TOKEN" ]]; then
|
||||
echo "Usage: install-agent.sh --panel-url URL --token TOKEN"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$STATE_DIR"
|
||||
|
||||
# Prefer shipping binary from panel releases; fallback: build if go present
|
||||
if command -v curl >/dev/null; then
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64|amd64) ARCH=amd64 ;;
|
||||
aarch64|arm64) ARCH=arm64 ;;
|
||||
esac
|
||||
TMP=$(mktemp)
|
||||
if curl -fsSL "${PANEL_URL}/releases/download/latest/telemt-panel-agent-linux-${ARCH}" -o "$TMP" 2>/dev/null; then
|
||||
install -m 755 "$TMP" "$BIN_PATH"
|
||||
rm -f "$TMP"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -x "$BIN_PATH" ]]; then
|
||||
echo "Agent binary not found at $BIN_PATH — place telemt-panel-agent there or build apps/agent"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > /etc/systemd/system/telemt-panel-agent.service <<EOF
|
||||
[Unit]
|
||||
Description=Telemt Panel Agent
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=${BIN_PATH} -panel-url ${PANEL_URL} -token ${TOKEN} -state ${STATE_DIR}/state.json -telemt-url ${TELEMT_URL}
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StateDirectory=telemt-panel-agent
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now telemt-panel-agent
|
||||
echo "Agent installed and started."
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Interactive / CI installer for Telemt Panel Docker
|
||||
# Usage: ./deploy/install.sh [--mode standalone|fleet] [--non-interactive]
|
||||
|
||||
MODE="${PANEL_MODE:-standalone}"
|
||||
NON_INTERACTIVE=0
|
||||
DATA_DIR="${DATA_DIR:-/var/lib/telemt-panel}"
|
||||
IMAGE="${PANEL_IMAGE:-git.shts.su/denozord/telemtPanel:latest}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--mode) MODE="$2"; shift 2 ;;
|
||||
--non-interactive) NON_INTERACTIVE=1; shift ;;
|
||||
--data-dir) DATA_DIR="$2"; shift 2 ;;
|
||||
--image) IMAGE="$2"; shift 2 ;;
|
||||
*) echo "Unknown arg: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$NON_INTERACTIVE" -eq 0 ]]; then
|
||||
read -r -p "PANEL_MODE [standalone/fleet] ($MODE): " input || true
|
||||
MODE="${input:-$MODE}"
|
||||
fi
|
||||
|
||||
mkdir -p "$DATA_DIR"
|
||||
|
||||
JWT_SECRET="${JWT_SECRET:-$(openssl rand -hex 32)}"
|
||||
PANEL_ENCRYPTION_KEY="${PANEL_ENCRYPTION_KEY:-$(openssl rand -hex 32)}"
|
||||
BOOTSTRAP_PASSWORD="${BOOTSTRAP_PASSWORD:-$(openssl rand -hex 12)}"
|
||||
TELEMT_API_URL="${TELEMT_API_URL:-http://127.0.0.1:9091}"
|
||||
PANEL_PUBLIC_URL="${PANEL_PUBLIC_URL:-http://127.0.0.1:8080}"
|
||||
|
||||
echo "Pulling $IMAGE ..."
|
||||
docker pull "$IMAGE"
|
||||
|
||||
NET_ARGS=()
|
||||
ENV_ARGS=(
|
||||
-e "PANEL_MODE=$MODE"
|
||||
-e "JWT_SECRET=$JWT_SECRET"
|
||||
-e "PANEL_ENCRYPTION_KEY=$PANEL_ENCRYPTION_KEY"
|
||||
-e "PANEL_PUBLIC_URL=$PANEL_PUBLIC_URL"
|
||||
-e "BOOTSTRAP_USERNAME=${BOOTSTRAP_USERNAME:-admin}"
|
||||
-e "BOOTSTRAP_PASSWORD=$BOOTSTRAP_PASSWORD"
|
||||
-e "DATABASE_URL=sqlite:/data/app.db"
|
||||
)
|
||||
|
||||
if [[ "$MODE" == "standalone" ]]; then
|
||||
ENV_ARGS+=(-e "TELEMT_API_URL=$TELEMT_API_URL")
|
||||
if [[ "$(uname -s)" == "Linux" ]]; then
|
||||
NET_ARGS=(--network host)
|
||||
else
|
||||
NET_ARGS=(-p 8080:8080 --add-host=host.docker.internal:host-gateway)
|
||||
ENV_ARGS+=(-e "TELEMT_API_URL=${TELEMT_API_URL/127.0.0.1/host.docker.internal}")
|
||||
fi
|
||||
else
|
||||
NET_ARGS=(-p 8080:8080)
|
||||
fi
|
||||
|
||||
docker rm -f telemt-panel 2>/dev/null || true
|
||||
docker run -d --name telemt-panel --restart unless-stopped \
|
||||
"${NET_ARGS[@]}" \
|
||||
"${ENV_ARGS[@]}" \
|
||||
-v "$DATA_DIR:/data" \
|
||||
"$IMAGE"
|
||||
|
||||
echo
|
||||
echo "Telemt Panel started (mode=$MODE)."
|
||||
echo "Admin: ${BOOTSTRAP_USERNAME:-admin} / $BOOTSTRAP_PASSWORD"
|
||||
echo "URL: $PANEL_PUBLIC_URL"
|
||||
echo "See docs/install.md for firewall and Telemt [server.api] whitelist."
|
||||
Reference in New Issue
Block a user