2026-05-27 07:45:13 +12:00
|
|
|
<#
|
|
|
|
|
Deploy embycovers to an Asustor NAS over SSH/SCP from Windows PowerShell.
|
|
|
|
|
|
2026-05-27 09:13:18 +12:00
|
|
|
Syncs project files to the NAS, then runs `docker compose build` and
|
|
|
|
|
`docker compose up -d` on the remote. All runtime configuration (Emby URL,
|
|
|
|
|
API key, ports, volumes) comes from docker-compose.yml — edit it there.
|
|
|
|
|
|
2026-05-27 07:45:13 +12:00
|
|
|
Prerequisites on your Windows machine:
|
|
|
|
|
- OpenSSH Client installed. Test with: ssh -V
|
|
|
|
|
- SSH enabled on the Asustor NAS.
|
|
|
|
|
- Docker / Docker Compose available on the Asustor NAS.
|
|
|
|
|
|
|
|
|
|
Example:
|
2026-05-27 09:13:18 +12:00
|
|
|
.\deploy.ps1 -NasHost MATT-NAS -NasUser ssh
|
2026-05-27 07:45:13 +12:00
|
|
|
#>
|
|
|
|
|
|
|
|
|
|
param(
|
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
|
|
|
[string]$NasHost,
|
|
|
|
|
|
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
|
|
|
[string]$NasUser,
|
|
|
|
|
|
2026-06-08 00:01:55 +12:00
|
|
|
[string]$RemoteAppDir = "/share/Docker/homelabtoolkit"
|
2026-05-27 07:45:13 +12:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
|
|
|
|
|
|
function Require-Command($Name) {
|
|
|
|
|
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
|
|
|
|
|
throw "$Name was not found. Install or enable it first."
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Require-Command ssh
|
|
|
|
|
Require-Command scp
|
|
|
|
|
|
|
|
|
|
$LocalDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
|
|
|
$Remote = "$NasUser@$NasHost"
|
|
|
|
|
|
2026-06-08 00:01:55 +12:00
|
|
|
Write-Host "Deploying HomelabToolkit to ${Remote}:$RemoteAppDir"
|
2026-05-27 07:45:13 +12:00
|
|
|
|
|
|
|
|
ssh $Remote @"
|
|
|
|
|
set -e
|
2026-06-08 00:01:55 +12:00
|
|
|
mkdir -p '$RemoteAppDir' '$RemoteAppDir/output' '$RemoteAppDir/cache' '$RemoteAppDir/static/studios' '$RemoteAppDir/services' '$RemoteAppDir/frontend'
|
2026-05-27 07:45:13 +12:00
|
|
|
"@
|
|
|
|
|
|
|
|
|
|
# Copy top-level project files.
|
|
|
|
|
scp `
|
|
|
|
|
"$LocalDir/app.py" `
|
|
|
|
|
"$LocalDir/Dockerfile" `
|
|
|
|
|
"$LocalDir/docker-compose.yml" `
|
|
|
|
|
"$LocalDir/requirements.txt" `
|
|
|
|
|
"${Remote}:$RemoteAppDir/"
|
|
|
|
|
|
2026-06-08 00:01:55 +12:00
|
|
|
# Copy static assets (studio logos, served at /static).
|
|
|
|
|
scp -r "$LocalDir/static/." "${Remote}:$RemoteAppDir/static/"
|
|
|
|
|
|
|
|
|
|
# Copy the service layer (Emby, Navidrome, music-covers). Exclude local __pycache__.
|
|
|
|
|
scp -r "$LocalDir/services/." "${Remote}:$RemoteAppDir/services/"
|
|
|
|
|
|
|
|
|
|
# Copy the React frontend SOURCE (built inside the Docker frontend stage).
|
|
|
|
|
# node_modules / dist are excluded — the image rebuilds them.
|
|
|
|
|
ssh $Remote "rm -rf '$RemoteAppDir/frontend/node_modules' '$RemoteAppDir/frontend/dist'"
|
|
|
|
|
scp "$LocalDir/frontend/package.json" "${Remote}:$RemoteAppDir/frontend/"
|
|
|
|
|
if (Test-Path "$LocalDir/frontend/package-lock.json") {
|
|
|
|
|
scp "$LocalDir/frontend/package-lock.json" "${Remote}:$RemoteAppDir/frontend/"
|
|
|
|
|
}
|
|
|
|
|
scp `
|
|
|
|
|
"$LocalDir/frontend/vite.config.ts" `
|
|
|
|
|
"$LocalDir/frontend/tsconfig.json" `
|
|
|
|
|
"$LocalDir/frontend/index.html" `
|
|
|
|
|
"${Remote}:$RemoteAppDir/frontend/"
|
|
|
|
|
scp -r "$LocalDir/frontend/src" "${Remote}:$RemoteAppDir/frontend/"
|
2026-05-27 07:45:13 +12:00
|
|
|
|
|
|
|
|
# Copy any loose logo images that live at the repo root.
|
|
|
|
|
$LogoFiles = Get-ChildItem -Path $LocalDir -File |
|
|
|
|
|
Where-Object { $_.Extension -in @('.png','.jpg','.jpeg') }
|
|
|
|
|
if ($LogoFiles) {
|
|
|
|
|
$LogoArgs = $LogoFiles | ForEach-Object { "`"$($_.FullName)`"" }
|
|
|
|
|
$ScpCmd = "scp $($LogoArgs -join ' ') `"${Remote}:$RemoteAppDir/`""
|
|
|
|
|
Invoke-Expression $ScpCmd
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 09:13:18 +12:00
|
|
|
# Build and run on the NAS using values from docker-compose.yml.
|
2026-05-27 07:45:13 +12:00
|
|
|
$RemoteCommands = @"
|
|
|
|
|
set -e
|
|
|
|
|
cd '$RemoteAppDir'
|
|
|
|
|
|
|
|
|
|
if command -v docker-compose >/dev/null 2>&1; then
|
|
|
|
|
docker-compose build
|
|
|
|
|
docker-compose up -d
|
|
|
|
|
else
|
|
|
|
|
docker compose build
|
|
|
|
|
docker compose up -d
|
|
|
|
|
fi
|
|
|
|
|
"@
|
|
|
|
|
|
|
|
|
|
ssh $Remote $RemoteCommands
|
|
|
|
|
|
|
|
|
|
Write-Host "Deployment complete."
|
|
|
|
|
Write-Host "To view logs:"
|
|
|
|
|
Write-Host " ssh $Remote 'cd $RemoteAppDir && docker compose logs -f'"
|