CondinAPT - minios-linux/minios-live GitHub Wiki
CondinAPT is a versatile tool for automating package installation in any Debian-like system (Debian, Ubuntu, and their derivatives). Its key feature is the ability to define complex conditions and rules for installing each package based on arbitrary system configurations.
Areas of Application:
- Linux distribution build systems
- Automation of server and workstation setup
- Deployment of various system configurations
- Package management in Docker containers
- CI/CD pipelines for environment setup
- Creation of custom installation images
Key Features:
- Conditional Installation: Install packages based on flexible filters (+, -).
- External Configuration: Complete separation of logic (package list) from data (system parameters).
- Installation Queues: Divide the process into sequential stages to resolve dependencies.
- Priority Queue: Guaranteed installation of critical packages first.
-
Complex Logic: Support for "AND" (
&&
), "OR" (||
) operators, as well as group filters (+{a|b}
,-{a&b}
). - Readability: Support for comments and empty lines to structure lists.
- Backward Compatibility: Supports simple package lists without conditions.
CondinAPT operates with four key files:
-
condinapt
script: The core, containing all processing logic. -
Main configuration file (
-c
): A file with bash variables describing the current environment.Example (
system.conf
):DISTRIBUTION="bookworm" SYSTEM_TYPE="server" ENVIRONMENT="production" LOCALE="en_US" FEATURES="web,database"
-
Filter mapping file (
-m
): Links short prefixes (used in the package list) to variable names from the main configuration file. This file is optional. If a filter is not present in the filter mapping file, it will be used as a variable name from the main configuration file. If the variable is not found, CondinAPT will declare it empty.Example (
filters.map
):d=DISTRIBUTION st=SYSTEM_TYPE env=ENVIRONMENT arch=ARCHITECTURE feat=FEATURES
-
Package list file (
-l
): The main file describing what to install and under what conditions.
To quickly get acquainted with CondinAPT, create a simple example:
1. Create the configuration file config.conf
:
# Basic system parameters
DISTRIBUTION="bookworm"
SYSTEM_TYPE="server"
ENVIRONMENT="production"
2. Create the package list packages.list
:
# Base packages - always installed
vim
curl
# Packages only for servers
nginx +SYSTEM_TYPE=server
mysql-server +SYSTEM_TYPE=server
# Exclude packages for production environment
debug-tools -ENVIRONMENT=production
3. Run the installation:
bash
./condinapt -l packages.list -c config.conf
4. Or test in simulation mode:
bash
./condinapt -l packages.list -c config.conf -s
./condinapt [OPTIONS]
Flag | Long Flag | Argument | Description |
---|---|---|---|
-l |
--package-list |
PATH |
(Required) Path to the package list file. |
-c |
--config |
PATH |
(Required) Path to the main configuration file. |
-m |
--filter-mapping |
PATH |
(Optional) Path to the filter mapping file. |
-P |
--priority-list |
PATH |
(Optional) Path to the priority package list file. |
-s |
--simulation |
Simulation mode. Packages will not be installed. | |
-C |
--check-only |
Only check if packages are already installed. | |
-v / -vv
|
--verbose / --very-verbose
|
Verbose / very verbose output. | |
-x |
--xtrace |
Enable set -x command tracing. |
|
-f |
--force |
Force apt cache update (apt update). | |
-h |
--help |
Show help. |
This is the heart of CondinAPT. All logic is described here.
Each line in the package list file consists of two main parts:
- Package name with optional version and release specification
- Condition filters - define the conditions under which the package will be installed
Basis for all examples below: For all subsequent examples, we will assume that the
system.conf
andfilters.map
files from the "How it Works and Core Components" section are used.
DISTRIBUTION
="bookworm"
SYSTEM_TYPE
="server"
ENVIRONMENT
="production"
Simple name:
vim
Package version:
-
package=version
— loose version requirement. If the required version is unavailable, an available version is installed.git=2.25.1
-
package==version
— strict requirement. If the version is not found, installation aborts with an error.curl==7.68.0
Release specification:
The release is specified using the @
symbol, which allows linking the installation to a specific repository branch.
telegram@bookworm-backports
kernel-image-6.5.0@trixie-backports
- Package names: Each package or condition is written on a new line.
-
Comments: Lines starting with
#
, or text after#
on a line, are completely ignored. - Empty lines: Ignored and serve for visual separation.
#=== Multimedia ===
vlc # Excellent media player
audacious # Another media player
#=== Graphics ===
gimp
Filters allow you to set additional conditions for package selection. They compare the values of system variables (architecture, distribution, working environment) with those specified in the configuration file.
-
+
(Positive): The condition is true if the variable value matches. Format:+<prefix>=<value>
-
Line:
nginx +st=server
-
Analysis:
SYSTEM_TYPE
is equal to"server"
. The condition is true. -
Result:
nginx
will be installed.
-
Line:
-
Multiple positive filters with the same prefix: Act as OR conditions. Format:
+<prefix>=<value1> +<prefix>=<value2>
-
Line:
debug-tools +env=development +env=testing
-
Analysis:
ENVIRONMENT
is equal to"production"
, which does not match either"development"
or"testing"
. The condition is false. -
Result:
debug-tools
will not be installed.
-
Line:
-
-
(Negative): The condition is true if the variable value does not match. Format:-<prefix>=<value>
-
Line:
monitoring-tools -st=desktop
-
Analysis:
SYSTEM_TYPE
is equal to"server"
, which is not equal to"desktop"
. The condition is true. -
Result:
monitoring-tools
will be installed.
-
Line:
-
Multiple negative filters: The package is excluded if ANY condition matches. Format:
-<prefix>=<value1> -<prefix>=<value2>
-
Line:
realtek-driver -d=trixie -d=sid
-
Analysis:
DISTRIBUTION
is equal to"bookworm"
, which is not equal to"trixie"
or"sid"
. The exclusion conditions do not trigger. -
Result:
realtek-driver
will be installed.
-
Line:
-
+{a|b}
(OR for inclusion): True if at least one of the conditions in the group is true.-
Line:
web-server +{st=server|st=web-server}
-
Analysis:
SYSTEM_TYPE
is equal to"server"
. The first condition is true, which is sufficient. - Result: The package will be installed.
-
Line:
-
+{a&b}
(AND for inclusion): True only if all conditions in the group are true.-
Line:
database-tools +{d=bookworm&st=server}
-
Analysis:
DISTRIBUTION
is equal to"bookworm"
(true) ANDSYSTEM_TYPE
is equal to"server"
(true). - Result: The package will be installed.
-
Line:
-
-{a|b}
(OR for exclusion): The package is excluded if at least one of the conditions is true.-
Line:
debug-tools -{env=production|st=minimal}
-
Analysis:
ENVIRONMENT
is equal to"production"
. The first condition is true, so the package is excluded. - Result: The package will not be installed.
-
Line:
-
-{a&b}
(AND for exclusion): The package is excluded only if all conditions are true.-
Line:
development-tools -{env=production&st=minimal}
-
Analysis:
ENVIRONMENT
is equal to"production"
(true), butSYSTEM_TYPE
is not equal to"minimal"
. The second condition is false. The group does not trigger for exclusion. - Result: The package will be installed (if no other filters).
-
Line:
Different packages can be offered for the same functionality and installed depending on conditions. Alternative options are separated by the ||
operator.
Important: Each alternative must include a complete description — package name (with optional version and release) and a set of filters.
Example:
postgresql +st=database-server || mysql-server +st=web-server
- If
SYSTEM_TYPE
isdatabase-server
, postgresql is selected. - If
SYSTEM_TYPE
isweb-server
, mysql-server is installed.
-
||
(OR / Fallback): Try to install the left part. If it fails (package not found or filtered), try to install the right part.-
Line:
exfatprogs -d=bookworm || exfat-utils
-
Analysis:
DISTRIBUTION
is not equal to"bookworm"
, the left part is filtered. CondinAPT proceeds to the right part.exfat-utils
has no filters, so it will be installed. -
Result:
exfat-utils
will be installed.
-
Line:
-
&&
(AND / Conjunction): All parts must successfully pass filter checks to be added to the queue.-
Line:
nginx +st=web-server && php-fpm
-
Analysis:
SYSTEM_TYPE
is equal to"server"
, but the condition requires"web-server"
. The left part fails. -
Result: No packages will be installed.
-
Complex example:
monitoring-tools +env=production && prometheus +env=production && grafana +env=production
-
Result: All three packages will be installed only if
ENVIRONMENT
isproduction
.
-
-
!
(Mandatory Package): If a package is marked with!
, but cannot be found in repositories, CondinAPT will abort execution with an error.-
Line:
!essential-package
-
Line:
-
@
(Release Specification): Install a package from a specific Debian/Ubuntu release (e.g.,bookworm-backports
).-
Line:
kernel-image-6.5.0 @trixie-backports
-
Line:
CondinAPT allows precise control over the versions of installed packages.
-
Syntax:
-
package=VERSION
: Attempts to install the specified version (VERSION
). If it's unavailable in repositories, CondinAPT will install any available version of the package.- Example:
my-app=1.2.3
(attempts to install 1.2.3, if not, installs, for example, 1.2.4)
- Example:
-
package==VERSION
: Strict installation of a specific version. If this version is unavailable in repositories, the package will not be installed. If the package was also marked as mandatory (!
), the script will exit with an error.- Example:
another-app==2.0.0
(installs only 2.0.0, otherwise skips the package or errors if mandatory)
- Example:
-
-
Behavior:
- CondinAPT first checks if the required package version is installed on the system. If yes, the package is considered installed and skipped.
- Then it checks if the specified version is available in repositories (
apt-cache madison
). -
When using
=
(loose version):- If the specified version is unavailable, CondinAPT will issue a warning that the exact version was not found.
- Nevertheless, it will attempt to install any available version of the package from the repositories.
-
When using
==
(strict version):- If the specified version is unavailable, CondinAPT will not install the package.
- If the package was marked as mandatory (
!
), the script will abort execution with an error.
-
Version holding (
apt-mark hold
):- If a package was successfully installed with the exact, specified version (i.e., if
package==VERSION
was successful, orpackage=VERSION
found exactly that version and installed it), CondinAPT will automatically apply theapt-mark hold
command for that package. - This prevents automatic updates of the package to a new version during subsequent
apt upgrade
operations.
- If a package was successfully installed with the exact, specified version (i.e., if
Task: Install database-tools
for the bookworm
distribution, but only if the system type is server
or database-server
, and not for the minimal
environment.
packages.list
:
database-tools +d=bookworm +{st=server|st=database-server} -env=minimal
Analysis (with our configuration):
-
+d=bookworm
: True. -
+{st=server|st=database-server}
: True, becauseSYSTEM_TYPE
is"server"
. -
-env=minimal
: True, becauseENVIRONMENT
is"production"
. Result: All conditions are true. The package will be installed.
Task: For Debian trixie
, install firefox-esr
. For bookworm
, install firefox
. For all other cases, install w3m
.
packages.list
:
firefox-esr +d=trixie || firefox +d=bookworm || w3m
Analysis:
-
firefox-esr +d=trixie
: Left part.DISTRIBUTION
is"bookworm"
, condition is false. -
firefox +d=bookworm
: Middle part.DISTRIBUTION
is"bookworm"
, condition is true. - Since the second part of the
||
chain worked, the third (w3m
) will be ignored. Result:firefox
will be installed.
Task: dkms
is critical for module building; it must be installed first. In the main list, it is marked as mandatory, but with a condition.
-
priority.list
:
dkms build-essential
* **`packages.list`:**
```text
!dkms +pv=standard # Mandatory, but with a condition
vim
Analysis:
-
dkms
andbuild-essential
are loaded into the priority queue. -
The line
!dkms +pv=standard
is removed frompackages.list
during scanning, asdkms
is in priority. -
Execution Plan:
-
Priority Queue: Install
dkms
andbuild-essential
. -
Normal Queue: (Continue processing remaining packages from
packages.list
).
-
Priority Queue: Install
Result: dkms
will be installed unconditionally at the very beginning. The !
modifier and +pv=standard
filter from the main list will have no effect.
The ---
separator on a separate line divides the list into groups (queues). Packages from one queue are installed together in a single apt
call. Queues are executed strictly sequentially.
Example:
# Queue 1: Base system
systemd
network-manager
---
# Queue 2: Web server
nginx
php-fpm
---
# Queue 3: Monitoring
prometheus
Packages with @release
automatically group into separate queues by release:
# Regular packages
vim
git
---
# Packages from backports (create a separate queue)
linux-image-amd64 @bookworm-backports
nvidia-driver @bookworm-backports
This mechanism is for unconditional installation of critical packages.
-
Principle: Packages listed in the file specified by the
-P
flag (one package per line, no filters) form a special "Queue #1", which is executed first. -
Override: Any package from the priority list is automatically removed from all regular queues and all target queues (with
@release
). This ensures it will be installed unconditionally, even ifpackages.list
has prohibitive filters or a specific release specified for it.
Example:
-
packages.list
:
git +st=full-server # Will only be installed for full servers gpg -st=minimal # Will be installed in all types except minimal curl # Always installed wget +d=trixie # Only for trixie vim +env=development # Only for development environment
* **`priority.list`:**
```text
gpg
git
-
Analysis:
-
CondinAPT reads
priority.list
and knows thatgpg
andgit
must be installed first. -
It scans
packages.list
and finds the linegit +st=full-server
. Sincegit
is in priority, this line is completely ignored. -
Final Plan:
-
Priority Queue: Install
gpg
andgit
. -
Normal Queue: (Continue processing remaining packages from
packages.list
).
-
Priority Queue: Install
-
Allows you to see which packages will be installed without actually installing them:
./condinapt -l packages.list -c system.conf -s
Example Output:
I: Installation Queue #1:
I: Simulation mode ON. These packages would be installed: firefox-esr vlc htop
I: Simulation mode ON. No installation will be performed.
Note: In simulation mode, the script exits with exit code 1.
Checks which packages from the list are already installed on the system:
./condinapt -l packages.list -c system.conf -C
Behavior:
- Shows errors for uninstalled packages
- Returns exit code 1 if there are uninstalled packages
- At the end, outputs a command to install missing packages
Verbose Output (-v
):
- Shows detailed information about filter checks
- Displays results for each package
Very Verbose Output (-vv
):
- Maximum process detail
- Shows all intermediate steps
Command Tracing (-x
):
- Enables
set -x
for script debugging - Shows each command being executed
Example with Debugging:
./condinapt -l packages.list -c system.conf -vv -x
Forces CondinAPT to run apt update
before installation:
./condinapt -l packages.list -c system.conf -f
CondinAPT can work with array variables in the configuration file:
system.conf
:
SUPPORTED_ARCHITECTURES=("amd64" "i386" "arm64")
AVAILABLE_ENVIRONMENTS=("production" "staging" "development")
filters.map
:
arch=SUPPORTED_ARCHITECTURES
env=AVAILABLE_ENVIRONMENTS
packages.list
:
# Install for any supported architecture
multilib-support +arch=amd64
# Install for any available environment
monitoring-tools +env=production
CondinAPT has built-in support for special packages that require special handling:
Virtual Packages:
-
qemu-kvm
- treated as a virtual package
Handling Mechanism:
- CondinAPT checks if the package is virtual using the
apt-cache show
command - If the package is marked as "purely virtual", it is considered available for installation
- The list of special packages is defined in the
SPECIAL_PACKAGES
array within the script:SPECIAL_PACKAGES=("qemu-kvm")
Extending the List: To add new special packages, you need to edit the SPECIAL_PACKAGES
array in the CondinAPT code.
If a package is marked as mandatory but not found in repositories, CondinAPT:
- Outputs an error message
- Aborts execution (unless in simulation mode)
- Returns exit code 1
Example:
!essential-package +pv=standard
If essential-package
is not found in repositories, execution will abort.
Loose Versions (=
):
- If the exact version is unavailable, any available version is installed
- A warning is issued about the unavailability of the requested version
Strict Versions (==
):
- If the exact version is unavailable, the package is skipped
- If the package is mandatory (
!
), execution aborts
CondinAPT automatically holds package versions in the following cases:
- When the exactly requested version was installed
- For packages with
==VERSION
, if the version was found and installed - For packages with
=VERSION
, if exactly that version was found and installed
CondinAPT easily integrates into build systems and automation scripts. For more details on package file syntax, see the Package List File Syntax section.
In an automation script (install.sh
):
#!/bin/bash
set -e
# Define base paths
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
CONFIG_DIR="${SCRIPT_DIR}/config"
# Install packages via CondinAPT
./condinapt \
-l "${SCRIPT_DIR}/packages.list" \
-c "${CONFIG_DIR}/system.conf" \
-m "${CONFIG_DIR}/filters.map"
Example filter mapping file (filters.map
):
# Basic system parameters
d=DISTRIBUTION
arch=ARCHITECTURE
st=SYSTEM_TYPE
env=ENVIRONMENT
# Additional features
feat=FEATURES
locale=LOCALE
version=VERSION
Example configuration (system.conf
):
# Basic parameters
DISTRIBUTION="bookworm"
ARCHITECTURE="amd64"
SYSTEM_TYPE="server"
ENVIRONMENT="production"
# System capabilities
FEATURES="web,database,monitoring"
LOCALE="en_US"
VERSION="1.0"
packages.list
:
# Basic multimedia codecs - always
gstreamer1.0-plugins-base
gstreamer1.0-plugins-good
# Additional codecs - not for minimal installation
gstreamer1.0-plugins-bad -st=minimal
gstreamer1.0-plugins-ugly -st=minimal
gstreamer1.0-libav -st=minimal
# Professional tools - only for full configuration
ffmpeg +st=media-server
vlc +st=media-server
---
# Distribution-specific packages from backports for older distributions
ffmpeg @bookworm-backports +d=bookworm
packages.list
:
# Basic web server components
nginx
openssl
# Database - only for full installations
mysql-server +st=full-server -{env=minimal}
postgresql +st=database-server
# PHP - for web servers
php-fpm +feat=php
php-mysql +{feat=php&st=full-server}
# Monitoring - not for development environment
prometheus-node-exporter -env=development
htop +env=production
packages.list
:
# Basic containerization tools
docker.io
containerd
# Kubernetes - only for cluster installations
kubectl +st=k8s-node
kubelet +st=k8s-master
kubeadm +st=k8s-master
# Container monitoring
docker-compose +env=development
portainer +feat=gui
# Network tools - exclude for minimal installations
bridge-utils -st=minimal
iptables-persistent -st=minimal
packages.list
:
# Complex conditions for databases
postgresql +{st=database-server&env=production} +arch=amd64
mysql-server +{st=web-server|st=full-server} -env=minimal
# Monitoring with exclusions
prometheus +env=production -st=desktop
grafana +{env=production|env=staging} +feat=monitoring
# Alternatives with conditions
nginx +st=web-server || apache2 +st=legacy-server || lighttpd -st=full-server
# Localization for different environments
language-pack-en +locale=en_US +env=production
language-pack-ru +locale=ru_RU -{env=minimal&st=embedded}
fonts-dejavu +{locale=ru_RU|locale=de_DE} +feat=gui
- Grouping by functionality:
#=== System ===
systemd
dbus
#=== Network ===
network-manager
wireless-tools
#=== Multimedia ===
pulseaudio
alsa-utils
- Using queues for dependencies:
# Base system - first queue
build-essential
pkg-config
---
# Development libraries - second queue
libgtk-3-dev
libqt5-dev
---
# Applications - third queue
gedit
qtcreator
- Optimizing conditions:
# Inefficient
package1 +st=server +env=production
package2 +st=server +env=production
package3 +st=server +env=production
# Better to group
package1 +{st=server&env=production}
package2 +{st=server&env=production}
package3 +{st=server&env=production}
- Use priority queues for critical packages
- Minimize the number of queues
- Group related packages into one queue
- Use APT caching for large builds
Problem: Package not installing despite correct conditions
Solution: Check with the -vv
flag for detailed filter information
Problem: CondinAPT aborts on a mandatory package Solution: Check package availability in repositories or use fallback. See Error Handling and Recovery section
Problem: Unexpected behavior with package versions
Solution: Use simulation mode (-s
) for verification
# Check a specific package
echo "package-name +condition" | ./condinapt -l /dev/stdin -c system.conf -s -vv
# Check the entire list in simulation mode
./condinapt -l packages.list -c system.conf -s -vv
# Check without installation
./condinapt -l packages.list -c system.conf -C
# View package information
apt-cache policy package-name
apt-cache madison package-name