├── ssh
├── .gitignore
├── hyperv
├── .gitignore
├── destroy_azure.sh
├── FirstLogonCommands.xml
├── variables.tf
├── README.md
├── packer-build.ps1
├── init_azure.sh
├── windows.tf
└── provision.ps1
├── images
└── packer_builder.png
├── DEBUG.md
├── Vagrantfile
├── packer-build.sh
├── README.md
├── .github
└── workflows
│ └── build.yml
├── scripts
└── provision-virtualbox+vmware-builder.sh
├── upload.sh
└── machine.sh
/ssh:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vagrant/
2 | *.jpg
3 | resources/
4 | arm/
5 | work/
6 |
--------------------------------------------------------------------------------
/hyperv/.gitignore:
--------------------------------------------------------------------------------
1 | terraform.tf*
2 | .terraform/
3 | .terraform.tfstate.lock.info
4 | packer-build.log
--------------------------------------------------------------------------------
/images/packer_builder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefanScherer/packer-builder/HEAD/images/packer_builder.png
--------------------------------------------------------------------------------
/DEBUG.md:
--------------------------------------------------------------------------------
1 | # Debugging packer builds
2 |
3 | ## hyperv
4 |
5 | Fetch the IP address of the Azure VM. Then adjust the login password
6 | trough SSH.
7 |
8 | ```
9 | ssh packer@1.2.3.4 net user packer TheNewPassword
10 | ```
11 |
12 | Now you can RDP into the machine with user packer and TheNewPassword
13 | and open the Hyper-V Manager and connect to the Hyper-V VM.
14 |
--------------------------------------------------------------------------------
/hyperv/destroy_azure.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | resource_group=$(grep -A1 resource_group variables.tf | grep -v resource_group | awk '{gsub(/"/, "", $3); print $3}')
4 |
5 | aadClientName="Terraform-$resource_group"
6 | echo "Deleting service principal $aadClientName"
7 | az ad app delete --id http://$aadClientName
8 |
9 | echo "Deleting resource group $resource_group"
10 | az group delete -n $resource_group
11 |
12 |
--------------------------------------------------------------------------------
/hyperv/FirstLogonCommands.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | cmd /c "copy C:\AzureData\CustomData.bin C:\provision.ps1"CopyScript
5 | 11
6 |
7 |
8 | powershell.exe -sta -ExecutionPolicy Unrestricted -file C:\provision.ps1RunScript
10 | 12
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure("2") do |config|
5 |
6 | config.vm.define "vmware", primary: true do |cfg|
7 | cfg.vm.box = "bento/ubuntu-20.04"
8 | cfg.vm.synced_folder "/Users/stefan/packer_cache", "/home/vagrant/packer_cache"
9 |
10 | cfg.vm.provision "shell", path: "scripts/provision-virtualbox+vmware-builder.sh"
11 | cfg.vm.provider "vmware_desktop" do |v, override|
12 | v.vmx["memsize"] = "6196"
13 | v.vmx["numvcpus"] = "4"
14 | v.vmx["vhv.enable"] = "TRUE"
15 | v.gui = true
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/hyperv/variables.tf:
--------------------------------------------------------------------------------
1 | # Settings
2 |
3 | variable "resource_group" {
4 | default = "packer-builder"
5 | }
6 |
7 | variable "location" {
8 | default = "westeurope"
9 | }
10 |
11 | variable "name" {
12 | default = "cirlce1"
13 | }
14 |
15 | variable "admin_username" {
16 | default = "packer"
17 | }
18 |
19 | variable "vm_size" {
20 | default = "Standard_D2s_v3"
21 | }
22 |
23 | variable "ssh" {
24 | default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDm3bZwzpnjklKH7D/w7a83pzqdvB340dBhQuOmpLszs0H+Js505zZWX3nb0OSFMJ6LjPHZBL9OTj6B+sWxj95QrUTonHso2Jb2bhe8UYwmqvKpmMHIjIjl4UV73tN4VJSWtBaxNdG7KYnpv0dyZu1JitR72+qRUohbzkUbVLQUQ/LE8LJI5ob0VK9EdFXl249gSgYOp4G6Tocy5aVYJAR80bC7Ujrn4tLB0dzBERNQjPrR5JHQ7OlFcaI0ho9zVy+GziU++vNols/Dl0TkvHJKxNE1XQTWAHj1YjVzTMfDlc2M9uoeY/GLXxlkPMskoKbopB1ZvAFGLP2ldUfQ7NA3"
25 | }
26 |
--------------------------------------------------------------------------------
/packer-build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | FILE=$1
3 | HYPERVISOR=$2
4 | GITHUB_URL=$3
5 | ISO_URL=$4
6 |
7 | log=packer-build.log
8 | echo $0 $* >> $log
9 |
10 | if [ ! -d work ]; then
11 | echo "Cloning $GITHUB_URL" >> $log
12 | git clone $GITHUB_URL work
13 | fi
14 | cd work
15 | touch $log
16 | git checkout -- *.json
17 | git pull
18 | rm -f *.box
19 | rm -rf output*
20 |
21 | isoflag=""
22 | if [ -z "${ISO_URL}" ]; then
23 | echo "Use default ISO." >> $log
24 | else
25 | echo "Use local ISO." >> $log
26 | if [ ! -e local.iso ]; then
27 | echo "Downloading ISO ..." >> $log
28 | curl -Lo local.iso $ISO_URL
29 | fi
30 | isoflag="--var iso_url=./local.iso"
31 | fi
32 |
33 | only=--only=${HYPERVISOR}-iso
34 | hypervisor1=${HYPERVISOR%+*}
35 | hypervisor2=${HYPERVISOR#*+}
36 | if [ "$hypervisor1" != "$hypervisor2" ]; then
37 | only="--only=${hypervisor1}-iso --only=${hypervisor2}-iso"
38 | fi
39 | echo Running packer build $only $isoflag --var headless=true "${FILE}.json" >> $log
40 | echo "" >> $log
41 | ls -l local.iso >> $log
42 | echo "" >> $log
43 | packer build $only $isoflag --var headless=true "${FILE}.json" | tee -a $log
44 |
45 | if [ ! -e ../packer-upload-and-destroy.sh ]; then
46 | sleep 30
47 | fi
48 |
49 | if [ -e ../packer-upload-and-destroy.sh ]; then
50 | ../packer-upload-and-destroy.sh | tee -a $log
51 | fi
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Packer Builder
2 |
3 | [](https://circleci.com/gh/StefanScherer/packer-builder)
4 |
5 | A Packer builder CI pipeline for VirtualBox, VMware and Hyper-V Vagrant boxes.
6 |
7 | 
8 |
9 | ## Packet.net
10 |
11 | Create a baremetal [packet.net](https://packet.net) machine and run Packer there.
12 |
13 | First you need the `packet` golang cli:
14 |
15 | ```bash
16 | go get -u github.com/ebsarr/packet
17 | ```
18 |
19 | Then use the script `machine.sh` to make things even simpler:
20 |
21 | ```bash
22 | ./machine.sh create p1
23 | ```
24 |
25 | And then build a VMware VM
26 |
27 | ```bash
28 | ./build.sh p1 windows_2019_docker vmware|virtualbox
29 | ```
30 |
31 | Afterwards remove the baremetal machine again
32 |
33 | ```bash
34 | ./machine.sh delete p1
35 | ```
36 |
37 | There are several other commands in `machine.sh`. Have a look at the usage.
38 |
39 | ## Azure
40 |
41 | See [hyperv](hyperv/README.md) sub folder.
42 |
43 | ## Vagrant
44 |
45 | Create a local VM and run Packer there. This is used to test the
46 | provision script.
47 |
48 | ```bash
49 | vagrant up
50 | vagrant ssh
51 | packer build ...
52 | ```
53 |
54 | ## Configuration
55 |
56 | ### CircleCI Environment Variables
57 |
58 | * AZURE_STORAGE_ACCESS_KEY
59 | * AZURE_STORAGE_ACCOUNT
60 | * AZURE_STORAGE_CONTAINER
61 | * PACKET_APIKEY
62 | * VAGRANT_CLOUD_TOKEN
63 | * VAGRANT_CLOUD_USER
64 | * windows_server_xxx_docker
65 |
--------------------------------------------------------------------------------
/hyperv/README.md:
--------------------------------------------------------------------------------
1 | # Packer Hyper-V builder in Azure
2 |
3 | This is a Terraform template to spin up a VM in Azure that has nested Hyper-V
4 | activated and tools like Git, Packer and Vagrant installed.
5 |
6 | Now you are able to build Vagrant base boxes for Hyper-V in the Cloud with Packer.
7 |
8 | ## Initialize Azure and CircleCI
9 |
10 | You need a personal API key for CircleCI. Set the environment variable `CIRCLECI_TOKEN`
11 | and run the script
12 |
13 | ```
14 | ./init_azure.sh
15 | ```
16 |
17 | It will create a resource group and service principal and set `ARM_SUBSCRIPTION_ID`, `ARM_CLIENT_ID`, `ARM_CLIENT_SECRET` and `ARM_TENANT_ID` in CircleCI.
18 |
19 | ## Destroy Azure
20 |
21 | If you want to clean up your Azure subscription run
22 |
23 | ```
24 | ./destroy_azure.sh
25 | ```
26 |
27 | It will remove the resource group and service princial and app from Azure.
28 |
29 | ## Spin up the Azure VM with Terraform from local machine
30 |
31 | ### Install Terraform
32 |
33 | ```
34 | brew install terraform
35 | ```
36 |
37 | ### Configure
38 |
39 | Adjust the file `variables.tf` to your needs to choose
40 |
41 | * location / region
42 | * resource group name
43 | * DNS prefix and suffix
44 | * size of the VM's, default is `Standard_E2s_v3` which is needed for nested virtualization
45 | * username and password
46 |
47 | ### Secrets
48 |
49 | For Terraform you will need these environment variables
50 |
51 | ```
52 | export ARM_SUBSCRIPTION_ID="uuid"
53 | export ARM_CLIENT_ID="uuid"
54 | export ARM_CLIENT_SECRET="secret"
55 | export ARM_TENANT_ID="uuid"
56 | ```
57 |
58 | ### Plan
59 |
60 | ```bash
61 | terraform plan
62 | ```
63 |
64 | ### Create / Apply
65 |
66 | Create the Azure VM with. After 5 minutes the VM should be up and running, and the provision.ps1 script will run inside the VM to install Packer, Vagrant, Hyper-V and then reboots the VM and adds the internal virtual switch 'packer-hyperv-iso' and DHCP server.
67 |
68 | ```bash
69 | terraform apply
70 | ```
71 |
72 | If you want more than one Packer VM, then use eg. `terraform apply -var name=circle123`.
73 |
--------------------------------------------------------------------------------
/hyperv/packer-build.ps1:
--------------------------------------------------------------------------------
1 | param ([String] $FILE, [String] $HYPERVISOR, [String] $GITHUB_URL, [String] $ISO_URL)
2 |
3 | if (!(Test-Path d:/work)) {
4 | Write-Host "Cloning $GITHUB_URL"
5 | git clone $GITHUB_URL d:/work
6 | }
7 |
8 | if ($HYPERVISOR -eq "azure") {
9 | $HYPERVISOR="hyperv"
10 | }
11 |
12 | cd d:/work
13 |
14 | git checkout -- *.json
15 | git pull
16 | Remove-Item *.box
17 | Remove-Item -recurse output*
18 | $isoflag=""
19 |
20 | # Allow me (user of that GitHub repo) to SSH into the machine.
21 | $keyPath = "~\.ssh\authorized_keys"
22 | if (!(Test-Path ~\.ssh)) {
23 | New-Item -Type Directory ~\.ssh > $null
24 | }
25 | $githubKeysUrl = $GITHUB_URL -replace "\/[^\/]+$", ".keys"
26 | $githubSshKey = $(curl.exe $githubKeysUrl)
27 | $githubSshKey | Out-File $keyPath -Append -Encoding Ascii
28 |
29 | $log = "packer-build.log"
30 | $null | Out-File -Encoding Ascii $log
31 |
32 | if ( "$ISO_URL" -eq "" ) {
33 | Write-Host "Use default ISO." >> $log
34 | } else {
35 | Write-Host "Use local ISO." >> $log
36 | if (!(Test-Path local.iso)) {
37 | curl.exe -Lo local.iso $ISO_URL
38 | }
39 | $isoflag="--var iso_url=./local.iso"
40 | }
41 | $only="--only=$HYPERVISOR-iso"
42 |
43 | Write-Host "Running packer build $only --var headless=true ${FILE}.json"
44 |
45 | # Use a CMD.exe script to have real pipes that do not buffer long-running packer builds
46 | @"
47 | rem use Azure temporary storage drive
48 | set TEMP=D:\temp
49 | if not exist %TEMP% (
50 | mkdir %TEMP%
51 | )
52 | set PACKER_TMP_DIR=%TEMP%
53 |
54 | powershell -File make_unattend_iso.ps1
55 |
56 | packer build $only $isoflag --var headless=true $FILE.json | "C:\Program Files\Git\usr\bin\tee.exe" -a $log
57 |
58 | if not exist %USERPROFILE%\packer-upload-and-destroy.ps1 (
59 | ping 127.0.0.1 -n 30 > nul
60 | )
61 |
62 | if exist %USERPROFILE%\packer-upload-and-destroy.ps1 (
63 | powershell -file %USERPROFILE%\packer-upload-and-destroy.ps1 | "C:\Program Files\Git\usr\bin\tee.exe" -a $log
64 | )
65 |
66 | ping 127.0.0.1 -n 6 > nul
67 |
68 | taskkill /F /IM tail.exe
69 | "@ | Out-File -Encoding Ascii packer-build.bat
70 |
71 | Start-Process cmd.exe -ArgumentList "/C", "packer-build.bat"
72 |
--------------------------------------------------------------------------------
/hyperv/init_azure.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | for i in CIRCLECI_TOKEN
5 | do
6 | if [ -z "${!i}" ]; then
7 | echo "Environment variable $i must be set"
8 | exit 5
9 | fi
10 | done
11 |
12 | location=$(grep -A1 location variables.tf | grep -v location | awk '{gsub(/"/, "", $3); print $3}')
13 | resource_group=$(grep -A1 resource_group variables.tf | grep -v resource_group | awk '{gsub(/"/, "", $3); print $3}')
14 |
15 | echo "Creating resource group $resource_group"
16 | scope=$(az group create -n "$resource_group" -l "$location" | jq -r .id)
17 |
18 | aadClientName="Terraform-$resource_group"
19 | ARM_CLIENT_SECRET=$(pwgen 30 1)
20 |
21 | echo "Creating service principal $aadClientName"
22 |
23 | ARM_SUBSCRIPTION_ID=$(az account show | jq -r .id)
24 | ARM_TENANT_ID=$(az account show | jq -r .tenantId)
25 |
26 | set +e
27 | aadClientId=$(az ad sp show --id "http://$aadClientName" | jq -r .id)
28 | if [ "$aadClientId" != "" ]; then
29 | echo "Deleting old service principal $aadClientName"
30 | az ad sp delete --id "http://$aadClientName"
31 | fi
32 | set -e
33 | ARM_CLIENT_ID=$(az ad sp create-for-rbac -n "$aadClientName" --password "$ARM_CLIENT_SECRET" --role contributor --scopes "$scope" | jq -r .appId)
34 |
35 | org=$(git remote get-url origin | sed 's/.*github.com://' | sed 's/.*github.com\///' | sed 's/\.git$//' | sed 's/\/.*$//' )
36 | repo=$(git remote get-url origin | sed 's/.*github.com://' | sed 's/.*github.com\///' | sed 's/\.git$//' | sed 's/.*\///' )
37 |
38 | circlevars="
39 | ARM_SUBSCRIPTION_ID
40 | ARM_CLIENT_ID
41 | ARM_CLIENT_SECRET
42 | ARM_TENANT_ID
43 | "
44 |
45 | echo "Deleting CircleCI environment variables for $org/$repo"
46 | for i in $circlevars
47 | do
48 | curl -X DELETE -sS --fail --header "Content-Type: application/json" "https://circleci.com/api/v1.1/project/github/$org/$repo/envvar/$i?circle-token=$CIRCLECI_TOKEN" >/dev/null || true
49 | done
50 |
51 | echo "Setting CircleCI environment variables for $org/$repo"
52 | for i in $circlevars
53 | do
54 | curl -X POST -sS --fail --header "Content-Type: application/json" -d "{\"name\":\"${i}\", \"value\":\"${!i}\"}" "https://circleci.com/api/v1.1/project/github/$org/$repo/envvar?circle-token=$CIRCLECI_TOKEN" >/dev/null
55 | done
56 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 |
10 | build:
11 | runs-on: ubuntu-latest
12 | env:
13 | PACKER_TEMPLATE: windows_10
14 | PACKET_PLAN: baremetal_1
15 | HYPERVISOR: virtualbox+vmware
16 | PACKET_APIKEY: ${{ secrets.PACKET_APIKEY }}
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Install SSH key
20 | uses: shimataro/ssh-key-action@v2
21 | with:
22 | key: ${{ secrets.SSH_KEY }}
23 | known_hosts: unnecessary
24 | - name: Install tools
25 | run: |
26 | docker create --name packet ebsarr/packet
27 | docker cp packet:/usr/local/bin/packet ./packet
28 | sudo mv ./packet /usr/local/bin/packet
29 | packet -v
30 | jq --version
31 | curl --version
32 | - name: Provision a packer build machine
33 | run: ./machine.sh create github${GITHUB_RUN_NUMBER} ${HYPERVISOR}
34 | - name: Run packer build
35 | run: ./build.sh github${GITHUB_RUN_NUMBER} ${PACKER_TEMPLATE} ${HYPERVISOR}
36 | env:
37 | AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }}
38 | AZURE_STORAGE_ACCESS_KEY: ${{ secrets.AZURE_STORAGE_ACCESS_KEY }}
39 | AZURE_STORAGE_CONTAINER: ${{ secrets.AZURE_STORAGE_CONTAINER }}
40 | ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
41 | ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
42 | ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
43 | ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
44 |
45 | # upload:
46 | # runs-on: ubuntu-latest
47 | # env:
48 | # PACKER_TEMPLATE: windows_10
49 | # HYPERVISOR: virtualbox+vmware
50 | # container:
51 | # image: mcr.microsoft.com/azure-cli:2.28.0
52 | # steps:
53 | # - uses: actions/checkout@v2
54 | # - name: Install tools
55 | # run: |
56 | # apk update && apk add jq curl
57 | # az --version
58 | # jq --version
59 | # curl --version
60 | # - name: Upload to Vagrant Cloud
61 | # run: ./upload.sh ${PACKER_TEMPLATE} ${HYPERVISOR}
62 | # env:
63 | # AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }}
64 | # AZURE_STORAGE_ACCESS_KEY: ${{ secrets.AZURE_STORAGE_ACCESS_KEY }}
65 | # AZURE_STORAGE_CONTAINER: ${{ secrets.AZURE_STORAGE_CONTAINER }}
66 | # ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
67 | # ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
68 | # ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
69 | # ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
70 | # VAGRANT_CLOUD_TOKEN: ${{ secrets.VAGRANT_CLOUD_TOKEN }}
71 | # VAGRANT_CLOUD_USER: ${{ secrets.VAGRANT_CLOUD_USER }}
72 |
--------------------------------------------------------------------------------
/scripts/provision-virtualbox+vmware-builder.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -x
3 |
4 | echo "Running provision-virtualbox+vmware-builder.sh"
5 |
6 | PACKER_VERSION=1.7.2
7 | VMWARE_VERSION=16.1.1-17801498
8 | VIRTUALBOX_VERSION=6.1
9 | TRIAL1=504RK
10 | TRIAL2=GV011
11 | TRIAL3=M88X2
12 | TRIAL4=0CAK6
13 | TRIAL5=2H2Q6
14 |
15 | PACKER_URL=https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_amd64.zip
16 | VMWARE_URL=http://download3.vmware.com/software/wkst/file/VMware-Workstation-Full-${VMWARE_VERSION}.x86_64.bundle
17 |
18 | # Install Virtualbox
19 | echo "deb http://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib" >> /etc/apt/sources.list
20 | wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
21 | wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -
22 | DEBIAN_FRONTEND=noninteractive apt-get update
23 | sudo DEBIAN_FRONTEND=noninteractive apt-get install -qq git unzip curl dkms build-essential \
24 | "linux-headers-$(uname -r)" x11-common x11-xserver-utils libxtst6 libxinerama1 psmisc
25 |
26 | sudo DEBIAN_FRONTEND=noninteractive apt-get install -y virtualbox-${VIRTUALBOX_VERSION}
27 |
28 | # Install VirtualBox extension pack
29 | vbox=$(VBoxManage --version)
30 | vboxversion=${vbox%r*}
31 | vboxrevision=${vbox#*r}
32 | wget https://download.virtualbox.org/virtualbox/${vboxversion}/Oracle_VM_VirtualBox_Extension_Pack-${vboxversion}-${vboxrevision}.vbox-extpack
33 | yes | VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-${vboxversion}-${vboxrevision}.vbox-extpack
34 | rm Oracle_VM_VirtualBox_Extension_Pack-${vboxversion}-${vboxrevision}.vbox-extpack
35 |
36 | # install packer
37 | mkdir /opt/packer
38 | pushd /opt/packer
39 | echo "Downloading packer ${PACKER_VERSION} ...."
40 | curl -L -o ${PACKER_VERSION}_linux_amd64.zip ${PACKER_URL}
41 | echo "Installing packer ${PACKER_VERSION} ..."
42 | unzip ${PACKER_VERSION}_linux_amd64.zip
43 | rm ${PACKER_VERSION}_linux_amd64.zip
44 | pushd /usr/bin
45 | ln -s /opt/packer/* .
46 | popd
47 | popd
48 |
49 | rmmod kvm_intel kvm
50 |
51 | echo "Downloading VMware Workstation ${VMWARE_VERSION} ..."
52 | curl -o VMware-Workstation.bundle ${VMWARE_URL}
53 | echo "Installing VMware Workstation ${VMWARE_VERSION} ..."
54 | sh ./VMware-Workstation.bundle --console --required --eulas-agreed --set-setting vmware-workstation serialNumber $TRIAL1-$TRIAL2-$TRIAL3-$TRIAL4-$TRIAL5
55 | rm ./VMware-Workstation.bundle
56 |
57 | echo "Installing Azure cli ..."
58 | sudo apt-get install -y ca-certificates curl apt-transport-https lsb-release gnupg
59 | curl -sL https://packages.microsoft.com/keys/microsoft.asc | \
60 | gpg --dearmor | \
61 | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc.gpg > /dev/null
62 | AZ_REPO=$(lsb_release -cs)
63 | echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | \
64 | sudo tee /etc/apt/sources.list.d/azure-cli.list
65 | sudo apt-get update
66 | sudo apt-get install -y azure-cli
67 |
--------------------------------------------------------------------------------
/upload.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | FILE=$1
5 | HYPERVISOR=$2
6 |
7 | if [ -z "${FILE}" ] || [ "${FILE}" == "--help" ] || [ -z "${HYPERVISOR}" ]; then
8 | echo "Usage: $0 template hypervisor"
9 | echo "$0 windows_2019_docker vmware"
10 | exit 1
11 | fi
12 |
13 | function upload {
14 | FILE=$1
15 | BOX_VERSION=$2
16 | HYPERVISOR=$3
17 |
18 | VAGRANT_PROVIDER="$HYPERVISOR"
19 | if [ "$HYPERVISOR" == "vmware" ]; then
20 | VAGRANT_PROVIDER="${HYPERVISOR}_desktop"
21 | fi
22 |
23 | echo "Create a new provider $VAGRANT_PROVIDER for version $BOX_VERSION"
24 | curl \
25 | --header "Content-Type: application/json" \
26 | --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
27 | "https://app.vagrantup.com/api/v1/box/$VAGRANT_CLOUD_USER/$FILE/version/$BOX_VERSION/providers" \
28 | --data "{ \"provider\": { \"name\": \"$VAGRANT_PROVIDER\" } }"
29 |
30 | echo "Prepare the provider for upload/get an upload URL"
31 | response=$(curl \
32 | --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
33 | "https://app.vagrantup.com/api/v1/box/$VAGRANT_CLOUD_USER/$FILE/version/$BOX_VERSION/provider/$VAGRANT_PROVIDER/upload")
34 |
35 | # Extract the upload URL from the response (requires the jq command)
36 | upload_path=$(echo "$response" | jq -r .upload_path)
37 |
38 | echo "Upload ${FILE}_${HYPERVISOR}.box to Vagrant Cloud"
39 | set +e
40 | output=$(curl $upload_path --request PUT --upload-file "${FILE}_${HYPERVISOR}.box")
41 | stat=$?
42 | if [ "$stat" == "52" ]; then
43 | echo "Got curl status 52, ignoring for now."
44 | fi
45 | set -e
46 |
47 | rm "${FILE}_${HYPERVISOR}.box"
48 | }
49 |
50 | function download {
51 | FILE=$1
52 | HYPERVISOR=$2
53 | echo "Download box ${FILE}_${HYPERVISOR}.box"
54 | today=$(date +%Y-%m-%d)
55 | az storage blob download --account-name "${AZURE_STORAGE_ACCOUNT}" --account-key "${AZURE_STORAGE_ACCESS_KEY}" --container-name "${AZURE_STORAGE_CONTAINER}" --name "${FILE}/$today/${FILE}_${HYPERVISOR}.box" --file "${FILE}_${HYPERVISOR}.box" || true
56 |
57 | if [ ! -e "${FILE}_${HYPERVISOR}.box" ]; then
58 | yesterday=$(date -d "yesterday 13:00" +%Y-%m-%d)
59 | az storage blob download --account-name "${AZURE_STORAGE_ACCOUNT}" --account-key "${AZURE_STORAGE_ACCESS_KEY}" --container-name "${AZURE_STORAGE_CONTAINER}" --name "${FILE}/$yesterday/${FILE}_${HYPERVISOR}.box" --file "${FILE}_${HYPERVISOR}.box" || true
60 | fi
61 |
62 | if [ ! -e "${FILE}_${HYPERVISOR}.box" ]; then
63 | twodaysago=$(date -d "2 days ago 13:00" +%Y-%m-%d)
64 | az storage blob download --account-name "${AZURE_STORAGE_ACCOUNT}" --account-key "${AZURE_STORAGE_ACCESS_KEY}" --container-name "${AZURE_STORAGE_CONTAINER}" --name "${FILE}/$twodaysago/${FILE}_${HYPERVISOR}.box" --file "${FILE}_${HYPERVISOR}.box"
65 | fi
66 | }
67 |
68 | BOX_VERSION=$(date +%Y.%m.%d)
69 | echo "Create a new version $BOX_VERSION for $FILE in Vagrant Cloud"
70 | curl \
71 | --header "Content-Type: application/json" \
72 | --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
73 | "https://app.vagrantup.com/api/v1/box/$VAGRANT_CLOUD_USER/$FILE/versions" \
74 | --data "{ \"version\": { \"version\": \"$BOX_VERSION\" } }"
75 |
76 | hypervisor1=${HYPERVISOR%+*}
77 | hypervisor2=${HYPERVISOR#*+}
78 |
79 | echo "Login to Azure"
80 | export AZURE_STORAGE_ACCOUNT=$AZURE_STORAGE_ACCOUNT
81 | export AZURE_STORAGE_ACCESS_KEY=$AZURE_STORAGE_ACCESS_KEY
82 |
83 | export ARM_SUBSCRIPTION_ID=$ARM_SUBSCRIPTION_ID
84 | export ARM_CLIENT_ID=$ARM_CLIENT_ID
85 | export ARM_CLIENT_SECRET=$ARM_CLIENT_SECRET
86 | export ARM_TENANT_ID=$ARM_TENANT_ID
87 |
88 | az login --service-principal --username "${ARM_CLIENT_ID}" --password "${ARM_CLIENT_SECRET}" --tenant "${ARM_TENANT_ID}" >az-login.txt
89 |
90 | download "$FILE" "$hypervisor1"
91 | upload "$FILE" "$BOX_VERSION" "$hypervisor1"
92 |
93 | if [ "$hypervisor1" != "$hypervisor2" ]; then
94 | download "$FILE" "$hypervisor2"
95 | upload "$FILE" "$BOX_VERSION" "$hypervisor2"
96 | fi
97 |
--------------------------------------------------------------------------------
/hyperv/windows.tf:
--------------------------------------------------------------------------------
1 | # Configure the Microsoft Azure Provider
2 | provider "azurerm" {
3 | version = "= 1.25.0"
4 | }
5 |
6 | provider "random" {
7 | version = "~> 1.1"
8 | }
9 |
10 | resource "random_string" "password" {
11 | length = 16
12 | special = false
13 | }
14 |
15 | # Create a storage account
16 | resource "azurerm_storage_account" "global" {
17 | account_tier = "Premium" # Only locally redundant
18 | account_replication_type = "LRS"
19 | location = "${var.location}"
20 | name = "${var.name}"
21 | resource_group_name = "${var.resource_group}"
22 | }
23 |
24 | resource "azurerm_virtual_network" "windows" {
25 | name = "virtnet-${var.name}"
26 | address_space = ["10.0.0.0/16"]
27 | location = "${var.location}"
28 | resource_group_name = "${var.resource_group}"
29 | }
30 |
31 | resource "azurerm_subnet" "windows" {
32 | name = "subnet-${var.name}"
33 | resource_group_name = "${var.resource_group}"
34 | virtual_network_name = "${azurerm_virtual_network.windows.name}"
35 | address_prefix = "10.0.2.0/24"
36 | }
37 |
38 | resource "azurerm_network_interface" "windows" {
39 | name = "nic-${var.name}"
40 | location = "${var.location}"
41 | resource_group_name = "${var.resource_group}"
42 |
43 | ip_configuration {
44 | name = "testconfiguration1"
45 | subnet_id = "${azurerm_subnet.windows.id}"
46 | public_ip_address_id = "${azurerm_public_ip.windows.id}"
47 | private_ip_address_allocation = "dynamic"
48 | }
49 | }
50 |
51 | resource "azurerm_public_ip" "windows" {
52 | idle_timeout_in_minutes = 30
53 | location = "${var.location}"
54 | name = "pubip-${var.name}"
55 | allocation_method = "Dynamic"
56 | resource_group_name = "${var.resource_group}"
57 | }
58 |
59 | resource "azurerm_storage_container" "windows" {
60 | container_access_type = "private"
61 | name = "windows-storage"
62 | resource_group_name = "${var.resource_group}"
63 | storage_account_name = "${azurerm_storage_account.global.name}"
64 | }
65 |
66 | resource "azurerm_virtual_machine" "windows" {
67 | name = "vm-${var.name}"
68 | location = "${var.location}"
69 | resource_group_name = "${var.resource_group}"
70 | network_interface_ids = ["${azurerm_network_interface.windows.id}"]
71 | vm_size = "${var.vm_size}"
72 |
73 | storage_image_reference {
74 | publisher = "MicrosoftWindowsServer"
75 | offer = "WindowsServer"
76 | sku = "2019-Datacenter"
77 | version = "latest"
78 | }
79 |
80 | storage_os_disk {
81 | name = "osdisk-${var.name}"
82 | vhd_uri = "${azurerm_storage_container.windows.id}/disk1.vhd"
83 | caching = "ReadWrite"
84 | create_option = "FromImage"
85 | }
86 |
87 | os_profile {
88 | computer_name = "${var.name}"
89 | admin_username = "${var.admin_username}"
90 | admin_password = "${random_string.password.result}"
91 | custom_data = "${base64encode("Param($Username=\"${var.admin_username}\", $Password=\"${random_string.password.result}\", $sshKey=\"${var.ssh}\") ${file("./provision.ps1")}")}"
92 | }
93 |
94 | os_profile_windows_config {
95 | provision_vm_agent = true
96 | enable_automatic_upgrades = true
97 | additional_unattend_config {
98 | pass = "oobeSystem"
99 | component = "Microsoft-Windows-Shell-Setup"
100 | setting_name = "AutoLogon"
101 | content = "${random_string.password.result}true1${var.admin_username}"
102 | }
103 | additional_unattend_config {
104 | pass = "oobeSystem"
105 | component = "Microsoft-Windows-Shell-Setup"
106 | setting_name = "FirstLogonCommands"
107 | content = "${file("./FirstLogonCommands.xml")}"
108 | }
109 | }
110 |
111 | tags {
112 | environment = "staging"
113 | }
114 | }
115 |
116 | output "ip" {
117 | value = "${azurerm_public_ip.windows.ip_address}"
118 | }
119 |
--------------------------------------------------------------------------------
/machine.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | COMMAND=$1
4 | NAME=$2
5 | HYPERVISOR=$3
6 |
7 | OSTYPE=ubuntu_20_04
8 | PACKET_PLAN=${PACKET_PLAN:-baremetal_0}
9 | PROJECT=${PACKET_PROJECT:-packer}
10 | AZURE_PLAN=${AZURE_PLAN:-Standard_D2s_v3}
11 |
12 | if [ -z "${COMMAND}" ] || [ "${COMMAND}" == "--help" ] ; then
13 | echo "Usage:"
14 | echo " $0 cleanup delete old machines"
15 | echo " $0 create name type create a new machine with vmware|virtualbox"
16 | echo " $0 delete name delete a machine"
17 | echo " $0 ip name get IP address of a machine"
18 | echo " $0 list list all machines"
19 | echo " $0 provision name type provision the machine with vmware|virtualbox"
20 | echo " $0 ssh name ssh into a machine"
21 | echo " $0 start name start a machine"
22 | echo " $0 stop name stop a machine"
23 | exit 1
24 | fi
25 |
26 | TOKEN=${PACKET_APIKEY}
27 |
28 | if [ -z "${TOKEN}" ]; then
29 | TOKEN=$(pass packet_token)
30 | fi
31 |
32 | function create {
33 | NAME=$1
34 | PROJECTID=$2
35 | HYPERVISOR=$3
36 |
37 | if [ -z "${NAME}" ]; then
38 | echo "Usage: $0 name"
39 | exit 1
40 | fi
41 |
42 | # create project if it does not exist
43 | if [ -z "${PROJECTID}" ]; then
44 | PROJECTID=$(packet -k "${TOKEN}" \
45 | admin create-project --name "${PROJECT}" | jq -r .id)
46 | fi
47 |
48 | for facility in ewr1 sjc1 dfw2 ams1 nrt1
49 | do
50 | echo "Creating baremetal machine in packet facility $facility"
51 | # create machine
52 | if packet -k "${TOKEN}" baremetal create-device \
53 | --billing hourly \
54 | --facility "${facility}" \
55 | --os-type "${OSTYPE}" \
56 | --plan "${PACKET_PLAN}" \
57 | --project-id "${PROJECTID}" \
58 | --hostname "${NAME}"; then
59 | break
60 | fi
61 | done
62 |
63 | provision "${NAME}" "${PROJECTID}" "${HYPERVISOR}"
64 | }
65 |
66 | function cmd {
67 | NAME=$1
68 | PROJECTID=$2
69 | CMD=$3
70 |
71 | if [ -z "${NAME}" ] || [ -z "${PROJECTID}" ] || [ -z "${CMD}" ]; then
72 | echo "Usage: $0 name id command"
73 | exit 1
74 | fi
75 |
76 | DEVICEID=$(packet -k "${TOKEN}" \
77 | baremetal list-devices --project-id "${PROJECTID}" | jq -r ".[] | select(.hostname == \"${NAME}\") .id")
78 |
79 | packet -k "${TOKEN}" \
80 | baremetal "${CMD}" --device-id "${DEVICEID}"
81 | }
82 |
83 | function start {
84 | echo "Starting $1"
85 | cmd "$1" "$2" poweron-device
86 | }
87 |
88 | function stop {
89 | echo "Stopping $1"
90 | cmd "$1" "$2" poweroff-device
91 | }
92 |
93 | function delete {
94 | echo "Deleting $1"
95 | cmd "$1" "$2" delete-device
96 | }
97 |
98 | function cleanup {
99 | machines=$(packet -k "${TOKEN}" baremetal list-devices --project-id "${PROJECTID}" | \
100 | jq -r '.[] | .hostname')
101 | for m in $machines
102 | do
103 | circle_build_num=${m#*e}
104 | RESPONSE=$(curl \
105 | --silent -S \
106 | --fail \
107 | "https://circleci.com/api/v1.1/project/github/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${circle_build_num}")
108 | STATE=$(echo "${RESPONSE}" | jq -r .lifecycle)
109 | echo "Found machine $m, CircleCI build ${circle_build_num} is ${STATE}"
110 |
111 | if [ "${STATE}" == "finished" ]; then
112 | echo "Removing resources of finished CircleCI job $circle_build_num"
113 | delete "$m" "$2"
114 | fi
115 | done
116 | echo "Cleanup done."
117 | }
118 |
119 | function list {
120 | packet -k "${TOKEN}" baremetal list-devices --project-id "${PROJECTID}" | \
121 | jq -r '.[] | .hostname + " " + .state'
122 | }
123 |
124 | function ip {
125 | packet -k "${TOKEN}" baremetal list-devices --project-id "${PROJECTID}" | \
126 | jq -r ".[] | select(.hostname == \"${NAME}\") | .ip_addresses[] | select(.public == true) | select(.address_family == 4).address" | head -1
127 | }
128 |
129 | function provision {
130 | echo "Provisioning $1"
131 | IP=$(ip)
132 | ssh-keygen -R "${IP}"
133 | ssh-keyscan "${IP}" >>~/.ssh/known_hosts
134 | /usr/bin/ssh "root@${IP}" < "scripts/provision-${HYPERVISOR}-builder.sh"
135 | }
136 |
137 | function ssh {
138 | /usr/bin/ssh "root@$(ip)"
139 | }
140 |
141 | function azure_create {
142 | NAME=$1
143 | HYPERVISOR=$2
144 |
145 | cd hyperv
146 | terraform init -input=false
147 | echo "Running Terraform to build VM ${NAME}"
148 | terraform apply -input=false -auto-approve --var "name=${NAME}" --var "vm_size=${AZURE_PLAN}"
149 |
150 | echo "Refreshing Terraform state"
151 | terraform refresh -input=false | grep -vi password
152 |
153 | IP=$(terraform output ip)
154 | if [ -z "$IP" ]; then
155 | echo "Waiting for IP"
156 | sleep 60
157 | IP=$(terraform output ip)
158 | fi
159 |
160 | echo "IP address of Azure VM $NAME: $IP"
161 |
162 | echo "Wait until SSH is available"
163 | maxConnectionAttempts=30
164 | sleepSeconds=20
165 | index=1
166 | success=0
167 |
168 | while (( index <= maxConnectionAttempts ))
169 | do
170 | /usr/bin/ssh -o StrictHostKeyChecking=no "packer@$IP" ver
171 | case $? in
172 | (0) echo "${index}> Success"; ((success+=1));;
173 | (*) echo "${index} of ${maxConnectionAttempts}> SSH server not ready yet, waiting ${sleepSeconds} seconds..."; success=0 ;;
174 | esac
175 | if [ $success -eq 2 ]; then
176 | break
177 | fi
178 | sleep $sleepSeconds
179 | ((index+=1))
180 | done
181 | set -e
182 |
183 | ssh-keygen -R "${IP}"
184 | ssh-keyscan "${IP}" >>~/.ssh/known_hosts
185 | }
186 |
187 | if [ "${HYPERVISOR}" == "hyperv" ]; then
188 | azure_create "${NAME}" "${HYPERVISOR}"
189 | elif [ "${HYPERVISOR}" == "azure" ]; then
190 | azure_create "${NAME}" "${HYPERVISOR}"
191 | else
192 | PROJECTID=$(packet -k "${TOKEN}" \
193 | admin list-projects | jq -r ".[] | select(.name == \"${PROJECT}\") .id")
194 |
195 | "${COMMAND}" "${NAME}" "${PROJECTID}" "${HYPERVISOR}"
196 | fi
197 |
--------------------------------------------------------------------------------
/hyperv/provision.ps1:
--------------------------------------------------------------------------------
1 |
2 | Start-Transcript -Path C:\provision.log -Append
3 |
4 | Function SetupPhase1 {
5 | Cscript $env:WinDir\System32\SCregEdit.wsf /AU 1
6 | Net stop wuauserv
7 | Net start wuauserv
8 |
9 | Set-MpPreference -DisableRealtimeMonitoring $true
10 |
11 | New-ItemProperty -Path HKCU:\Software\Microsoft\ServerManager -Name DoNotOpenServerManagerAtLogon -PropertyType DWORD -Value "1" -Force
12 |
13 | Write-Output "Installing Chocolatey"
14 | curl.exe -o install-chocolatey.ps1 https://chocolatey.org/install.ps1
15 | .\install-chocolatey.ps1
16 | choco feature disable --name showDownloadProgress
17 | choco install -y git
18 | choco install -y curl
19 | choco install -y packer -version 1.4.1
20 | # choco install -y vagrant -version 2.0.3
21 | choco install -y terraform -version 0.11.14
22 | choco install -y procexp
23 | choco install -y procmon
24 | choco install -y azure-cli
25 |
26 | Write-Output "Installing Hyper-V"
27 | Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All -NoRestart
28 | Install-WindowsFeature Hyper-V-Tools
29 | Install-WindowsFeature Hyper-V-PowerShell
30 |
31 | #Write-Output Install all Windows Updates
32 | #Get-Content C:\windows\system32\en-us\WUA_SearchDownloadInstall.vbs | ForEach-Object {
33 | # $_ -replace 'confirm = msgbox.*$', 'confirm = vbNo'
34 | #} | Out-File $env:TEMP\WUA_SearchDownloadInstall.vbs
35 | #"a`na" | cscript $env:TEMP\WUA_SearchDownloadInstall.vbs
36 |
37 | Write-Output "Rebooting"
38 | Restart-Computer
39 | }
40 |
41 | Function SetupPhase2 {
42 |
43 | # Write-Output "Installing Vagrant plugins"
44 | # vagrant plugin install vagrant-reload
45 |
46 | Write-Output "Adding NAT"
47 | New-VMSwitch -SwitchName "packer-hyperv-iso" -SwitchType Internal
48 | New-NetIPAddress -IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceIndex (Get-NetAdapter -name "vEthernet (packer-hyperv-iso)").ifIndex
49 | New-NetNat -Name MyNATnetwork -InternalIPInterfaceAddressPrefix 192.168.0.0/24
50 |
51 | Write-Output "Adding DHCP scope"
52 | Install-WindowsFeature DHCP -IncludeManagementTools
53 | Add-DhcpServerv4Scope -Name "Internal" -StartRange 192.168.0.10 -EndRange 192.168.0.250 -SubnetMask 255.255.255.0 -Description "Internal Network"
54 | Set-DhcpServerv4OptionValue -ScopeID 192.168.0 -DNSServer 8.8.8.8 -Router 192.168.0.1
55 |
56 | Write-Output "Allow Packer http server"
57 | New-NetFirewallRule -DisplayName "Allow Packer" -Direction Inbound -Program "C:\ProgramData\chocolatey\lib\packer\tools\packer.exe" -RemoteAddress LocalSubnet -Action Allow
58 |
59 | Write-Output "Disabling autologon"
60 | New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -PropertyType DWORD -Value "0" -Force
61 |
62 | Write-Output "Downloading OpenSSH"
63 | curl.exe -o OpenSSH-Win64.zip -L https://github.com/PowerShell/Win32-OpenSSH/releases/download/v8.0.0.0p1-Beta/OpenSSH-Win64.zip
64 |
65 | Write-Output "Expanding OpenSSH"
66 | Expand-Archive OpenSSH-Win64.zip -DestinationPath 'C:\Program Files'
67 | Remove-Item -Force OpenSSH-Win64.zip
68 |
69 | Push-Location 'C:\Program Files\OpenSSH-Win64'
70 |
71 | Write-Output "Installing OpenSSH"
72 | & .\install-sshd.ps1
73 |
74 | if ( ! (Test-Path $env:ProgramData\ssh) ) {
75 | New-Item -Type Directory $env:ProgramData\ssh
76 | }
77 |
78 | Write-Output "Generating host keys"
79 | .\ssh-keygen.exe -A
80 |
81 | Write-Output "Fixing host file permissions"
82 | & .\FixHostFilePermissions.ps1 -Confirm:$false
83 |
84 | Write-Output "Fixing user file permissions"
85 | & .\FixUserFilePermissions.ps1 -Confirm:$false
86 |
87 | $newPath = 'C:\Program Files\OpenSSH-Win64;' + [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::Machine)
88 | [Environment]::SetEnvironmentVariable("PATH", $newPath, [EnvironmentVariableTarget]::Machine)
89 |
90 | Write-Output 'Editing OpenSSH config'
91 | $sshd_config = Get-Content sshd_config_default
92 | $sshd_config = $sshd_config -replace 'StrictModes yes', 'StrictModes no'
93 | $sshd_config = $sshd_config -replace '#PubkeyAuthentication yes', 'PubkeyAuthentication yes'
94 | $sshd_config = $sshd_config -replace 'Match Group administrators', '#Match Group administrators'
95 | $sshd_config = $sshd_config -replace 'AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys', '#AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys'
96 | Set-Content $env:ProgramData\ssh\sshd_config $sshd_config
97 |
98 | Write-Output "Adding public key to authorized_keys"
99 | $keyPath = "~\.ssh\authorized_keys"
100 | New-Item -Type Directory ~\.ssh > $null
101 | $sshKey | Out-File $keyPath -Encoding Ascii
102 |
103 | Import-Module .\OpenSSHUtils.psd1 -Force
104 | Repair-AuthorizedKeyPermission -FilePath $keyPath
105 |
106 | Pop-Location
107 |
108 | Write-Output "Setting sshd service startup type to 'Automatic'"
109 | Set-Service sshd -StartupType Automatic
110 | Set-Service ssh-agent -StartupType Automatic
111 | Write-Output "Setting sshd service restart behavior"
112 | sc.exe failure sshd reset= 86400 actions= restart/500
113 |
114 | Write-Output "Starting sshd service"
115 | Start-Service sshd
116 | Start-Service ssh-agent
117 |
118 | Write-Output "Opening firewall port 22"
119 | New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
120 |
121 | Write-Output "Removing scheduled job"
122 | Unregister-ScheduledJob -Name NewServerSetupResume -Force
123 | }
124 |
125 | if (!(Test-Path c:\ProgramData\chocolatey)) {
126 | $pwd = ConvertTo-SecureString -String $Password -AsPlainText -Force
127 | $cred = New-Object System.Management.Automation.PSCredential($Username, $pwd)
128 | $AtStartup = New-JobTrigger -AtStartup
129 | Register-ScheduledJob -Name NewServerSetupResume `
130 | -Credential $cred `
131 | -Trigger $AtStartup `
132 | -ScriptBlock { c:\provision.ps1 }
133 | SetupPhase1
134 | } else {
135 | SetupPhase2
136 | }
137 |
--------------------------------------------------------------------------------