A community-maintained repo of AutoPkg recipes for uploading macOS installer packages to Fleet. Contributions are welcome!
Run autopkg repo-add fleet-recipes to add this repo.
Fleet recipes depend on parent recipes from other AutoPkg repositories. See PARENT_RECIPE_DEPENDENCIES.md for the complete list of required repositories and setup instructions.
FleetImporter extends AutoPkg to integrate with Fleet's software management. Recipes use a combined format that supports both deployment modes in a single file:
- Direct mode: Upload packages directly to Fleet via API
- GitOps mode: Upload to S3 and create pull requests for Git-based configuration management
Mode is controlled by the GITOPS_MODE input variable (default: false). Users can switch modes via recipe overrides without maintaining separate recipe files.
- Python 3.9+: Required by FleetImporter processor
- AutoPkg 2.3+: Required for recipe execution
- boto3 1.18.0+: Required for GitOps mode S3 operations (optional for direct mode)
- Must be installed manually into AutoPkg's Python environment:
/Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/python3 -m pip install boto3>=1.18.0 - Direct mode uses only native Python libraries (no external dependencies)
- Must be installed manually into AutoPkg's Python environment:
FleetImporter recipes support the following variables. Configuration can be set via AutoPkg preferences or recipe overrides.
| Variable | Direct Mode | GitOps Mode | Default | Description |
|---|---|---|---|---|
| Mode Control | ||||
GITOPS_MODE |
Optional | Required | false |
Set to true to enable GitOps mode |
| Package Information | ||||
pkg_path |
Required | Required | - | Path to the .pkg file (typically from parent recipe) |
software_title |
Required | Required | - | Software display name |
version |
Required | Required | - | Software version (typically from parent recipe) |
display_name |
Optional | Optional | software_title |
Custom display name for the software package in Fleet |
| Fleet API (Direct Mode) | ||||
FLEET_API_BASE |
Required | Not used | - | Fleet server URL (e.g., https://fleet.example.com) |
FLEET_API_TOKEN |
Required | Not used | - | Fleet API authentication token |
FLEET_TEAM_ID |
Required | Not used | - | Fleet team ID for software assignment |
| AWS S3 (GitOps Mode) | ||||
AWS_S3_BUCKET |
Not used | Required | - | S3 bucket name for package storage |
AWS_CLOUDFRONT_DOMAIN |
Not used | Required | - | CloudFront domain for package URLs |
AWS_ACCESS_KEY_ID |
Not used | Optional | - | AWS access key (can use ~/.aws/credentials instead) |
AWS_SECRET_ACCESS_KEY |
Not used | Optional | - | AWS secret key (can use ~/.aws/credentials instead) |
AWS_DEFAULT_REGION |
Not used | Required | us-east-1 |
AWS region for S3 operations |
| GitOps Repository | ||||
FLEET_GITOPS_REPO_URL |
Not used | Required | - | Git repository URL for Fleet configuration |
FLEET_GITOPS_GITHUB_TOKEN |
Not used | Required | - | GitHub token with repository write permissions |
FLEET_GITOPS_SOFTWARE_DIR |
Not used | Optional | lib/macos/software |
Directory for software YAML files in GitOps repo |
FLEET_GITOPS_TEAM_YAML_PATH |
Not used | Optional | teams/workstations.yml |
Path to team YAML file in GitOps repo |
| Software Configuration | ||||
self_service |
Optional | Optional | true |
Show software in Fleet Desktop |
automatic_install |
Optional | Optional | false |
Auto-install on matching devices |
categories |
Optional | Optional | [] |
Categories for self-service (Browsers, Communication, Developer tools, Productivity) |
labels_include_any |
Optional | Optional | [] |
Only install on devices with these labels |
labels_exclude_any |
Optional | Optional | [] |
Exclude devices with these labels |
icon |
Optional | Optional | - | Path to PNG icon (square, 120-1024px, max 100KB). Auto-extracts from app bundle if not provided |
install_script |
Optional | Optional | - | Custom installation script |
uninstall_script |
Optional | Optional | - | Custom uninstall script |
pre_install_query |
Optional | Optional | - | osquery to run before install |
post_install_script |
Optional | Optional | - | Script to run after install |
| Auto-Update Policies | ||||
automatic_update |
Optional | Optional | false |
Create/update policies for automatic version detection and installation |
auto_update_policy_query |
Optional | Optional | Auto-generated | Custom osquery for version detection (uses %VERSION% placeholder). Auto-generates from bundle ID if not provided |
AUTO_UPDATE_POLICY_NAME |
Optional | Optional | autopkg-auto-update-%NAME% |
Policy name template (%NAME% replaced with slugified software title) |
| GitOps-Specific Options | ||||
s3_retention_versions |
Not used | Optional | 0 |
Number of old package versions to retain in S3 (0 = no pruning) |
Upload packages directly to your Fleet server. This is the default mode for all recipes.
# Set required configuration
defaults write com.github.autopkg FLEET_API_BASE "https://fleet.example.com"
defaults write com.github.autopkg FLEET_API_TOKEN "your-fleet-api-token"
defaults write com.github.autopkg FLEET_TEAM_ID "1"
# Run any recipe (defaults to direct mode)
autopkg run VendorName/SoftwareName.fleet.recipe.yamlUpload packages to S3 and create GitOps pull requests for Fleet configuration management.
Note: GitOps mode requires you to provide your own S3 bucket and CloudFront distribution. When Fleet operates in GitOps mode, it deletes any packages not defined in the YAML files during sync (fleetdm/fleet#34137). By hosting packages externally and using pull requests, you can stage updates and merge them at your own pace.
Prerequisites:
-
Install boto3 into AutoPkg's Python environment (required for S3 operations):
/Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/python3 -m pip install boto3>=1.18.0 -
Create a recipe override and set
GITOPS_MODE: true:# Create an override autopkg make-override VendorName/SoftwareName.fleet.recipe.yaml # Edit the override to set GITOPS_MODE: true # Then run it autopkg run SoftwareName.fleet.recipe.yaml
- AWS S3 bucket for package storage
- CloudFront distribution pointing to the S3 bucket
- AWS credentials with read/write access to the S3 bucket
Set via AutoPkg preferences:
defaults write com.github.autopkg AWS_S3_BUCKET "my-fleet-packages"
defaults write com.github.autopkg AWS_CLOUDFRONT_DOMAIN "cdn.example.com"
defaults write com.github.autopkg AWS_ACCESS_KEY_ID "your-access-key"
defaults write com.github.autopkg AWS_SECRET_ACCESS_KEY "your-secret-key"
defaults write com.github.autopkg AWS_DEFAULT_REGION "us-east-1"
defaults write com.github.autopkg FLEET_GITOPS_REPO_URL "https://github.com/org/fleet-gitops.git"
defaults write com.github.autopkg FLEET_GITOPS_GITHUB_TOKEN "your-github-token"- Package is uploaded to S3
- CloudFront URL is generated
- Software YAML files are created in GitOps repo
- Pull request is opened for review
FleetImporter automatically extracts and uploads application icons from .pkg files without requiring manual icon files:
- Automatic extraction: Finds the
.appbundle in the package, extracts the icon fromInfo.plist, and converts it to PNG format - Size optimization: Automatically compresses icons that exceed Fleet's 100 KB limit by resizing to 512px, 256px, or 128px
- Format conversion: Converts macOS
.icnsfiles to PNG format using the built-insipstool - Fallback: If extraction fails, continues without an icon (or uses manual
iconpath if provided) - Override: Specify
icon: path/to/icon.pngin your recipe to use a custom icon instead of auto-extraction
FleetImporter supports custom install, uninstall, and post-install scripts. Scripts can be provided as inline content or as file paths.
Provide the script content directly in the recipe:
Input:
UNINSTALL_SCRIPT: |
#!/bin/bash
rm -rf "/Applications/MyApp.app"
rm -rf "$HOME/Library/Application Support/MyApp"Reference a script file stored alongside the recipe:
Input:
UNINSTALL_SCRIPT: uninstall-myapp.shFleetImporter automatically detects file paths (scripts ending in .sh or containing /) and reads the file content. Relative paths are resolved relative to the recipe directory.
Benefits of script files:
- Keeps recipes clean and readable
- Makes scripts easier to maintain and test independently
- Supports syntax highlighting in editors
- Enables script reuse across multiple recipes
When creating AutoPkg overrides with autopkg make-override, script file references continue to work because:
- Script files stay with the original recipe - The override only changes Input values, not companion files
- Paths resolve to the original recipe directory - AutoPkg's
RECIPE_DIRalways points to the original recipe location - You can override with custom scripts by:
- Providing inline script content in your override
- Specifying an absolute path to your own script file
- Copying the script to your override directory and using a relative path
Example override customization:
Input:
# Option 1: Use inline script
UNINSTALL_SCRIPT: |
#!/bin/bash
echo "Custom uninstall logic"
# Option 2: Use absolute path to custom script
UNINSTALL_SCRIPT: /path/to/my-custom-uninstall.sh
# Option 3: Default - uses original recipe's script file
UNINSTALL_SCRIPT: uninstall-myapp.shAll three script parameters support both inline and file path modes:
install_script: Custom installation scriptuninstall_script: Custom uninstall scriptpost_install_script: Script to run after installation
FleetImporter can automatically create Fleet policies that detect outdated software versions and trigger automatic updates via policy automation. When enabled, a policy is created for each software package that:
- Detects outdated versions: Uses osquery to find hosts running any version except the latest
- Triggers installation: Automatically installs the updated package when policy fails
Auto-update policies are disabled by default for backward compatibility. Enable them via recipe overrides:
# Enable in a recipe override (per-recipe control)
autopkg make-override VendorName/SoftwareName.fleet.recipe.yaml
# Edit the override to set automatic_update: true
autopkg run SoftwareName.fleet.recipe.yamlWhen automatic_update is set to true, FleetImporter:
-
Builds version query: Creates an osquery SQL query to detect outdated versions using one of two modes:
Automatic Bundle ID Mode (Recommended): If no custom query is provided, the processor automatically:
- Extracts the bundle identifier from the
.pkgfile - Generates a default query using the
appstable with!=comparison - Works for most standard macOS applications
- Requires no manual configuration
Custom Query Mode (Advanced use cases): Define
auto_update_policy_queryin your recipe with a%VERSION%placeholder:auto_update_policy_query: | SELECT 1 WHERE NOT EXISTS ( SELECT 1 FROM apps WHERE bundle_identifier = 'com.github.GitHubClient' AND bundle_short_version != '%VERSION%' );
The
%VERSION%placeholder is replaced with the actual version at runtime. Use custom queries for:- Non-standard bundle ID detection
- Windows registry-based detection
- Linux package managers
- Custom osquery tables or complex version logic
- Extracts the bundle identifier from the
-
Creates policy (Direct mode): Uses Fleet API to create or update a policy with:
- Descriptive name (e.g.,
autopkg-auto-update-github-desktop) - Version detection query (custom or auto-generated)
- Link to install package automatically on policy failure
- Platform targeting (macOS only)
- Descriptive name (e.g.,
-
Creates policy YAML (GitOps mode): Writes policy definition to
lib/policies/
Policy names are generated from the AUTO_UPDATE_POLICY_NAME template:
- Default template:
autopkg-auto-update-%NAME% - %NAME% placeholder: Replaced with slugified software title
- Slugification: Converts to lowercase, removes special characters, replaces spaces with hyphens
- Customization: Override
AUTO_UPDATE_POLICY_NAMEin your recipe to use a different naming pattern
Examples:
GitHub Desktop→autopkg-auto-update-github-desktopVisual Studio Code→autopkg-auto-update-visual-studio-code1Password 8→autopkg-auto-update-1password-8
All bundle identifiers and versions are automatically escaped to prevent SQL injection:
- Single quotes are doubled:
com.o'reilly.app→com.o''reilly.app - Query remains safe even with malicious input
- Tested against common injection patterns (OR clauses, UNION, DROP TABLE, etc.)
-
Query modes:
- Custom queries (via
auto_update_policy_query) give full control and support any osquery table - Automatic mode extracts CFBundleIdentifier from
.pkgfiles and works for standard macOS apps - If automatic extraction fails and no custom query is provided, policy creation is skipped with a warning
- Custom queries (via
-
Version comparison: Uses exact version matching with
!=comparison. Policies pass when no apps exist with incorrect versions (app not installed OR all instances have correct version). Policies fail when any app instance has a version that doesn't match the required version. -
Policy cleanup: Policies are NOT automatically deleted when software is removed. You should manually delete outdated policies or implement cleanup automation.
-
Error handling: Policy creation failures are logged as warnings and don't block package uploads. Check AutoPkg output for any policy-related errors.
-
Team vs global policies:
- Direct mode: Creates team-specific policies when
FLEET_TEAM_ID> 0, global policies whenFLEET_TEAM_ID= 0 - GitOps mode: Policy scope determined by GitOps repository structure
- Direct mode: Creates team-specific policies when
-
Idempotency: Existing policies with the same name are updated (not duplicated) when recipes run again
AutoPkg not found
- Ensure AutoPkg is installed:
autopkg version - Download from AutoPkg releases if needed
Recipe execution fails
- Verify environment variables are set correctly
- Check AutoPkg recipe dependencies:
autopkg list-repos - Run with verbose output:
autopkg run -v YourRecipe.recipe.yaml
Fleet API authentication errors
- Verify
FLEET_API_BASEURL is correct and accessible - Check that
FLEET_API_TOKENhas software management permissions - Ensure
FLEET_TEAM_IDexists and is accessible with your token
GitOps mode issues
- Verify AWS credentials are configured
- Check S3 bucket permissions for upload/delete operations
- Ensure GitHub token has repository write permissions
- Verify GitOps repository URL and paths are correct
Package upload failures
- Check package file exists and is readable
- Verify package is a valid macOS installer (.pkg)
- Ensure sufficient disk space and network connectivity
# Check AutoPkg installation
autopkg version
# List installed repos
autopkg list-repos
# Validate recipe syntax
autopkg verify YourRecipe.recipe.yaml
# Run with maximum verbosity
autopkg run -vvv YourRecipe.recipe.yaml
# Run style guide compliance tests
python3 tests/test_style_guide_compliance.py- Ask questions in the #autopkg channel on MacAdmins Slack
- Open an issue for bugs or feature requests
- See CONTRIBUTING.md for contribution guidelines
See LICENSE file.