summaryrefslogtreecommitdiff
path: root/docs/automation
diff options
context:
space:
mode:
authorYuriy Andamasov <yuriy@vyos.io>2026-05-06 23:24:45 +0300
committerYuriy Andamasov <yuriy@vyos.io>2026-05-06 23:24:45 +0300
commit89f86b481456437f3e9f16895e7408fe460de3f3 (patch)
treef1bb09b203d56234c4518e6ab2d7fa5ca8610dec /docs/automation
parent6ce9145fa101e623c61f009c9cf5bb75a8a4a108 (diff)
parent7cf51e1c2901f6d1b01e9bff194f7188bc29e417 (diff)
downloadvyos-documentation-89f86b481456437f3e9f16895e7408fe460de3f3.tar.gz
vyos-documentation-89f86b481456437f3e9f16895e7408fe460de3f3.zip
Merge remote-tracking branch 'origin/current' into feat/docs-llms-txt-current
# Conflicts: # docs/conf.py
Diffstat (limited to 'docs/automation')
-rw-r--r--docs/automation/cloud-init.md378
-rw-r--r--docs/automation/command-scripting.md225
-rw-r--r--docs/automation/index.md16
-rw-r--r--docs/automation/rst-cloud-init.rst (renamed from docs/automation/cloud-init.rst)0
-rw-r--r--docs/automation/rst-command-scripting.rst (renamed from docs/automation/command-scripting.rst)0
-rw-r--r--docs/automation/rst-index.rst (renamed from docs/automation/index.rst)0
-rw-r--r--docs/automation/rst-vyos-ansible.rst (renamed from docs/automation/vyos-ansible.rst)0
-rw-r--r--docs/automation/rst-vyos-api.rst (renamed from docs/automation/vyos-api.rst)0
-rw-r--r--docs/automation/rst-vyos-govyos.rst (renamed from docs/automation/vyos-govyos.rst)0
-rw-r--r--docs/automation/rst-vyos-napalm.rst (renamed from docs/automation/vyos-napalm.rst)0
-rw-r--r--docs/automation/rst-vyos-netmiko.rst (renamed from docs/automation/vyos-netmiko.rst)0
-rw-r--r--docs/automation/rst-vyos-pyvyos.rst (renamed from docs/automation/vyos-pyvyos.rst)0
-rw-r--r--docs/automation/rst-vyos-salt.rst (renamed from docs/automation/vyos-salt.rst)0
-rw-r--r--docs/automation/terraform/index.md29
-rw-r--r--docs/automation/terraform/rst-index.rst (renamed from docs/automation/terraform/index.rst)0
-rw-r--r--docs/automation/terraform/rst-terraformAWS.rst (renamed from docs/automation/terraform/terraformAWS.rst)0
-rw-r--r--docs/automation/terraform/rst-terraformAZ.rst (renamed from docs/automation/terraform/terraformAZ.rst)0
-rw-r--r--docs/automation/terraform/rst-terraformGoogle.rst (renamed from docs/automation/terraform/terraformGoogle.rst)0
-rw-r--r--docs/automation/terraform/rst-terraformvSphere.rst (renamed from docs/automation/terraform/terraformvSphere.rst)0
-rw-r--r--docs/automation/terraform/terraformAWS.md548
-rw-r--r--docs/automation/terraform/terraformAZ.md501
-rw-r--r--docs/automation/terraform/terraformGoogle.md703
-rw-r--r--docs/automation/terraform/terraformvSphere.md388
-rw-r--r--docs/automation/terraform/terraformvyos.md44
-rw-r--r--docs/automation/vyos-ansible.md101
-rw-r--r--docs/automation/vyos-api.md587
-rw-r--r--docs/automation/vyos-govyos.md197
-rw-r--r--docs/automation/vyos-napalm.md152
-rw-r--r--docs/automation/vyos-netmiko.md76
-rw-r--r--docs/automation/vyos-pyvyos.md149
-rw-r--r--docs/automation/vyos-salt.md211
31 files changed, 4305 insertions, 0 deletions
diff --git a/docs/automation/cloud-init.md b/docs/automation/cloud-init.md
new file mode 100644
index 00000000..b6350b54
--- /dev/null
+++ b/docs/automation/cloud-init.md
@@ -0,0 +1,378 @@
+---
+lastproofread: '2026-04-13'
+---
+
+(cloud-init)=
+
+# VyOS cloud-init
+
+VyOS instances in cloud and virtualized environments are initialized using the
+industry-standard `cloud-init`. Through `cloud-init`, VyOS injects SSH
+keys, configures network settings, and applies custom configurations during the
+initial instance boot.
+
+## Configuration sources
+
+VyOS `cloud-init` obtains configuration data from the following sources:
+
+- `meta-data`: Instance-specific details provided by the cloud platform or
+ hypervisor. In some cloud environments, this data is available via an HTTP
+ endpoint at `http://169.254.169.254`.
+- `network configuration`: Network settings such as IP addresses, routes, and
+ DNS (only available on certain cloud and virtualization platforms).
+- `user-data`: User-supplied CLI configuration commands.
+
+## User-data
+
+Major cloud providers support injecting `user-data` as plain text or base64
+encoding text during initial instance boot. As `user-data` has a strict size
+limit of \~16384 bytes, long configuration command lists can be compressed using
+`gzip`.
+
+The recommended method for configuring VyOS instances via `user-data` is to
+use the `cloud-config` syntax described below.
+
+## Cloud-config modules
+
+By default, VyOS enables only two `cloud-config` modules:
+
+- `write_files`: Inserts user-provided files such as encryption keys,
+ certificates, or `config.boot` into the filesystem during the initial
+ instance boot. See [Cloud-init-write_files] for file syntax and file format
+ requirements.
+- `vyos_userdata`: Executes user-provided CLI configuration commands during
+ the initial instance boot.
+
+The files to insert and the CLI commands to execute must be provided in a
+`cloud-config` YAML file.
+
+## Cloud-config file format
+
+`cloud-config` files are written in YAML and must begin with the
+`#cloud-config` line. Only `vyos_config_commands` and `write_files` are
+supported as top-level keys. The use of these keys is described in the
+following two sections.
+
+## Vyos_config_commands key
+
+Use the `vyos_config_commands` key to define configuration commands for
+initializing your VyOS instance. Commands must follow the set-style syntax
+and can include both `set` and `delete` statements.
+
+Syntax requirements:
+
+- Place one command per line.
+- Enclose values in single quotes.
+- Avoid single quotes within commands or values.
+
+Applying commands from `cloud-config` overrides both settings configured via
+`meta-data` and default VyOS settings. After commands are applied,
+`cloud-init` automatically performs `commit` and `save`.
+
+The following is an example of a `cloud-config` file:
+
+```yaml
+#cloud-config
+vyos_config_commands:
+ - set system host-name 'vyos-prod-ashburn'
+ - set service ntp server 1.pool.ntp.org
+ - set service ntp server 2.pool.ntp.org
+ - delete interfaces ethernet eth1 address 'dhcp'
+ - set interfaces ethernet eth1 address '192.0.2.247/24'
+ - set protocols static route 198.51.100.0/24 next-hop '192.0.2.1'
+```
+
+
+### Instance defaults/fallbacks
+
+If no external configuration data is provided, VyOS applies the following
+defaults:
+
+- **SSH:** port 22.
+- **Credentials:** `vyos`/`vyos`.
+- **Networking:** DHCP is enabled on the first Ethernet interface.
+
+All defaults can be overridden via `user-data` configurations.
+
+## Write_files key
+
+VyOS allows you to run custom scripts during the initial instance boot to
+execute operational, configuration, and standard Linux commands.
+
+Use the `write_files` key to insert these scripts into the
+`/opt/vyatta/etc/config/scripts/` directory.
+
+Depending on when your commands need to run, use one of the following paths:
+
+- `/opt/vyatta/etc/config/scripts/vyos-preconfig-bootup.script`: Commands
+ defined here are executed before the system configuration is applied.
+- `/opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script`: Commands
+ defined here are executed after the system configuration is applied.
+
+In both cases, commands are executed with `root` privileges.
+
+:::{note}
+Use the `/opt/vyatta/etc/config/` path instead of `/config/scripts/` as
+referenced in the {ref}`command-scripting` section. The `/config/scripts/`
+directory is not mounted when the `write_files` module runs.
+:::
+
+The following example shows how to use `write_files` to execute an
+operational command **after** the initial configuration is complete:
+
+```yaml
+#cloud-config
+write_files:
+ - path: /opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script
+ owner: root:vyattacfg
+ permissions: '0775'
+ content: |
+ #!/bin/vbash
+ source /opt/vyatta/etc/functions/script-template
+ filename=/tmp/bgp_status_`date +"%Y_%m_%d_%I_%M_%p"`.log
+ run show ip bgp summary >> $filename
+```
+
+You can combine standard Linux commands to fetch data and VyOS configuration
+commands (like `set` and `commit`) in the same script.
+
+The following example sets the `hostname` based on the instance identifier
+obtained from the EC2 Instance Metadata Service (IMDS).
+
+```yaml
+#cloud-config
+write_files:
+ - path: /opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script
+ owner: root:vyattacfg
+ permissions: '0775'
+ content: |
+ #!/bin/vbash
+ source /opt/vyatta/etc/functions/script-template
+ hostname=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
+ configure
+ set system host-name $hostname
+ commit
+ exit
+```
+
+
+## NoCloud
+
+Injecting configuration data is not limited to cloud platforms. The NoCloud
+data source allows you to inject `user-data` and `meta-data` on
+virtualization platforms such as VMware, Hyper-V, and KVM.
+
+The simplest way to use the NoCloud data source is to create a `seed.iso`
+file and attach it to the virtual machine as a CD drive. The volume must be
+formatted as a VFAT or ISO 9660 file system with the label `cidata` or
+`CIDATA`.
+
+Create text files named `user-data` and `meta-data`. On Linux-based
+systems, use the `mkisofs` utility to create the `seed.iso` file. The
+following syntax adds these files to the ISO 9660 file system:
+
+```none
+mkisofs -joliet -rock -volid "cidata" -output seed.iso meta-data user-data
+```
+
+Once generated, attach the `seed.iso` file to your virtual machine. The
+following example shows how to attach the file as a CD drive using KVM:
+
+```none
+$ virt-install -n vyos_r1 \
+ --ram 4096 \
+ --vcpus 2 \
+ --cdrom seed.iso \
+ --os-type linux \
+ --os-variant debian10 \
+ --network network=default \
+ --graphics vnc \
+ --hvm \
+ --virt-type kvm \
+ --disk path=/var/lib/libvirt/images/vyos_kvm.qcow2,bus=virtio \
+ --import \
+ --noautoconsole
+```
+
+For more information on the NoCloud data source, visit the [NoCloud] page in
+the `cloud-init` documentation.
+
+## Troubleshooting
+
+If your configuration does not apply as expected, follow these troubleshooting
+steps:
+
+1. **Validate your YAML**: Ensure your `cloud-config` file follows proper
+ YAML syntax. Online resources such as [YAML Lint](https://www.yamllint.com/)
+ provide simple validation tools.
+2. **Check the logs**: `cloud-init` writes logs to `/var/log/cloud-init.log`.
+ Filter for VyOS-specific entries using:
+
+```none
+sudo grep vyos /var/log/cloud-init.log
+```
+
+
+## Cloud-init on Proxmox
+
+Before you begin, review the `cloud-init` [network-config-docs] to
+understand how to import user and network configuration data.
+
+Key considerations:
+
+- Define VyOS configuration commands in the `user-data` file.
+- Avoid including network configuration data in the `user-data` file.
+- If no network configuration data is provided, the DHCP client is enabled on
+ the first interface. This happens at the OS level and is not reflected in the
+ VyOS CLI.
+
+The following example shows how to disable the DHCP client on `eth0` to
+address this behavior.
+
+In this example:
+
+- **Proxmox IP address**: `192.168.0.253/24`.
+- **Storage**: The `local` volume is mounted at `/var/lib/vz` and contains
+ all content types, including snippets.
+
+The goal is to remove the default DHCP client from the first interface and
+apply a custom configuration during the initial instance boot using
+`cloud-init`.
+
+### Generate .qcow2 image
+
+First, generate a VyOS `.qcow2` image with `cloud-init` support from the
+[vyos-vm-images] repository:
+
+1. Clone the `vyos-vm-images` repository and comment out the `download-iso`
+ role in `qemu.yml`.
+2. Download your preferred VyOS `.iso` file and save it as `/tmp/vyos.iso`.
+3. Generate the `.qcow2` image (using a 10G disk size for this example):
+
+```sh
+sudo ansible-playbook qemu.yml -e disk_size=10 \
+ -e iso_local=/tmp/vyos.iso -e grub_console=serial -e vyos_version=1.5.0 \
+ -e cloud_init=true -e cloud_init_ds=NoCloud
+```
+
+This generates your new image at `/tmp/vyos-1.5.0-cloud-init-10G-qemu.qcow2`.
+
+4. Copy the resulting image to the Proxmox server:
+
+```sh
+sudo scp /tmp/vyos-1.5.0-cloud-init-10G-qemu.qcow2 root@192.168.0.253:/tmp/
+```
+
+
+### Prepare cloud-init files
+
+Create the following files on your Proxmox server to proceed with this setup:
+
+- `user-data`: Contains VyOS configuration commands.
+- `network-config`: Disables the DHCP client on the first interface.
+- `meta-data`: An empty file (required by `cloud-init`).
+
+All files must be placed in the `/tmp/` directory.
+
+Follow these steps to create the required files:
+
+1. Navigate to the `/tmp/` directory:
+
+ ```sh
+ cd /tmp/
+ ```
+
+2. Create the `user-data` file. Begin the file with `#cloud-config` and
+ include VyOS configuration commands.
+
+ ```none
+ #cloud-config
+ vyos_config_commands:
+ - set system host-name 'vyos-BRAS'
+ - set service ntp server '1.pool.ntp.org'
+ - set service ntp server '2.pool.ntp.org'
+ - delete interfaces ethernet eth0 address 'dhcp'
+ - set interfaces ethernet eth0 address '198.51.100.2/30'
+ - set interfaces ethernet eth0 description 'WAN - ISP01'
+ - set interfaces ethernet eth1 address '192.168.25.1/24'
+ - set interfaces ethernet eth1 description 'Coming through VLAN 25'
+ - set interfaces ethernet eth2 address '192.168.26.1/24'
+ - set interfaces ethernet eth2 description 'Coming through VLAN 26'
+ - set protocols static route 0.0.0.0/0 next-hop '198.51.100.1'
+ ```
+
+3. Create the `network-config` file. Include the following:
+
+ ```none
+ version: 2
+ ethernets:
+ eth0:
+ dhcp4: false
+ dhcp6: false
+ ```
+
+4. Create the required empty `meta-data` file.
+
+### Create seed.iso
+
+Once you have created the necessary files, generate the `seed.iso` image and
+mount it as a CD drive to the new VM.
+
+```sh
+mkisofs -joliet -rock -volid "cidata" -output seed.iso meta-data \
+user-data network-config
+```
+
+:::{note}
+Be careful while copying and pasting the above commands. Double quotes may need
+to be corrected.
+:::
+
+### Create the VM
+
+Note that the following settings apply to this particular example and may
+require adjustment for other setups:
+
+- **VM ID**: `555`.
+- **VM and .iso file storage**: The local volume (`directory` type,
+ mounted at `/var/lib/vz`).
+- **VM resources**: Can be modified as needed.
+
+The `seed.iso` file was previously created in the `/tmp/` directory. Move
+it to `/var/lib/vz/template/iso`:
+
+```sh
+mv /tmp/seed.iso /var/lib/vz/template/iso/
+```
+
+On the Proxmox server:
+
+```none
+## Create VM, import disk and define boot order
+qm create 555 --name vyos-1.5.0-cloudinit --memory 1024 --net0 virtio,bridge=vmbr0
+qm importdisk 555 vyos-1.5.0-cloud-init-10G-qemu.qcow2 local
+qm set 555 --virtio0 local:555/vm-555-disk-0.raw
+qm set 555 --boot order=virtio0
+
+## Import seed.iso for cloud init
+qm set 555 --ide2 media=cdrom,file=local:iso/seed.iso
+
+## Since this server has 1 nic, lets add network intefaces (vlan 25 and 26)
+qm set 555 --net1 virtio,bridge=vmbr0,firewall=1,tag=25
+qm set 555 --net2 virtio,bridge=vmbr0,firewall=1,tag=26
+```
+
+
+### Power on and verify the VM
+
+Power on the VM using the CLI or GUI. After it boots, verify the configuration.
+
+### References
+
+- Cloud-init [network-config-docs].
+- Proxmox [Cloud-init-Support].
+[cloud-init-support]: <https://pve.proxmox.com/pve-docs/pve-admin-guide.html#qm_cloud_init>
+[cloud-init-write_files]: https://cloudinit.readthedocs.io/en/latest/topics/examples.html#writing-out-arbitrary-files
+[network-config-docs]: https://cloudinit.readthedocs.io/en/latest/topics/network-config.html
+[nocloud]: https://cloudinit.readthedocs.io/en/latest/reference/datasources/nocloud.html
+[vyos-vm-images]: https://github.com/vyos/vyos-vm-images
diff --git a/docs/automation/command-scripting.md b/docs/automation/command-scripting.md
new file mode 100644
index 00000000..7e736152
--- /dev/null
+++ b/docs/automation/command-scripting.md
@@ -0,0 +1,225 @@
+---
+lastproofread: '2026-03-16'
+---
+
+(command-scripting)=
+
+# Command scripting
+
+VyOS supports executing configuration and operational commands non-interactively
+from shell scripts.
+
+To include VyOS-specific functions and aliases, source the
+`/opt/vyatta/etc/functions/script-template` file at the beginning of your
+script.
+
+```none
+#!/bin/vbash
+source /opt/vyatta/etc/functions/script-template
+exit
+```
+
+
+## Script execute permissions
+
+Simply placing script files in `/config/scripts/` does not mean the system
+can execute them.
+
+To make your scripts executable, grant them **execute permissions**. Use the
+following command:
+
+```none
+chmod +x /config/scripts/script-name.sh
+```
+
+
+## Run configuration commands
+
+In scripts, present configuration commands as in a standard configuration
+session.
+
+For example, to disable a BGP peer during a VRRP transition to the backup
+state, use the following syntax:
+
+```none
+#!/bin/vbash
+source /opt/vyatta/etc/functions/script-template
+configure
+set protocols bgp system-as 65536
+set protocols bgp neighbor 192.168.2.1 shutdown
+commit
+exit
+```
+
+
+## Run operational commands
+
+In scripts, **always** prefix operational commands with `run`.
+
+```none
+#!/bin/vbash
+source /opt/vyatta/etc/functions/script-template
+run show interfaces
+exit
+```
+
+
+## Run commands remotely
+
+You can execute multiple **operational commands** on a remote VyOS system by
+passing a script block over SSH.
+
+```none
+ssh 192.0.2.1 'vbash -s' <<EOF
+source /opt/vyatta/etc/functions/script-template
+run show interfaces
+exit
+EOF
+```
+
+Example output:
+
+```none
+Welcome to VyOS
+Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
+Interface IP Address S/L Description
+--------- ---------- --- -----------
+eth0 192.0.2.1/24 u/u
+lo 127.0.0.1/8 u/u
+ ::1/128
+```
+
+
+## Other script languages
+
+If you use a scripting language other than bash, configure your script to
+output the relevant commands, and then source that output into a bash script.
+
+The following example demonstrates this two-step process:
+
+```python
+#!/usr/bin/env python3
+print("delete firewall group address-group somehosts")
+print("set firewall group address-group somehosts address '192.0.2.3'")
+print("set firewall group address-group somehosts address '203.0.113.55'")
+```
+
+```none
+#!/bin/vbash
+source /opt/vyatta/etc/functions/script-template
+configure
+source <(/config/scripts/setfirewallgroup.py)
+commit
+```
+
+
+## Execute configuration scripts
+
+In Linux, it is common practice to prefix system commands with `sudo`.
+
+In VyOS, if you prefix a script that modifies the configuration with `sudo`
+(see the code snippet below), subsequent manual configuration changes fail with
+the `Set failed` error. Recovery requires a system reboot.
+
+```none
+sudo ./myscript.sh # Modifies config
+configure
+set ... # Any configuration parameter
+```
+
+To avoid this issue, run scripts under the `vyattacfg` group using the `sg`
+command:
+
+```none
+sg vyattacfg -c ./myscript.sh
+```
+
+To ensure the script is executed under the `vyattacfg` group, safeguard it as
+follows:
+
+```none
+if [ "$(id -g -n)" != 'vyattacfg' ] ; then
+ exec sg vyattacfg -c "/bin/vbash $(readlink -f $0) $@"
+fi
+```
+
+
+## Executing pre-hooks/post-hooks scripts
+
+VyOS allows you to run custom scripts **before** and **after** each commit.
+
+Place your custom scripts in the following default directories:
+
+```none
+/config/scripts/commit/pre-hooks.d - Directory with scripts that run before
+ each commit.
+
+/config/scripts/commit/post-hooks.d - Directory with scripts that run after
+ each commit.
+```
+
+Scripts run in alphabetical order. Filenames must consist only of ASCII letters
+(upper and lowercase), digits (0-9), underscores (\_), and hyphens (-). No other
+characters are allowed.
+
+:::{note}
+Custom scripts are executed **without** root privileges. Prefix
+specific commands with `sudo` in your script when required.
+:::
+
+The following example shows the output after executing a post-hook script
+that runs the `show interfaces` command:
+
+```none
+vyos@vyos# set interfaces ethernet eth1 address 192.0.2.3/24
+vyos@vyos# commit
+Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
+Interface IP Address S/L Description
+--------- ---------- --- -----------
+eth0 198.51.100.10/24 u/u
+eth1 192.0.2.3/24 u/u
+eth2 - u/u
+eth3 - u/u
+lo 203.0.113.5/24 u/u
+```
+
+
+## Preconfig script on boot
+
+VyOS runs `/config/scripts/vyos-preconfig-bootup.script` at boot, **before**
+the system configuration is applied.
+
+Use this script to apply **pre-configuration** workarounds for unresolved bugs
+or enhancements not yet available in VyOS.
+
+The default script contains the following:
+
+```none
+#!/bin/sh
+# This script is executed at boot time before VyOS configuration is applied.
+# Any modifications required to work around unfixed bugs or use
+# services not available through the VyOS CLI system can be placed here.
+```
+
+
+## Postconfig script on boot
+
+VyOS runs `/config/scripts/vyos-postconfig-bootup.script` at boot, **after**
+the system configuration is applied.
+
+Use this script to apply **post-configuration** workarounds for unresolved bugs
+or enhancements not yet available in VyOS.
+
+The default script contains the following:
+
+```none
+#!/bin/sh
+# This script is executed at boot time after VyOS configuration is fully
+# applied. Any modifications required to work around unfixed bugs or use
+# services not available through the VyOS CLI system can be placed here.
+```
+
+:::{warning}
+For configuration or upgrade management issues, modify this script
+only as a last resort. Always try CLI-based solutions first.
+:::
diff --git a/docs/automation/index.md b/docs/automation/index.md
new file mode 100644
index 00000000..62e60f84
--- /dev/null
+++ b/docs/automation/index.md
@@ -0,0 +1,16 @@
+# VyOS Automation
+
+```{toctree}
+:maxdepth: 2
+
+vyos-api
+vyos-ansible
+terraform/index
+vyos-napalm
+vyos-netmiko
+vyos-salt
+command-scripting
+cloud-init
+vyos-pyvyos
+vyos-govyos
+```
diff --git a/docs/automation/cloud-init.rst b/docs/automation/rst-cloud-init.rst
index 29f56d0d..29f56d0d 100644
--- a/docs/automation/cloud-init.rst
+++ b/docs/automation/rst-cloud-init.rst
diff --git a/docs/automation/command-scripting.rst b/docs/automation/rst-command-scripting.rst
index 91086b42..91086b42 100644
--- a/docs/automation/command-scripting.rst
+++ b/docs/automation/rst-command-scripting.rst
diff --git a/docs/automation/index.rst b/docs/automation/rst-index.rst
index f153b730..f153b730 100644
--- a/docs/automation/index.rst
+++ b/docs/automation/rst-index.rst
diff --git a/docs/automation/vyos-ansible.rst b/docs/automation/rst-vyos-ansible.rst
index 12d4e9fb..12d4e9fb 100644
--- a/docs/automation/vyos-ansible.rst
+++ b/docs/automation/rst-vyos-ansible.rst
diff --git a/docs/automation/vyos-api.rst b/docs/automation/rst-vyos-api.rst
index e96723e6..e96723e6 100644
--- a/docs/automation/vyos-api.rst
+++ b/docs/automation/rst-vyos-api.rst
diff --git a/docs/automation/vyos-govyos.rst b/docs/automation/rst-vyos-govyos.rst
index 17e15b0e..17e15b0e 100644
--- a/docs/automation/vyos-govyos.rst
+++ b/docs/automation/rst-vyos-govyos.rst
diff --git a/docs/automation/vyos-napalm.rst b/docs/automation/rst-vyos-napalm.rst
index f2f27124..f2f27124 100644
--- a/docs/automation/vyos-napalm.rst
+++ b/docs/automation/rst-vyos-napalm.rst
diff --git a/docs/automation/vyos-netmiko.rst b/docs/automation/rst-vyos-netmiko.rst
index b94b0129..b94b0129 100644
--- a/docs/automation/vyos-netmiko.rst
+++ b/docs/automation/rst-vyos-netmiko.rst
diff --git a/docs/automation/vyos-pyvyos.rst b/docs/automation/rst-vyos-pyvyos.rst
index cbd315e5..cbd315e5 100644
--- a/docs/automation/vyos-pyvyos.rst
+++ b/docs/automation/rst-vyos-pyvyos.rst
diff --git a/docs/automation/vyos-salt.rst b/docs/automation/rst-vyos-salt.rst
index 3a5b17d7..3a5b17d7 100644
--- a/docs/automation/vyos-salt.rst
+++ b/docs/automation/rst-vyos-salt.rst
diff --git a/docs/automation/terraform/index.md b/docs/automation/terraform/index.md
new file mode 100644
index 00000000..dc787db1
--- /dev/null
+++ b/docs/automation/terraform/index.md
@@ -0,0 +1,29 @@
+---
+lastproofread: '2026-03-23'
+---
+
+# VyOS Terraform
+
+VyOS supports development infrastructure via Terraform and provisioning
+via Ansible.
+Terraform allows you to automate the deployment of instances on a number of
+cloud and virtual platforms. This section shows how to deploy VyOS on
+multiple platforms: AWS, Microsoft Azure, Google Cloud Platform (GCP),
+and VMware vSphere.
+For more information, see the
+official documentation for [Terraform] and [Ansible].
+
+```{toctree}
+:caption: Guides
+:maxdepth: 1
+
+terraformvyos
+terraformAWS
+terraformAZ
+terraformGoogle
+terraformvSphere
+```
+
+[ansible]: https://docs.ansible.com
+[install]: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli
+[terraform]: https://developer.hashicorp.com/terraform/intro
diff --git a/docs/automation/terraform/index.rst b/docs/automation/terraform/rst-index.rst
index f81820d2..f81820d2 100644
--- a/docs/automation/terraform/index.rst
+++ b/docs/automation/terraform/rst-index.rst
diff --git a/docs/automation/terraform/terraformAWS.rst b/docs/automation/terraform/rst-terraformAWS.rst
index 8156fac4..8156fac4 100644
--- a/docs/automation/terraform/terraformAWS.rst
+++ b/docs/automation/terraform/rst-terraformAWS.rst
diff --git a/docs/automation/terraform/terraformAZ.rst b/docs/automation/terraform/rst-terraformAZ.rst
index 9e094aea..9e094aea 100644
--- a/docs/automation/terraform/terraformAZ.rst
+++ b/docs/automation/terraform/rst-terraformAZ.rst
diff --git a/docs/automation/terraform/terraformGoogle.rst b/docs/automation/terraform/rst-terraformGoogle.rst
index eb7e01fe..eb7e01fe 100644
--- a/docs/automation/terraform/terraformGoogle.rst
+++ b/docs/automation/terraform/rst-terraformGoogle.rst
diff --git a/docs/automation/terraform/terraformvSphere.rst b/docs/automation/terraform/rst-terraformvSphere.rst
index 1866fa8e..1866fa8e 100644
--- a/docs/automation/terraform/terraformvSphere.rst
+++ b/docs/automation/terraform/rst-terraformvSphere.rst
diff --git a/docs/automation/terraform/terraformAWS.md b/docs/automation/terraform/terraformAWS.md
new file mode 100644
index 00000000..488e7926
--- /dev/null
+++ b/docs/automation/terraform/terraformAWS.md
@@ -0,0 +1,548 @@
+---
+lastproofread: '2026-03-16'
+---
+
+(terraformaws)=
+
+# Deploy VyOS on AWS with Terraform and Ansible
+
+You can use Terraform to quickly deploy VyOS-based infrastructure
+on AWS and remove infrastructure when it's no longer needed.
+Additionally, you can use Ansible for provisioning.
+
+```{eval-rst}
+.. image:: /_static/images/aws.webp
+ :width: 50%
+ :align: center
+ :alt: Network Topology Diagram
+```
+
+On this page you'll learn how to:
+- Create the necessary files for Terraform and Ansible.
+- Use Terraform to create a single instance on AWS and use Ansible for
+ provisioning.
+
+## Prepare to deploy VyOS with Terraform on AWS
+
+To create a single instance and install your configuration using
+Terraform, Ansible, and AWS, follow these steps:
+
+### AWS
+
+1. Create an account with AWS and get your `access_key` and `secret_key`.
+2. Create a key [pair] and download your `.pem` key.
+
+```{eval-rst}
+.. image:: /_static/images/keypairs.webp
+ :width: 50%
+ :align: center
+ :alt: Network Topology Diagram
+```
+
+3. Create a security [group] for the new VyOS instance and open all traffic.
+
+```{eval-rst}
+.. image:: /_static/images/sg.webp
+ :width: 50%
+ :align: center
+ :alt: Network Topology Diagram
+```
+
+```{eval-rst}
+.. image:: /_static/images/traffic.webp
+ :width: 50%
+ :align: center
+ :alt: Network Topology Diagram
+```
+
+
+### Terraform
+
+```{eval-rst}
+1. Create an UNIX or Windows instance.
+
+2. Download and install
+ `Terraform <https://developer.hashicorp.com/terraform/install>`__.
+
+3. Create a folder, for example ``/root/awsterraform``:
+
+ .. code-block:: none
+
+ mkdir /root/awsterraform
+
+.. stop_vyoslinter
+
+4. Copy all files into your Terraform project
+ (``vyos.tf``, ``var.tf``, ``terraform.tfvars``, ``version.tf``).
+ See `Structure of files in Terraform for AWS <#structure-of-files-in-terraform-for-aws>`__ for more details.
+
+.. start_vyoslinter
+
+5. Run the following commands:
+
+.. code-block:: none
+
+ cd /<your folder>
+ terraform init
+```
+
+### Ansible
+
+```{eval-rst}
+1. Create a UNIX instance whenever you need.
+
+2. Download and install Ansible
+
+3. Create a folder, for example ``/root/aws/``.
+
+.. stop_vyoslinter
+
+4. Copy all files into your Ansible project
+ (``ansible.cfg``, ``instance.yml``,
+ ``mykey.pem``, and ``all``).
+ See `Structure of files in Ansible for AWS <#structure-of-files-in-ansible-for-aws>`__ for more details.
+ You can obtain ``mykey.pem`` by creating a key `pair <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html>`__ in AWS and
+ downloading your ``.pem`` key.
+```
+
+### Deploy with Terraform
+
+Run the following commands on your Terraform instance:
+
+```none
+cd /<your folder>
+terraform plan
+terraform apply
+yes
+```
+
+## Create an AWS instance and check its configuration
+
+```none
+root@localhost:~/awsterraform# terraform apply
+
+Terraform used the selected providers to generate the following execution plan.
+Resource actions are indicated with the following symbols:
+ + create
+
+Terraform will perform the following actions:
+
+ # aws_instance.myVyOSec2 will be created
+ + resource "aws_instance" "myVyOSec2" {
+ + ami = "ami-************62c2d"
+ + arn = (known after apply)
+ + associate_public_ip_address = (known after apply)
+ + availability_zone = (known after apply)
+ + cpu_core_count = (known after apply)
+ + cpu_threads_per_core = (known after apply)
+ + disable_api_stop = (known after apply)
+ + disable_api_termination = (known after apply)
+ + ebs_optimized = (known after apply)
+ + get_password_data = false
+ + host_id = (known after apply)
+ + host_resource_group_arn = (known after apply)
+ + iam_instance_profile = (known after apply)
+ + id = (known after apply)
+ + instance_initiated_shutdown_behavior = (known after apply)
+ + instance_lifecycle = (known after apply)
+ + instance_state = (known after apply)
+ + instance_type = "t2.micro"
+ + ipv6_address_count = (known after apply)
+ + ipv6_addresses = (known after apply)
+ + key_name = "awsterraform"
+ + monitoring = (known after apply)
+ + outpost_arn = (known after apply)
+ + password_data = (known after apply)
+ + placement_group = (known after apply)
+ + placement_partition_number = (known after apply)
+ + primary_network_interface_id = (known after apply)
+ + private_dns = (known after apply)
+ + private_ip = (known after apply)
+ + public_dns = (known after apply)
+ + public_ip = (known after apply)
+ + secondary_private_ips = (known after apply)
+ + security_groups = [
+ + "awsterraformsg",
+ ]
+ + source_dest_check = true
+ + spot_instance_request_id = (known after apply)
+ + subnet_id = (known after apply)
+ + tags = {
+ + "name" = "VyOS System"
+ }
+ + tags_all = {
+ + "name" = "VyOS System"
+ }
+ + tenancy = (known after apply)
+ + user_data = (known after apply)
+ + user_data_base64 = (known after apply)
+ + user_data_replace_on_change = false
+ + vpc_security_group_ids = (known after apply)
+ }
+
+ # local_file.ip will be created
+ + resource "local_file" "ip" {
+ + content = (known after apply)
+ + content_base64sha256 = (known after apply)
+ + content_base64sha512 = (known after apply)
+ + content_md5 = (known after apply)
+ + content_sha1 = (known after apply)
+ + content_sha256 = (known after apply)
+ + content_sha512 = (known after apply)
+ + directory_permission = "0777"
+ + file_permission = "0777"
+ + filename = "ip.txt"
+ + id = (known after apply)
+ }
+
+ # null_resource.SSHconnection1 will be created
+ + resource "null_resource" "SSHconnection1" {
+ + id = (known after apply)
+ }
+
+ # null_resource.SSHconnection2 will be created
+ + resource "null_resource" "SSHconnection2" {
+ + id = (known after apply)
+ }
+
+Plan: 4 to add, 0 to change, 0 to destroy.
+
+Changes to Outputs:
+ + my_IP = (known after apply)
+
+Do you want to perform these actions?
+ Terraform will perform the actions described above.
+ Only 'yes' will be accepted to approve.
+
+ Enter a value: yes
+
+aws_instance.myVyOSec2: Creating...
+aws_instance.myVyOSec2: Still creating... [10s elapsed]
+aws_instance.myVyOSec2: Still creating... [20s elapsed]
+aws_instance.myVyOSec2: Still creating... [30s elapsed]
+aws_instance.myVyOSec2: Still creating... [40s elapsed]
+aws_instance.myVyOSec2: Creation complete after 44s [id=i-09edfca15aac2fe0a]
+null_resource.SSHconnection1: Creating...
+null_resource.SSHconnection2: Creating...
+null_resource.SSHconnection1: Provisioning with 'file'...
+null_resource.SSHconnection2: Provisioning with 'remote-exec'...
+null_resource.SSHconnection2 (remote-exec): Connecting to remote host via SSH...
+null_resource.SSHconnection2 (remote-exec): Host: 10.217.80.104
+null_resource.SSHconnection2 (remote-exec): User: root
+null_resource.SSHconnection2 (remote-exec): Password: true
+null_resource.SSHconnection2 (remote-exec): Private key: false
+null_resource.SSHconnection2 (remote-exec): Certificate: false
+null_resource.SSHconnection2 (remote-exec): SSH Agent: false
+null_resource.SSHconnection2 (remote-exec): Checking Host Key: false
+null_resource.SSHconnection2 (remote-exec): Target Platform: unix
+local_file.ip: Creating...
+local_file.ip: Creation complete after 0s [id=e8e91f2e24579cd28b92e2d152c0c24c3bf4b52c]
+null_resource.SSHconnection2 (remote-exec): Connected!
+null_resource.SSHconnection1: Creation complete after 0s [id=7070868940858935600]
+
+null_resource.SSHconnection2 (remote-exec): PLAY [integration of terraform and ansible] ************************************
+
+null_resource.SSHconnection2 (remote-exec): TASK [Wait 300 seconds, but only start checking after 60 seconds] **************
+null_resource.SSHconnection2: Still creating... [10s elapsed]
+null_resource.SSHconnection2: Still creating... [20s elapsed]
+null_resource.SSHconnection2: Still creating... [30s elapsed]
+null_resource.SSHconnection2: Still creating... [40s elapsed]
+null_resource.SSHconnection2: Still creating... [50s elapsed]
+null_resource.SSHconnection2: Still creating... [1m0s elapsed]
+null_resource.SSHconnection2 (remote-exec): ok: [54.xxx.xxx.xxx]
+
+null_resource.SSHconnection2 (remote-exec): TASK [Configure general settings for the vyos hosts group] *********************
+null_resource.SSHconnection2: Still creating... [1m10s elapsed]
+null_resource.SSHconnection2 (remote-exec): changed: [54.xxx.xxx.xxx]
+
+null_resource.SSHconnection2 (remote-exec): PLAY RECAP *********************************************************************
+null_resource.SSHconnection2 (remote-exec): 54.xxx.xxx.xxx : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+
+null_resource.SSHconnection2: Creation complete after 1m16s [id=4902256962410024771]
+
+Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
+
+Outputs:
+
+my_IP = "54.xxx.xxx.xxx"
+```
+
+After running all the commands, your VyOS instance is deployed on
+AWS with your specified configuration.
+To delete the instance, type the following command:
+
+```none
+terraform destroy
+```
+
+## Troubleshooting
+
+1. If Ansible doesn't connect via SSH to your AWS instance, verify that
+ your SSH key is in the path `/root/aws/`. You might need to
+ increase the timeout in `instance.yml` from 300 seconds to 500
+ seconds or more, depending on your location. Make sure that the
+ security group allows access to the instance.
+2. If Terraform doesn't connect via SSH to your Ansible instance,
+ verify the correct login and password in the `VyOS.tf` file.
+
+```{eval-rst}
+ .. code-block:: none
+
+ connection {
+ type = "ssh"
+ user = "root" # open root access using login and password on your Ansible
+ password = var.password # check password in the file terraform.tfvars isn't empty
+ host = var.host # check the correct IP address of your Ansible host
+ }
+```
+
+Make sure Ansible can ping from Terraform.
+
+## Structure of files in Terraform for AWS
+
+```none
+.
+├── vyos.tf # The main script
+├── var.tf # The file of all variables in "vyos.tf"
+├── versions.tf # File for the changing version of Terraform.
+└── terraform.tfvars # The value of all variables (passwords, login, ip adresses and so on)
+```
+
+## File contents of Terraform for AWS
+
+`vyos.tf`
+
+```none
+##############################################################################
+# Build a VyOS VM from the Marketplace.
+# Find the necessary AMI image_ in AWS.
+#
+# The vyos.tf script uses default values (you can change them as
+# needed)
+# AWS Region = "us-east-1"
+# AMI = "standard AMI of VyOS from AWS Marketplace"
+# Size of VM = "t2.micro"
+# AWS Region = "us-east-1"
+# After deploying the AWS instance and getting an IP address, the IP address is copied into the file
+#"ip.txt" and copied to the Ansible node for provisioning.
+##############################################################################
+
+provider "aws" {
+ access_key = var.access
+ secret_key = var.secret
+ region = var.region
+}
+
+variable "region" {
+ default = "us-east-1"
+ description = "AWS Region"
+}
+
+variable "ami" {
+ default = "ami-**************3b3" # ami image please enter your details
+ description = "Amazon Machine Image ID for VyOS"
+}
+
+variable "type" {
+ default = "t2.micro"
+ description = "Size of VM"
+}
+
+# my resource for VyOS
+
+resource "aws_instance" "myVyOSec2" {
+ ami = var.ami
+ key_name = "awsterraform" # Please enter your details from 1.2 of Preparation steps for deploying VyOS on AWS
+ security_groups = ["awsterraformsg"] # Please enter your details from 1.3 of Preparation steps for deploying VyOS on AWS
+ instance_type = var.type
+ tags = {
+ name = "VyOS System"
+ }
+}
+
+##############################################################################
+# Specific variable (to getting type "terraform plan"):
+# aws_instance.myVyOSec2.public_ip - the information about public IP address
+# of our instance, needs for provisioning and SSH connection from Ansible
+##############################################################################
+
+output "my_IP"{
+value = aws_instance.myVyOSec2.public_ip
+}
+
+##############################################################################
+# The IP address of the AWS instance is copied to the ip.txt file
+# on the local Terraform system. The ip.txt file contains the public
+# IP address in the format: xxx.xxx.xxx.xxx
+##############################################################################
+
+resource "local_file" "ip" {
+ content = aws_instance.myVyOSec2.public_ip
+ filename = "ip.txt"
+}
+
+#connecting to the Ansible control node using SSH connection
+
+##############################################################################
+# The "SSHconnection1" and "SSHconnection2" steps retrieve ip.txt
+# from the Terraform node and run the Ansible playbook remotely.
+##############################################################################
+
+resource "null_resource" "SSHconnection1" {
+depends_on = [aws_instance.myVyOSec2]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.password
+ host = var.host
+}
+
+# Copy the ip.txt file to the Ansible control node from the local
+# system
+ provisioner "file" {
+ source = "ip.txt"
+ destination = "/root/aws/ip.txt" # The folder of your Ansible project
+ }
+}
+
+resource "null_resource" "SSHconnection2" {
+depends_on = [aws_instance.myVyOSec2]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.password
+ host = var.host
+}
+# Run Ansible playbook on remote Linux OS
+provisioner "remote-exec" {
+ inline = [
+ "cd /root/aws/",
+ "ansible-playbook instance.yml" # more detailed in "File contents of Ansible for AWS"
+]
+}
+}
+```
+
+`var.tf`
+
+```none
+variable "password" {
+ description = "pass for Ansible"
+ type = string
+ sensitive = true
+}
+variable "host"{
+ description = "The IP of my Ansible"
+ type = string
+}
+variable "access" {
+ description = "my access_key for AWS"
+ type = string
+ sensitive = true
+}
+variable "secret" {
+ description = "my secret_key for AWS"
+ type = string
+ sensitive = true
+}
+```
+
+`versions.tf`
+
+```none
+ terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 5.0"
+ }
+ }
+}
+```
+
+`terraform.tfvars`
+
+```none
+password = "" # password for Ansible SSH
+host = "" # IP of my Ansible
+access = "" # access_key for AWS
+secret = "" # secret_key for AWS
+```
+
+## Structure of files in Ansible for AWS
+
+```none
+.
+├── group_vars
+ └── all
+├── ansible.cfg
+├── mykey.pem
+└── instance.yml
+```
+
+## File contents of Ansible for AWS
+
+`ansible.cfg`
+
+```none
+[defaults]
+inventory = /root/aws/ip.txt
+host_key_checking= False
+private_key_file = /root/aws/awsterraform.pem # check the name
+remote_user=vyos
+```
+
+`mykey.pem`
+
+```none
+Copy your key.pem from AWS
+```
+
+`instance.yml`
+
+```none
+##############################################################################
+# About tasks:
+# "Wait 300 seconds, but only start checking after 60 seconds" -
+# attempts SSH connection every 60 seconds until 300 seconds
+# "Configure general settings for the VyOS hosts group" -
+# provisions the AWS VyOS node
+# Add all necessary VyOS commands under the "lines:" block
+##############################################################################
+
+- name: integration of terraform and ansible
+ hosts: all
+ gather_facts: 'no'
+
+ tasks:
+
+ - name: "Wait 300 seconds, but only start checking after 60 seconds"
+ wait_for_connection:
+ delay: 60
+ timeout: 300
+
+ - name: "Configure general settings for the VyOS hosts group"
+ vyos_config:
+ lines:
+ - set system name-server xxx.xxx.xxx.xxx
+ save:
+ true
+```
+
+`group_vars/all`
+
+```none
+ansible_connection: ansible.netcommon.network_cli
+ansible_network_os: vyos.vyos.vyos
+ansible_user: vyos
+```
+
+
+## Source files on GitHub
+
+All files related to deploying VyOS on AWS with Terraform and Ansible
+can be found in the [vyos-automation] repository.
+
+[group]: https://docs.aws.amazon.com/cli/latest/userguide/cli-services-ec2-sg.html
+[pair]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html
+[vyos-automation]: <https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/AWS_terraform_ansible_single_vyos_instance-main>
diff --git a/docs/automation/terraform/terraformAZ.md b/docs/automation/terraform/terraformAZ.md
new file mode 100644
index 00000000..b1b8fac0
--- /dev/null
+++ b/docs/automation/terraform/terraformAZ.md
@@ -0,0 +1,501 @@
+---
+lastproofread: '2026-03-19'
+---
+
+(terraformaz)=
+
+# Deploy VyOS on Microsoft Azure with Terraform and Ansible
+
+You can use Terraform to quickly deploy VyOS-based infrastructure
+on Microsoft Azure (hereafter referred to as *Azure*) and remove
+infrastructure when it's no longer needed.
+Additionally, you can use Ansible for provisioning.
+
+On this page you'll learn how to:
+
+- Create the necessary files for Terraform and Ansible.
+- Use Terraform to create a single instance on Azure and use Ansible for
+ provisioning.
+
+## Prepare to deploy VyOS with Terraform on Azure
+
+To create a single instance and install your configuration using
+Terraform, Ansible, and Azure, follow these steps:
+
+### Azure
+
+- Create an [Azure account](https://azure.microsoft.com/).
+
+### Terraform
+
+```{eval-rst}
+1. Create an UNIX or Windows instance.
+
+2. Download and install
+ `Terraform <https://developer.hashicorp.com/terraform/install>`__.
+
+3. Create the folder for example ``/root/azvyos/``.
+
+.. code-block:: none
+
+ mkdir /root/azvyos
+
+.. stop_vyoslinter
+
+4. Copy all files into your Terraform project "/root/azvyos"
+ (``vyos.tf``, ``var.tf``, ``terraform.tfvars``). For more details, see
+ `Structure of files in Terraform for Azure <#structure-of-files-in-terraform-for-azure>`_.
+
+.. start_vyoslinter
+
+5. Log in to Azure using the command:
+
+ .. code-block:: none
+
+ az login
+
+6. Run the following commands to initialize Terraform:
+
+ .. code-block:: none
+
+ cd /<your folder>
+ terraform init
+```
+
+
+### Ansible
+
+1. Create an UNIX instance either locally or in the cloud.
+
+2. Download and install Ansible
+
+3. Create a folder, for example `/root/az/`.
+
+4. Copy all files into your Ansible project `/root/az/` (`ansible.cfg`,
+ `instance.yml`, `all`). For more details, see
+ [Structure of files in Ansible for Azure](#structure-of-files-in-ansible-for-azure)
+
+### Deploy with Terraform
+
+Run the following commands on your Terraform instance:
+
+```none
+cd /<your folder>
+terraform plan
+terraform apply
+yes
+```
+
+After executing all the commands, your VyOS instance is deployed to
+Azure with your configuration.
+If you need to delete the instance, run the following command:
+
+```none
+terraform destroy
+```
+
+
+## Structure of files in Terraform for Azure
+
+```none
+.
+├── vyos.tf # The main script
+├── var.tf # File for the Terraform version.
+└── terraform.tfvars # Values for all variables (passwords,
+ # login, IP addresses, etc.)
+```
+
+
+## File contents of Terraform for Azure
+
+`vyos.tf`
+
+```none
+##############################################################################
+# HashiCorp Guide to Using Terraform on Azure
+# This Terraform configuration will create the following:
+# Resource group with a virtual network and subnet
+# A VyOS server without SSH key (only login+password)
+##############################################################################
+
+# Choose a provider
+
+provider "azurerm" {
+ features {}
+}
+
+# Create a resource group. In Azure, every resource belongs to a
+# resource group.
+
+resource "azurerm_resource_group" "azure_vyos" {
+ name = "${var.resource_group}"
+ location = "${var.location}"
+}
+
+# The next resource is a Virtual Network.
+
+resource "azurerm_virtual_network" "vnet" {
+ name = "${var.virtual_network_name}"
+ location = "${var.location}"
+ address_space = ["${var.address_space}"]
+ resource_group_name = "${var.resource_group}"
+}
+
+# Build a subnet to run your VMs.
+
+resource "azurerm_subnet" "subnet" {
+ name = "${var.prefix}subnet"
+ virtual_network_name = "${azurerm_virtual_network.vnet.name}"
+ resource_group_name = "${var.resource_group}"
+ address_prefixes = ["${var.subnet_prefix}"]
+}
+
+##############################################################################
+# Build a VyOS VM from the Marketplace.
+# To find the necessary image, use the command:
+#
+# az vm image list --offer vyos --all
+#
+# Now that you have a network, you can deploy a VyOS server.
+# An Azure Virtual Machine has several components. In this example,
+# you build a security group, a network interface, a public IP
+# address, a storage account, and finally the VM itself. Terraform
+# handles all the dependencies automatically, and each resource is
+# named with user-defined variables.
+##############################################################################
+
+
+# Security group to allow inbound access on port 22 (SSH)
+
+resource "azurerm_network_security_group" "vyos-sg" {
+ name = "${var.prefix}-sg"
+ location = "${var.location}"
+ resource_group_name = "${var.resource_group}"
+
+ security_rule {
+ name = "SSH"
+ priority = 100
+ direction = "Inbound"
+ access = "Allow"
+ protocol = "Tcp"
+ source_port_range = "*"
+ destination_port_range = "22"
+ source_address_prefix = "${var.source_network}"
+ destination_address_prefix = "*"
+ }
+}
+
+# A network interface.
+
+resource "azurerm_network_interface" "vyos-nic" {
+ name = "${var.prefix}vyos-nic"
+ location = "${var.location}"
+ resource_group_name = "${var.resource_group}"
+
+ ip_configuration {
+ name = "${var.prefix}ipconfig"
+ subnet_id = "${azurerm_subnet.subnet.id}"
+ private_ip_address_allocation = "Dynamic"
+ public_ip_address_id = "${azurerm_public_ip.vyos-pip.id}"
+ }
+}
+
+# Add a public IP address.
+
+resource "azurerm_public_ip" "vyos-pip" {
+ name = "${var.prefix}-ip"
+ location = "${var.location}"
+ resource_group_name = "${var.resource_group}"
+ allocation_method = "Dynamic"
+}
+
+# Build a virtual machine. This is a standard VyOS instance from
+# Marketplace.
+
+resource "azurerm_virtual_machine" "vyos" {
+ name = "${var.hostname}-vyos"
+ location = "${var.location}"
+ resource_group_name = "${var.resource_group}"
+ vm_size = "${var.vm_size}"
+
+ network_interface_ids = ["${azurerm_network_interface.vyos-nic.id}"]
+ delete_os_disk_on_termination = "true"
+
+# To find information about the plan, use the command:
+# az vm image list --offer vyos --all
+
+ plan {
+ publisher = "sentriumsl"
+ name = "vyos-1-3"
+ product = "vyos-1-2-lts-on-azure"
+ }
+
+ storage_image_reference {
+ publisher = "${var.image_publisher}"
+ offer = "${var.image_offer}"
+ sku = "${var.image_sku}"
+ version = "${var.image_version}"
+ }
+
+ storage_os_disk {
+ name = "${var.hostname}-osdisk"
+ managed_disk_type = "Standard_LRS"
+ caching = "ReadWrite"
+ create_option = "FromImage"
+ }
+
+ os_profile {
+ computer_name = "${var.hostname}"
+ admin_username = "${var.admin_username}"
+ admin_password = "${var.admin_password}"
+ }
+
+ os_profile_linux_config {
+ disable_password_authentication = false
+ }
+}
+
+data "azurerm_public_ip" "example" {
+ depends_on = ["azurerm_virtual_machine.vyos"]
+ name = "vyos-ip"
+ resource_group_name = "${var.resource_group}"
+}
+output "public_ip_address" {
+ value = data.azurerm_public_ip.example.ip_address
+}
+
+# IP of AZ instance copied to a file ip.txt in the local system.
+
+resource "local_file" "ip" {
+ content = data.azurerm_public_ip.example.ip_address
+ filename = "ip.txt"
+}
+
+# Connect to the Ansible control node via SSH
+
+resource "null_resource" "nullremote1" {
+depends_on = ["azurerm_virtual_machine.vyos"]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.password
+ host = var.host
+}
+
+# Copy the ip.txt file to the Ansible control node from the local
+# system
+
+ provisioner "file" {
+ source = "ip.txt"
+ destination = "/root/az/ip.txt"
+ }
+}
+
+resource "null_resource" "nullremote2" {
+depends_on = ["azurerm_virtual_machine.vyos"]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.password
+ host = var.host
+}
+
+# Run the Ansible playbook on the remote Linux OS
+
+provisioner "remote-exec" {
+
+ inline = [
+ "cd /root/az/",
+ "ansible-playbook instance.yml"
+]
+}
+}
+```
+
+`var.tf`
+
+```none
+##############################################################################
+# Variables File
+#
+# Default values for all variables used in Terraform code.
+##############################################################################
+
+variable "resource_group" {
+ description = "The name of your Azure Resource Group."
+ default = "my_resource_group"
+}
+
+variable "prefix" {
+ description = "This prefix will be included in the name of some resources."
+ default = "vyos"
+}
+
+variable "hostname" {
+ description = "Virtual machine hostname. Used for local hostname, DNS, and storage-related names."
+ default = "vyos_terraform"
+}
+
+variable "location" {
+ description = "The region where the virtual network is created."
+ default = "centralus"
+}
+
+variable "virtual_network_name" {
+ description = "The name for your virtual network."
+ default = "vnet"
+}
+
+variable "address_space" {
+ description = "The address space that is used by the virtual network. You can supply more than one address space. Changing this forces a new resource to be created."
+ default = "10.0.0.0/16"
+}
+
+variable "subnet_prefix" {
+ description = "The address prefix to use for the subnet."
+ default = "10.0.10.0/24"
+}
+
+variable "storage_account_tier" {
+ description = "Defines the storage tier. Valid options are Standard and Premium."
+ default = "Standard"
+}
+
+variable "storage_replication_type" {
+ description = "Defines the replication type to use for this storage account. Valid options include LRS, GRS etc."
+ default = "LRS"
+}
+
+# The most cost-effective size
+
+variable "vm_size" {
+ description = "Specifies the size of the virtual machine."
+ default = "Standard_B1s"
+}
+
+variable "image_publisher" {
+ description = "Name of the publisher of the image (az vm image list)"
+ default = "sentriumsl"
+}
+
+variable "image_offer" {
+ description = "Name of the offer (az vm image list)"
+ default = "vyos-1-2-lts-on-azure"
+}
+
+variable "image_sku" {
+ description = "Image SKU to apply (az vm image list)"
+ default = "vyos-1-3"
+}
+
+variable "image_version" {
+ description = "Version of the image to apply (az vm image list)"
+ default = "1.3.3"
+}
+
+variable "admin_username" {
+ description = "Administrator user name"
+ default = "vyos"
+}
+
+variable "admin_password" {
+ description = "Administrator password"
+ type = string
+ sensitive = true
+}
+
+variable "source_network" {
+ description = "Allow access from this network prefix. Defaults to '*'."
+ default = "*"
+}
+
+variable "password" {
+ description = "pass for Ansible"
+ type = string
+ sensitive = true
+}
+variable "host"{
+ description = "IP of my Ansible"
+}
+```
+
+`terraform.tfvars`
+
+```none
+password = "" # password for Ansible SSH
+host = "" # IP of my Ansible
+```
+
+
+## Structure of files in Ansible for Azure
+
+```none
+.
+├── group_vars
+ └── all
+├── ansible.cfg
+└── instance.yml
+```
+
+
+## File contents of Ansible for Azure
+
+`ansible.cfg`
+
+```none
+[defaults]
+inventory = /root/az/ip.txt
+host_key_checking= False
+remote_user=vyos
+```
+
+`instance.yml`
+
+```none
+##############################################################################
+# About tasks:
+# "Wait 300 seconds, but only start checking after 60 seconds" - Tries
+# to make SSH connection every 60 seconds until 300 seconds.
+# "Configure general settings for the VyOS hosts group" - Provision
+# the Azure VyOS node.
+# Add all necessary commands for VyOS under the block "lines:"
+##############################################################################
+
+
+- name: integration of terraform and ansible
+ hosts: all
+ gather_facts: 'no'
+
+ tasks:
+
+ - name: "Wait 300 seconds, but only start checking after 60 seconds"
+ wait_for_connection:
+ delay: 60
+ timeout: 300
+
+ - name: "Configure general settings for the VyOS hosts group"
+ vyos_config:
+ lines:
+ - set system name-server xxx.xxx.xxx.xxx
+ save:
+ true
+```
+
+`group_vars/all`
+
+```none
+ansible_connection: ansible.netcommon.network_cli
+ansible_network_os: vyos.vyos.vyos
+
+# user and password gets from terraform variables "admin_username" and "admin_password" in the file /root/azvyos/var.tf
+ansible_user: vyos
+ansible_ssh_pass: "{{ vault_vyos_ssh_pass }}"
+```
+
+
+## Source files on GitHub
+
+All files related to deploying VyOS on Azure with Terraform and Ansible
+can be found in the [vyos-automation] repository.
+
+[vyos-automation]: <https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Azure_terraform_ansible_single_vyos_instance-main>
diff --git a/docs/automation/terraform/terraformGoogle.md b/docs/automation/terraform/terraformGoogle.md
new file mode 100644
index 00000000..f9c002a7
--- /dev/null
+++ b/docs/automation/terraform/terraformGoogle.md
@@ -0,0 +1,703 @@
+---
+lastproofread: '2026-03-23'
+---
+
+(terraformgoogle)=
+
+# Deploy VyOS on Google Cloud with Terraform and Ansible
+
+Using Terraform, you can quickly deploy VyOS-based infrastructure on
+Google Cloud Platform (GCP) and remove the
+infrastructure when it's no longer needed.
+Additionally, you can use Ansible for provisioning.
+
+On this page you'll learn how to:
+
+- Create the necessary files for Terraform and Ansible.
+- Use Terraform to create a single instance on GCP and use Ansible for
+ provisioning.
+
+## Prepare to deploy VyOS with Terraform on GCP
+
+To create a single instance and install your configuration using
+Terraform, Ansible, and GCP, follow these steps:
+
+### GCP
+
+1. Create an account with GCP and a new project.
+
+```{image} /_static/images/project.webp
+:align: center
+:alt: Network Topology Diagram
+:width: 50%
+```
+
+2. Create a service account and download your key (a JSON file).
+
+```{image} /_static/images/service.webp
+:align: center
+:alt: Network Topology Diagram
+:width: 50%
+```
+
+```{image} /_static/images/key.webp
+:align: center
+:alt: Network Topology Diagram
+:width: 50%
+```
+
+The .JSON file downloads automatically after you create it and looks
+like the following:
+
+```{image} /_static/images/json.webp
+:align: center
+:alt: Network Topology Diagram
+:width: 50%
+```
+
+### Terraform
+
+1. Create an UNIX or Windows instance.
+
+2. Download and install
+ [Terraform](https://developer.hashicorp.com/terraform/install).
+
+3. Create the folder. For example, `/root/google`.
+
+```none
+mkdir /root/google
+```
+
+4. Copy all files into your Terraform project `/root/google`
+ (`vyos.tf`, `var.tf`, `terraform.tfvars`, `mykey.json`).
+ For more details,
+ see [Structure of files Terraform for Google Cloud](#structure-of-files-in-terraform-for-google-cloud)
+
+<!-- -->
+
+5. Run the following commands:
+
+```none
+cd /<your folder>
+terraform init
+```
+
+### Ansible
+
+1. Create an UNIX instance either locally or in the cloud.
+
+2. Download and install Ansible
+
+3. Create the folder for example /root/google/
+
+4. Copy all files into your Ansible project `/root/google/`
+ (`ansible.cfg`, `instance.yml`, `mykey.json`, and `all`). For more
+ details, see [Structure of files in Ansible for Google Cloud](#structure-of-files-in-ansible-for-google-cloud)
+
+You obtain `mykey.json` when you create a service account in GCP
+and download the key (a JSON file).
+
+### Deploy with Terraform
+
+Run the following commands on your Terraform instance:
+
+```none
+cd /<your folder>
+terraform plan
+terraform apply
+yes
+```
+
+## Create a GCP instance and check its configuration
+
+```none
+# terraform apply
+
+Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ + create
+
+Terraform will perform the following actions:
+
+ # google_compute_firewall.tcp_22[0] will be created
+ + resource "google_compute_firewall" "tcp_22" {
+ + creation_timestamp = (known after apply)
+ + destination_ranges = (known after apply)
+ + direction = (known after apply)
+ + enable_logging = (known after apply)
+ + id = (known after apply)
+ + name = "vyos-tcp-22"
+ + network = "default"
+ + priority = 1000
+ + project = "vyosproject"
+ + self_link = (known after apply)
+ + source_ranges = [
+ + "0.0.0.0/0",
+ ]
+ + target_tags = [
+ + "vyos-deployment",
+ ]
+
+ + allow {
+ + ports = [
+ + "22",
+ ]
+ + protocol = "tcp"
+ }
+ }
+
+ # google_compute_firewall.udp_500_4500[0] will be created
+ + resource "google_compute_firewall" "udp_500_4500" {
+ + creation_timestamp = (known after apply)
+ + destination_ranges = (known after apply)
+ + direction = (known after apply)
+ + enable_logging = (known after apply)
+ + id = (known after apply)
+ + name = "vyos-udp-500-4500"
+ + network = "default"
+ + priority = 1000
+ + project = "vyosproject"
+ + self_link = (known after apply)
+ + source_ranges = [
+ + "0.0.0.0/0",
+ ]
+ + target_tags = [
+ + "vyos-deployment",
+ ]
+
+ + allow {
+ + ports = [
+ + "500",
+ + "4500",
+ ]
+ + protocol = "udp"
+ }
+ }
+
+ # google_compute_instance.default will be created
+ + resource "google_compute_instance" "default" {
+ + can_ip_forward = true
+ + cpu_platform = (known after apply)
+ + current_status = (known after apply)
+ + deletion_protection = false
+ + effective_labels = (known after apply)
+ + guest_accelerator = (known after apply)
+ + id = (known after apply)
+ + instance_id = (known after apply)
+ + label_fingerprint = (known after apply)
+ + machine_type = "n2-highcpu-4"
+ + metadata = {
+ + "enable-oslogin" = "FALSE"
+ + "serial-port-enable" = "TRUE"
+ + "user-data" = ""
+ }
+ + metadata_fingerprint = (known after apply)
+ + min_cpu_platform = (known after apply)
+ + name = "vyos"
+ + project = "vyosproject"
+ + self_link = (known after apply)
+ + tags_fingerprint = (known after apply)
+ + terraform_labels = (known after apply)
+ + zone = "us-west1-a"
+
+ + boot_disk {
+ + auto_delete = true
+ + device_name = (known after apply)
+ + disk_encryption_key_sha256 = (known after apply)
+ + kms_key_self_link = (known after apply)
+ + mode = "READ_WRITE"
+ + source = (known after apply)
+
+ + initialize_params {
+ + image = "projects/sentrium-public/global/images/vyos-1-3-5-20231222143039"
+ + labels = (known after apply)
+ + provisioned_iops = (known after apply)
+ + provisioned_throughput = (known after apply)
+ + size = (known after apply)
+ + type = (known after apply)
+ }
+ }
+
+ + network_interface {
+ + internal_ipv6_prefix_length = (known after apply)
+ + ipv6_access_type = (known after apply)
+ + ipv6_address = (known after apply)
+ + name = (known after apply)
+ + network = "default"
+ + network_ip = (known after apply)
+ + nic_type = "GVNIC"
+ + stack_type = (known after apply)
+ + subnetwork = "default"
+ + subnetwork_project = (known after apply)
+
+ + access_config {
+ + nat_ip = (known after apply)
+ + network_tier = (known after apply)
+ }
+ }
+ }
+
+ # local_file.ip will be created
+ + resource "local_file" "ip" {
+ + content = (known after apply)
+ + content_base64sha256 = (known after apply)
+ + content_base64sha512 = (known after apply)
+ + content_md5 = (known after apply)
+ + content_sha1 = (known after apply)
+ + content_sha256 = (known after apply)
+ + content_sha512 = (known after apply)
+ + directory_permission = "0777"
+ + file_permission = "0777"
+ + filename = "ip.txt"
+ + id = (known after apply)
+ }
+
+ # null_resource.SSHconnection1 will be created
+ + resource "null_resource" "SSHconnection1" {
+ + id = (known after apply)
+ }
+
+ # null_resource.SSHconnection2 will be created
+ + resource "null_resource" "SSHconnection2" {
+ + id = (known after apply)
+ }
+
+Plan: 6 to add, 0 to change, 0 to destroy.
+
+Changes to Outputs:
+ + public_ip_address = (known after apply)
+â•·
+│ Warning: Quoted references are deprecated
+│
+│ on vyos.tf line 126, in resource "null_resource" "SSHconnection1":
+│ 126: depends_on = ["google_compute_instance.default"]
+│
+│ In this context, references are expected literally rather than in quotes. Terraform 0.11 and earlier required quotes, but quoted references are now deprecated and will be removed in a
+│ future version of Terraform. Remove the quotes surrounding this reference to silence this warning.
+│
+│ (and one more similar warning elsewhere)
+╵
+
+Do you want to perform these actions?
+ Terraform will perform the actions described above.
+ Only 'yes' will be accepted to approve.
+
+ Enter a value: yes
+
+google_compute_firewall.udp_500_4500[0]: Creating...
+google_compute_firewall.tcp_22[0]: Creating...
+google_compute_instance.default: Creating...
+google_compute_firewall.udp_500_4500[0]: Still creating... [10s elapsed]
+google_compute_firewall.tcp_22[0]: Still creating... [10s elapsed]
+google_compute_instance.default: Still creating... [10s elapsed]
+google_compute_firewall.tcp_22[0]: Creation complete after 16s [id=projects/vyosproject/global/firewalls/vyos-tcp-22]
+google_compute_firewall.udp_500_4500[0]: Creation complete after 16s [id=projects/vyosproject/global/firewalls/vyos-udp-500-4500]
+google_compute_instance.default: Creation complete after 20s [id=projects/vyosproject/zones/us-west1-a/instances/vyos]
+null_resource.SSHconnection1: Creating...
+null_resource.SSHconnection2: Creating...
+null_resource.SSHconnection1: Provisioning with 'file'...
+null_resource.SSHconnection2: Provisioning with 'remote-exec'...
+null_resource.SSHconnection2 (remote-exec): Connecting to remote host via SSH...
+null_resource.SSHconnection2 (remote-exec): Host: 10.***.***.104
+null_resource.SSHconnection2 (remote-exec): User: root
+null_resource.SSHconnection2 (remote-exec): Password: true
+null_resource.SSHconnection2 (remote-exec): Private key: false
+null_resource.SSHconnection2 (remote-exec): Certificate: false
+null_resource.SSHconnection2 (remote-exec): SSH Agent: false
+null_resource.SSHconnection2 (remote-exec): Checking Host Key: false
+null_resource.SSHconnection2 (remote-exec): Target Platform: unix
+local_file.ip: Creating...
+local_file.ip: Creation complete after 0s [id=7d568c3b994a018c942a3cdb952ccbf3c729d0ca]
+null_resource.SSHconnection2 (remote-exec): Connected!
+null_resource.SSHconnection1: Creation complete after 4s [id=5175298735911137161]
+
+null_resource.SSHconnection2 (remote-exec): PLAY [integration of terraform and ansible] ************************************
+
+null_resource.SSHconnection2 (remote-exec): TASK [Wait 300 seconds, but only start checking after 60 seconds] **************
+null_resource.SSHconnection2: Still creating... [10s elapsed]
+null_resource.SSHconnection2: Still creating... [20s elapsed]
+null_resource.SSHconnection2: Still creating... [30s elapsed]
+null_resource.SSHconnection2: Still creating... [40s elapsed]
+null_resource.SSHconnection2: Still creating... [50s elapsed]
+null_resource.SSHconnection2: Still creating... [1m0s elapsed]
+null_resource.SSHconnection2: Still creating... [1m10s elapsed]
+null_resource.SSHconnection2 (remote-exec): ok: [104.***.***.158]
+
+null_resource.SSHconnection2 (remote-exec): TASK [Configure general settings for the vyos hosts group] *********************
+null_resource.SSHconnection2: Still creating... [1m20s elapsed]
+null_resource.SSHconnection2 (remote-exec): changed: [104.***.***.158]
+
+null_resource.SSHconnection2 (remote-exec): PLAY RECAP *********************************************************************
+null_resource.SSHconnection2 (remote-exec): 104.***.***.158 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+
+null_resource.SSHconnection2: Creation complete after 1m22s [id=3355727070503709742]
+
+Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
+
+Outputs:
+
+public_ip_address = "104.***.***.158"
+```
+
+After running all the commands, your VyOS instance is deployed on
+GCP with your specified configuration.
+To delete the instance, type the following command:
+
+```none
+terraform destroy
+```
+
+## Troubleshooting
+
+- Increase the timeout value in `instance.yml` from 300 seconds to
+ 500 seconds or more (depends on your location). Ensure that the
+ security group allows access to the instance.
+- If Terraform doesn't connect via SSH to your Ansible instance:
+ Check the correct login and password in the `VyOS.tf` file.
+
+```none
+connection {
+ type = "ssh"
+ user = "root" # open root access using login and password on your Ansible
+ password = var.password # check password in the file terraform.tfvars isn't empty
+ host = var.host # check the correct IP address of your Ansible host
+}
+```
+
+Verify that Ansible can ping from Terraform.
+
+## Structure of files in Terraform for Google Cloud
+
+```none
+.
+├── vyos.tf # The main script
+├── ***.JSON # The credential file from GCP
+├── var.tf # The file of all variables in "vyos.tf"
+└── terraform.tfvars # The value of all variables (passwords, login, IP addresses and so on)
+```
+
+## File contents of Terraform for Google Cloud
+
+`vyos.tf`
+
+```none
+##############################################################################
+# Build a VyOS VM from the Marketplace
+#
+# After deploying the GCP instance and getting an IP address, the IP address is copied into the file
+#"ip.txt" and copied to the Ansible node for provisioning.
+##############################################################################
+
+terraform {
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ }
+ }
+}
+
+provider "google" {
+ project = var.project_id
+ request_timeout = "60s"
+ credentials = file(var.gcp_auth_file)
+}
+
+locals {
+ network_interfaces = [for i, n in var.networks : {
+ network = n,
+ subnetwork = length(var.sub_networks) > i ? element(var.sub_networks, i) : null
+ external_ip = length(var.external_ips) > i ? element(var.external_ips, i) : "NONE"
+ }
+ ]
+}
+
+resource "google_compute_instance" "default" {
+ name = var.goog_cm_deployment_name
+ machine_type = var.machine_type
+ zone = var.zone
+
+ metadata = {
+ enable-oslogin = "FALSE"
+ serial-port-enable = "TRUE"
+ user-data = var.vyos_user_data
+ }
+ boot_disk {
+ initialize_params {
+ image = var.image
+ }
+ }
+
+ can_ip_forward = true
+
+ dynamic "network_interface" {
+ for_each = local.network_interfaces
+ content {
+ network = network_interface.value.network
+ subnetwork = network_interface.value.subnetwork
+ nic_type = "GVNIC"
+ dynamic "access_config" {
+ for_each = network_interface.value.external_ip == "NONE" ? [] : [1]
+ content {
+ nat_ip = network_interface.value.external_ip == "EPHEMERAL" ? null : network_interface.value.external_ip
+ }
+ }
+ }
+ }
+}
+
+resource "google_compute_firewall" "tcp_22" {
+ count = var.enable_tcp_22 ? 1 : 0
+
+ name = "${var.goog_cm_deployment_name}-tcp-22"
+ network = element(var.networks, 0)
+
+ allow {
+ ports = ["22"]
+ protocol = "tcp"
+ }
+
+ source_ranges = ["0.0.0.0/0"]
+
+ target_tags = ["${var.goog_cm_deployment_name}-deployment"]
+}
+
+resource "google_compute_firewall" "udp_500_4500" {
+ count = var.enable_udp_500_4500 ? 1 : 0
+
+ name = "${var.goog_cm_deployment_name}-udp-500-4500"
+ network = element(var.networks, 0)
+
+ allow {
+ ports = ["500", "4500"]
+ protocol = "udp"
+ }
+
+ source_ranges = ["0.0.0.0/0"]
+
+ target_tags = ["${var.goog_cm_deployment_name}-deployment"]
+}
+
+output "public_ip_address" {
+ value = google_compute_instance.default.network_interface[0].access_config[0].nat_ip
+}
+
+##############################################################################
+#
+# IP of google instance copied to a file ip.txt in local system Terraform
+# ip.txt looks like:
+# cat ./ip.txt
+# Ñ…Ñ…Ñ….Ñ…Ñ…Ñ….Ñ…Ñ…Ñ….Ñ…Ñ…Ñ…
+##############################################################################
+
+resource "local_file" "ip" {
+ content = google_compute_instance.default.network_interface[0].access_config[0].nat_ip
+ filename = "ip.txt"
+}
+
+#connecting to the Ansible control node using SSH connection
+
+##############################################################################
+# Steps "SSHconnection1" and "SSHconnection2" need to get file ip.txt from the terraform node and start remotely the playbook of Ansible.
+##############################################################################
+
+resource "null_resource" "SSHconnection1" {
+depends_on = ["google_compute_instance.default"]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.password
+ host = var.host
+}
+
+#copying the ip.txt file to the Ansible control node from local system
+
+ provisioner "file" {
+ source = "ip.txt"
+ destination = "/root/google/ip.txt" # The folder of your Ansible project
+ }
+}
+
+resource "null_resource" "SSHconnection2" {
+depends_on = ["google_compute_instance.default"]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.password
+ host = var.host
+}
+
+#command to run Ansible playbook on remote Linux OS
+
+provisioner "remote-exec" {
+ inline = [
+ "cd /root/google/",
+ "ansible-playbook instance.yml" # more detailed in "File contents of Ansible for Google Cloud"
+]
+}
+}
+```
+
+`var.tf`
+
+```none
+variable "image" {
+ type = string
+ default = "projects/sentrium-public/global/images/vyos-1-3-5-20231222143039"
+}
+
+variable "project_id" {
+ type = string
+}
+
+variable "zone" {
+ type = string
+}
+
+##############################################################################
+# You can choose a lower cost machine type than n2-highcpu-4
+##############################################################################
+
+variable "machine_type" {
+ type = string
+ default = "n2-highcpu-4"
+}
+
+variable "networks" {
+ description = "The network name to attach the VM instance."
+ type = list(string)
+ default = ["default"]
+}
+
+variable "sub_networks" {
+ description = "The sub network name to attach the VM instance."
+ type = list(string)
+ default = ["default"]
+}
+
+variable "external_ips" {
+ description = "The external IPs assigned to the VM for public access."
+ type = list(string)
+ default = ["EPHEMERAL"]
+}
+
+variable "enable_tcp_22" {
+ description = "Allow SSH traffic from the Internet"
+ type = bool
+ default = true
+}
+
+variable "enable_udp_500_4500" {
+ description = "Allow IKE/IPSec traffic from the Internet"
+ type = bool
+ default = true
+}
+
+variable "vyos_user_data" {
+ type = string
+ default = ""
+}
+
+// Marketplace requires this variable name to be declared
+variable "goog_cm_deployment_name" {
+ description = "VyOS Universal Router Deployment"
+ type = string
+ default = "vyos"
+}
+
+# GCP authentication file
+variable "gcp_auth_file" {
+ type = string
+ description = "GCP authentication file"
+}
+
+variable "password" {
+ description = "pass for Ansible"
+ type = string
+ sensitive = true
+}
+variable "host"{
+ description = "The IP of my Ansible"
+ type = string
+}
+```
+
+`terraform.tfvars`
+
+```none
+##############################################################################
+# Must be filled in
+##############################################################################
+
+zone = "us-west1-a"
+gcp_auth_file = "/root/***/***.json" # path of your .json file
+project_id = "" # the google project
+password = "" # password for Ansible SSH
+host = "" # IP of my Ansible
+```
+
+## Structure of files in Ansible for Google Cloud
+
+```none
+.
+├── group_vars
+ └── all
+├── ansible.cfg
+└── instance.yml
+```
+
+## File contents of Ansible for Google Cloud
+
+`ansible.cfg`
+
+```none
+[defaults]
+inventory = /root/google/ip.txt
+host_key_checking= False
+remote_user=vyos
+```
+
+`instance.yml`
+
+```none
+##############################################################################
+# About tasks:
+# "Wait 300 seconds, but only start checking after 60 seconds" - try to make ssh connection every 60 seconds until 300 seconds
+# "Configure general settings for the VyOS hosts group" - make provisioning into Google Cloud VyOS node
+# Add all necessary VyOS commands under the "lines:" block
+##############################################################################
+
+
+- name: integration of terraform and ansible
+ hosts: all
+ gather_facts: 'no'
+
+ tasks:
+
+ - name: "Wait 300 seconds, but only start checking after 60 seconds"
+ wait_for_connection:
+ delay: 60
+ timeout: 300
+
+ - name: "Configure general settings for the VyOS hosts group"
+ vyos_config:
+ lines:
+ - set system name-server xxx.xxx.xxx.xxx
+ save:
+ true
+```
+
+`group_vars/all`
+
+```none
+ansible_connection: ansible.netcommon.network_cli
+ansible_network_os: vyos.vyos.vyos
+ansible_user: vyos
+ansible_ssh_pass: vyos
+```
+
+
+## Source files on GitHub
+
+All files related to deploying VyOS on Google Cloud Platform with
+Terraform and Ansible can be found in the [vyos-automation] repository.
+
+[vyos-automation]: <https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Google_terraform_ansible_single_vyos_instance-main>
diff --git a/docs/automation/terraform/terraformvSphere.md b/docs/automation/terraform/terraformvSphere.md
new file mode 100644
index 00000000..abcef5fa
--- /dev/null
+++ b/docs/automation/terraform/terraformvSphere.md
@@ -0,0 +1,388 @@
+---
+lastproofread: '2026-03-23'
+---
+
+(terraformvSphere)=
+
+# Deploy VyOS on VMware vSphere with Terraform and Ansible
+
+You can use Terraform to quickly deploy VyOS-based infrastructure
+on VMware vSphere (hereafter referred to as *vSphere*) and remove
+infrastructure when it's no longer needed.
+Additionally, you can use Ansible for provisioning.
+
+On this page you'll learn how to:
+
+- Create the necessary files for Terraform and Ansible.
+- Use Terraform to create a single instance on vSphere and use Ansible for
+ provisioning.
+
+## Prepare to deploy VyOS with Terraform on vSphere
+
+To create a single instance and install your configuration using
+Terraform, Ansible, and vSphere, follow these steps:
+
+### vSphere
+
+- Add all necessary data to the `terraform.tfvars`
+ [file](<https://github.com/vyos/vyos-automation/blob/main/TerraformCloud/Vsphere_terraform_ansible_single_vyos_instance-main/terraform.tfvars>)
+ and create resources.
+
+### Terraform
+
+- Create an UNIX or Windows instance.
+- Download and install
+ [Terraform](https://developer.hashicorp.com/terraform/install).
+- Create the folder for example `/root/vsphereterraform`.
+
+```none
+mkdir /root/vsphereterraform
+```
+
+- Copy all files into your Terraform project `/root/vsphereterraform`
+ (`vyos.tf`, `var.tf`, `terraform.tfvars`, `version.tf`).
+ For more details,
+ see [Structure of files in Terraform for vSphere](#structure-of-files-in-terraform-for-vsphere)
+- Run the following commands:
+
+```none
+cd /<your folder>
+terraform init
+```
+
+
+### Ansible
+
+- Create an UNIX instance either locally or in the cloud.
+- Download and install Ansible.
+- Create the folder. For example, `/root/vsphereterraform/`.
+- Copy all files into your Ansible project `/root/vsphereterraform/`
+ (`ansible.cfg`, `instance.yml`, `all`). For more details, see
+ [Structure of files in Ansible for vSphere](#structure-of-files-in-ansible-for-vsphere)
+
+### Deploy with Terraform
+
+Run the following commands on your Terraform instance:
+
+```none
+cd /<your folder>
+terraform plan
+terraform apply
+yes
+```
+
+After executing these commands, your VyOS instance is deployed to
+vSphere with your configuration.
+If you need to delete the instance, run the following command:
+
+```none
+terraform destroy
+```
+
+## Structure of files in Terraform for vSphere
+
+```none
+.
+├── vyos.tf # The main script.
+├── versions.tf # File for Terraform version.
+├── var.tf # File for Terraform version.
+└── terraform.tfvars # Values for all variables (passwords,
+ # login, IP addresses, etc.).
+```
+
+## File contents of Terraform for vSphere
+
+`vyos.tf`
+
+```none
+provider "vsphere" {
+ user = var.vsphere_user
+ password = var.vsphere_password
+ vsphere_server = var.vsphere_server
+ allow_unverified_ssl = true
+}
+
+data "vsphere_datacenter" "datacenter" {
+ name = var.datacenter
+}
+
+data "vsphere_datastore" "datastore" {
+ name = var.datastore
+ datacenter_id = data.vsphere_datacenter.datacenter.id
+}
+
+data "vsphere_compute_cluster" "cluster" {
+ name = var.cluster
+ datacenter_id = data.vsphere_datacenter.datacenter.id
+}
+
+data "vsphere_resource_pool" "default" {
+ name = format("%s%s", data.vsphere_compute_cluster.cluster.name, "/Resources/terraform") # set as you need
+ datacenter_id = data.vsphere_datacenter.datacenter.id
+}
+
+data "vsphere_host" "host" {
+ name = var.host
+ datacenter_id = data.vsphere_datacenter.datacenter.id
+}
+
+data "vsphere_network" "network" {
+ name = var.network_name
+ datacenter_id = data.vsphere_datacenter.datacenter.id
+}
+
+# Deployment of VM from Remote OVF
+resource "vsphere_virtual_machine" "vmFromRemoteOvf" {
+ name = var.remotename
+ datacenter_id = data.vsphere_datacenter.datacenter.id
+ datastore_id = data.vsphere_datastore.datastore.id
+ host_system_id = data.vsphere_host.host.id
+ resource_pool_id = data.vsphere_resource_pool.default.id
+ network_interface {
+ network_id = data.vsphere_network.network.id
+ }
+ wait_for_guest_net_timeout = 2
+ wait_for_guest_ip_timeout = 2
+
+ ovf_deploy {
+ allow_unverified_ssl_cert = true
+ remote_ovf_url = var.url_ova
+ disk_provisioning = "thin"
+ ip_protocol = "IPv4"
+ ip_allocation_policy = "dhcpPolicy"
+ ovf_network_map = {
+ "Network 1" = data.vsphere_network.network.id
+ "Network 2" = data.vsphere_network.network.id
+ }
+ }
+ vapp {
+ properties = {
+ "password" = "12345678",
+ "local-hostname" = "terraform_vyos"
+ }
+ }
+}
+
+output "ip" {
+ description = "default ip address of the deployed VM"
+ value = vsphere_virtual_machine.vmFromRemoteOvf.default_ip_address
+}
+
+# IP of vSphere instance copied to a file ip.txt in local system
+
+resource "local_file" "ip" {
+ content = vsphere_virtual_machine.vmFromRemoteOvf.default_ip_address
+ filename = "ip.txt"
+}
+
+#Connecting to the Ansible control node using SSH connection
+
+resource "null_resource" "nullremote1" {
+depends_on = ["vsphere_virtual_machine.vmFromRemoteOvf"]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.ansiblepassword
+ host = var.ansiblehost
+
+}
+
+# Copying the ip.txt file to the Ansible control node from local system
+
+ provisioner "file" {
+ source = "ip.txt"
+ destination = "/root/vsphere/ip.txt"
+ }
+}
+
+resource "null_resource" "nullremote2" {
+depends_on = ["vsphere_virtual_machine.vmFromRemoteOvf"]
+connection {
+ type = "ssh"
+ user = "root"
+ password = var.ansiblepassword
+ host = var.ansiblehost
+}
+
+# Command to run ansible playbook on remote Linux OS
+
+provisioner "remote-exec" {
+
+ inline = [
+ "cd /root/vsphere/",
+ "ansible-playbook instance.yml"
+]
+}
+}
+```
+
+`versions.tf`
+
+```none
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+terraform {
+ required_providers {
+ vsphere = {
+ source = "hashicorp/vsphere"
+ version = "2.4.0"
+ }
+ }
+}
+```
+
+`var.tf`
+
+```none
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+variable "vsphere_server" {
+ description = "vSphere server"
+ type = string
+}
+
+variable "vsphere_user" {
+ description = "vSphere username"
+ type = string
+}
+
+variable "vsphere_password" {
+ description = "vSphere password"
+ type = string
+ sensitive = true
+}
+
+variable "datacenter" {
+ description = "vSphere data center"
+ type = string
+}
+
+variable "cluster" {
+ description = "vSphere cluster"
+ type = string
+}
+
+variable "datastore" {
+ description = "vSphere datastore"
+ type = string
+}
+
+variable "network_name" {
+ description = "vSphere network name"
+ type = string
+}
+
+variable "host" {
+ description = "Name of your host"
+ type = string
+}
+
+variable "remotename" {
+ description = "The name of your VM"
+ type = string
+}
+
+variable "url_ova" {
+ description = "The URL to the .OVA file or cloud storage"
+ type = string
+}
+
+variable "ansiblepassword" {
+ description = "Ansible password"
+ type = string
+}
+
+variable "ansiblehost" {
+ description = "Ansible host name or IP"
+ type = string
+}
+```
+
+`terraform.tfvars`
+
+```none
+vsphere_user = ""
+vsphere_password = ""
+vsphere_server = ""
+datacenter = ""
+datastore = ""
+cluster = ""
+network_name = ""
+host = ""
+url_ova = ""
+ansiblepassword = ""
+ansiblehost = ""
+remotename = ""
+```
+
+## Structure of files in Ansible for vSphere
+
+```none
+.
+├── group_vars
+ └── all
+├── ansible.cfg
+└── instance.yml
+```
+
+## File contents of Ansible for vSphere
+
+`ansible.cfg`
+
+```none
+[defaults]
+inventory = /root/vsphere/ip.txt
+host_key_checking= False
+remote_user=vyos
+```
+
+`instance.yml`
+
+```none
+##############################################################################
+# About tasks:
+# "Wait 300 seconds, but only start checking after 60 seconds" - try to make ssh connection every 60 seconds until 300 seconds
+# "Configure general settings for the VyOS hosts group" - make provisioning into vSphere VyOS node
+# You have to add all necessary commands of VyOS under the block "lines:"
+##############################################################################
+
+
+- name: integration of terraform and ansible
+ hosts: all
+ gather_facts: 'no'
+
+ tasks:
+
+ - name: "Wait 300 seconds, but only start checking after 60 seconds"
+ wait_for_connection:
+ delay: 60
+ timeout: 300
+ - name: "Configure general settings for the VyOS hosts group"
+ vyos_config:
+ lines:
+ - set system name-server 192.0.2.1
+ save:
+ true
+```
+
+`group_vars/all`
+
+```none
+ansible_connection: ansible.netcommon.network_cli
+ansible_network_os: vyos.vyos.vyos
+
+# user and password gets from terraform variables "admin_username" and "admin_password"
+ansible_user: vyos
+# get from vyos.tf "vapp"
+ansible_ssh_pass: 12345678
+```
+
+
+## Source files on GitHub
+
+All files related to deploying VyOS on vSphere with Terraform and Ansible
+can be found in the [vyos-automation] repository.
+
+[vyos-automation]: <https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Vsphere_terraform_ansible_single_vyos_instance-main>
diff --git a/docs/automation/terraform/terraformvyos.md b/docs/automation/terraform/terraformvyos.md
new file mode 100644
index 00000000..bfe1b6d1
--- /dev/null
+++ b/docs/automation/terraform/terraformvyos.md
@@ -0,0 +1,44 @@
+---
+lastproofread: '2024-03-03'
+---
+
+(terraformvyos)=
+
+# Terraform for VyOS
+
+VyOS supports development infrastructure via Terraform and
+provisioning via Ansible. Terraform allows you to automate the
+process of deploying instances on many cloud and virtual
+platforms. In this article, we will look at using Terraform to
+deploy VyOS on platforms - AWS, Azure, and vSphere. For more
+details about Terraform please have a look at [link].
+
+You will need to [install] Terraform before proceeding.
+
+Structure of files in the standard Terraform project:
+
+```none
+.
+├── main.tf # The main script
+├── version.tf # File for the changing version of Terraform.
+├── variables.tf # The file of all variables in "main.tf"
+└── terraform.tfvars # The value of all variables (passwords, login, IP addresses and so on)
+```
+
+General commands that we will use for running Terraform scripts
+
+```none
+cd /<your folder> # go to the Terraform project
+terraform init # install all add-ons and providers (AWS, Azure, and so on)
+terraform plan # show what is changing
+terraform apply # run script
+yes # apply running
+```
+
+% stop_vyoslinter
+
+% start_vyoslinter
+
+[install]: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli
+[link]: https://developer.hashicorp.com/terraform/intro
+
diff --git a/docs/automation/vyos-ansible.md b/docs/automation/vyos-ansible.md
new file mode 100644
index 00000000..8e94b251
--- /dev/null
+++ b/docs/automation/vyos-ansible.md
@@ -0,0 +1,101 @@
+---
+lastproofread: '2026-04-13'
+---
+
+(vyos-ansible)=
+
+# Ansible
+
+VyOS can be configured using Ansible. To use it, install the `ansible`
+package and the `python3-paramiko` module.
+
+## Directory structure
+
+Arrange your Ansible project directory as follows:
+
+```none
+.
+├── ansible.cfg
+├── files
+│ └── id_rsa_docker.pub
+├── hosts
+└── main.yml
+```
+
+
+## File contents
+
+- `ansible.cfg`
+
+```none
+[defaults]
+host_key_checking = no
+retry_files_enabled = False
+ANSIBLE_INVENTORY_UNPARSED_FAILED = true
+```
+
+- `id_rsa_docker.pub`
+
+Contains only the SSH public key.
+
+```none
+AAAAB3NzaC1yc2EAAAADAQABAAABAQCoDgfhQJuJRFWJijHn7ZinZ3NWp4hWVrt7HFcvn0kgtP/5PeCtMt
+```
+
+- `hosts`
+
+Defines the target VyOS devices and the connection parameters required to reach
+them.
+
+```none
+[vyos_hosts]
+r11 ansible_ssh_host=192.0.2.11
+
+[vyos_hosts:vars]
+ansible_python_interpreter=/usr/bin/python3
+ansible_user=vyos
+ansible_ssh_pass=vyos
+ansible_network_os=vyos
+ansible_connection=network_cli
+```
+
+- `main.yml`
+
+Defines the configuration tasks to be applied to the target VyOS devices.
+
+```none
+---
+
+- hosts: r11
+
+ connection: network_cli
+ gather_facts: 'no'
+
+ tasks:
+ - name: Configure remote r11
+ vyos_config:
+ lines:
+ - set system host-name r11
+ - set system name-server 203.0.113.254
+ - set service ssh disable-host-validation
+ - set system login user vyos authentication public-keys docker@work type ssh-rsa
+ - set system login user vyos authentication public-keys docker@work key "{{ lookup('file', 'id_rsa_docker.pub') }}"
+ - set system time-zone America/Los_Angeles
+ - set interfaces ethernet eth0 description WAN
+```
+
+
+## Run Ansible
+
+To apply the configuration, use the following command:
+
+```none
+$ ansible-playbook -i hosts main.yml
+
+PLAY [r11] **************************************************************************************************
+
+TASK [Configure remote r11] *********************************************************************************
+
+PLAY RECAP **************************************************************************************************
+r11 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+```
diff --git a/docs/automation/vyos-api.md b/docs/automation/vyos-api.md
new file mode 100644
index 00000000..66e8250c
--- /dev/null
+++ b/docs/automation/vyos-api.md
@@ -0,0 +1,587 @@
+---
+lastproofread: '2026-04-13'
+---
+
+(vyosapi)=
+
+# VyOS API
+
+For instructions on configuring and enabling the API, see {ref}`http-api`.
+
+## Authentication
+
+All endpoints, except one, accept HTTP POST requests. The API key must be
+provided as the `key` field in the form data. The only public endpoint
+accepts HTTP GET requests and supports optional query parameters.
+
+Below are examples of API requests in cURL and Python. All other code examples
+in this documentation use cURL.
+
+```none
+curl --location --request POST 'https://vyos/retrieve' \
+--form data='{"op": "showConfig", "path": []}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+```
+
+```python
+import requests
+url = "https://vyos/retrieve"
+payload={'data': '{"op": "showConfig", "path": []}',
+ 'key': 'MY-HTTPS-API-PLAINTEXT-KEY'
+ }
+headers = {}
+response = requests.request("POST", url, headers=headers, data=payload)
+print(response.text)
+```
+
+
+## API endpoints
+
+### /info
+
+This is the only API endpoint that does not require authentication and can be
+accessed by anonymous users. The info endpoint returns general system
+information, including the VyOS version, system hostname, and a welcome banner.
+
+This endpoint accepts **only** HTTP GET requests.
+
+```none
+curl --location --request GET 'https://vyos/info'
+
+response
+{
+ "success": true,
+ "data": {
+ "version": "1.5-rolling",
+ "hostname": "vyos",
+ "banner": "Welcome to VyOS"
+ },
+ "error": null
+}
+```
+
+**Query parameters**
+
+This endpoint accepts two optional query parameters, version and hostname. Each
+parameter accepts values convertible to Boolean (e.g., `yes/no`, `1/0`, or
+`true/false`) to control the inclusion of related fields in the response.
+
+If no query parameters are provided, both parameters default to `true`.
+
+```none
+curl --location --request GET 'https://vyos/info?version=1&hostname=1'
+
+response {
+ "success": true,
+ "data": {
+ "version": "1.5-rolling",
+ "hostname": "vyos",
+ "banner": "Welcome to VyOS"
+ },
+ "error": null
+}
+```
+
+If either parameter is set to a value corresponding to false, its field is
+returned as an empty string in the response:
+
+```none
+curl --location --request GET 'https://vyos/info?version=0&hostname=1'
+
+response {
+ "success": true,
+ "data": {
+ "version": "",
+ "hostname": "vyos",
+ "banner": "Welcome to VyOS"
+ },
+ "error": null
+}
+```
+
+You do not need to specify both parameters if you want to hide only one. Any
+missing query parameter defaults to true.
+
+```none
+curl --location --request GET 'https://vyos/info?hostname=no'
+
+response {
+ "success": true,
+ "data": {
+ "version": "1.5-rolling",
+ "hostname": "",
+ "banner": "Welcome to VyOS"
+ },
+ "error": null
+}
+```
+
+Note that while you can disable output for both `hostname` and `version`,
+the `banner` is always included in the response.
+
+:::{Important}
+The endpoint accepts **ONLY** `hostname` and `version` query
+parameters. Including any other parameters results in an HTTP 400 Bad Request.
+:::
+
+```none
+curl --location --request GET \
+ 'https://192.168.56.119/info?hostname=1&url=https://evilsite.com'
+
+response {
+ "success": false,
+ "error": "{'type': 'extra_forbidden', 'loc': ('query', 'url'), 'msg': 'Extra inputs are not permitted', 'input': 'https://evilsite.com'}",
+ "data": null
+}
+```
+
+Values passed to the query string are validated to ensure they are strictly
+Boolean. Other data types are not accepted.
+
+```none
+curl --location --request GET 'https://vyos/info?hostname=1; eval"sudo rm -rf /"'
+
+response
+{
+ "success": false,
+ "error": "{'type': 'bool_parsing', 'loc': ('query', 'hostname'), 'msg': 'Input should be a valid boolean, unable to interpret input', 'input': '1; eval \"sudo rm -rf /\"'}",
+ "data": null
+}
+```
+
+
+### /retrieve
+
+The `/retrieve` endpoint returns either specific parts or the entire
+configuration.
+
+To retrieve the entire configuration, pass an empty list to the `path` field.
+
+```none
+curl --location --request POST 'https://vyos/retrieve' \
+--form data='{"op": "showConfig", "path": []}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+
+response (shortened)
+{
+ "success": true,
+ "data": {
+ "interfaces": {
+ "ethernet": {
+ "eth0": {
+ "address": "dhcp",
+ "duplex": "auto",
+ "hw-id": "50:00:00:01:00:00",
+ "speed": "auto"
+ },
+ "eth1": {
+ "duplex": "auto",
+ "hw-id": "50:00:00:01:00:01",
+ "speed": "auto"
+ ...
+ },
+ "error": null
+}
+```
+
+To retrieve a specific configuration part, such as `system syslog`, specify
+the desired path.
+
+```none
+curl -k --location --request POST 'https://vyos/retrieve' \
+--form data='{"op": "showConfig", "path": ["system", "syslog"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+
+response:
+{
+ "success": true,
+ "data": {
+ "global": {
+ "facility": {
+ "all": {
+ "level": "info"
+ },
+ "protocols": {
+ "level": "debug"
+ }
+ }
+ }
+ },
+ "error": null
+}
+```
+
+If you only need the value of a multi-valued node, use the `returnValues`
+operation.
+
+For example, to get the addresses of a `dum0` interface:
+
+```none
+curl -k --location --request POST 'https://vyos/retrieve' \
+--form data='{"op": "returnValues", "path": ["interfaces","dummy","dum0","address"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": [
+ "10.10.10.10/24",
+ "10.10.10.11/24",
+ "10.10.10.12/24"
+ ],
+ "error": null
+}
+```
+
+To check whether a configuration path exists, use the `exists` operation. It
+returns `true` for an existing path:
+
+```none
+curl -k --location --request POST 'https://vyos/retrieve' \
+--form data='{"op": "exists", "path": ["service","https","api"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": true,
+ "error": null
+}
+```
+
+It returns `false` for a non-existing path:
+
+```none
+curl -k --location --request POST 'https://vyos/retrieve' \
+--form data='{"op": "exists", "path": ["service","non","existent","path"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": false,
+ "error": null
+}
+```
+
+
+### /reset
+
+The `/reset` endpoint runs the `reset` command.
+
+```none
+curl --location --request POST 'https://vyos/reset' \
+--form data='{"op": "reset", "path": ["ip", "bgp", "192.0.2.11"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "",
+ "error": null
+}
+```
+
+
+### /reboot
+
+To initiate a reboot, use the `/reboot` endpoint.
+
+```none
+curl --location --request POST 'https://vyos/reboot' \
+--form data='{"op": "reboot", "path": ["now"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "",
+ "error": null
+}
+```
+
+
+### /poweroff
+
+To power off the system, use the `/poweroff` endpoint.
+
+```none
+curl --location --request POST 'https://vyos/poweroff' \
+--form data='{"op": "poweroff", "path": ["now"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "",
+ "error": null
+}
+```
+
+
+### /image
+
+To add or delete an image, use the `/image` endpoint.
+
+To add an image:
+
+```none
+curl -k --location --request POST 'https://vyos/image' \
+--form data='{"op": "add", "url": "https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response (shortened):
+{
+ "success": true,
+ "data": "Trying to fetch ISO file from https://downloads.vyos.io/rolling-latest.iso\n
+ ...
+ Setting up grub configuration...\nDone.\n",
+ "error": null
+}
+```
+
+To delete an image, for example `1.3-rolling-202006070117`:
+
+```none
+curl -k --location --request POST 'https://vyos/image' \
+--form data='{"op": "delete", "name": "1.3-rolling-202006070117"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "Deleting the \"1.3-rolling-202006070117\" image...\nDone\n",
+ "error": null
+}
+```
+
+
+### /show
+
+The `/show` endpoint runs operational mode commands and returns the resulting
+output.
+
+For example, to show the installed images:
+
+```none
+curl -k --location --request POST 'https://vyos/show' \
+--form data='{"op": "show", "path": ["system", "image"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "The system currently has the following image(s) installed:\n\n
+ 1: 1.4-rolling-202102280559 (default boot)\n
+ 2: 1.4-rolling-202102230218\n
+ 3: 1.3-beta-202102210443\n\n",
+ "error": null
+}
+```
+
+
+### /generate
+
+The `/generate` endpoint runs a `generate` command.
+
+```none
+curl -k --location --request POST 'https://vyos/generate' \
+--form data='{"op": "generate", "path": ["pki", "wireguard", "key-pair"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "Private key: CFZR2eyhoVZwk4n3JFPMJx3E145f1EYgDM+ubytXYVY=\n
+ Public key: jjtpPT8ycI1Q0bNtrWuxAkO4k88Xwzg5VHV9xGZ58lU=\n\n",
+ "error": null
+}
+```
+
+
+### /configure
+
+The `/configure` endpoint accepts `set`, `delete`, and `comment` commands.
+
+To apply a `set` command:
+
+```none
+curl -k --location --request POST 'https://vyos/configure' \
+--form data='{"op": "set", "path": ["interfaces", "dummy", "dum1", "address", "10.11.0.1/32"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": null,
+ "error": null
+}
+```
+
+To apply a `delete` command:
+
+```none
+curl -k --location --request POST 'https://vyos/configure' \
+--form data='{"op": "delete", "path": ["interfaces", "dummy", "dum1", "address", "10.11.0.1/32"]}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": null,
+ "error": null
+}
+```
+
+The API processes each request in a session and commits it. For components such
+as DHCP and PPPoE servers, IPsec, VXLAN, and other tunnels, VyOS requires the
+entire configuration block for a commit.
+
+The endpoint can process multiple commands if you pass them as a list to
+the `data` field.
+
+```none
+curl -k --location --request POST 'https://vyos/configure' \
+--form data='[{"op": "set","path":["interfaces","vxlan","vxlan1","remote","203.0.113.99"]}, {"op": "set","path":["interfaces","vxlan","vxlan1","vni","1"]}]' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": null,
+ "error": null
+}
+```
+
+
+### /config-file
+
+The `/config-file` endpoint allows you to save, load, or merge a
+configuration.
+
+If you do not specify a file during the `save` operation, the configuration
+is automatically saved to `/config/config.boot`.
+
+```none
+curl -k --location --request POST 'https://vyos/config-file' \
+--form data='{"op": "save"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "Saving configuration to '/config/config.boot'...\nDone\n",
+ "error": null
+}
+```
+
+To save a running configuration to a file:
+
+```none
+curl -k --location --request POST 'https://vyos/config-file' \
+--form data='{"op": "save", "file": "/config/test.config"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": "Saving configuration to '/config/test.config'...\nDone\n",
+ "error": null
+}
+```
+
+To load a configuration file:
+
+```none
+curl -k --location --request POST 'https://vyos/config-file' \
+--form data='{"op": "load", "file": "/config/test.config"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": null,
+ "error": null
+}
+```
+
+To merge a configuration file:
+
+```none
+curl -k --location --request POST 'https://vyos/config-file' \
+--form data='{"op": "merge", "file": "/config/test.config"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": null,
+ "error": null
+}
+```
+
+For both `load` and `merge` operations, you can pass a string in the
+request body. For example:
+
+```none
+curl -k --location --request POST 'https://vyos/config-file' \
+--form data='{"op": "merge", "string": "interfaces {\nethernet eth1 {\naddress \"192.168.2.137/24\"\ndescription \"test\"\n}\n}\n"}' \
+--form key='MY-HTTPS-API-PLAINTEXT-KEY'
+
+response:
+{
+ "success": true,
+ "data": null,
+ "error": null
+}
+```
+
+
+## Commit-confirm
+
+For the previous two endpoints, a `commit` command is executed automatically
+after a successful request operation (`set`, `delete`, `load`, `merge`,
+or a list of `set` and `delete` operations).
+
+Alternatively, you can initiate a `commit-confirm`. Include the
+`confirm_time` field in your request and set it to an integer greater than
+`0`.
+
+The following example uses the JSON format for brevity, though the standard
+form data format is equally valid:
+
+```none
+curl -k -X POST -d '{"key": "MY-HTTPS-API-PLAINTEXT-KEY", "op": "merge", "string": "interfaces {\nethernet eth1 {\naddress \"192.168.137.1/24\"\ndescription \"internal\"\n}\n}\n", "confirm_time": 1}' https://vyos/config-file
+
+response:
+{
+ "success": true,
+ "data": "Initialized commit-confirm; 1 minutes to confirm before reload\n",
+ "error": null
+}
+```
+
+If not confirmed within the specified time, the committed changes will be
+reverted. To confirm and keep the changes:
+
+```none
+curl -k -X POST -d '{"key": "MY-HTTPS-API-PLAINTEXT-KEY", "op": "confirm"}' https://vyos/config-file
+
+response:
+{
+ "success": true,
+ "data": "Reload timer stopped\n",
+ "error": null
+}
+```
+
+If the commit is not confirmed, the revert behavior is controlled by:
+
+```none
+vyos@vyos# set system config-management commit-confirm action
+Possible completions:
+ reload Reload previous configuration if not confirmed
+ reboot Reboot to saved configuration if not confirmed (default)
+```
diff --git a/docs/automation/vyos-govyos.md b/docs/automation/vyos-govyos.md
new file mode 100644
index 00000000..c1d0b24a
--- /dev/null
+++ b/docs/automation/vyos-govyos.md
@@ -0,0 +1,197 @@
+---
+lastproofread: '2026-04-14'
+---
+
+(vyos-govyos)=
+
+# Go-VyOS
+
+Go-VyOS is a Go library for configuring and managing VyOS devices through
+their API.
+
+- [GitHub repository](https://github.com/ganawaj/go-vyos): Hosts the source
+ code.
+- [Documentation](https://pkg.go.dev/github.com/ganawaj/go-vyos@v0.1.0/vyos):
+ Provides the complete API reference, including available types, functions, and
+ methods.
+
+## Installation
+
+To install Go-VyOS, run:
+
+```bash
+go install "github.com/ganawaj/go-vyos/vyos"
+```
+
+
+## Getting started
+
+### Import and disable TLS verification
+
+```none
+import "github.com/ganawaj/go-vyos/vyos"
+client := vyos.NewClient(nil).WithToken("AUTH_KEY").WithURL("https://192.168.0.1").Insecure()
+```
+
+
+### Initialize a VyDevice object
+
+```none
+import (
+ "github.com/ganawaj/go-vyos/vyos"
+ "os"
+)
+
+hostname := os.Getenv("VYDEVICE_HOSTNAME")
+port := os.Getenv("VYDEVICE_PORT")
+url := fmt.Sprintf("https://%s:%s", hostname, port)
+
+apikey := os.Getenv("VYDEVICE_APIKEY")
+verify_ssl := os.Getenv("VYDEVICE_VERIFY_SSL")
+
+client := vyos.NewClient(nil).WithToken(apikey).WithURL(url)
+
+if verify_ssl == "false" {
+ client = client.Insecure()
+}
+```
+
+
+## Use Go-VyOS
+
+### Configure, then set
+
+```none
+out, resp, err := c.Conf.Set(ctx, "interfaces ethernet eth0 address 192.168.1.1/24")
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+```
+
+
+### Show a single object value
+
+```none
+out, resp, err := c.Show.Do(ctx, "interfaces dummy dum1 address")
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+fmt.Printf("Data: %v\n", out.Data)
+```
+
+
+### Configure, then show object
+
+```none
+out, resp, err := c.Conf.Get(ctx, "interfaces dummy dum1", nil)
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+fmt.Printf("Data: %v\n", out.Data)
+```
+
+
+### Configure, then show multivalue object
+
+```none
+options := RetrieveOptions{
+ Multivalue: true,
+}
+
+out, resp, err := c.Conf.Get(ctx, "interfaces dummy dum1", options)
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+```
+
+
+### Configure, then delete object
+
+```none
+out, resp, err := c.Conf.Delete(ctx, "interfaces dummy dum1")
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+```
+
+
+### Configure, then save
+
+```none
+out, resp, err := c.Conf.Save(ctx, "")
+
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+```
+
+
+### Configure, then save file
+
+```none
+out, resp, err := c.Conf.Save(ctx, "/config/test300.config")
+
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+```
+
+
+### Show object
+
+```none
+out, resp, err := c.Show.Do(ctx, "system image")
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+fmt.Printf("Data: %v\n", out.Data)
+```
+
+
+### Generate object
+
+```none
+out, resp, err := c.Generate.Do(ctx, "pki wireguard key-pair")
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+fmt.Printf("Data: %v\n", out.Data)
+```
+
+
+### Reset object
+
+```none
+out, resp, err := c.Reset.Do(ctx, "ip bgp 192.0.2.11")
+if err != nil {
+ panic(fmt.Sprintf("Error: %v", err))
+}
+
+fmt.Println(out.Success)
+fmt.Printf("Data: %v\n", out.Data)
+```
+
+
+### Configure, then load file
+
+```none
+out, resp, err := c.ConfigFile.Load(ctx, "/config/test300.config")
+```
diff --git a/docs/automation/vyos-napalm.md b/docs/automation/vyos-napalm.md
new file mode 100644
index 00000000..d656c7c2
--- /dev/null
+++ b/docs/automation/vyos-napalm.md
@@ -0,0 +1,152 @@
+---
+lastproofread: '2026-04-13'
+---
+
+(vyos-napalm)=
+
+# NAPALM VyOS driver
+
+VyOS can be configured using the [NAPALM VyOS driver], which enables you to
+retrieve device data and apply configurations via SSH.
+
+:::{note}
+The `napalm-vyos` module is currently in testing.
+:::
+
+To use the NAPALM VyOS driver, install the following packages:
+
+```none
+apt install python3-pip
+pip3 install napalm
+pip3 install napalm-vyos
+```
+
+
+## Retrieve device data
+
+The following script connects to a VyOS device, retrieves device facts and
+the ARP table, and prints the output in JSON format.
+
+```none
+#!/usr/bin/env python3
+
+import json
+from napalm import get_network_driver
+
+driver = get_network_driver('vyos')
+
+vyos_router = driver(
+ hostname="192.0.2.1",
+ username="vyos",
+ password="vyospass",
+ optional_args={"port": 22},
+)
+
+vyos_router.open()
+output = vyos_router.get_facts()
+print(json.dumps(output, indent=4))
+
+output = vyos_router.get_arp_table()
+print(json.dumps(output, indent=4))
+
+vyos_router.close()
+```
+
+Output:
+
+```none
+$ ./vyos-napalm.py
+{
+ "uptime": 7185,
+ "vendor": "VyOS",
+ "os_version": "1.3.0-rc5",
+ "serial_number": "",
+ "model": "Standard PC (Q35 + ICH9, 2009)",
+ "hostname": "r4-1.3",
+ "fqdn": "vyos.local",
+ "interface_list": [
+ "eth0",
+ "eth1",
+ "eth2",
+ "lo",
+ "vtun10"
+ ]
+}
+[
+ {
+ "interface": "eth1",
+ "mac": "52:54:00:b2:38:2c",
+ "ip": "192.0.2.2",
+ "age": 0.0
+ },
+ {
+ "interface": "eth0",
+ "mac": "52:54:00:a2:b9:5b",
+ "ip": "203.0.113.11",
+ "age": 0.0
+ }
+]
+```
+
+
+## Apply a configuration
+
+To apply a configuration using NAPALM VyOS driver, you will need a file with
+configuration commands (`commands.conf`) and a script that executes and
+commits them (`vyos-napalm.py`).
+
+- `commands.conf`
+
+```none
+set service ssh disable-host-validation
+set service ssh port '2222'
+set system name-server '192.0.2.8'
+set system name-server '203.0.113.8'
+set interfaces ethernet eth1 description 'FOO'
+```
+
+- `vyos-napalm.py`
+
+```none
+#!/usr/bin/env python3
+
+from napalm import get_network_driver
+
+driver = get_network_driver('vyos')
+
+vyos_router = driver(
+ hostname="192.0.2.1",
+ username="vyos",
+ password="vyospass",
+ optional_args={"port": 22},
+)
+
+vyos_router.open()
+vyos_router.load_merge_candidate(filename='commands.conf')
+diffs = vyos_router.compare_config()
+
+if bool(diffs) == True:
+ print(diffs)
+ vyos_router.commit_config()
+else:
+ print('No configuration changes to commit')
+ vyos_router.discard_config()
+
+vyos_router.close()
+```
+
+Output:
+
+```none
+$./vyos-napalm.py
+[edit interfaces ethernet eth1]
++description FOO
+[edit service ssh]
++disable-host-validation
++port 2222
+[edit system]
++name-server 192.0.2.8
++name-server 203.0.113.8
+[edit]
+```
+[NAPALM VyOS driver]: https://github.com/napalm-automation-community/napalm-vyos
diff --git a/docs/automation/vyos-netmiko.md b/docs/automation/vyos-netmiko.md
new file mode 100644
index 00000000..2e947b6a
--- /dev/null
+++ b/docs/automation/vyos-netmiko.md
@@ -0,0 +1,76 @@
+---
+lastproofread: '2026-04-13'
+---
+
+(vyos-netmiko)=
+
+# Netmiko
+
+VyOS can be configured using [Netmiko]. To use Netmiko, install the
+`python3-netmiko` module.
+
+## Example
+
+The following script connects to a VyOS device, applies configuration changes,
+commits them, and runs an operational mode command to verify the updated
+configuration.
+
+```none
+#!/usr/bin/env python3
+
+from netmiko import ConnectHandler
+
+vyos_router = {
+ "device_type": "vyos",
+ "host": "192.0.2.1",
+ "username": "vyos",
+ "password": "vyospass",
+ "port": 22,
+ }
+
+net_connect = ConnectHandler(**vyos_router)
+
+config_commands = [
+ 'set interfaces ethernet eth0 description WAN',
+ 'set interfaces ethernet eth1 description LAN',
+ ]
+
+# set configuration
+output = net_connect.send_config_set(config_commands, exit_config_mode=False)
+print(output)
+
+# commit configuration
+output = net_connect.commit()
+print(output)
+
+# operational mode commands
+output = net_connect.send_command("run show interfaces")
+print(output)
+```
+
+Output
+
+```none
+$ ./vyos-netmiko.py
+configure
+set interfaces ethernet eth0 description WAN
+[edit]
+vyos@r4-1.5# set interfaces ethernet eth1 description LAN
+[edit]
+vyos@r4-1.5#
+commit
+[edit]
+vyos@r4-1.5#
+Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
+Interface IP Address S/L Description
+--------- ---------- --- -----------
+eth0 203.0.113.1/24 u/u WAN
+eth1 192.0.2.1/30 u/u LAN
+eth2 - u/u
+lo 127.0.0.1/8 u/u
+ ::1/128
+vtun10 10.10.0.1/24 u/u
+[edit]
+```
+
+[netmiko]: https://github.com/ktbyers/netmiko
diff --git a/docs/automation/vyos-pyvyos.md b/docs/automation/vyos-pyvyos.md
new file mode 100644
index 00000000..1a6a09fd
--- /dev/null
+++ b/docs/automation/vyos-pyvyos.md
@@ -0,0 +1,149 @@
+---
+lastproofread: '2026-04-14'
+---
+
+(vyos-pyvyos)=
+
+# PyVyOS
+
+PyVyOS is a Python library for configuring and managing VyOS devices through
+their API.
+
+**Key resources:**
+
+- [Documentation](https://pyvyos.readthedocs.io/en/latest/): Provides
+ installation, configuration, and usage instructions.
+- [GitHub repository](https://github.com/robertoberto/pyvyos): Hosts the
+ source code.
+- [PyPI](https://pypi.org/project/pyvyos/): Hosts distribution packages for
+ installation via the Python package installer (`pip`).
+
+## Installation
+
+To install PyVyOS via `pip`, run:
+
+```bash
+pip install pyvyos
+```
+
+
+## Getting started
+
+### Import and disable warnings for verify=false
+
+```none
+import urllib3
+urllib3.disable_warnings()
+```
+
+
+### Use API response class
+
+```none
+@dataclass
+class ApiResponse:
+ status: int
+ request: dict
+ result: dict
+ error: str
+```
+
+
+### Initialize a VyDevice object
+
+```none
+from dotenv import load_dotenv
+load_dotenv()
+
+hostname = os.getenv('VYDEVICE_HOSTNAME')
+apikey = os.getenv('VYDEVICE_APIKEY')
+port = os.getenv('VYDEVICE_PORT')
+protocol = os.getenv('VYDEVICE_PROTOCOL')
+verify_ssl = os.getenv('VYDEVICE_VERIFY_SSL')
+
+verify = verify_ssl.lower() == "true" if verify_ssl else True
+
+device = VyDevice(hostname=hostname, apikey=apikey, port=port, protocol=protocol, verify=verify)
+```
+
+
+## Use PyVyOS
+
+### Configure, then set
+
+```none
+response = device.configure_set(path=["interfaces", "ethernet", "eth0", "address", "192.168.1.1/24"])
+if not response.error:
+ print(response.result)
+```
+
+
+### Configure, then show a single object value
+
+```none
+response = device.retrieve_return_values(path=["interfaces", "dummy", "dum1", "address"])
+print(response.result)
+```
+
+
+### Configure, then show object
+
+```none
+response = device.retrieve_show_config(path=[])
+if not response.error:
+ print(response.result)
+```
+
+
+### Configure, then delete object
+
+```none
+response = device.configure_delete(path=["interfaces", "dummy", "dum1"])
+```
+
+
+### Configure, then save
+
+```none
+response = device.config_file_save()
+```
+
+
+### Configure, then save file
+
+```none
+response = device.config_file_save(file="/config/test300.config")
+```
+
+
+### Show object
+
+```none
+response = device.show(path=["system", "image"])
+print(response.result)
+```
+
+
+### Generate object
+
+```none
+randstring = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(20))
+keyrand = f'/tmp/key_{randstring}'
+response = device.generate(path=["ssh", "client-key", keyrand])
+```
+
+
+### Reset object
+
+```none
+response = device.reset(path=["conntrack-sync", "internal-cache"])
+if not response.error:
+ print(response.result)
+```
+
+
+### Configure, then load file
+
+```none
+response = device.config_file_load(file="/config/test300.config")
+```
diff --git a/docs/automation/vyos-salt.md b/docs/automation/vyos-salt.md
new file mode 100644
index 00000000..7b306cb8
--- /dev/null
+++ b/docs/automation/vyos-salt.md
@@ -0,0 +1,211 @@
+---
+lastproofread: '2023-01-16'
+---
+
+(vyos-salt)=
+
+```{include} /_include/need_improvement.txt
+```
+
+
+# Salt
+
+VyOS supports op-mode and configuration via [salt].
+
+Without proxy it requires VyOS minion configuration
+and supports op-mode data:
+
+```none
+set service salt-minion id 'r14'
+set service salt-minion master '192.0.2.250'
+```
+
+Check salt-keys on the salt master
+
+```none
+/ # salt-key --list-all
+Accepted Keys:
+r11
+Denied Keys:
+Unaccepted Keys:
+r14
+Rejected Keys:
+```
+
+Accept minion key
+
+```none
+/ # salt-key --accept r14
+The following keys are going to be accepted:
+Unaccepted Keys:
+r14
+Proceed? [n/Y] y
+Key for minion r14 accepted.
+```
+
+Check that salt master can communicate with minions
+
+```none
+/ # salt '*' test.ping
+r14:
+ True
+r11:
+ True
+```
+
+At this step we can get some op-mode information from VyOS nodes:
+
+```none
+/ # salt '*' network.interface eth0
+r11:
+ |_
+ ----------
+ address:
+ 192.0.2.11
+ broadcast:
+ 192.0.2.255
+ label:
+ eth0
+ netmask:
+ 255.255.255.0
+r14:
+ |_
+ ----------
+ address:
+ 192.0.2.14
+ broadcast:
+ 192.0.2.255
+ label:
+ eth0
+ netmask:
+ 255.255.255.0
+
+
+/ # salt r14 network.arp
+r14:
+ ----------
+ aa:bb:cc:dd:f3:db:
+ 192.0.2.1
+ aa:bb:cc:dd:2e:80:
+ 203.0.113.1
+```
+
+## Netmiko-proxy
+
+It is possible to configure VyOS via [netmiko] proxy module.
+It requires a minion with installed packet `python3-netmiko` module
+who has a connection to VyOS nodes. Salt-minion have to communicate
+with salt master
+
+### Configuration
+
+Salt master configuration:
+
+```none
+/ # cat /etc/salt/master
+file_roots:
+ base:
+ - /srv/salt/states
+
+pillar_roots:
+ base:
+ - /srv/salt/pillars
+```
+
+Structure of /srv/salt:
+
+```none
+/ # tree /srv/salt/
+/srv/salt/
+|___ pillars
+| |__ r11-proxy.sls
+| |__ top.sls
+|___ states
+ |__ commands.txt
+```
+
+top.sls
+
+```none
+/ # cat /srv/salt/pillars/top.sls
+base:
+ r11-proxy:
+ - r11-proxy
+```
+
+r11-proxy.sls Includes parameters for connecting to salt-proxy minion
+
+```none
+/ # cat /srv/salt/pillars/r11-proxy.sls
+proxy:
+ proxytype: netmiko # how to connect to proxy minion, change it
+ device_type: vyos #
+ host: 192.0.2.250
+ username: user
+ password: secret_passwd
+```
+
+commands.txt
+
+```none
+/ # cat /srv/salt/states/commands.txt
+set interfaces ethernet eth0 description 'WAN'
+set interfaces ethernet eth1 description 'LAN'
+```
+
+Check that proxy minion is alive:
+
+```none
+/ # salt r11-proxy test.ping
+r11-proxy:
+ True
+/ #
+```
+
+### Examples
+
+Example of op-mode:
+
+```none
+/ # salt r11-proxy netmiko.send_command 'show interfaces ethernet eth0 brief' host=192.0.2.14 device_type=vyos username=vyos password=vyos
+r11-proxy:
+ Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
+ Interface IP Address S/L Description
+ --------- ---------- --- -----------
+ eth0 192.0.2.14/24 u/u Upstream
+/ #
+```
+
+Example of configuration:
+
+```none
+/ # salt r11-proxy netmiko.send_config config_commands=['set interfaces ethernet eth0 description Link_to_WAN'] commit=True host=192.0.2.14 device_type=vyos username=vyos password=vyos
+r11-proxy:
+ configure
+ set interfaces ethernet eth0 description Link_to_WAN
+ [edit]
+ vyos@r14# commit
+ [edit]
+ vyos@r14#
+/ #
+```
+
+Example of configuration commands from the file
+"/srv/salt/states/commands.txt"
+
+```none
+/ # salt r11-proxy netmiko.send_config config_file=salt://commands.txt commit=True host=192.0.2.11 device_type=vyos username=vyos password=vyos
+r11-proxy:
+ configure
+ set interfaces ethernet eth0 description 'WAN'
+ [edit]
+ vyos@r1# set interfaces ethernet eth1 description 'LAN'
+ [edit]
+ vyos@r1# commit
+ [edit]
+ vyos@r1#
+/ #
+```
+
+[netmiko]: <https://docs.saltproject.io/en/latest/ref/modules/all/salt.modules.netmiko_mod.html#module-salt.modules.netmiko_mod>
+[salt]: https://docs.saltproject.io/en/latest/contents.html