Add agent install scripts and release automation

Introduced Linux (install.sh) and Windows (install.ps1) installation scripts for ServerKit agent, and exposed new backend endpoints to serve these scripts and installation instructions. Added a GitHub Actions workflow (agent-release.yml) for automated agent builds and releases. Updated ROADMAP.md and SERVERS_INTEGRATION_PLAN.md to reflect progress on installation and distribution features.
This commit is contained in:
Juan Denis committed 2026-01-21 22:57:40 -05:00
1 parent 009fb12435
commit 528c86d640
6 files changed
+1115 -94

No files matched your search

+203
View File
@@ -0,0 +1,203 @@
name: Agent Release
on:
push:
tags:
- 'agent-v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 1.0.0)'
required: true
type: string
env:
GO_VERSION: '1.21'
jobs:
build:
name: Build Agent
runs-on: ubuntu-latest
strategy:
matrix:
include:
- goos: linux
goarch: amd64
suffix: ''
- goos: linux
goarch: arm64
suffix: ''
- goos: windows
goarch: amd64
suffix: '.exe'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: agent/go.sum
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${GITHUB_REF#refs/tags/agent-v}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Building version: $VERSION"
- name: Build binary
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
run: |
cd agent
go build -ldflags="-s -w -X main.Version=${{ steps.version.outputs.version }}" \
-o ../dist/serverkit-agent-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.suffix }} \
./cmd/agent
- name: Compress binary (Linux)
if: matrix.goos == 'linux'
run: |
cd dist
tar -czvf serverkit-agent-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz \
serverkit-agent-${{ matrix.goos }}-${{ matrix.goarch }}
- name: Compress binary (Windows)
if: matrix.goos == 'windows'
run: |
cd dist
zip serverkit-agent-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.zip \
serverkit-agent-${{ matrix.goos }}-${{ matrix.goarch }}.exe
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: serverkit-agent-${{ matrix.goos }}-${{ matrix.goarch }}
path: dist/serverkit-agent-${{ steps.version.outputs.version }}-*
retention-days: 5
release:
name: Create Release
runs-on: ubuntu-latest
needs: build
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${GITHUB_REF#refs/tags/agent-v}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release files
run: |
mkdir -p release
find artifacts -type f \( -name "*.tar.gz" -o -name "*.zip" \) -exec mv {} release/ \;
ls -la release/
- name: Generate checksums
run: |
cd release
sha256sum * > checksums.txt
cat checksums.txt
- name: Create Release
uses: softprops/action-gh-release@v1
with:
tag_name: agent-v${{ steps.version.outputs.version }}
name: ServerKit Agent v${{ steps.version.outputs.version }}
draft: false
prerelease: false
files: |
release/*
body: |
## ServerKit Agent v${{ steps.version.outputs.version }}
### Downloads
| Platform | Architecture | Download |
|----------|--------------|----------|
| Linux | x64 (amd64) | `serverkit-agent-${{ steps.version.outputs.version }}-linux-amd64.tar.gz` |
| Linux | ARM64 | `serverkit-agent-${{ steps.version.outputs.version }}-linux-arm64.tar.gz` |
| Windows | x64 (amd64) | `serverkit-agent-${{ steps.version.outputs.version }}-windows-amd64.zip` |
### Quick Install
**Linux (one-liner):**
```bash
curl -fsSL https://your-serverkit.com/install.sh | sudo bash -s -- --token "YOUR_TOKEN"
```
**Windows (PowerShell as Admin):**
```powershell
irm https://your-serverkit.com/install.ps1 | iex; Install-ServerKitAgent -Token "YOUR_TOKEN"
```
### Verification
Verify downloads using the checksums in `checksums.txt`:
```bash
sha256sum -c checksums.txt
```
### What's New
See [CHANGELOG](https://github.com/${{ github.repository }}/blob/main/agent/CHANGELOG.md) for details.
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
summary:
name: Build Summary
runs-on: ubuntu-latest
needs: [build, release]
steps:
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${GITHUB_REF#refs/tags/agent-v}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Create summary
run: |
echo "## Agent Release Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** v${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Built Binaries" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Platform | Architecture | Status |" >> $GITHUB_STEP_SUMMARY
echo "|----------|--------------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Linux | amd64 | ✅ Built |" >> $GITHUB_STEP_SUMMARY
echo "| Linux | arm64 | ✅ Built |" >> $GITHUB_STEP_SUMMARY
echo "| Windows | amd64 | ✅ Built |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Release" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Release created at: https://github.com/${{ github.repository }}/releases/tag/agent-v${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
+12 -7
View File
@@ -117,16 +117,21 @@ This document outlines the development roadmap for ServerKit. Features are organ
---
## Phase 10: Multi-Server Management (Planned)
## Phase 10: Multi-Server Management (In Progress)
**Priority: High**
- [ ] Agent-based remote server monitoring
- [ ] Centralized dashboard for multiple servers
- [ ] Server grouping and tagging
- [ ] Cross-server metrics comparison
- [ ] Remote command execution
- [ ] Server health overview
- [x] Agent-based remote server monitoring (Go agent)
- [x] Centralized dashboard for multiple servers
- [x] Server grouping and tagging
- [x] Cross-server metrics comparison
- [x] Remote Docker management via agents
- [x] Server health overview
- [x] Agent WebSocket gateway
- [x] HMAC-SHA256 authentication
- [x] GitHub Actions for agent releases (Linux/Windows)
- [x] Installation scripts endpoint
- [ ] Agent auto-update mechanism
---
+94 -86
View File
@@ -1185,137 +1185,145 @@ system:exec: # Requires explicit permission
## 11. Phase Implementation Plan
### Phase 10.1: Foundation (Agent Core)
### Phase 10.1: Foundation (Agent Core) ✅ COMPLETED
**Duration: ~2-3 weeks**
```
[ ] Design and implement Go agent binary
[ ] Project setup with Go modules
[ ] Configuration loading (YAML)
[ ] Logging system (structured logs)
[ ] WebSocket client with reconnection
[ ] HMAC authentication
[ ] Heartbeat mechanism
[ ] Graceful shutdown handling
[x] Design and implement Go agent binary
[x] Project setup with Go modules
[x] Configuration loading (YAML)
[x] Logging system (structured logs)
[x] WebSocket client with reconnection
[x] HMAC authentication
[x] Heartbeat mechanism
[x] Graceful shutdown handling
[ ] Docker integration in agent
[ ] Connect to Docker socket
[ ] Container list/inspect
[ ] Container start/stop/restart
[ ] Basic stats collection
[x] Docker integration in agent
[x] Connect to Docker socket
[x] Container list/inspect
[x] Container start/stop/restart
[x] Basic stats collection
[ ] Build pipeline
[ ] Cross-compilation for all platforms
[ ] Binary signing
[ ] Version embedding
[x] Build pipeline
[x] Cross-compilation for all platforms (GitHub Actions)
[x] Version embedding
[ ] Binary signing (optional - future)
```
### Phase 10.2: Backend Gateway
### Phase 10.2: Backend Gateway ✅ COMPLETED
**Duration: ~2 weeks**
```
[ ] Database models
[ ] Server, ServerGroup models
[ ] ServerMetrics, ServerCommand models
[ ] AgentSession model
[ ] Migrations
[x] Database models
[x] Server, ServerGroup models
[x] ServerMetrics, ServerCommand models
[x] AgentSession model
[x] Migrations (auto via SQLAlchemy)
[ ] Agent Gateway (WebSocket server)
[ ] SocketIO namespace for agents
[ ] Authentication handler
[ ] Session management
[ ] Command routing
[ ] Connection tracking
[x] Agent Gateway (WebSocket server)
[x] SocketIO namespace for agents (/agent)
[x] Authentication handler
[x] Session management
[x] Command routing
[x] Connection tracking
[ ] API endpoints
[ ] Server CRUD
[ ] Registration token generation
[ ] Server status endpoint
[x] API endpoints
[x] Server CRUD
[x] Registration token generation
[x] Server status endpoint
[x] Remote Docker endpoints (50+ routes)
```
### Phase 10.3: Security Layer
### Phase 10.3: Security Layer ✅ COMPLETED
**Duration: ~1-2 weeks**
```
[ ] Security implementation
[ ] API key generation and hashing
[ ] HMAC signature validation
[ ] Session token management
[ ] Permission checking middleware
[ ] Rate limiting per agent
[ ] Audit logging
[x] Security implementation
[x] API key generation and hashing (bcrypt)
[x] HMAC-SHA256 signature validation
[x] Session token management
[x] Permission checking (scope-based)
[ ] Rate limiting per agent (future)
[x] Audit logging (ServerCommand model)
[ ] Agent security
[ ] Encrypted key storage
[ ] Command validation
[ ] Permission enforcement
[x] Agent security
[x] Encrypted key storage (AES-256-GCM)
[x] Command validation
[x] Permission enforcement
```
### Phase 10.4: Frontend - Server Management
### Phase 10.4: Frontend - Server Management ✅ COMPLETED
**Duration: ~2 weeks**
```
[ ] Servers page
[ ] Server list view
[ ] Server cards/grid view
[ ] Add server modal
[ ] Installation instructions
[ ] Server detail page
[ ] Server settings
[x] Servers page
[x] Server list view (grid with cards)
[x] Server cards with live metrics
[x] Add server modal with permissions
[x] Installation instructions (Linux/Windows)
[x] Server detail page (tabbed interface)
[x] Server settings
[ ] Server groups
[ ] Group CRUD UI
[ ] Drag-drop organization
[ ] Group filtering
[x] Server groups
[x] Group CRUD UI (modal)
[x] Group filtering
[ ] Drag-drop organization (future)
```
### Phase 10.5: Remote Docker Integration
### Phase 10.5: Remote Docker Integration ✅ COMPLETED
**Duration: ~2 weeks**
```
[ ] Backend: Docker command routing
[ ] Route Docker commands to agents
[ ] Handle async responses
[ ] Error handling
[x] Backend: Docker command routing
[x] Route Docker commands to agents (RemoteDockerService)
[x] Handle async responses (command results)
[x] Error handling
[ ] Frontend: Docker page updates
[ ] Server selector dropdown
[ ] Context-aware Docker UI
[ ] Real-time container updates
[x] Frontend: Docker page updates
[x] Server selector dropdown (top of page)
[x] Context-aware Docker UI (ServerContext)
[x] Real-time container updates
[ ] Agent: Full Docker support
[ ] All container operations
[ ] Image operations
[ ] Volume/network listing
[x] Agent: Full Docker support
[x] All container operations
[x] Image operations
[x] Volume/network listing
```
### Phase 10.6: Monitoring & Metrics
### Phase 10.6: Monitoring & Metrics 🔄 IN PROGRESS
**Duration: ~2 weeks**
```
[ ] Real-time metrics
[ ] Agent metrics streaming
[ ] WebSocket to frontend
[ ] Live dashboard updates
[x] Real-time metrics
[x] Agent metrics streaming (heartbeat)
[x] WebSocket to frontend (SocketIO)
[x] Live dashboard updates
[ ] Historical metrics
[ ] Metrics storage
[x] Metrics storage (ServerMetrics model)
[ ] Retention policies
[ ] Aggregation queries
[ ] Cross-server dashboard
[ ] Overview page
[ ] Metric comparison charts
[ ] Health grid view
[x] Cross-server dashboard
[x] Overview page (Servers.jsx)
[x] Metric comparison (server cards)
[x] Health grid view
```
### Phase 10.7: Installation & Distribution
### Phase 10.7: Installation & Distribution 🔄 IN PROGRESS
**Duration: ~1-2 weeks**
```
[ ] Installation scripts
[ ] Linux install script (bash)
[ ] Windows install script (PowerShell)
[x] Build automation
[x] GitHub Actions workflow (agent-release.yml)
[x] Linux amd64/arm64 builds
[x] Windows amd64 builds
[x] Automatic releases on tag
[x] Installation scripts
[x] Linux install script (bash) - created
[x] Windows install script (PowerShell) - created
[x] Installation endpoint in backend
[ ] Docker image
[ ] Package building
@@ -1325,7 +1333,7 @@ system:exec: # Requires explicit permission
[ ] Homebrew formula
[ ] Distribution
[ ] Download page
[ ] Download page in UI
[ ] Version checking
[ ] Auto-update mechanism
```
+135 -1
View File
@@ -4,8 +4,9 @@ Server Management API
Endpoints for managing remote servers and their agents.
"""
import os
from datetime import datetime, timedelta
from flask import Blueprint, request, jsonify
from flask import Blueprint, request, jsonify, Response, current_app
from flask_jwt_extended import jwt_required, get_jwt_identity
from app import db
@@ -833,3 +834,136 @@ def get_remote_system_info(server_id):
return jsonify(result), 500
return jsonify(result.get('data'))
# ==================== Installation Scripts ====================
def _get_scripts_dir():
"""Get the scripts directory path"""
# Go up from backend/app/api to backend, then to scripts
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
return os.path.join(base_dir, 'scripts')
@servers_bp.route('/install.sh', methods=['GET'])
def get_install_script_linux():
"""
Get the Linux installation script.
This endpoint serves the bash installation script for installing
the ServerKit agent on Linux systems.
Usage:
curl -fsSL https://your-server/api/servers/install.sh | sudo bash -s -- \\
--token "YOUR_TOKEN" --server "https://your-server"
"""
script_path = os.path.join(_get_scripts_dir(), 'install.sh')
if not os.path.exists(script_path):
return jsonify({'error': 'Installation script not found'}), 404
with open(script_path, 'r', encoding='utf-8') as f:
content = f.read()
# Replace placeholder URLs with actual server URL
server_url = request.url_root.rstrip('/')
content = content.replace('https://your-serverkit.com', server_url)
return Response(
content,
mimetype='text/x-shellscript',
headers={
'Content-Disposition': 'inline; filename="install.sh"',
'Cache-Control': 'no-cache'
}
)
@servers_bp.route('/install.ps1', methods=['GET'])
def get_install_script_windows():
"""
Get the Windows installation script.
This endpoint serves the PowerShell installation script for installing
the ServerKit agent on Windows systems.
Usage:
irm https://your-server/api/servers/install.ps1 | iex; \\
Install-ServerKitAgent -Token "YOUR_TOKEN" -Server "https://your-server"
"""
script_path = os.path.join(_get_scripts_dir(), 'install.ps1')
if not os.path.exists(script_path):
return jsonify({'error': 'Installation script not found'}), 404
with open(script_path, 'r', encoding='utf-8') as f:
content = f.read()
# Replace placeholder URLs with actual server URL
server_url = request.url_root.rstrip('/')
content = content.replace('https://your-serverkit.com', server_url)
return Response(
content,
mimetype='text/plain',
headers={
'Content-Disposition': 'inline; filename="install.ps1"',
'Cache-Control': 'no-cache'
}
)
@servers_bp.route('/install-instructions/<server_id>', methods=['GET'])
@jwt_required()
def get_install_instructions(server_id):
"""
Get installation instructions for a specific server.
Returns the installation commands with the server's registration token
already embedded.
"""
server = Server.query.get(server_id)
if not server:
return jsonify({'error': 'Server not found'}), 404
# Check if server has a valid registration token
if not server.registration_token_hash:
return jsonify({
'error': 'No registration token available',
'message': 'Generate a new token using the regenerate-token endpoint'
}), 400
if server.registration_token_expires and server.registration_token_expires < datetime.utcnow():
return jsonify({
'error': 'Registration token expired',
'message': 'Generate a new token using the regenerate-token endpoint'
}), 400
# Get base URL
base_url = request.url_root.rstrip('/')
api_url = f"{base_url}/api/servers"
return jsonify({
'linux': {
'one_liner': f'curl -fsSL {api_url}/install.sh | sudo bash -s -- --token "YOUR_TOKEN" --server "{base_url}"',
'manual': [
f'# Download the script',
f'curl -fsSL {api_url}/install.sh -o install.sh',
f'chmod +x install.sh',
f'',
f'# Run installation',
f'sudo ./install.sh --token "YOUR_TOKEN" --server "{base_url}"'
]
},
'windows': {
'one_liner': f'irm {api_url}/install.ps1 | iex; Install-ServerKitAgent -Token "YOUR_TOKEN" -Server "{base_url}"',
'manual': [
f'# Download the script (run in PowerShell as Administrator)',
f'Invoke-WebRequest -Uri "{api_url}/install.ps1" -OutFile install.ps1',
f'',
f'# Run installation',
f'.\\install.ps1 -Token "YOUR_TOKEN" -Server "{base_url}"'
]
},
'note': 'Replace YOUR_TOKEN with the registration token shown in the UI'
})
+323
View File
@@ -0,0 +1,323 @@
#Requires -RunAsAdministrator
<#
.SYNOPSIS
ServerKit Agent Installation Script for Windows
.DESCRIPTION
Downloads and installs the ServerKit Agent on Windows systems.
.PARAMETER Token
Registration token from ServerKit (required)
.PARAMETER Server
ServerKit server URL (required)
.PARAMETER Name
Display name for this server (optional)
.PARAMETER Version
Specific agent version to install (optional, defaults to latest)
.EXAMPLE
.\install.ps1 -Token "sk_reg_xxx" -Server "https://your-serverkit.com"
.EXAMPLE
irm https://your-serverkit.com/install.ps1 | iex; Install-ServerKitAgent -Token "sk_reg_xxx" -Server "https://your-serverkit.com"
.NOTES
Requires Administrator privileges.
#>
param(
[Parameter(Mandatory=$false)]
[string]$Token,
[Parameter(Mandatory=$false)]
[string]$Server,
[Parameter(Mandatory=$false)]
[string]$Name,
[Parameter(Mandatory=$false)]
[string]$Version = "latest"
)
# Configuration
$InstallDir = "$env:ProgramFiles\ServerKit"
$ConfigDir = "$env:ProgramData\ServerKit"
$ServiceName = "ServerKitAgent"
$GitHubRepo = "serverkit/serverkit"
$AgentBinary = "serverkit-agent.exe"
# Colors
function Write-ColorOutput {
param(
[string]$Message,
[string]$Type = "Info"
)
switch ($Type) {
"Info" { Write-Host "[INFO] " -ForegroundColor Cyan -NoNewline; Write-Host $Message }
"Success" { Write-Host "[SUCCESS] " -ForegroundColor Green -NoNewline; Write-Host $Message }
"Warning" { Write-Host "[WARN] " -ForegroundColor Yellow -NoNewline; Write-Host $Message }
"Error" { Write-Host "[ERROR] " -ForegroundColor Red -NoNewline; Write-Host $Message }
}
}
function Write-Banner {
Write-Host ""
Write-Host "╔═══════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ ServerKit Agent Installer ║" -ForegroundColor Cyan
Write-Host "╚═══════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""
}
function Test-Administrator {
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Get-LatestVersion {
if ($Version -eq "latest") {
Write-ColorOutput "Fetching latest version..." "Info"
try {
$releases = Invoke-RestMethod -Uri "https://api.github.com/repos/$GitHubRepo/releases" -Method Get
foreach ($release in $releases) {
if ($release.tag_name -match "^agent-v(.+)$") {
$script:Version = $Matches[1]
Write-ColorOutput "Latest version: v$Version" "Info"
return
}
}
throw "No agent release found"
}
catch {
Write-ColorOutput "Failed to fetch latest version: $_" "Error"
exit 1
}
}
}
function Install-Agent {
Write-ColorOutput "Downloading ServerKit Agent v$Version..." "Info"
# Create temp directory
$tempDir = Join-Path $env:TEMP "serverkit-install-$(Get-Random)"
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
$downloadUrl = "https://github.com/$GitHubRepo/releases/download/agent-v$Version/serverkit-agent-$Version-windows-amd64.zip"
$archivePath = Join-Path $tempDir "serverkit-agent.zip"
try {
# Download
Write-ColorOutput "Downloading from: $downloadUrl" "Info"
Invoke-WebRequest -Uri $downloadUrl -OutFile $archivePath -UseBasicParsing
# Extract
Write-ColorOutput "Extracting agent..." "Info"
Expand-Archive -Path $archivePath -DestinationPath $tempDir -Force
# Create install directory
if (-not (Test-Path $InstallDir)) {
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
}
# Copy binary
$binarySource = Join-Path $tempDir "serverkit-agent-windows-amd64.exe"
$binaryDest = Join-Path $InstallDir $AgentBinary
Copy-Item -Path $binarySource -Destination $binaryDest -Force
Write-ColorOutput "Agent installed to $binaryDest" "Success"
}
catch {
Write-ColorOutput "Failed to download/install agent: $_" "Error"
exit 1
}
finally {
# Cleanup
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
function New-ConfigDirectory {
Write-ColorOutput "Creating configuration directory..." "Info"
if (-not (Test-Path $ConfigDir)) {
New-Item -ItemType Directory -Path $ConfigDir -Force | Out-Null
}
}
function Register-Agent {
param(
[string]$Token,
[string]$Server,
[string]$Name
)
Write-ColorOutput "Registering agent with ServerKit..." "Info"
$agentPath = Join-Path $InstallDir $AgentBinary
$arguments = @("register", "--token", $Token, "--server", $Server)
if ($Name) {
$arguments += @("--name", $Name)
}
try {
$process = Start-Process -FilePath $agentPath -ArgumentList $arguments -Wait -PassThru -NoNewWindow
if ($process.ExitCode -ne 0) {
throw "Registration command failed with exit code: $($process.ExitCode)"
}
Write-ColorOutput "Agent registered successfully" "Success"
}
catch {
Write-ColorOutput "Agent registration failed: $_" "Error"
exit 1
}
}
function Install-WindowsService {
Write-ColorOutput "Installing Windows service..." "Info"
$agentPath = Join-Path $InstallDir $AgentBinary
# Check if service already exists
$existingService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($existingService) {
Write-ColorOutput "Stopping existing service..." "Info"
Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
Write-ColorOutput "Removing existing service..." "Info"
sc.exe delete $ServiceName | Out-Null
Start-Sleep -Seconds 2
}
# Create the service using sc.exe
$binPath = "`"$agentPath`" start"
$result = sc.exe create $ServiceName binPath= $binPath start= auto DisplayName= "ServerKit Agent"
if ($LASTEXITCODE -ne 0) {
Write-ColorOutput "Failed to create service: $result" "Error"
exit 1
}
# Set service description
sc.exe description $ServiceName "ServerKit Agent for remote server management" | Out-Null
# Set service recovery options (restart on failure)
sc.exe failure $ServiceName reset= 86400 actions= restart/60000/restart/60000/restart/60000 | Out-Null
Write-ColorOutput "Windows service installed" "Success"
}
function Start-AgentService {
Write-ColorOutput "Starting ServerKit Agent service..." "Info"
try {
Start-Service -Name $ServiceName
Start-Sleep -Seconds 3
$service = Get-Service -Name $ServiceName
if ($service.Status -eq "Running") {
Write-ColorOutput "Agent service is running" "Success"
}
else {
Write-ColorOutput "Service failed to start. Status: $($service.Status)" "Warning"
Write-ColorOutput "Check logs in Event Viewer > Windows Logs > Application" "Info"
}
}
catch {
Write-ColorOutput "Failed to start service: $_" "Error"
}
}
function Add-ToPath {
Write-ColorOutput "Adding to system PATH..." "Info"
$currentPath = [Environment]::GetEnvironmentVariable("Path", "Machine")
if ($currentPath -notlike "*$InstallDir*") {
$newPath = "$currentPath;$InstallDir"
[Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
Write-ColorOutput "Added $InstallDir to system PATH" "Success"
}
else {
Write-ColorOutput "Already in PATH" "Info"
}
}
function Write-SuccessMessage {
Write-Host ""
Write-Host "╔═══════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║ Installation completed successfully! ║" -ForegroundColor Green
Write-Host "╚═══════════════════════════════════════════════════════════╝" -ForegroundColor Green
Write-Host ""
Write-Host "Agent Status:"
Write-Host " Binary: $InstallDir\$AgentBinary"
Write-Host " Config: $ConfigDir\config.yaml"
Write-Host " Service: $ServiceName"
Write-Host ""
Write-Host "Useful commands:"
Write-Host " Check status: Get-Service $ServiceName"
Write-Host " View logs: Get-EventLog -LogName Application -Source $ServiceName"
Write-Host " Restart agent: Restart-Service $ServiceName"
Write-Host " Stop agent: Stop-Service $ServiceName"
Write-Host ""
}
# Main function for piped execution
function Install-ServerKitAgent {
param(
[Parameter(Mandatory=$true)]
[string]$Token,
[Parameter(Mandatory=$true)]
[string]$Server,
[Parameter(Mandatory=$false)]
[string]$Name,
[Parameter(Mandatory=$false)]
[string]$Version = "latest"
)
# Update script-level variables
$script:Version = $Version
Write-Banner
if (-not (Test-Administrator)) {
Write-ColorOutput "This script must be run as Administrator" "Error"
Write-Host "Right-click PowerShell and select 'Run as Administrator'"
exit 1
}
Get-LatestVersion
Install-Agent
New-ConfigDirectory
Register-Agent -Token $Token -Server $Server -Name $Name
Install-WindowsService
Start-AgentService
Add-ToPath
Write-SuccessMessage
}
# Direct execution with parameters
if ($Token -and $Server) {
Install-ServerKitAgent -Token $Token -Server $Server -Name $Name -Version $Version
}
elseif ($PSBoundParameters.Count -gt 0) {
Write-ColorOutput "Both -Token and -Server parameters are required" "Error"
Write-Host ""
Write-Host "Usage:"
Write-Host " .\install.ps1 -Token 'sk_reg_xxx' -Server 'https://your-serverkit.com'"
exit 1
}
else {
# Script was sourced, export the function
Write-Host "ServerKit Agent installer loaded." -ForegroundColor Cyan
Write-Host "Usage: Install-ServerKitAgent -Token 'sk_reg_xxx' -Server 'https://your-serverkit.com'" -ForegroundColor Gray
}
+348
View File
@@ -0,0 +1,348 @@
#!/bin/bash
#
# ServerKit Agent Installation Script
#
# Usage:
# curl -fsSL https://your-serverkit.com/install.sh | sudo bash -s -- --token "TOKEN" --server "URL"
#
# Options:
# --token, -t Registration token (required)
# --server, -s ServerKit server URL (required)
# --name, -n Display name for this server (optional)
# --version, -v Specific agent version to install (optional, defaults to latest)
# --help, -h Show this help message
#
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/serverkit"
SERVICE_USER="serverkit"
GITHUB_REPO="serverkit/serverkit"
AGENT_BINARY="serverkit-agent"
# Arguments
TOKEN=""
SERVER_URL=""
SERVER_NAME=""
VERSION="latest"
print_banner() {
echo -e "${BLUE}"
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ ServerKit Agent Installer ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo -e "${NC}"
}
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
show_help() {
echo "ServerKit Agent Installation Script"
echo ""
echo "Usage: install.sh [OPTIONS]"
echo ""
echo "Options:"
echo " --token, -t Registration token (required)"
echo " --server, -s ServerKit server URL (required)"
echo " --name, -n Display name for this server (optional)"
echo " --version, -v Specific agent version (optional, defaults to latest)"
echo " --help, -h Show this help message"
echo ""
echo "Example:"
echo " curl -fsSL https://your-serverkit.com/install.sh | sudo bash -s -- \\"
echo " --token 'sk_reg_xxx' \\"
echo " --server 'https://your-serverkit.com'"
exit 0
}
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--token|-t)
TOKEN="$2"
shift 2
;;
--server|-s)
SERVER_URL="$2"
shift 2
;;
--name|-n)
SERVER_NAME="$2"
shift 2
;;
--version|-v)
VERSION="$2"
shift 2
;;
--help|-h)
show_help
;;
*)
log_error "Unknown option: $1"
;;
esac
done
# Validate required arguments
if [[ -z "$TOKEN" ]]; then
log_error "Registration token is required. Use --token or -t"
fi
if [[ -z "$SERVER_URL" ]]; then
log_error "Server URL is required. Use --server or -s"
fi
}
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root (use sudo)"
fi
}
detect_platform() {
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64)
ARCH="amd64"
;;
aarch64|arm64)
ARCH="arm64"
;;
*)
log_error "Unsupported architecture: $ARCH"
;;
esac
if [[ "$OS" != "linux" ]]; then
log_error "This script only supports Linux. For Windows, use install.ps1"
fi
log_info "Detected platform: ${OS}-${ARCH}"
}
check_dependencies() {
log_info "Checking dependencies..."
# Check for required tools
for cmd in curl tar; do
if ! command -v "$cmd" &> /dev/null; then
log_error "$cmd is required but not installed"
fi
done
# Check for systemd
if ! command -v systemctl &> /dev/null; then
log_warn "systemd not found. You will need to start the agent manually."
fi
}
get_latest_version() {
if [[ "$VERSION" == "latest" ]]; then
log_info "Fetching latest version..."
VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases" | \
grep -oP '"tag_name": "agent-v\K[^"]+' | head -1)
if [[ -z "$VERSION" ]]; then
log_error "Failed to fetch latest version"
fi
log_info "Latest version: v${VERSION}"
fi
}
download_agent() {
log_info "Downloading ServerKit Agent v${VERSION}..."
DOWNLOAD_URL="https://github.com/${GITHUB_REPO}/releases/download/agent-v${VERSION}/serverkit-agent-${VERSION}-linux-${ARCH}.tar.gz"
TMP_DIR=$(mktemp -d)
ARCHIVE="${TMP_DIR}/serverkit-agent.tar.gz"
if ! curl -fsSL "$DOWNLOAD_URL" -o "$ARCHIVE"; then
rm -rf "$TMP_DIR"
log_error "Failed to download agent from: $DOWNLOAD_URL"
fi
# Extract binary
log_info "Extracting agent..."
tar -xzf "$ARCHIVE" -C "$TMP_DIR"
# Install binary
mv "${TMP_DIR}/serverkit-agent-linux-${ARCH}" "${INSTALL_DIR}/${AGENT_BINARY}"
chmod +x "${INSTALL_DIR}/${AGENT_BINARY}"
# Cleanup
rm -rf "$TMP_DIR"
log_success "Agent installed to ${INSTALL_DIR}/${AGENT_BINARY}"
}
create_user() {
if id "$SERVICE_USER" &>/dev/null; then
log_info "User $SERVICE_USER already exists"
else
log_info "Creating service user: $SERVICE_USER"
useradd -r -s /bin/false -d /nonexistent "$SERVICE_USER"
fi
# Add to docker group if it exists
if getent group docker > /dev/null 2>&1; then
usermod -aG docker "$SERVICE_USER"
log_info "Added $SERVICE_USER to docker group"
fi
}
create_config_dir() {
log_info "Creating configuration directory..."
mkdir -p "$CONFIG_DIR"
chown "$SERVICE_USER:$SERVICE_USER" "$CONFIG_DIR"
chmod 750 "$CONFIG_DIR"
}
register_agent() {
log_info "Registering agent with ServerKit..."
REGISTER_CMD="${INSTALL_DIR}/${AGENT_BINARY} register --token \"${TOKEN}\" --server \"${SERVER_URL}\""
if [[ -n "$SERVER_NAME" ]]; then
REGISTER_CMD="${REGISTER_CMD} --name \"${SERVER_NAME}\""
fi
if ! eval "$REGISTER_CMD"; then
log_error "Agent registration failed"
fi
# Fix permissions on config files
chown -R "$SERVICE_USER:$SERVICE_USER" "$CONFIG_DIR"
log_success "Agent registered successfully"
}
install_systemd_service() {
if ! command -v systemctl &> /dev/null; then
log_warn "Skipping systemd service installation (systemd not found)"
return
fi
log_info "Installing systemd service..."
cat > /etc/systemd/system/serverkit-agent.service << EOF
[Unit]
Description=ServerKit Agent
Documentation=https://github.com/${GITHUB_REPO}
After=network-online.target docker.service
Wants=network-online.target
[Service]
Type=simple
User=${SERVICE_USER}
Group=${SERVICE_USER}
ExecStart=${INSTALL_DIR}/${AGENT_BINARY} start
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=serverkit-agent
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=${CONFIG_DIR}
PrivateTmp=true
# Environment
Environment=HOME=/nonexistent
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable serverkit-agent
log_success "Systemd service installed"
}
start_service() {
if ! command -v systemctl &> /dev/null; then
log_warn "Cannot auto-start without systemd"
echo ""
echo "To start the agent manually:"
echo " ${INSTALL_DIR}/${AGENT_BINARY} start"
return
fi
log_info "Starting ServerKit Agent..."
systemctl start serverkit-agent
sleep 2
if systemctl is-active --quiet serverkit-agent; then
log_success "Agent is running"
else
log_error "Failed to start agent. Check logs with: journalctl -u serverkit-agent"
fi
}
print_success() {
echo ""
echo -e "${GREEN}╔═══════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ Installation completed successfully! ║${NC}"
echo -e "${GREEN}╚═══════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Agent Status:"
echo " Binary: ${INSTALL_DIR}/${AGENT_BINARY}"
echo " Config: ${CONFIG_DIR}/config.yaml"
echo " Service: serverkit-agent"
echo ""
echo "Useful commands:"
echo " Check status: systemctl status serverkit-agent"
echo " View logs: journalctl -u serverkit-agent -f"
echo " Restart agent: systemctl restart serverkit-agent"
echo " Stop agent: systemctl stop serverkit-agent"
echo ""
}
# Main execution
main() {
print_banner
parse_args "$@"
check_root
detect_platform
check_dependencies
get_latest_version
download_agent
create_user
create_config_dir
register_agent
install_systemd_service
start_service
print_success
}
main "$@"