Skip to content

Repository files navigation

GPOA - GPO Applier for Linux

Contents


Introduction

GPOA (GPO Applier for Linux) is a comprehensive facility to fetch, reinterpret and apply Group Policy Objects (GPOs) from Windows Active Directory domains in Linux environments. Developed by ALT Linux team, it enables seamless integration of Linux machines into corporate Windows infrastructure.

Packages

Starting from version 0.15.0, the project is split into two RPM packages:

PackageDescription
gpupdateEntry points, backends, GPT processing. Depends on gpoa-lib.
gpoa-libStandalone library: policy appliers, storage, plugin framework, utilities. Can be used independently.

The gpoa/ directory contains thin wrappers that re-export from gpoa_lib/ for backward compatibility. All implementation lives in gpoa_lib/.

Features

Core Functionality

  • Multi-backend Support: Samba, FreeIPA, and no-domain backends
  • Policy Types: Registry settings, files, folders, environment variables, scripts, services, and more
  • Display Manager Integration: LightDM, GDM, SDDM with background and theme support
  • Plugin System: Extensible architecture for custom policy types
  • Targeting Filters: 15 filter types (computer, domain, user, group, date, time, CPU, battery, disk, RAM, language, file, environment variable, IP range, MAC range)
  • Privilege Separation: Secure execution with proper privilege contexts
  • External API: StorageAdapter, StorageWriter, ApplierRunner, and Result for using gpoa-lib as a standalone library

Supported Policy Areas

  • System Configuration: Control facilities, systemd units, environment variables, NTP, firewall
  • Desktop Settings: GSettings, KDE configuration
  • Security: Polkit policies, LAPS (Local Administrator Password Solution)
  • Network: CIFS/autofs network shares
  • Applications: Firefox, Chromium, Thunderbird, Yandex Browser
  • Files and Folders: File deployment, folder redirection, INI file configuration
  • Hardware: Udev rules (via external plugin)

Architecture

Backend System

  • Samba Backend: Traditional Active Directory integration
  • FreeIPA Backend: Enhanced FreeIPA/IdM integration
  • No-domain Backend: Local policy application

Frontend System

  • Policy Appliers: 20 specialized modules for different policy types
  • Plugin Framework: Extensible plugin system with logging and translations
  • Targeting Filters: GPP preference-level targeting with caching

Storage

  • Dconf Registry: Policy data stored in dconf databases
  • GPP State: Lifecycle management (applyOnce, removePolicy, disabled)
  • File Cache: Secure file storage and retrieval

Plugin System

  • Machine Context: Root-privileged system-wide changes
  • User Context: User-specific configuration application with privilege dropping
  • Message Codes: Structured logging with translation support
  • Registry Access: Secure access to policy registry data via get_dict_registry()
  • Custom registry_path: Override registry path at construction time

Installation

From Source

# Clone the repository
git clone https://github.com/altlinux/gpupdate.git
cd gpupdate
# Build RPM packages (produces gpupdate and gpoa-lib)
rpmbuild -ba gpupdate.spec
# Install both packages
rpm -ivh ~/rpmbuild/RPMS/noarch/gpupdate-*.rpm ~/rpmbuild/RPMS/noarch/gpoa-lib-*.rpm
# Or install only the library
rpm -ivh ~/rpmbuild/RPMS/noarch/gpoa-lib-*.rpm

Dependencies

  • Python 3.8+
  • Samba client tools
  • FreeIPA client (optional)
  • Systemd
  • D-Bus

Usage

Apply Policies for Machine

# Run as root for system-wide policies
sudo gpoa

Apply Policies for User

# Run as root for user-specific policies
sudo gpoa username

Force Policy Refresh

# Can be run as regular user
gpupdate --force

Plugin Management

Plugins are automatically discovered from:

  • /usr/lib/gpoa/plugins/ (system-wide plugins)

External API (gpoa-lib)

gpoa-lib provides a public API for applying policies without the full gpupdate stack.

ApplierRunner

High-level facade for running policy appliers:

fromgpoa_libimportApplierRunner# From a dconf databaserunner=ApplierRunner(db_name='mydb')
result=runner.run('control')
ifnotresult:
print('Error:', result.error)
# From a plain dict (no dconf needed)runner=ApplierRunner(data={
'Software/BaseALT/Policies/Control': {
'sshd-gssapi-auth': '1',
}
})
runner.run('control')
# Auto-detect applier from key pathrunner.run_auto(['Software/BaseALT/Policies/Control/sshd-gssapi-auth'])
# Force re-apply from a specific databaserunner=ApplierRunner(db_name='policy', force=True)
runner.run('control')
# List available appliersprint(ApplierRunner.list_appliers())
# Resolve applier name from key pathprint(ApplierRunner.resolve('Software/BaseALT/Policies/Control/sshd'))

StorageAdapter

Low-level access to policy data from dconf or dict:

