How to build Photon OS images using POI - dcasota/photonos-scripts GitHub Wiki
prerequisites.
tdnf makecache
tdnf install -y git docker docker-buildx
systemctl enable docker
systemctl start docker
# credentials
docker login
Clean an old installation.
CONTAINERNAME="photon-os-installer"
rm -rf /root/repo
docker image rm $CONTAINERNAME --force && docker system prune --force && docker image prune --force && docker container prune --force && docker volume prune --force
Clone photon-os-installer.
RELEASE="4.0"
mkdir -p $HOME/repo/$RELEASE
cd $HOME/repo/$RELEASE
# tags might be necessary
git clone --branch v2.7 https://github.com/vmware/photon-os-installer
cd $HOME/repo/$RELEASE/photon-os-installer
Copy the following zip file into $HOME/repo/$RELEASE/photon-os-installer. minimal-iso-4.0_x86_64.zip
Unzip it.
tdnf install -y unzip wget
wget https://github.com/user-attachments/files/21205924/minimal-iso-4.0_x86_64.zip
unzip ./minimal-iso-4.0_x86_64.zip
Build the container and start it interactively.
docker buildx build -t $CONTAINERNAME --build-context poi-helper=/root/repo/4.0/photon-os-installer ./minimal-iso-4.0_x86_64/.
docker run --rm -it --privileged -v /dev:/dev -v /$HOME/repo/4.0/photon-os-installer/minimal-iso-4.0_x86_64:/output $CONTAINERNAME /bin/bash
Make the iso.
# run inside the container
cd examples/iso
photon-iso-builder -y iso.yaml
# after the iso has been created, copy it to /output
cp photon-4.0.iso /output
Setup of a vm from the iso still fails. See https://github.com/vmware/photon-os-installer/issues/35 (edited 9th July 2025).
Cleanup.
# cleanup old photon-iso-builder directories
rm -rf /$HOME/repo/4.0/photon-os-installer/examples/iso/photon-*
docker image rm $CONTAINERNAME --force && docker system prune --force && docker image prune --force && docker container prune --force && docker volume prune --force
vmdk-convert Dockerfile. Dockerfile.txt
local cached repo
Optional: classic make minimal iso build with official remote sources Insert here the classic make build process or copy all official RPMS from https://packages.vmware.com/photon/4.0/photon_release_4.0_x86_64.
#!/bin/bash
# define the path
mkdir -p $HOME/4.0/stage/RPMS
cd $HOME/4.0/stage/RPMS
# Array of URLs and corresponding output directories
urls=(
"https://packages.vmware.com/photon/4.0/photon_release_4.0_x86_64/x86_64/"
"https://packages.vmware.com/photon/4.0/photon_release_4.0_x86_64/noarch/"
)
output_dirs=(
"./x86_64"
"./noarch"
)
# Check if the number of URLs matches the number of output directories
if [ ${#urls[@]} -ne ${#output_dirs[@]} ](/dcasota/photonos-scripts/wiki/-${#urls[@]}--ne-${#output_dirs[@]}-); then
echo "Error: Number of URLs (${#urls[@]}) does not match number of output directories (${#output_dirs[@]})"
exit 1
fi
# Loop through URLs and output directories
for ((i=0; i<${#urls[@]}; i++)); do
url="${urls[$i]}"
output_dir="${output_dirs[$i]}"
# Create output directory if it doesn't exist
mkdir -p "$output_dir"
# Fetch directory listing and extract .rpm file URLs
echo "Processing URL: $url"
curl -s "$url" | grep -o 'href="[^"]*\.rpm"' | sed 's/href="//' | sed 's/"//' | while read -r file; do
# Decode %2B%2B to ++ in the filename
decoded_file=$(echo "$file" | sed 's/%2B%2B/++/g')
# Download the file, saving it with the decoded filename
curl -s -o "$output_dir/$decoded_file" "$url$file"
if [ $? -ne 0 ](/dcasota/photonos-scripts/wiki/-$?--ne-0-); then
echo "Error: Failed to download $decoded_file from $url"
exit 1
fi
echo "Downloaded: $output_dir/$decoded_file"
done
# Check if any files were downloaded for this URL
if ls "$output_dir"/*.rpm >/dev/null 2>&1; then
echo "Successfully downloaded RPMs to $output_dir"
else
echo "Warning: No RPM files downloaded to $output_dir from $url"
fi
done
echo "All downloads completed"
Copy the missing RPMS from photon_updates_4.0/RPMS/noarch.
cd $HOME/4.0
mkdir -p ./photon_updates_4.0/RPMS/noarch
cd ./photon_updates_4.0/RPMS/noarch
wget https://packages.vmware.com/photon/4.0/photon_updates_4.0_x86_64/noarch/stig-hardening-1.5-2.ph4.noarch.rpm
wget https://packages.vmware.com/photon/4.0/photon_updates_4.0_x86_64/noarch/grub2-theme-4.0-2.ph4.noarch.rpm
wget https://packages.vmware.com/photon/4.0/photon_updates_4.0_x86_64/noarch/python3-requests-2.26.0-5.ph4.noarch.rpm
mkdir -p ./photon_updates_4.0/RPMS/x86_64/
cd /root/4.0/photon_updates_4.0/RPMS/x86_64/
wget https://packages.vmware.com/photon/4.0/photon_updates_4.0_x86_64/x86_64/rpm-plugin-systemd-inhibit-4.16.1.3-21.ph4.x86_64.rpm
content of rpmdb.sqlite.
#!/bin/bash
# SQLite database file
db_file="/var/lib/rpm/rpmdb.sqlite"
# Check if file exists
if [ ! -f "$db_file" ](/dcasota/photonos-scripts/wiki/-!--f-"$db_file"-); then
echo "Error: SQLite file $db_file not found"
exit 1
fi
# Check if sqlite3 is installed
if ! command -v sqlite3 >/dev/null 2>&1; then
echo "Error: sqlite3 command not found. Install with 'tdnf install sqlite'"
exit 1
fi
# List all tables
echo "Tables in $db_file:"
sqlite3 "$db_file" ".tables"
# Loop through each table and display schema and data
tables=$(sqlite3 "$db_file" ".tables")
for table in $tables; do
echo -e "\nSchema for table '$table':"
sqlite3 "$db_file" ".schema $table"
echo -e "\nData in table '$table':"
sqlite3 -column -header "$db_file" "SELECT * FROM $table;"
done
run container interactively:
# cleanup old photon-iso-builder directories
rm -rf /workdir/photon-*
docker run --rm -it --privileged -v /dev:/dev -v /$HOME/4.0/photon_updates_4.0:/photon_updates_4.0 -v /$HOME/4.0/stage:/repo -v /$HOME/repo/4.0/photon-os-installer/examples/iso:/workdir $CONTAINERNAME /bin/bash
Run inside the interactive shell.
createrepo /repo
createrepo /photon_updates_4.0
Some remarks. The more you use the /repo repository, adopt the yaml files to use local rpms. (todo)
The following script modifies packages_installer_40_initrd.json with the /repo path and full file name of the package. update_json_packages.txt
mv update_json_packages.txt update_json_packages.sh
chmod a+x ./update_json_packages.sh
./update_json_packages.sh ./packages_installer_40_initrd.json
./update_json_packages.sh ./packages_minimal.json
Make the iso.
cd /$HOME/repo/4.0/photon-os-installer/examples/iso
# -v /$HOME/repo/4.0/photon-os-installer/examples/iso:/workdir : Here are all .json and .yaml files
# -v /$HOME/4.0/stage:/repo : Here is the local repository done by classic make build
docker run --rm --privileged -v /dev:/dev -v /$HOME/4.0/stage:/repo -v /$HOME/repo/4.0/photon-os-installer/examples/iso:/workdir $CONTAINERNAME photon-iso-builder -y iso_40_minimal.yaml