⚠️ WARNING: Thedockercontainer engine is currently broken and does not work with this CI/CD pipeline. Please usepodmanas the container engine. Attempts to usedockerwill result in failed builds.
This repository provides a CI/CD setup for building one-apps project images in an automated pipeline. The pipeline is designed to be flexible, supporting user-defined inputs and customizations, and is intended for use with OpenNebula environments.
- Overview
- Prerequisites
- CI/CD Pipeline
- OpenNebula Runner Registration
- Additional Notes
- Security
- Build Data and Artefact Storage
- Automated Image Building: Uses GitLab CI/CD to build Linux and Windows images for the one-apps project.
- User Inputs: The pipeline supports user-supplied parameters to customize builds.
- Submodule Support: The
one-appsproject is included as a submodule and can be modified as needed. - Containerfiles Included: The repository contains all required containerfiles (Dockerfiles) for the build process, located in the
containers/directory. These must be built and pushed to your container registry before first use by running thebuild-containersjob. - OpenNebula Integration: Built images are intended for deployment in OpenNebula.
- Runner Template: The repository contains the runner template for the build process.
- Container Registry Required: The pipeline requires access to a container registry to store and retrieve the custom build images. Make sure your GitLab project or environment is configured with a suitable registry and credentials.
- Required CI/CD Variables:
ONE_XMLRPC: URL of the OpenNebula XML-RPC API endpoint. This variable must be set for the pipeline to interact with your OpenNebula instance.ONE_AUTH: A hidden, protected, and masked file variable containing the OpenNebula credentials in the formatuser:passwordoruser:token. This is required for authentication with the OpenNebula API and should be securely managed in your CI/CD settings. This variable must be masked and hidden, and should only be available to protected branches.
The pipeline is defined in .gitlab-ci.yml and consists of several stages:
- build-containers: Builds required container images.
- prepare-dependencies: Prepares build contexts and downloads dependencies.
- build-images: Builds the actual VM images using Packer and Makefiles.
- deploy-images: Deploys built images to the target environment.
- cleanup: Cleans up temporary files and artifacts.
- cleanup: Cleans up temporary files and artefacts.
- delete-images: (Manual) Deletes images and templates from OpenNebula.
The pipeline supports the following user inputs, which can be set as pipeline variables. The distro_name, distro_versions, and distro_editions variables are combined to create build targets defined in the one-apps/Makefile.config file.
pipeline_type: Type of pipeline run (build-containersorbuild-images, default:build-images).image_datastore_id: Target OpenNebula datastore ID for image upload (default:100).image_name_prefix: Prefix for generated image names (default: empty).image_name_suffix: Suffix for generated image names (default:$CI_PIPELINE_ID).distro_name: The base name of the distribution (e.g.,ubuntu,debian,windows). For all Windows builds, this value must bewindows, as this is used to trigger the correct pipeline jobs.distro_versions: An array of distribution versions to build (e.g.,["12", "13"]for Debian).distro_editions: An array of distribution editions (e.g.,["Pro", "Education"]for Windows, or["", "min"]for Ubuntu). An empty string""can be used if there is no edition.remove_artefacts: Whether to remove build artefacts from the runner after deployment (true/false, default:true).debug: Enable more verbose information in CI/CD job output (true/false).
These inputs are referenced in the pipeline and can be set via the GitLab UI or API when triggering a pipeline.
How Build Targets are Created:
The pipeline concatenates the three distro variables to form a make target. For example:
- To build
windows11Proandwindows11Education:distro_name:windowsdistro_versions:["11"]distro_editions:["Pro", "Education"]
- To build
debian12anddebian13:distro_name:debiandistro_versions:["12", "13"]distro_editions:[""]
- To build
ubuntu2204andubuntu2204min:distro_name:ubuntudistro_versions:["2204"]distro_editions:["", "min"]
Refer to the one-apps/Makefile.config file for a full list of available build targets.
The one-apps directory is included as a git submodule. By default, the submodule points to a downstream repository maintained by the Faculty of Informatics, Masaryk University (MU), which may contain customizations specific to this environment. You can make local modifications to this submodule to customize the build process or add new features. After making changes, ensure you commit and push updates to the submodule as needed.
Alternatively, you can point the submodule to a different repository, such as the original one-apps repository, your own fork, or any compatible upstream. This allows you to easily track upstream changes or use a custom version of one-apps as required for your environment.
Note: The provided runner setup scripts and templates are tested and configured for a Debian 13 base system. The
runner/start_script.shuses Debian-specific package management (apt-get) and therunner/vm_template.tmpldefaults to aDebian 13.0.0image. While other Debian-based systems may work, they are not guaranteed to be compatible without modification.
To use the CI/CD pipeline with OpenNebula, you must register a custom runner. This involves setting up a VM template in OpenNebula with a custom startup script.
Instructions:
-
Obtain the runner start script:
- The script is located at
runner/start_script.shin this repository.
- The script is located at
-
Encode the script in base64:
base64 -w 0 runner/start_script.sh
-
Register the template in OpenNebula:
- Create a VM template in OpenNebula.
- Copy contents of
runner/vm_template.tmplinto it. - Set the
START_SCRIPT_64attribute to the base64 output from the previous step. - Important: Configure the runner to run only on protected branches in your GitLab project. Protected branches restrict access to sensitive variables (like
ONE_AUTH) and help prevent unauthorized use of credentials. If you are using a fork, ensure protected branches are set up in your fork as well.
-
Instantiate the template in OpenNebula:
-
Launch a new VM instance from the registered template.
-
When instantiating, provide the required runner configuration parameters as template inputs. The following inputs are supported:
Variable Type Description Default Value CI_SERVER_TOKENstring GitLab runner registration token (required) CI_SERVER_URLstring GitLab CI server URL (required) https://gitlab.fi.muni.czCONCURRENT_JOBSnumber Number of concurrent jobs to run (optional) 1CONTAINER_ENGINElist Container engine to use (required) podman(podman,docker) -
Resource Recommendations:
- Allocate at least 2 GB RAM for the runner itself, plus an additional 4 GB RAM and 4 CPU cores for each parallel build you plan to run. Consider extra CPU and RAM for the runner process if running multiple builds concurrently.
- Disk Space: Builds are stored on the main OS drive during the build process. Ensure there is enough free space for the OS image you are building.
- For Windows builds, a minimum of 32 GB free disk space per parallel build is recommended, plus extra space for the Windows ISO files, which will be cached on the runner. - For Linux builds, ensure sufficient space for the base image, build artifacts, and any dependencies.
-
This step ensures the runner VM is configured with the correct GitLab server, token, and container engine, and is ready to execute CI/CD jobs as defined in this project pipeline.
This configuration ensures that the runner initialization script executes upon VM startup, installing the GitLab Runner package with the specified container runtime, configuring udev rules, and registering the runner.
containers/— Containerfiles (Dockerfiles) for all build and deploy images.one-apps/— The one-apps submodule (can be pointed to any compatible repo).runner/— Scripts and templates for registering Gitlab runner.deploy_image.py,delete_images.py— Scripts for image deployment and cleanup..gitlab-ci.yml— Main CI/CD pipeline definition.
- Ensure your OpenNebula environment is properly configured to accept and run the generated images.
- For advanced usage or troubleshooting, refer to the scripts and Makefiles in the
one-appsrepository. - The pipeline is designed to be extensible; you can add new stages or customize existing ones as needed.
- The provided
template.tmplis used as a base for the newly built images. It is optimized for Windows Client editions. For Windows Server editions, theTOPOLOGYattribute can be removed. For Linux images,LOCALTIMEandHYPERVshould be set tono.
- Unprivileged Containers: All containers (except the deploy container) run as an unprivileged user at runtime. The deploy container requires elevated privileges for block device operations and is mapped to UID of the
gitlab-runneruser. - Unprivileged GitLab Runner: The GitLab Runner service itself runs as the unprivileged
gitlab-runneruser (not root). Both rootless Podman and rootless Docker are supported and configured for the runner. - Device Access: Containers have access to
/dev/kvmfor hardware virtualization and the entire/dev/tree is mounted inside the containers to support VM image operations. - Udev Rules: Udev rules are set to allow read/write access to
/dev/sd[b-z]*and/dev/sd[a-z][a-z]*block devices (i.e., all disks except/dev/sda) for thegitlab-runnergroup. This is required for direct disk operations during image builds, but ensures the system disk is not exposed to the runner. - Credential Security: The CI/CD variable
ONE_AUTHis always masked and hidden, and is only available to protected branches. Protected branches in GitLab restrict access to sensitive variables and prevent unauthorized use of credentials. If you are using a fork of this repository, make sure to configure protected branches in your fork as well to maintain security.
- No CI/CD Artefacts: Build artefacts (such as VM images) are not stored as GitLab artefacts due to their large file sizes.
- Cache Usage: The CI/CD cache is used for caching VirtIO driver downloads and context builds. This improves build speed and reduces redundant downloads.
- /cache Volume: The
/cachedirectory inside the container is not an anonymous volume. It is mapped to/home/gitlab-runner/runner-cacheon the runner VM, ensuring cache persistence across parallel jobs and pipelines. - /mnt/data Volume: The
/mnt/datadirectory inside the container is mapped to/home/gitlab-runner/runner-dataon the runner VM. This directory stores all build artefacts, including finished (exported) images, organized in subfolders by pipeline ID (e.g.,/mnt/data/<pipeline_id>/export). - Packer Caching:
packer_cachedirectory is used for caching ISO/source disk downloads, reducing repeated downloads for subsequent builds.packer_pluginsdirectory is used for caching Packer plugins, improving build start times.
This storage strategy ensures that large build outputs and caches persist across parallel job runs, while keeping the CI/CD system scalable and performant.