Manage OpenVPN Access Server Configuration as Code with Puppet and sacli

Illustration of a laptop connected to a stack of servers
Share
Manage OpenVPN Access Server with Puppet and sacli
8:01

Keep OpenVPN Access Server config consistent with Puppet: the openvpnas types for config, users and properties, restart handling, and caveats.

Short answer: The puppet-openvpnas module lets you declare OpenVPN Access Server settings, users and user properties as Puppet resources. It provides three resource types, openvpnas_config, openvpnas_user and openvpnas_userprop, which drive the sacli command-line tool, and it is licensed BSD-2-Clause. It does not restart Access Server when configuration changes, so you handle that yourself.

OpenVPN Access Server banner

Why manage Access Server configuration with Puppet

Access Server is easy to configure by hand in the Admin UI, which is exactly how servers drift: one admin changes a setting, nobody records it, and the replacement server built from the same template behaves differently. Many settings can also be set from the command line, and the Access Server documentation covers configuration and user and group properties through sacli. The Puppet module wraps those sacli calls in resources that Puppet compares against reality on every run. The result is a file in Git as the source of truth, a no-op mode that shows drift before it matters, and a way to rebuild a server's settings without remembering what was clicked.

Where this fits

Terraform (post 1) created the server and its first admin. Day 2 is about keeping it that way. The module drives sacli on a host where Puppet runs, so it fits the VM-based platform-dev access server. For the Kubernetes deployment in post 2, the chart's postStart script plays this role instead.

The spec is the same one used throughout the series: DNS name vpn-dev.example.com, superuser admin1, test user eng-test, and vpn.tls_refresh.interval set to 100. Terraform already handled the admin account, so Puppet now enforces everything else.

What the module gives you

 
 

Piece

 

What it manages

 

openvpnas class

The package, service and configuration; parameters include package_ensure, service_ensure, service_enable, service_name, config and userprop

openvpnas_config

Access Server configuration keys (ensurable)

openvpnas_user

Users, with ensure set to present or absent

openvpnas_userprop

User and group properties, titled <user-or-group>-<property>, such as openvpn-prop_superuser

 
 
 

The README describes the module as currently containing only types and providers, with more planned, and it also documents the openvpnas class and its parameters. Check the module version you install to see which parts it ships.

Install the module and the package

Access Server itself can be installed from OpenVPN's official apt or yum repositories, and the openvpnas class can manage the package and service. Add the module to your Puppetfile, then set the class parameters in Hiera:

 
openvpnas::package_ensure: present openvpnas::service_ensure: running openvpnas::service_enable: true

Pin the module version in your Puppetfile and read the README for the version you install, because the module is still evolving.

Declare the spec

 
include ::openvpnas openvpnas_config { 'host.name': value => 'vpn-dev.example.com', } openvpnas_config { 'vpn.tls_refresh.interval': value => '100', } openvpnas_user { 'eng-test': ensure => present, } openvpnas_userprop { 'admin1-prop_superuser': value => 'true', }

All property values must be strings, including values that look like booleans, which is why 'true' and '100' are quoted. The same settings can live in Hiera through the openvpnas::config and openvpnas::userprop hashes, which keeps node data out of manifests.

Handle restarts yourself

Because changing configuration does not restart the service, add an explicit trigger that fires only when a setting changes:

 
exec { 'apply-access-server-config': command => '/usr/local/openvpn_as/scripts/sacli start', refreshonly => true, subscribe => [ Openvpnas_config['host.name'], Openvpnas_config['vpn.tls_refresh.interval'], ], }

The Access Server Kubernetes tutorials follow the same pattern: they set a value with sacli ... ConfigPut and then run sacli start (see the GKE tutorial).

Detect drift and adopt an existing server

Run the agent in no-op mode to see what Puppet would change without changing it:

 
puppet agent -t --noop

For a server that already exists, export the current settings as a starting point:

 
puppet resource openvpnas_config --to_yaml

Prune the output before committing it. The subscription.saved_state key changes often, so the README discourages pinning it in Puppet.

A change workflow that fits

  1. Open a pull request that edits the manifest or the Hiera data.
  2. Run puppet agent -t --noop on a staging server and read the proposed changes.
  3. Merge, then let the agent apply the change, or run puppet agent -t yourself.
  4. Verify with sacli UserPropGet for properties, and confirm the restart trigger fired if a setting changed.
  5. Promote the same change to production.

How Terraform and Puppet divide the work

Give each setting one owner. Terraform owns the lifecycle of the server and the first admin credential, which it takes from TF_VAR_admin_password. Puppet owns what happens inside the server afterward: the DNS name, users, properties and tuning keys. If you also extend Terraform's cloud-init to set the same keys, the two will disagree on the first Puppet run, so choose one place for each.

Production caveats and fixes

  • No validation. sacli does not validate values, so an invalid value can break the VPN configuration. Test changes with --noop and on a staging server first.
  • No automatic restart. Add the exec trigger above, or schedule restarts for a maintenance window.
  • Strings only. Quote every value.
  • Removals are real. openvpnas_config and openvpnas_userprop can remove keys, so review removals before they reach production.
  • Secrets appear in plain text when you export configuration. The README recommends encrypting them with eYAML. Keep credentials out of manifests; Terraform and your secret manager own the admin password in this series.
  • Title rules. Usernames in openvpnas_userprop titles are limited to word characters, dots and underscores. Other characters fail catalog compilation unless you edit the validation regex.
  • Support scope. The module is open source (BSD-2-Clause) and its repository shows few releases and a small community, so pin a version and review changes before upgrading.

FAQ

Does the Puppet module restart Access Server after a configuration change?

No. The README states that changing configuration does not restart the service automatically, so add your own restart or apply step.

What does the puppet-openvpnas module manage?

Configuration keys with openvpnas_config, users with openvpnas_user, and user and group properties with openvpnas_userprop, all through sacli, plus package installation from the official repositories through the openvpnas class.

Can I use it with the Helm deployment?

The module drives sacli on a host where Puppet runs. For Kubernetes, use the chart's postStart script, covered in post 2.

How do I adopt a server I already built by hand?

Run puppet resource openvpnas_config --to_yaml, prune volatile keys such as subscription.saved_state, and commit the rest.

What you built

One spec, three tools: Terraform provisioned the server, Helm ran the same spec on Kubernetes, and Puppet keeps a host-based server consistent. The common thread is that the spec (a DNS name, an admin, a test user and a tuning key) lives in version control, and every environment is built from it. Secrets stay outside it: the admin password comes from your secret store, never from a manifest, values file or tfvars file. Return to the VPN as Code hub for the full series.

Try it: Browse the module on GitHub, read the Access Server configuration overview, or try Access Server free (two free connections). 

Get started

Pick the stage that matches your stack and start there. When you are ready, try Access Server with our free plan or read the official tutorials.

Start Access Server Free

Related posts from OpenVPN

Subscribe for Blog Updates