application-workloads/traefik/docker-portainer-traefik-windows-vm/setup.ps1 (110 lines of code) (raw):

param ( $mail, $publicdnsname, $adminPwd, $basePath, $publicSshKey ) $ProgressPreference = 'SilentlyContinue' # format disk and create folders Get-Disk | Where-Object partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -UseMaximumSize -DriveLetter F | Format-Volume -FileSystem NTFS -Confirm:$false -Force New-Item -Path f:\le -ItemType Directory | Out-Null New-Item -Path f:\le\acme.json | Out-Null New-Item -Path f:\dockerdata -ItemType Directory | Out-Null New-Item -Path f:\portainerdata -ItemType Directory | Out-Null New-Item -Path f:\compose -ItemType Directory | Out-Null # install vim and openssh using chocolatey [DownloadWithRetry]::DoDownloadWithRetry("https://chocolatey.org/install.ps1", 5, 10, $null, ".\chocoInstall.ps1", $false) & .\chocoInstall.ps1 choco feature enable -n allowGlobalConfirmation choco install --no-progress --limit-output vim choco install --no-progress --limit-output pwsh choco install --no-progress --limit-output openssh -params '"/SSHServerFeature"' # configure OpenSSH, make pwsh the default shell, show hostname in shell and restart sshd Copy-Item "$basePath\sshd_config_wopwd" 'C:\ProgramData\ssh\sshd_config' $path = "c:\ProgramData\ssh\administrators_authorized_keys" "$publicSshKey" | Out-File -Encoding utf8 -FilePath $path $acl = Get-Acl -Path $path $acl.SetSecurityDescriptorSddlForm("O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") Set-Acl -Path $path -AclObject $acl New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Program Files\PowerShell\7\pwsh.exe" -PropertyType String -Force 'function prompt { "PS [$env:COMPUTERNAME]:$($executionContext.SessionState.Path.CurrentLocation)$(''>'' * ($nestedPromptLevel + 1)) " }' | Out-File -FilePath "$($PROFILE.AllUsersAllHosts)" -Encoding utf8 Restart-Service sshd # relocate docker data Stop-Service docker $dockerDaemonConfig = @" { `"data-root`": `"f:\\dockerdata`" } "@ $dockerDaemonConfig | Out-File "c:\programdata\docker\config\daemon.json" -Encoding ascii # avoid https://github.com/docker/for-win/issues/12358#issuecomment-964937374 Remove-Item 'f:\dockerdata\panic.log' -Force -ErrorAction SilentlyContinue | Out-Null New-Item 'f:\dockerdata\panic.log' -ItemType File -ErrorAction SilentlyContinue | Out-Null # avoid containers stuck in "create" Add-MpPreference -ExclusionPath 'C:\Program Files\docker\' Add-MpPreference -ExclusionPath 'f:\dockerdata' Start-Service docker # prepare password file for portainer $adminPwd | Out-File -NoNewline -Encoding ascii "f:\portainerdata\passwordfile" # download compose, the compose file and deploy it [DownloadWithRetry]::DoDownloadWithRetry("https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Windows-x86_64.exe", 5, 10, $null, "$($Env:ProgramFiles)\Docker\docker-compose.exe", $false) $template = Get-Content (Join-Path $basepath 'docker-compose.yml.template') -Raw $expanded = Invoke-Expression "@`"`r`n$template`r`n`"@" $expanded | Out-File "f:\compose\docker-compose.yml" -Encoding ASCII Set-Location "f:\compose" Invoke-Expression "docker-compose up -d" class DownloadWithRetry { static [string] DoDownloadWithRetry([string] $uri, [int] $maxRetries, [int] $retryWaitInSeconds, [string] $authToken, [string] $outFile, [bool] $metadata) { $retryCount = 0 $headers = @{} if (-not ([string]::IsNullOrEmpty($authToken))) { $headers = @{ 'Authorization' = $authToken } } if ($metadata) { $headers.Add('Metadata', 'true') } while ($retryCount -le $maxRetries) { try { if ($headers.Count -ne 0) { if ([string]::IsNullOrEmpty($outFile)) { $result = Invoke-WebRequest -Uri $uri -Headers $headers -UseBasicParsing return $result.Content } else { $result = Invoke-WebRequest -Uri $uri -Headers $headers -UseBasicParsing -OutFile $outFile return "" } } else { throw; } } catch { if ($headers.Count -ne 0) { write-host "download of $uri failed" } try { if ([string]::IsNullOrEmpty($outFile)) { $result = Invoke-WebRequest -Uri $uri -UseBasicParsing return $result.Content } else { $result = Invoke-WebRequest -Uri $uri -UseBasicParsing -OutFile $outFile return "" } } catch { write-host "download of $uri failed" $retryCount++; if ($retryCount -le $maxRetries) { Start-Sleep -Seconds $retryWaitInSeconds } } } } return "" } }