fromgpoa_libimportStorageAdapter# From dconf databasestorage=StorageAdapter.from_dconf_db('mydb')
# From dictstorage=StorageAdapter.from_dict({
'Software/BaseALT/Policies/Control': {
'sshd-gssapi-auth': '1',
}
})
# Get raw dict (for passing to plugins)data=storage.get_dict()
# Query specific entriesentries=storage.filter_hklm_entries('Software/BaseALT/Policies/Control')
value=storage.get_key_value('Software/BaseALT/Policies/Control/sshd-gssapi-auth')

StorageWriter

Write policy data to arbitrary dconf databases:

fromgpoa_libimportStorageWriterwriter=StorageWriter('local')
writer.write_keys({
'Software/BaseALT/Policies/Control/sshd-gssapi-auth': '1',
})
writer.compile()

Running Plugins with Custom Data

importsyssys.path.insert(0, '/usr/lib/gpoa/plugins')
fromgpoa_libimportStorageAdapterfromudev_applierimportUdevApplier# From dict with default registry pathstorage=StorageAdapter.from_dict({
'Software/BaseALT/Policies/Udev': {'BlockUSBAll': '1'}
})
plugin=UdevApplier(storage.get_dict())
plugin.apply()
# With custom registry_pathplugin=UdevApplier(storage.get_dict(), registry_path='My/Custom/Path')
plugin.apply()

See EXAMPLES.md for complete examples. See API_REFERENCE.md for the full API reference. See API_REFERENCE_RU.md for the Russian API reference.

Plugin Development

GPOA features a comprehensive plugin system. See documentation for detailed information:

Documentation covers:

  • Plugin architecture and API
  • Creating custom plugins
  • Logging and message codes
  • Translation support
  • Best practices

Quick Plugin Example

fromgpoa_lib.plugin.plugin_baseimportFrontendPluginclassMyPlugin(FrontendPlugin):
domain='my_plugin'def__init__(self, dict_dconf_db, username=None, fs_file_cache=None, registry_path=None):
super().__init__(dict_dconf_db, username, fs_file_cache, registry_path)
self._init_plugin_log(message_dict={
'i': {1: "Plugin initialized"},
'e': {1: "Plugin failed"}
}, domain="my_plugin")
self.config=self.get_dict_registry(
self._registry_pathor'Software/MyOrg/Policies/MyPlugin')
defrun(self, **kwargs):
self.log("I1")
returnTruedefcreate_machine_applier(dict_dconf_db, username=None, fs_file_cache=None, registry_path=None):
returnMyPlugin(dict_dconf_db, username, fs_file_cache, registry_path)

Project Structure

gpupdate/
├── gpoa/ # Entry points and thin wrappers → gpoa_lib
│ ├── backend/ # Samba, FreeIPA, nodomain backends
│ ├── frontend/ # Thin wrappers for appliers
│ │ └── appliers/ # Individual applier wrappers
│ ├── frontend_plugins/ # Built-in frontend plugins
│ ├── gpt/ # GPT parsing and filter processing
│ ├── locale/ # Russian translations
│ ├── messages/ # Message code definitions
│ ├── plugin/ # Plugin manager wrapper
│ ├── storage/ # Storage wrapper
│ ├── templates/ # Jinja2 templates (autofs, dconf)
│ ├── util/ # Utility wrappers
│ ├── gpoa # Main GPOA entry point
│ ├── gpupdate # gpupdate CLI entry point
│ └── gpupdate-setup # Enable/disable configuration tool
│
├── gpoa_lib/
│ └── gpoa_lib/ # Standalone library (gpoa-lib RPM)
│ ├── frontend/ # 20 policy appliers
│ │ └── appliers/ # Individual applier implementations
│ ├── frontend_plugins/ # Built-in plugin implementations
│ ├── plugin/ # Plugin framework (base, manager, logging)
│ ├── storage/ # Dconf registry, GPP state, StorageAdapter
│ ├── util/ # Utilities, filters, logging, paths
│ ├── messages/ # Localized message definitions
│ ├── test/ # Unit tests (430+ tests)
│ ├── __init__.py # Public API exports
│ ├── applier_runner.py # ApplierRunner facade
│ └── result.py # Result type (ok/fail pattern)
│
├── dist/ # systemd units, polkit, PAM rules
├── doc/ # Man pages
├── completions/ # Bash completion scripts
├── tools/ # Auxiliary scripts
├── gpupdate.spec # RPM spec (gpupdate + gpoa-lib subpackage)
├── API_REFERENCE.md # API reference (English)
├── API_REFERENCE_RU.md # API reference (Russian)
├── PLUGIN_DEVELOPMENT_GUIDE.md # Plugin development guide (English)
├── PLUGIN_DEVELOPMENT_GUIDE_RU.md # Plugin development guide (Russian)
└── EXAMPLES.md # External API usage examples

Contributing

The main communication channel for GPOA is Samba@ALT Linux mailing lists. The mailing list is in Russian but you may also send e-mail in English or German.

License

GPOA - GPO Applier for Linux

Copyright (C) 2019-2026 BaseALT Ltd.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

About

Utility to apply GPOs from Windows Active Directory domains in UNIX environments

Resources

Stars

26 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages