class: center, middle, inverse # Bringing OpenBolt
into Foreman ??? --- ## $ whoami
* Tim 'bastelfreak' Meusel * Puppet Contributor since 2012 * Merging stuff on [Vox Pupuli](https://voxpupuli.org/) (Puppet Community) since 2015 * Vox Pupuli Project Management Committee member * Senior IT Automation Consultant at [betadots](https://betadots.de/) * Certified Puppet Solution Consultant [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * who has seen this picture before because I reviewed/merged your pull request? --- count: false ## $ whoami
* Tim 'bastelfreak' Meusel * Puppet Contributor since 2012 * Merging stuff on [Vox Pupuli](https://voxpupuli.org/) (Puppet Community) since 2015 * Vox Pupuli Project Management Committee member * Senior IT Automation Consultant at [betadots](https://betadots.de/) * Certified Puppet Solution Consultant * New: Clojure & [ezbake](https://github.com/OpenVoxProject/ezbake) "expert" [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * who has seen this picture before because I reviewed/merged your pull request? --- class: center, middle, inverse # OpenVox
??? * Who knows OpenVox? --- .left-column[ ## OpenVox ### What? ] .right-column[ * Perforce stopped open source development * Vox Pupuli continues the open source development ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- count: false .left-column[ ## OpenVox ### What? ] .right-column[ * Perforce stopped open source development * Vox Pupuli continues the open source development * puppet-agent -> [openvox-agent](https://github.com/OpenVoxProject/openvox?tab=readme-ov-file#openvox) * puppetserver -> [openvox-server](https://github.com/OpenVoxProject/openvox-server) * puppetdb -> [openvoxdb](https://github.com/OpenVoxProject/openvoxdb) * bolt -> [openbolt](https://github.com/OpenVoxProject/openbolt) ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- .left-column[ ## OpenVox ### What? ### How? ] .right-column[ example class for managing nginx ```puppet # @summary configures nginx in a bad way # @param content the whole nginx config class nginx ( Sensitive[String[1]] $content, ) { package { 'nginx': ensure => 'installed', } -> file { '/etc/nginx/nginx.conf': ensure => 'file', content => $content, } ~> service { 'nginx': ensure => 'running', enable => true, } } ``` ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * We have inline documentation with puppet-strings * the class keyword * parameter with datatype * some resources --- class: center, middle, inverse # OpenBolt ## Tasks & Plans ??? * Who knows bolt? --- .left-column[ ## OpenBolt ### Tasks?! ] .right-column[ * Runs tasks via ssh or WinRM on remote systems * CLI only * A task is a executable binary/script + json file ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * So what's a task? --- count: false .left-column[ ## OpenBolt ### Tasks?! ] .right-column[ ```json { "puppet_task_version": 1, "supports_noop": false, "description": "Rename branch", "parameters": { "control_repo_branch": { "description": "Control-repo branch", "type": "String" } } } ``` ```sh #!/bin/bash pushd /tmp/control-repo || exit git branch -m production old_prod git branch -m "$PT_control_repo_branch" production ``` ] [](https://www.betadots.de) [](https://puppet.run) ??? --- .left-column[ ## OpenBolt ### Tasks?! ] .right-column[ * Runs tasks via ssh or WinRM on remote systems * CLI only * A task is a executable binary/script + json file * Input and output of each task is JSON * makes parsing, scripting and concatenating easy ] [](https://www.betadots.de) [](https://puppet.run) ??? --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ] .right-column[ * Plans are written in OpenVox DSL (or [YAML](https://www.puppet.com/docs/bolt/latest/writing_yaml_plans.html)) * Plans apply puppet code, execute OpenBolt or OpenVox functions, start tasks or other plans ```puppet # @summary Conference Demo plan # @param message the string we want to paste to STDOUT plan test::foo ( String[1] $message = 'Hi CfgMgmtCamp 2026!', ) { out::message($message) run_task('puppet_agent::install', get_targets('all')) } ``` ] [](https://www.betadots.de) [](https://puppet.run) ??? * plans and tasks are organized in modules * plans are parsed top to bottom * there's a config file with all nodes + credentials * you can do a bunch of error checking and retrying! --- class: center, middle, inverseold ## OpenBolt is the missing part in the ecosystem for imperative workflows and orchestration ### It combines scripts and OpenVox code ??? * bolt has more features, please check them out * but this isn't a bolt talk, just an intro * people comparing ansible with puppet are doing it wrong. The counterpart of ansible is bolt, not puppet --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[ * OpenBolt is a CLI only application * Puppet Enterprise has a Web-UI & API * closed source & expensive * Most Puppet/OpenVox users run Foreman anyways and don't want another UI ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- count: false .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[ * OpenBolt is a CLI only application * Puppet Enterprise has a Web-UI & API * closed source & expensive * Most Puppet/OpenVox users run Foreman anyways and don't want another UI * Why not add OpenBolt support to Foreman?! ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * OpenBolt supports different transport protocols * lxd, podman, docker, BSD jails, local * plugin system --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * The "Launch Task" option allows you to select any smartproxy with the openbolt feature (which is available when the OpenBolt Smartproxy plugin is installed). Afterwards you can select N targets to run the task and select an available task from the selected Smartproxy. On the right side you can configure OpenBolt connection settings. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * After selecting a task, the task metadata is fetched and shown. Additional input elements will appear, if the task support it. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * The metadata can contains a description and datatypes for tasks. Those information can be shown as well. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[ .img80[] ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * While the task is running, the UI polls the status from the smart proxy. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * After the task finished, it will display a success for failure page. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * We also display the used OpenBolt command line, in case you want to manually run it or debug it. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[  ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * OpenBolt returns JSON for executed tasks. That's visible in the UI. For failed tasks but also for passed tasks. --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ] .right-column[ .img57[] ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ### Choria?! ] .right-column[ * [Choria Orchestration System](https://choria.io/docs/concepts/architecture/) .img70[] ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * successor of mcollective, or mcollective 2.0. same developers. scales to tens of thousands of systems --- count: false .left-column[ ## OpenBolt ### Tasks?! ### Plans?! ### Foreman?! ### Choria?! ] .right-column[ * [Choria Orchestration System](https://choria.io/docs/concepts/architecture/) .img70[] ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? * successor of mcollective, or mcollective 2.0. same developers. scales to tens of thousands of systems --- .left-column[ ## Conclusion ] .right-column[ * OpenBolt is a great addition to the Foreman ecosystem * Makes it easy to reuse existing Tasks (and soon Plans) ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- count: false .left-column[ ## Conclusion ] .right-column[ * OpenBolt is a great addition to the Foreman ecosystem * Makes it easy to reuse existing Tasks (and soon Plans) * Choria provides almost infinite scaling and opposite firewalling ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ??? --- count: false .left-column[ ## Conclusion ] .right-column[ * OpenBolt is a great addition to the Foreman ecosystem * Makes it easy to reuse existing Tasks (and soon Plans) * Choria provides almost infinite scaling and opposite firewalling * Please join our [IRC/Slack](https://voxpupuli.org/connect/) to provide feedback * For feedback: `bastelfreak` on IRC/ Slack or [tim@bastelfreak.de](mailto:tim@bastelfreak.de) * This talk and previous ones: [github.com/bastelfreak/talks](https://github.com/bastelfreak/talks) ### Thanks for your attention! ] [](https://www.betadots.de) [](https://cfgmgmtcamp.org/ghent2026/) ???