Ubuntu Server - ISO for releases?

The ISOs for releases are available when navigating the site starting at

However, for some reason, a peak under “ubuntu-server” shows no link to “releases”, the way others do. We have only daily builds offered.

Is that an oversight?

1 Like

No, not an oversight. That’s not where main releases are officially found. This is:

E.g. for 26.04, click https://releases.ubuntu.com/26.04/

The server image is linked on the page.

cdimage is and always has been an internal project resource, and not intended to be the main public facing place where users get the most popular ISOs. However, people will often grub around there looking for them, especially just prior to final release day.

What you will find on cdimage is ISOs for other supported architectures, like 64-bit ARM, RISC-V and more, here:

7 Likes

Thank you, Alan.

Darn!         That’s unfortunate, because I was hoping to continue using my custom script that simplifies things for me (for both Daily Builds and Releases). Unfortunately, the ubuntu-server hierarchy did not fall under the same “distribution” model for mirroring of those ISO images. I like things clean and regimented. :frowning:


Script: UTIL__Distro_GetRelatedDownloads.sh

#!/bin/sh

###
###	Version 4.0 - Limited checksum to specific ISO file that was downloaded
###
###	Version 3.0 - Updated to incorporate checksum of the ISO file
###
###	Version 2.0 - Updated to allow for selection of
###	              either Daily Build or Production Release
###	              as well as limited selection of Versions
###

doRelease=0
doTorrent=0
getAll=0
dbg=0
sep="<><><><><><><><><><><><><><><><><><><><>"


	mode=""
	resume="--continue"
#	addSuffix="--adjust-extension"
	allSources="--span-hosts"
#	makeLocal="--convert-links"
#	getParts="--page-requisites"
#	getParts="--no-parent    -mpEk --user-agent='Mozilla/5.0'"	### This does not work because it downloads too much using -m

while [ $# -gt 0 ]
do
	case $1 in
		"--release" )
			doRelease=1
			shift
			;;
		"--daily" )
			doRelease=0
			shift
			;;
		"--torrent" )
			doTorrent=1
			shift
			;;
		"--download" )
			getAll=1
			shift
			;;
		"--showfiles" )
			getAll=2
			shift
			;;
		"--verbose" )
			mode="$1"
			dbg=1
			shift
			;;
		"--debug" )
			mode="$1"
			dbg=2
			shift
			;;
		* )
			echo "\n\t Invalid option used.  Only valid options:  [ --download ] | [ --showfiles ] \n" ; exit 1
			;;
	esac
done

reportCommandComponents()
{
	echo "
	      mode = ${mode}
	    resume = ${resume}
	 addSuffic = ${addSuffix}
	allSources = ${allSources}
	 makeLocal = ${makeLocal}
	  getParts = ${getParts}
	 localFile = ${localFile}
	   url_DIR = ${url_DIR}\n"
}


chooseBuild()
{
	buildList=$(basename "$0" ".sh" ).buildslist
	rm -f buildslist

	#    ubuntu-base/
	#    ubuntu-core-desktop/
	#    ubuntu-core-installer/
	#    ubuntu-core/
	#    ubuntu-unity/
	#    ubuntu-wsl/
	#    ubuntukylin/

	echo "\n NOTES:
 	Download of Daily Builds is the default setting (--daily flag).
	To download production releases, run with '--release' flag.

 	if the '--torrent' flag is set on the command line,
	downloading of the *.iso file will be suppressed.


 Choose which ${scope} BUILD you wish to download ...

	[1]   ubuntu-mate
	[2]   ubuntu (Gnome)
	[3]   edubuntu
	[4]   kubuntu
	[5]   lubuntu
	[6]   xubuntu
	[7]   ubuntu-budgie
	[8]   ubuntucinnamon
	[9]   ubuntustudio"

	if [ ${doRelease} -eq 0 ]
	then
		echo "
	[10]  ubuntu-mini-iso
	[11]  ubuntu-server"
	fi
		echo "
	[Q]   Quit

 Enter selection [${choiceRange}|Q] => \c" ; read ans

	if [ -z "${ans}" ] ; then  ans="Q" ; fi


	case "${ans}" in
		1 )	isoBuild="ubuntu-mate" ;;
		2 )	isoBuild="ubuntu" ;;
		3 )	isoBuild="edubuntu" ;;
		4 )	isoBuild="kubuntu" ;;
		5 )	isoBuild="lubuntu" ;;
		6 )	isoBuild="xubuntu" ;;
		7 )	isoBuild="ubuntu-budgie" ;;
		8 )	isoBuild="ubuntucinnamon" ;;
		9 )	isoBuild="ubuntustudio" ;;
		10 )	isoBuild="ubuntu-mini-iso" ;;
		11 )	isoBuild="ubuntu-server" ;;
		q* | Q* )	echo "" ; exit ;;
	esac
} #chooseBuild_Daily()

getBuildsVersion()
{
	#https://cdimage.ubuntu.com/xubuntu/releases/26.04/release/
	#https://cdimages.ubuntu.com/xubuntu/releases/26.04/release/

	url_DIR="https://cdimages.ubuntu.com/${isoBuild}/releases/"
	localFile="-O ${localVers}"

	#rm -f ${localName}
	if [ -s "${localVers}" ]
	then
		echo "\n Using existing file '${localVers}' ..."
	else
		echo "\n${sep}${sep}${sep}\n Downloading information page for ${scope} ISO build  '${isoBuild}' ...\n"
		test ${dbg} -eq 2 && \
		echo " COMMAND:  wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} ${localFile} '${url_DIR}'"
		                 wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} ${localFile} "${url_DIR}"

		if [ $? -gt 0 ]
		then
			echo "\n\t Unable to proceed because a list of versions is not available for that ISO build.\n" ; exit 1
		fi
	fi

#more "${localVers}"

	thisYear=$(date '+%y' )
	thisMth=$(date '+%m' )
	rm -f ${jobList}
	rm -f ${jobList}.full

	#echo $thisYear $thisMth

	awk 'BEGIN{
		pr=0 ;
	}{
		if( pr == 1 ){
			print $0 ;
			if( $0 ~ /<[/]ul>/ ){
				exit ;
			} ;
		}else{
			if( $0 ~ /<ul>/ ){
				pr=1 ;
				print $0 ;
			} ;
		} ;
	}' <${localVers} | grep '[1-9]' |
	awk '{
		pos=index( $0, "<li><a href=\"" ) ;
		if( pos > 0 ){
			rem=substr( $0 , pos+13 ) ;
			#print rem ;
			posE=index( rem, "\">" ) ;
			printf("%s\n", substr( rem , 1, posE-2 ) ) ;
		} ;
	}' | sort -r > ${jobList}.full

	if [ -s ${jobList}.full ]
	then
		test ${dbg} -eq 2 && { 
			echo " == DEBUG == RAW LIST OF VERSIONS AVAILABLE ===" ;
			awk '{ printf("\t | %s\n", $0 ) ; }' <${jobList}.full ;
			echo "" ; } 
	else
		echo "\n ABORT ... Could not identify the associated versions for the ${scope} ISO builds."
		echo " Process Abandonned!\n"
		exit 1 
	fi
	
	awk -v yr="${thisYear}" -v mth="${thisMth}" '{
		ref=0.0+sprintf("%02d.%02d", yr, mth ) ;
		lst=ref-2.5 ;
		if( $1 < ref && $1 >= lst ){
			print $0 ;
		} ;
	}' <${jobList}.full >${jobList}

	if [ -s ${jobList} ]
	then
		test ${dbg} -eq 2 && { 
			echo " == DEBUG == REDUCED SET OF VERSIONS AVAILABLE ===" ;
			awk '{ printf("\t | %s\n", $0 ) ; }' <${jobList} ;
			echo "" ; } 
	else
		echo "\n ABORT ... Could not identify the associated versions for the ${scope} ISO builds."
		echo " Process Abandonned!\n"
		exit 1 
	fi
	
	echo "\n The following are the available ${scope} ISO build versions available:\n"

	awk '{ printf("\t %s\n", $0 ) ; }' <${jobList}

	echo "\n Please enter your choice of ${scope} version => \c" ; read buildVers
	if [ -z "${buildVers}" ]
	then
		echo "\n ABORT ... No selection entered!\n"
		echo " Process Abandonned!\n"
		exit 2
	fi
	
	testor=$(grep '^'${buildVers}'$' ${jobList} )

	if [ -n "${testor}" ]
	then
		test ${dbg} -eq 2 && echo "\n DEBUG ... version = ${testor} "
	else
		echo "\n ABORT ... Version '${buildVers}' entered is not available."
		echo " Process Abandonned!\n"
		exit 2
	fi
} #getBuildsVersion()

