Tutorial: Manage Failover Settings Using the Access Server CLI
Configure and manage failover settings in OpenVPN Access Server using the Web API or sacli CLI tools. Learn how to configure, initialize, and test failover nodes for high availability.
Overview
This tutorial shows how to configure and manage failover settings in OpenVPN Access Server using either the Web API or the sacli command-line tool.
Access Server supports failover deployments for high availability within a local area network (LAN). In a failover deployment:
The primary node handles active traffic.
The secondary node remains in standby mode.
If the primary node becomes unavailable, the secondary node automatically takes over.
This tutorial explains how to:
Validate the failover configuration.
Configure failover settings.
Initialize the secondary node.
Verify failover state changes.
Test failover behavior.
To learn more about failover deployments, refer to the Failover Setup Guide.
Prerequisites
Access Server 3.1.0 or newer (required for Step 1 / Web API method)
Root access to both Access Server nodes.
A completed failover deployment setup.
Important
Before following this tutorial, complete Steps 1-6 in Tutorial: How To Set Up Failover Mode.
(Optional) A remote system for API calls.
Choose a configuration method
This tutorial provides two ways to configure failover settings:
Method | Availability | Best for |
|---|---|---|
Web API ( | Access Server 3.1.0 and newer | Automation and API workflows |
| All supported Access Server versions | Direct server administration |
Use the method that best fits your environment and workflow.
Important
The failover API specification may change between Access Server releases. Always verify the API documentation for your current version. Refer to: View the API specification.
Placeholder values used in this tutorial
Replace the following placeholders with values for your environment:
Placeholder | Description |
|---|---|
| Shared virtual failover IP address |
| UCARP shared secret password |
| IP address of the primary node |
| IP address of the secondary node |
Tip
The UCARP secret can be any secure string. Access Server typically generates a random 16-character value containing uppercase letters, lowercase letters, and numbers.
Note
This method requires Access Server 3.1.0 or newer.
Important
This tutorial uses sacli apicall, but you can also use cURL or Swagger UI. Refer to Tutorial: Test the New Web API (OpenAPI) in Access Server 3.0.
Configure failover settings
Connect to the primary node and get root privileges.
Note
All commands in this section run on the primary node.
Test the failover configuration:
sacli --method POST --url 'api/server/failover-test' --value '{"failover.mode":"ucarp","ucarp.addr":"<FAILOVER_IP>","ucarp.secret":"<UCARP_PASSWORD>","dbpush.hosts.0.enable":true,"dbpush.hosts.0.public":"<PRIMARY_IP>","dbpush.hosts.0.internal":"PRIMARY","dbpush.hosts.0.username":"root","dbpush.hosts.0.password":"","dbpush.hosts.0.ssh_port":22,"dbpush.hosts.1.enable":true,"dbpush.hosts.1.public":"<SECONDARY_IP>","dbpush.hosts.1.internal":"SECONDARY","dbpush.hosts.1.username":"root","dbpush.hosts.1.password":"","dbpush.hosts.1.ssh_port":22}' apicallExample output:
{"ucarp":{"status":true,"message":"UCARP_ADDR_GOOD: ucarp address <FAILOVER_IP> is reachable from locally connected interface on both primary and secondary nodes","friendly":"Shared virtual IP address is directly accessible via locally connected interface on both primary and secondary nodes."},"license_primary":{"status":true,"message":"GOOD_LICENSE: Licensed for 2 concurrent connections.","friendly":"Licensed for 2 concurrent connections."},"license_secondary":{"status":true,"message":"GOOD_LICENSE: Licensed for 2 concurrent connections.","friendly":"Licensed for 2 concurrent connections."},"connectivity":{"status":true,"message":"SUCCEED: failover connectivity test succeeded","friendly":"Connectivity test between primary and secondary nodes succeeded."}}
Save the failover directives/keys into the database:
sacli --method POST --url 'api/config-items/Default' --value '{"failover.mode":"ucarp","ucarp.addr":"<FAILOVER_IP>","ucarp.secret":"<UCARP_PASSWORD>","dbpush.hosts.0.enable":true,"dbpush.hosts.0.public":"<PRIMARY_IP>","dbpush.hosts.0.internal":"PRIMARY","dbpush.hosts.0.username":"root","dbpush.hosts.0.password":"","dbpush.hosts.0.ssh_port":22,"dbpush.hosts.1.enable":true,"dbpush.hosts.1.public":"<SECONDARY_IP>","dbpush.hosts.1.internal":"SECONDARY","dbpush.hosts.1.username":"root","dbpush.hosts.1.password":"","dbpush.hosts.1.ssh_port":22}' apicallExample output:
null
Initiate the secondary node (BACKUP):
sacli --method POST --url 'api/server/failover-init' --value '{"new_config":{"failover.mode":"ucarp","ucarp.addr":"<FAILOVER_IP>","ucarp.secret":"<UCARP_PASSWORD>","dbpush.hosts.0.enable":"true","dbpush.hosts.0.public":"<PRIMARY_IP>","dbpush.hosts.0.internal":"PRIMARY","dbpush.hosts.0.username":"root","dbpush.hosts.0.password":"","dbpush.hosts.0.ssh_port":"22","dbpush.hosts.1.enable":"true","dbpush.hosts.1.public":"<SECONDARY_IP>","dbpush.hosts.1.internal":"SECONDARY","dbpush.hosts.1.username":"root","dbpush.hosts.1.password":"","dbpush.hosts.1.ssh_port":"22"},"old_config":{"failover.mode":"ucarp","ucarp.addr":"<FAILOVER_IP>","ucarp.secret":"<UCARP_PASSWORD>","dbpush.hosts.0.enable":"true","dbpush.hosts.0.public":"<PRIMARY_IP>","dbpush.hosts.0.internal":"PRIMARY","dbpush.hosts.0.username":"root","dbpush.hosts.0.password":"","dbpush.hosts.0.ssh_port":"22","dbpush.hosts.1.enable":"true","dbpush.hosts.1.public":"<SECONDARY_IP>","dbpush.hosts.1.internal":"SECONDARY","dbpush.hosts.1.username":"root","dbpush.hosts.1.password":"","dbpush.hosts.1.ssh_port":"22"}}' apicallExample output:
{"reason":"Success"}
Restart the primary node (MASTER):
sacli --method POST --url 'api/server/restart?restartMode=systemctl' --value '' apicall
Example output:
{}
Verify node status:
systemctl status openvpnas | grep "Switching to state:" | tail -n1
Example output of MASTER:
[WARNING] Switching to state: MASTER
Example output of BACKUP:
[WARNING] Switching to state: BACKUP
This method works on all supported Access Server versions.
Note
All commands in this section run on the primary node.
Create the failover configuration file
Connect to the primary node and get root privileges.
Create the configuration file:
nano failover.json
Add the following configuration:
{ "failover.mode": "ucarp", "ucarp.addr": "<FAILOVER_IP>", "ucarp.secret": "<UCARP_PASSWORD>", "dbpush.hosts.0.enable": "true", "dbpush.hosts.0.public": "<PRIMARY_IP>", "dbpush.hosts.0.internal": "PRIMARY", "dbpush.hosts.0.username": "root", "dbpush.hosts.0.password": "", "dbpush.hosts.0.ssh_port": "22", "dbpush.hosts.1.enable": "true", "dbpush.hosts.1.public": "<SECONDARY_IP>", "dbpush.hosts.1.internal": "SECONDARY", "dbpush.hosts.1.username": "root", "dbpush.hosts.1.password": "", "dbpush.hosts.1.ssh_port": "22" }Save and exit (
Ctrl+x,y,Enter).Tip
This example stores the file in
/root/failover.json.
Test the failover configuration
Run:
sacli --foconf /root/failover.json FailTest
Example output:
{ "connectivity": { "friendly": "Connectivity test between primary and secondary nodes succeeded.", "message": "SUCCEED: failover connectivity test succeeded", "status": true }, "license_primary": { "friendly": "Licensed for 2 concurrent connections.", "message": "GOOD_LICENSE: Licensed for 2 concurrent connections.", "status": true }, "license_secondary": { "friendly": "Licensed for 2 concurrent connections.", "message": "GOOD_LICENSE: Licensed for 2 concurrent connections.", "status": true }, "ucarp": { "friendly": "Shared virtual IP address is directly accessible via locally connected interface on both primary and secondary nodes.", "message": "UCARP_ADDR_GOOD: ucarp address <FAILOVER_IP> is reachable from locally connected interface on both primary and secondary nodes", "status": true } }
Save failover settings
Save the failover directives/keys into the database:
sacli --key "failover.mode" --value "ucarp" ConfigPut sacli --key "ucarp.addr" --value "<FAILOVER_IP>" ConfigPut sacli --key "ucarp.secret" --value "<UCARP_PASSWORD>" ConfigPut sacli --key "dbpush.hosts.0.enable" --value "true" ConfigPut sacli --key "dbpush.hosts.0.public" --value "<PRIMARY_IP>" ConfigPut sacli --key "dbpush.hosts.0.internal" --value "PRIMARY" ConfigPut sacli --key "dbpush.hosts.0.username" --value "root" ConfigPut sacli --key "dbpush.hosts.0.password" --value "" ConfigPut sacli --key "dbpush.hosts.0.ssh_port" --value "22" ConfigPut sacli --key "dbpush.hosts.1.enable" --value "true" ConfigPut sacli --key "dbpush.hosts.1.public" --value "<SECONDARY_IP>" ConfigPut sacli --key "dbpush.hosts.1.internal" --value "SECONDARY" ConfigPut sacli --key "dbpush.hosts.1.username" --value "root" ConfigPut sacli --key "dbpush.hosts.1.password" --value "" ConfigPut sacli --key "dbpush.hosts.1.ssh_port" --value "22" ConfigPut
Initialize the secondary node
Restart Access Server:
systemctl restart openvpnas
Wait approximately 10 seconds.
Create the
db_pushdirectory:ssh root@<SECONDARY_IP> "mkdir /usr/local/openvpn_as/etc/db_push/"
Wait approximately 10 seconds.
Initialize the secondary node:
sacli --foconf=/root/failover.json --init_cmd=restart InitPeer
Verify node state:
systemctl status openvpnas | grep "Switching to state:" | tail -n1
Example output of MASTER:
[WARNING] Switching to state: MASTER
Example output of BACKUP:
[WARNING] Switching to state: BACKUP
Simulate failover
Restart Access Server on the primary node:
systemctl restart openvpnas
Wait approximately 10 seconds.
Verify node state changes:
Primary node should be BACKUP:
[WARNING] Switching to state: BACKUP
Secondary node should be MASTER:
[WARNING] Switching to state: MASTER
Open the failover IP address in a web browser.
The Admin Web UI should now display the secondary node.
Restore the primary node
Restart Access Server on the secondary node:
systemctl restart openvpnas
Wait approximately 10 seconds.
Verify node state changes:
Primary node should be MASTER again:
[WARNING] Switching to state: MASTER
Secondary node should be BACKUP again:
[WARNING] Switching to state: BACKUP
Open the failover IP address in a web browser.
The Admin Web UI should now display the primary node.
To monitor failover state changes, review:
/var/log/openvpnas.log /var/log/openvpnas-node.log