# CareTV Windows Standard Setup # Version: v001 # Date: 2026-08-26 # # STANDARD ACCOUNTS # caretv-admin = local administrator / CareTV maintenance # caretv-service = standard non-admin / CareTV background services # caretv-mom = standard non-admin / Mom's interactive CareTV account # # CURRENT TEMPORARY STORAGE SERVER # \\LIVING-ROOM\CareTV-SSD-Pool # # Safe to re-run. # Does NOT enable SMB1. # Does NOT format, initialize, pool, rebalance, or alter physical disks. # Does NOT delete existing shares or existing ACLs. param( [ValidateSet("All","Network","Accounts","Storage")] [string]$Mode = "All", [string]$ServerName = "LIVING-ROOM", [string]$ShareName = "CareTV-SSD-Pool", [string]$MomDrive = "M:" ) $ErrorActionPreference = "Continue" $AdminUser = "caretv-admin" $ServiceUser = "caretv-service" $MomUser = "caretv-mom" $MomRelativePath = "Users\Mom" $MomUNC = "\\$ServerName\$ShareName\$MomRelativePath" function Write-Section([string]$Text) { Write-Host "" Write-Host "============================================================" Write-Host " $Text" Write-Host "============================================================" } function Require-Administrator { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Host "ERROR: Run the CareTV launcher BAT as Administrator." exit 1 } } function Ensure-StandardUser { param( [string]$Name, [string]$FullName, [string]$Description, [securestring]$Password, [bool]$Administrator ) $existing = Get-LocalUser -Name $Name -ErrorAction SilentlyContinue if (-not $existing) { New-LocalUser ` -Name $Name ` -Password $Password ` -FullName $FullName ` -Description $Description ` -PasswordNeverExpires | Out-Null Write-Host "Created: $Name" } else { Set-LocalUser -Name $Name -Password $Password -PasswordNeverExpires $true Enable-LocalUser -Name $Name -ErrorAction SilentlyContinue Write-Host "Updated: $Name" } if ($Administrator) { Add-LocalGroupMember -Group "Administrators" -Member $Name -ErrorAction SilentlyContinue Write-Host " Role: Administrator" } else { Remove-LocalGroupMember -Group "Administrators" -Member $Name -ErrorAction SilentlyContinue Add-LocalGroupMember -Group "Users" -Member $Name -ErrorAction SilentlyContinue Write-Host " Role: Standard user" } } function Configure-Networking { Write-Section "CareTV Permanent Windows Networking" Get-NetConnectionProfile | ForEach-Object { try { if ($_.NetworkCategory -ne "DomainAuthenticated") { Set-NetConnectionProfile ` -InterfaceIndex $_.InterfaceIndex ` -NetworkCategory Private Write-Host "Private network: $($_.InterfaceAlias)" } } catch { Write-Warning "Could not change network profile: $($_.InterfaceAlias)" } } Get-NetFirewallRule -DisplayGroup "Network Discovery" -ErrorAction SilentlyContinue | Set-NetFirewallRule -Enabled True -Profile Private Get-NetFirewallRule -DisplayGroup "File and Printer Sharing" -ErrorAction SilentlyContinue | Set-NetFirewallRule -Enabled True -Profile Private $services = @( "FDResPub", "fdPHost", "SSDPSRV", "upnphost", "LanmanServer", "LanmanWorkstation" ) foreach ($service in $services) { try { Set-Service -Name $service -StartupType Automatic Start-Service -Name $service -ErrorAction SilentlyContinue Write-Host "Automatic: $service" } catch { Write-Warning "Could not configure service: $service" } } Write-Host "" Write-Host "Network discovery and SMB networking are permanently enabled." Write-Host "SMB1 remains disabled." } function Configure-Accounts { Write-Section "CareTV Standard Accounts" Write-Host "This setup ALWAYS asks you to set the three CareTV passwords." Write-Host "For easy Windows pass-through networking, use the SAME corresponding" Write-Host "passwords on each CareTV Windows machine." Write-Host "" $adminPassword = Read-Host "Create/set password for caretv-admin" -AsSecureString $servicePassword = Read-Host "Create/set password for caretv-service" -AsSecureString $momPassword = Read-Host "Create/set password for caretv-mom" -AsSecureString Write-Host "" Ensure-StandardUser ` -Name $AdminUser ` -FullName "CareTV Administrator" ` -Description "CareTV maintenance and recovery administrator" ` -Password $adminPassword ` -Administrator $true Ensure-StandardUser ` -Name $ServiceUser ` -FullName "CareTV Service" ` -Description "CareTV background service and automation account" ` -Password $servicePassword ` -Administrator $false Ensure-StandardUser ` -Name $MomUser ` -FullName "CareTV Mom" ` -Description "Standard interactive CareTV account for Mom" ` -Password $momPassword ` -Administrator $false } function Configure-ServerStorage { Write-Section "CareTV Server Storage" $share = Get-SmbShare -Name $ShareName -ErrorAction SilentlyContinue if (-not $share) { Write-Host "This computer is not hosting the SMB share '$ShareName'." Write-Host "Server-side storage setup skipped." Write-Host "This is expected on BEDROOM and other client nodes." return } $root = $share.Path if (-not $root -or -not (Test-Path $root)) { Write-Warning "The share exists but its backing path cannot be accessed: $root" return } Write-Host "Detected local CareTV pool automatically:" Write-Host " Share: \\$env:COMPUTERNAME\$ShareName" Write-Host " Path: $root" Write-Host "" $folders = @( "Users", "Users\Mom", "Users\Mom\Audio", "Users\Mom\Video", "Users\Mom\Screens", "Users\Mom\Photos", "Users\Mom\Documents", "Users\Mom\CareTV-Captures" ) foreach ($relative in $folders) { $folder = Join-Path $root $relative if (-not (Test-Path $folder)) { New-Item -Path $folder -ItemType Directory -Force | Out-Null Write-Host "Created: $folder" } else { Write-Host "Exists: $folder" } } $localAdmin = "$env:COMPUTERNAME\$AdminUser" $localService = "$env:COMPUTERNAME\$ServiceUser" $localMom = "$env:COMPUTERNAME\$MomUser" $momRoot = Join-Path $root $MomRelativePath Write-Host "" Write-Host "Adding CareTV NTFS permissions (non-destructive/additive)..." # v001 is deliberately additive. Existing DrivePool/admin ACLs are preserved. & icacls.exe "$root" /grant:r "${localAdmin}:(OI)(CI)F" /T /C | Out-Null & icacls.exe "$root" /grant:r "${localService}:(OI)(CI)M" /T /C | Out-Null & icacls.exe "$momRoot" /grant:r "${localMom}:(OI)(CI)M" /T /C | Out-Null Write-Host " caretv-admin = Full Control across CareTV pool tree" Write-Host " caretv-service = Modify across CareTV pool tree" Write-Host " caretv-mom = Modify in Users\Mom tree" Write-Host "" Write-Host "Adding SMB share permissions..." Grant-SmbShareAccess -Name $ShareName -AccountName $localAdmin -AccessRight Full -Force -ErrorAction SilentlyContinue | Out-Null Grant-SmbShareAccess -Name $ShareName -AccountName $localService -AccessRight Change -Force -ErrorAction SilentlyContinue | Out-Null Grant-SmbShareAccess -Name $ShareName -AccountName $localMom -AccessRight Change -Force -ErrorAction SilentlyContinue | Out-Null Write-Host "Server permissions added." Write-Host "" Write-Host "NOTE: v001 is intentionally additive. It does not remove existing" Write-Host "DrivePool/share permissions, so it will not unexpectedly lock out" Write-Host "existing administrators. Permissions can be tightened later." } function Configure-MomMapping { Write-Section "CareTV Mom Storage Mapping" $careTVDir = Join-Path $env:ProgramData "CareTV" New-Item -Path $careTVDir -ItemType Directory -Force | Out-Null $mapFile = Join-Path $careTVDir "Map-CareTV-Mom-Storage.cmd" $mapText = @" @echo off net use $MomDrive /delete /y >nul 2>&1 net use $MomDrive "$MomUNC" /persistent:yes "@ Set-Content -Path $mapFile -Value $mapText -Encoding ASCII $taskName = "CareTV - Map Mom Storage" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c `"$mapFile`"" $trigger = New-ScheduledTaskTrigger -AtLogOn -User "$env:COMPUTERNAME\$MomUser" $principal = New-ScheduledTaskPrincipal ` -UserId "$env:COMPUTERNAME\$MomUser" ` -LogonType Interactive ` -RunLevel Limited try { Register-ScheduledTask ` -TaskName $taskName ` -Action $action ` -Trigger $trigger ` -Principal $principal ` -Force | Out-Null Write-Host "At caretv-mom login this machine will automatically map:" Write-Host " $MomDrive -> $MomUNC" } catch { Write-Warning "Could not install Mom's automatic M: mapping task." Write-Warning $_ } [Environment]::SetEnvironmentVariable("CARETV_MOM_DATA", $MomUNC, "Machine") Write-Host "System variable CARETV_MOM_DATA = $MomUNC" } Require-Administrator Write-Section "CareTV Windows Standard Setup v001" Write-Host "Computer: $env:COMPUTERNAME" Write-Host "Mode: $Mode" Write-Host "Server: \\$ServerName\$ShareName" Write-Host "" if ($Mode -eq "All" -or $Mode -eq "Network") { Configure-Networking } if ($Mode -eq "All" -or $Mode -eq "Accounts") { Configure-Accounts } if ($Mode -eq "All" -or $Mode -eq "Storage") { Configure-ServerStorage } if ($Mode -eq "All") { Configure-MomMapping } Write-Section "CareTV Setup v001 Complete" Write-Host "Computer: $env:COMPUTERNAME" Write-Host "" Write-Host "Standard accounts:" Write-Host " caretv-admin = Administrator" Write-Host " caretv-service = Standard service account" Write-Host " caretv-mom = Standard Mom account" Write-Host "" Write-Host "Current CareTV pool:" Write-Host " \\$ServerName\$ShareName" Write-Host "" Write-Host "Mom data:" Write-Host " $MomUNC" Write-Host " M: maps automatically when caretv-mom logs in." Write-Host ""