getBuildsInfo()
{
	echo "\n${sep}${sep}${sep}\n Downloading checksum files for ISO build '${isoBuild}' ...\n"
	wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} "${url_DIR}/SHA256SUMS"

	echo "\n${sep}${sep}${sep}\n"
	wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} "${url_DIR}/SHA256SUMS.gpg"

	echo ""

	buildLabel=$(head -1 SHA256SUMS | awk '{ print $2 ; exit }' | sed 's+^[*]++' | sed 's+[.]iso$++' )

	echo "\n Shared identifier string for ISO build files:  '${buildLabel}' ..."
} #getBuildsInfo()

getBuildsList()
{
	rm -f ${jobList}

	if [ -s "${localName}" ]
	then
		echo "\n Using existing file '${localName}' ..."
	else

reportCommandComponents

		echo "\n${sep}${sep}${sep}\n Downloading information page for ISO build  '${isoBuild}' ...\n"
		test ${dbg} -eq 2 && \
		echo " COMMAND:  wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} ${localFile} '${url_DIR}'"
		                 wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} ${localFile} "${url_DIR}"
	fi

	pageTitle=$(awk 'BEGIN{
		capt=0 ;
		strng="" ;
	}{
		if( capt == 1 ){
			posE=index( $0, "</title>" ) ;
			if( posE > 0 ){
				pends=substr( $0, 1, posE-1 ) ;
				printf("%s%s\n", strng, pends ) ;
				exit ;
			}else{
				strng=sprintf("%s%s", strng, $0 ) ;
			} ;
		}else{
			posS=index( $0, "<title>" ) ;
			if( posS > 0 ){
				capt=1 ;
				strng=substr( $0, posS+7 ) ;
			} ;
			posE=index( strng, "</title>" ) ;
			if( posE > 0 ){
				strng=substr( strng, 1, posE-1 ) ;
				printf("%s\n", strng ) ;
				exit ;
			} ;
		} ;
	}' <"${localName}" )

	echo "\n\n\n${sep}${sep}${sep}\n${sep}${sep}${sep}\n\n BANNER:   ${pageTitle}\n"

	awk 'BEGIN{
		pr=0 ;
	}{
		if( pr == 1 ){
			print $0 ;
			if( $0 ~ /<[/]table>/ ){
				exit ;
			} ;
		}else{
			if( $0 ~ /<table>/ ){
				pr=1 ;
				print $0 ;
			} ;
		} ;
	}' <${localName} | grep '/cdicons/' |
	awk -v prefix="${url_DIR}" '{
		pos=index( $0, "<td><a href=\"" ) ;
		if( pos > 0 ){
			rem=substr( $0 , pos+13 ) ;
			#print rem ;
			posE=index( rem, "\">" ) ;
			printf("%s%s\n", prefix, substr( rem , 1, posE-1 ) ) ;
		} ;
	}' >${jobList}

	grep '/SHA256SUMS' ${jobList} >${jobList}.reduced
	grep -v '/SHA256SUMS' ${jobList} | grep "${buildLabel}" >>${jobList}.reduced

	mv ${jobList}.reduced ${jobList}
} #getBuildsList()

reviewContinue()
{
	echo "\n ISO build '${isoBuild}' lists the following associated files:"
	awk '{ printf("\t | %s\n", $0 ) ; }' <${jobList}

	case ${getAll} in
		0 )	echo "\n Proceed with download of all files identified? [y|N] => \c" ; read ans
			if [ -z "${ans}" ] ; then  ans="N" ; fi
			;;
		1 )	ans="y" ;;
		2 )	ans="N" ;;
	esac
} #reviewContinue()


getBuildsComp()
{
	case "${ans}" in
		y* | Y* )
			for suf in iso iso.zsync list manifest
			do
				if [ ${suf} = "iso" -a ${doTorrent} -eq 1 ]
				then
					suf="torrent"
				fi

				item="${buildLabel}.${suf}"
				testor=$(grep "${item}" ${jobList} )
				if [ -n "${testor}" ]
				then
					echo "\n${sep}${sep}${sep}\n Downloading build file '${buildLabel}.${suf}' ..."
					test ${dbg} -eq 2 && \
					echo " COMMAND:  wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} '${url_DIR}/${buildLabel}.${suf}'\n"
					                 wget ${mode} ${resume} ${addSuffix} ${allSources} ${makeLocal} ${getParts} "${url_DIR}/${buildLabel}.${suf}"

					if [ $? -ne 0 ]
					then
						echo " File '${buildLabel}.${suf}' was missing ... or failed to download ..."
						if [ "${suf}" = "iso" ]
						then
							test -s "${buildLabel}.${suf}" && echo "\t Retaining partial download for later re-attempt ..."
							ls -l "${buildLabel}.${suf}" | awk '{ printf("\t %s\n", $0 ) ; }'
						else
							rm -i "${buildLabel}.${suf}"
						fi
					fi
				else
					echo " NOTE:  File '${buildLabel}.${suf}' is not listed as an ISO build related item ..."
				fi
			done
			;;
		* )	echo "\n That list of files has been saved in '${jobList}'.\n" ; exit ;;
	esac
} #getBuildsComponent()


verifyISO()
{
	#set -x

	# resolute-live-server-amd64.iso: OK
	isoFile=$(ls -dtr *.iso | head -1 )	
	grep "${isoFile}" SHA256SUMS >SHA256SUMS_this
	chkMsgs="${buildLabel}.checksums"

	if [ $(sha256sum -c SHA256SUMS_this 2>"${chkMsgs}" | grep "${buildLabel}.${suf}" | 
		awk '{ if( $2 == "OK" ){ print $2 ; } ; }' ) = "OK" ]
	then
		echo "\n Download of image '${buildLabel}.${suf}' was successful."
		if [ -s "${chkMsgs}" ]
		then
			echo "\n Other messages generated by 'sha256sum':"
			awk '{ printf("\t | %s\n", $0 ) ; }' <"${chkMsgs}"
		fi
		echo ""
		exit 0
	else
		echo "\n Checksum for '${buildLabel}.${suf}' image FAILED!\n"
		exit 1
	fi

	#set +x
}


####################################################
###	This section not tested or integrated
####################################################

getArchBits()
{
	thisArch=$( inxi -C 2>&1 |
		awk -v dbg="${dbg}" '{
			if( $1 == "Info:" ){
				posA=index( $0, "model:" ) ;
				posB=index( $0, "bits:" ) ;

				remA=substr( $0, posA, posB-(posA) ) ;
				remB=substr( $0, posB ) ;

				if( dbg == 1 ){ print remA | "cat 1>&2" } ;
				if( dbg == 1 ){ print remB | "cat 1>&2" } ;

				n=split( remA, vals ) ;
				arch=tolower(vals[2]) ;

				n=split( remB, vals ) ;
				bits=vals[2] ;

				printf("%s%s\n", arch, bits ) ;
				exit ;
			} ;
		}' )
}


################################################


jobList=$(basename "$0" ".sh" ).joblist
rm -f jobList

if [ ${doRelease} -eq 1 ]
then
	scope="Release"
 	choiceRange="1-9"

	chooseBuild

	localVers="${isoBuild}_versions.html"
	localFile="-O ${localName}"

	getBuildsVersion

	#url_DIR="https://cdimage.ubuntu.com/${isoBuild}/releases/${buildVers}/release/"
	url_DIR="https://cdimages.ubuntu.com/${isoBuild}/releases/${buildVers}/release/"
	test ${dbg} -eq 2 && { echo "\t DEBUG ... url_DIR = ${url_DIR}" ; }

else
	scope="Daily"
 	choiceRange="1-11"

	chooseBuild

	url_DIR="https://cdimages.ubuntu.com/${isoBuild}/daily-live/current/"
	test ${dbg} -eq 2 && { echo "\t DEBUG ... url_DIR = ${url_DIR}" ; }
fi


localName="${isoBuild}_details.html"
localFile="-O ${localName}"

getBuildsInfo
getBuildsList
reviewContinue
getBuildsComp
verifyISO

exit 0
exit 0
exit 0


P.S. I even thought about incorporating the “arch” option, but haven’t done that, although I did already discuss it over under UbuntuMATE. :slight_smile:

1 Like

Oh, if it’s just a script for personal use, or for the community of contributors, it’s probably fine, and you could patch it to get the server ISOs from the releases site, I guess.

There’s always been a reluctance to promote the use of cdimage because it’s not mirrored, and doesn’t have the same resources as other servers. Also, good one using zsync :slight_smile:

2 Likes

This topic was automatically closed 18 hours after the last reply. New replies are no longer allowed.