From 5d6fa52b8985f8068314aba26878a1d7d5cb84e5 Mon Sep 17 00:00:00 2001 From: Yuriy Andamasov Date: Wed, 6 May 2026 20:42:32 +0300 Subject: feat: flip swap mechanism — MD as primary, RST as override (Phase 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the first of three phases inverting the per-page swap mechanism so MD becomes the canonical primary and RST becomes the rare override. Phase 1 — file renames + conf.py exclude_patterns flip only: - Rename docs/**/md-.md to docs/**/.md (drop md- prefix) for all 254 stems previously listed in docs/_swap.txt - Rename docs/**/.rst to docs/**/rst-.rst (add rst- prefix) for the same 254 stems - Repurpose docs/_swap.txt as docs/_rst_overrides.txt; initially empty comment-only since no pages need the RST fallback right now - conf.py exclude_patterns flipped: rst-*.rst is now excluded by default instead of md-*.md - conf.py runtime-artifact references updated to _rst_override_state.json and _md_exclude.txt (Phase 2 will rewrite swap_sources.py to produce these names; for now no swap script runs because overrides list is empty) Phase 2 (next commit on this branch) will rewrite scripts/swap_sources.py with inverted rename direction, delete scripts/import_myst.py + tests, and update tests/test_swap_sources.py for the new semantics. Phase 3 will be the cleanup pass and ready-for-review flip. Generated by robots https://vyos.io --- docs/automation/cloud-init.md | 378 +++++++++++ docs/automation/cloud-init.rst | 416 ------------ docs/automation/command-scripting.md | 225 +++++++ docs/automation/command-scripting.rst | 224 ------- docs/automation/index.md | 16 + docs/automation/index.rst | 17 - docs/automation/md-cloud-init.md | 378 ----------- docs/automation/md-command-scripting.md | 225 ------- docs/automation/md-index.md | 16 - docs/automation/md-vyos-ansible.md | 101 --- docs/automation/md-vyos-api.md | 587 ----------------- docs/automation/md-vyos-govyos.md | 197 ------ docs/automation/md-vyos-napalm.md | 152 ----- docs/automation/md-vyos-netmiko.md | 76 --- docs/automation/md-vyos-pyvyos.md | 149 ----- docs/automation/md-vyos-salt.md | 211 ------ docs/automation/rst-cloud-init.rst | 416 ++++++++++++ docs/automation/rst-command-scripting.rst | 224 +++++++ docs/automation/rst-index.rst | 17 + docs/automation/rst-vyos-ansible.rst | 105 +++ docs/automation/rst-vyos-api.rst | 601 +++++++++++++++++ docs/automation/rst-vyos-govyos.rst | 212 ++++++ docs/automation/rst-vyos-napalm.rst | 155 +++++ docs/automation/rst-vyos-netmiko.rst | 76 +++ docs/automation/rst-vyos-pyvyos.rst | 156 +++++ docs/automation/rst-vyos-salt.rst | 232 +++++++ docs/automation/terraform/index.md | 29 + docs/automation/terraform/index.rst | 33 - docs/automation/terraform/md-index.md | 29 - docs/automation/terraform/md-terraformAWS.md | 548 --------------- docs/automation/terraform/md-terraformAZ.md | 501 -------------- docs/automation/terraform/md-terraformGoogle.md | 703 -------------------- docs/automation/terraform/md-terraformvSphere.md | 388 ----------- docs/automation/terraform/rst-index.rst | 33 + docs/automation/terraform/rst-terraformAWS.rst | 576 ++++++++++++++++ docs/automation/terraform/rst-terraformAZ.rst | 514 +++++++++++++++ docs/automation/terraform/rst-terraformGoogle.rst | 732 +++++++++++++++++++++ docs/automation/terraform/rst-terraformvSphere.rst | 426 ++++++++++++ docs/automation/terraform/terraformAWS.md | 548 +++++++++++++++ docs/automation/terraform/terraformAWS.rst | 576 ---------------- docs/automation/terraform/terraformAZ.md | 501 ++++++++++++++ docs/automation/terraform/terraformAZ.rst | 514 --------------- docs/automation/terraform/terraformGoogle.md | 703 ++++++++++++++++++++ docs/automation/terraform/terraformGoogle.rst | 732 --------------------- docs/automation/terraform/terraformvSphere.md | 388 +++++++++++ docs/automation/terraform/terraformvSphere.rst | 426 ------------ docs/automation/vyos-ansible.md | 101 +++ docs/automation/vyos-ansible.rst | 105 --- docs/automation/vyos-api.md | 587 +++++++++++++++++ docs/automation/vyos-api.rst | 601 ----------------- docs/automation/vyos-govyos.md | 197 ++++++ docs/automation/vyos-govyos.rst | 212 ------ docs/automation/vyos-napalm.md | 152 +++++ docs/automation/vyos-napalm.rst | 155 ----- docs/automation/vyos-netmiko.md | 76 +++ docs/automation/vyos-netmiko.rst | 76 --- docs/automation/vyos-pyvyos.md | 149 +++++ docs/automation/vyos-pyvyos.rst | 156 ----- docs/automation/vyos-salt.md | 211 ++++++ docs/automation/vyos-salt.rst | 232 ------- 60 files changed, 8736 insertions(+), 8736 deletions(-) create mode 100644 docs/automation/cloud-init.md delete mode 100644 docs/automation/cloud-init.rst create mode 100644 docs/automation/command-scripting.md delete mode 100644 docs/automation/command-scripting.rst create mode 100644 docs/automation/index.md delete mode 100644 docs/automation/index.rst delete mode 100644 docs/automation/md-cloud-init.md delete mode 100644 docs/automation/md-command-scripting.md delete mode 100644 docs/automation/md-index.md delete mode 100644 docs/automation/md-vyos-ansible.md delete mode 100644 docs/automation/md-vyos-api.md delete mode 100644 docs/automation/md-vyos-govyos.md delete mode 100644 docs/automation/md-vyos-napalm.md delete mode 100644 docs/automation/md-vyos-netmiko.md delete mode 100644 docs/automation/md-vyos-pyvyos.md delete mode 100644 docs/automation/md-vyos-salt.md create mode 100644 docs/automation/rst-cloud-init.rst create mode 100644 docs/automation/rst-command-scripting.rst create mode 100644 docs/automation/rst-index.rst create mode 100644 docs/automation/rst-vyos-ansible.rst create mode 100644 docs/automation/rst-vyos-api.rst create mode 100644 docs/automation/rst-vyos-govyos.rst create mode 100644 docs/automation/rst-vyos-napalm.rst create mode 100644 docs/automation/rst-vyos-netmiko.rst create mode 100644 docs/automation/rst-vyos-pyvyos.rst create mode 100644 docs/automation/rst-vyos-salt.rst create mode 100644 docs/automation/terraform/index.md delete mode 100644 docs/automation/terraform/index.rst delete mode 100644 docs/automation/terraform/md-index.md delete mode 100644 docs/automation/terraform/md-terraformAWS.md delete mode 100644 docs/automation/terraform/md-terraformAZ.md delete mode 100644 docs/automation/terraform/md-terraformGoogle.md delete mode 100644 docs/automation/terraform/md-terraformvSphere.md create mode 100644 docs/automation/terraform/rst-index.rst create mode 100644 docs/automation/terraform/rst-terraformAWS.rst create mode 100644 docs/automation/terraform/rst-terraformAZ.rst create mode 100644 docs/automation/terraform/rst-terraformGoogle.rst create mode 100644 docs/automation/terraform/rst-terraformvSphere.rst create mode 100644 docs/automation/terraform/terraformAWS.md delete mode 100644 docs/automation/terraform/terraformAWS.rst create mode 100644 docs/automation/terraform/terraformAZ.md delete mode 100644 docs/automation/terraform/terraformAZ.rst create mode 100644 docs/automation/terraform/terraformGoogle.md delete mode 100644 docs/automation/terraform/terraformGoogle.rst create mode 100644 docs/automation/terraform/terraformvSphere.md delete mode 100644 docs/automation/terraform/terraformvSphere.rst create mode 100644 docs/automation/vyos-ansible.md delete mode 100644 docs/automation/vyos-ansible.rst create mode 100644 docs/automation/vyos-api.md delete mode 100644 docs/automation/vyos-api.rst create mode 100644 docs/automation/vyos-govyos.md delete mode 100644 docs/automation/vyos-govyos.rst create mode 100644 docs/automation/vyos-napalm.md delete mode 100644 docs/automation/vyos-napalm.rst create mode 100644 docs/automation/vyos-netmiko.md delete mode 100644 docs/automation/vyos-netmiko.rst create mode 100644 docs/automation/vyos-pyvyos.md delete mode 100644 docs/automation/vyos-pyvyos.rst create mode 100644 docs/automation/vyos-salt.md delete mode 100644 docs/automation/vyos-salt.rst (limited to 'docs/automation') 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]: +[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/cloud-init.rst b/docs/automation/cloud-init.rst deleted file mode 100644 index 29f56d0d..00000000 --- a/docs/automation/cloud-init.rst +++ /dev/null @@ -1,416 +0,0 @@ -: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: - -.. code-block:: 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: - -.. code-block:: 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). - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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 `_ - provide simple validation tools. -2. **Check the logs**: ``cloud-init`` writes logs to ``/var/log/cloud-init.log``. - Filter for VyOS-specific entries using: - - -.. code-block:: 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: - -#. Clone the ``vyos-vm-images`` repository and comment out the ``download-iso`` - role in ``qemu.yml``. -#. Download your preferred VyOS ``.iso`` file and save it as ``/tmp/vyos.iso``. -#. Generate the ``.qcow2`` image (using a 10G disk size for this example): - -.. code-block:: 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``. - -#. Copy the resulting image to the Proxmox server: - -.. code-block:: 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: - - .. code-block:: sh - - cd /tmp/ - -2. Create the ``user-data`` file. Begin the file with ``#cloud-config`` and - include VyOS configuration commands. - - .. code-block:: 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: - - .. code-block:: 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. - -.. code-block:: 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``: - -.. code-block:: sh - - mv /tmp/seed.iso /var/lib/vz/template/iso/ - -On the Proxmox server: - -.. code-block:: 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`_. - -.. stop_vyoslinter - -.. _network-config-docs: https://cloudinit.readthedocs.io/en/latest/topics/network-config.html -.. _vyos-vm-images: https://github.com/vyos/vyos-vm-images -.. _cloud-init-docs: https://docs.vyos.io/en/equuleus/automation/cloud-init.html?highlight=cloud-init#vyos-cloud-init -.. _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 -.. _nocloud: https://cloudinit.readthedocs.io/en/latest/reference/datasources/nocloud.html -.. start_vyoslinter 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' <> $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]: -[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/md-command-scripting.md b/docs/automation/md-command-scripting.md deleted file mode 100644 index 7e736152..00000000 --- a/docs/automation/md-command-scripting.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -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' < -[salt]: https://docs.saltproject.io/en/latest/contents.html diff --git a/docs/automation/rst-cloud-init.rst b/docs/automation/rst-cloud-init.rst new file mode 100644 index 00000000..29f56d0d --- /dev/null +++ b/docs/automation/rst-cloud-init.rst @@ -0,0 +1,416 @@ +: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: + +.. code-block:: 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: + +.. code-block:: 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). + +.. code-block:: 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: + +.. code-block:: 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: + +.. code-block:: 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 `_ + provide simple validation tools. +2. **Check the logs**: ``cloud-init`` writes logs to ``/var/log/cloud-init.log``. + Filter for VyOS-specific entries using: + + +.. code-block:: 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: + +#. Clone the ``vyos-vm-images`` repository and comment out the ``download-iso`` + role in ``qemu.yml``. +#. Download your preferred VyOS ``.iso`` file and save it as ``/tmp/vyos.iso``. +#. Generate the ``.qcow2`` image (using a 10G disk size for this example): + +.. code-block:: 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``. + +#. Copy the resulting image to the Proxmox server: + +.. code-block:: 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: + + .. code-block:: sh + + cd /tmp/ + +2. Create the ``user-data`` file. Begin the file with ``#cloud-config`` and + include VyOS configuration commands. + + .. code-block:: 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: + + .. code-block:: 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. + +.. code-block:: 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``: + +.. code-block:: sh + + mv /tmp/seed.iso /var/lib/vz/template/iso/ + +On the Proxmox server: + +.. code-block:: 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`_. + +.. stop_vyoslinter + +.. _network-config-docs: https://cloudinit.readthedocs.io/en/latest/topics/network-config.html +.. _vyos-vm-images: https://github.com/vyos/vyos-vm-images +.. _cloud-init-docs: https://docs.vyos.io/en/equuleus/automation/cloud-init.html?highlight=cloud-init#vyos-cloud-init +.. _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 +.. _nocloud: https://cloudinit.readthedocs.io/en/latest/reference/datasources/nocloud.html +.. start_vyoslinter diff --git a/docs/automation/rst-command-scripting.rst b/docs/automation/rst-command-scripting.rst new file mode 100644 index 00000000..91086b42 --- /dev/null +++ b/docs/automation/rst-command-scripting.rst @@ -0,0 +1,224 @@ +: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. + +.. code-block:: 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: + +.. code-block:: 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: + +.. code-block:: 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``. + +.. code-block:: 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. + +.. code-block:: none + + ssh 192.0.2.1 'vbash -s' <`_: Hosts the source + code. +- `Documentation `_: + Provides the complete API reference, including available types, functions, and + methods. + + +Installation +------------ + +To install Go-VyOS, run: + +.. code-block:: bash + + go install "github.com/ganawaj/go-vyos/vyos" + +Getting started +--------------- + +Import and disable TLS verification +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. stop_vyoslinter + +.. code-block:: none + + import "github.com/ganawaj/go-vyos/vyos" + client := vyos.NewClient(nil).WithToken("AUTH_KEY").WithURL("https://192.168.0.1").Insecure() + +.. start_vyoslinter + +Initialize a VyDevice object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: 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 +^^^^^^^^^^^^^^^^^^^ + +.. stop_vyoslinter + +.. code-block:: none + + out, resp, err := c.Conf.Set(ctx, "interfaces ethernet eth0 address 192.168.1.1/24") + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + +.. start_vyoslinter + +Show a single object value +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Show.Do(ctx, "interfaces dummy dum1 address") + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + fmt.Printf("Data: %v\n", out.Data) + +Configure, then show object +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Conf.Get(ctx, "interfaces dummy dum1", nil) + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + fmt.Printf("Data: %v\n", out.Data) + +Configure, then show multivalue object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + options := RetrieveOptions{ + Multivalue: true, + } + + out, resp, err := c.Conf.Get(ctx, "interfaces dummy dum1", options) + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + + +Configure, then delete object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Conf.Delete(ctx, "interfaces dummy dum1") + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + +Configure, then save +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Conf.Save(ctx, "") + + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + +Configure, then save file +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Conf.Save(ctx, "/config/test300.config") + + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + +Show object +^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Show.Do(ctx, "system image") + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + fmt.Printf("Data: %v\n", out.Data) + +Generate object +^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Generate.Do(ctx, "pki wireguard key-pair") + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + fmt.Printf("Data: %v\n", out.Data) + +Reset object +^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.Reset.Do(ctx, "ip bgp 192.0.2.11") + if err != nil { + panic("Error: %v", err) + } + + fmt.Println(out.Success) + fmt.Printf("Data: %v\n", out.Data) + +Configure, then load file +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + out, resp, err := c.ConfigFile.Load(ctx, "/config/test300.config") + +.. _go-vyos: https://github.com/ganawaj/go-vyos \ No newline at end of file diff --git a/docs/automation/rst-vyos-napalm.rst b/docs/automation/rst-vyos-napalm.rst new file mode 100644 index 00000000..f2f27124 --- /dev/null +++ b/docs/automation/rst-vyos-napalm.rst @@ -0,0 +1,155 @@ +: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: + +.. code-block:: 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. + +.. code-block:: 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: + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: 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: + +.. code-block:: 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: https://napalm.readthedocs.io/en/latest/base.html +.. _NAPALM VyOS driver: https://github.com/napalm-automation-community/napalm-vyos \ No newline at end of file diff --git a/docs/automation/rst-vyos-netmiko.rst b/docs/automation/rst-vyos-netmiko.rst new file mode 100644 index 00000000..b94b0129 --- /dev/null +++ b/docs/automation/rst-vyos-netmiko.rst @@ -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. + +.. code-block:: 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 + +.. code-block:: 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/rst-vyos-pyvyos.rst b/docs/automation/rst-vyos-pyvyos.rst new file mode 100644 index 00000000..cbd315e5 --- /dev/null +++ b/docs/automation/rst-vyos-pyvyos.rst @@ -0,0 +1,156 @@ +:lastproofread: 2026-04-14 + +.. _vyos-pyvyos: + +###### +PyVyOS +###### + +PyVyOS is a Python library for configuring and managing VyOS devices through +their API. + +**Key resources:** + +- `Documentation `_: Provides + installation, configuration, and usage instructions. +- `GitHub repository `_: Hosts the + source code. +- `PyPI `_: Hosts distribution packages for + installation via the Python package installer (``pip``). + + +Installation +------------ + +To install PyVyOS via ``pip``, run: + +.. code-block:: bash + + pip install pyvyos + +Getting started +--------------- + +Import and disable warnings for verify=false +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + import urllib3 + urllib3.disable_warnings() + +Use API response class +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + @dataclass + class ApiResponse: + status: int + request: dict + result: dict + error: str + +Initialize a VyDevice object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: 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 +^^^^^^^^^^^^^^^^^^^ + +.. code-block:: 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 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + response = device.retrieve_return_values(path=["interfaces", "dummy", "dum1", "address"]) + print(response.result) + +Configure, then show object +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + response = device.retrieve_show_config(path=[]) + if not response.error: + print(response.result) + +Configure, then delete object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + response = device.configure_delete(path=["interfaces", "dummy", "dum1"]) + +Configure, then save +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + response = device.config_file_save() + +Configure, then save file +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + response = device.config_file_save(file="/config/test300.config") + +Show object +^^^^^^^^^^^ + +.. code-block:: none + + response = device.show(path=["system", "image"]) + print(response.result) + +Generate object +^^^^^^^^^^^^^^^ + +.. code-block:: 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 +^^^^^^^^^^^^ + +.. code-block:: none + + response = device.reset(path=["conntrack-sync", "internal-cache"]) + if not response.error: + print(response.result) + +Configure, then load file +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + response = device.config_file_load(file="/config/test300.config") + + +.. _pyvyos: https://github.com/robertoberto/pyvyos diff --git a/docs/automation/rst-vyos-salt.rst b/docs/automation/rst-vyos-salt.rst new file mode 100644 index 00000000..3a5b17d7 --- /dev/null +++ b/docs/automation/rst-vyos-salt.rst @@ -0,0 +1,232 @@ +: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: + +.. code-block:: none + + set service salt-minion id 'r14' + set service salt-minion master '192.0.2.250' + +Check salt-keys on the salt master + +.. code-block:: none + + / # salt-key --list-all + Accepted Keys: + r11 + Denied Keys: + Unaccepted Keys: + r14 + Rejected Keys: + +Accept minion key + +.. code-block:: 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 + +.. code-block:: none + + / # salt '*' test.ping + r14: + True + r11: + True + +At this step we can get some op-mode information from VyOS nodes: + +.. code-block:: 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: + +.. code-block:: none + + / # cat /etc/salt/master + file_roots: + base: + - /srv/salt/states + + pillar_roots: + base: + - /srv/salt/pillars + +Structure of /srv/salt: + +.. code-block:: none + + / # tree /srv/salt/ + /srv/salt/ + |___ pillars + | |__ r11-proxy.sls + | |__ top.sls + |___ states + |__ commands.txt + +top.sls + +.. code-block:: none + + / # cat /srv/salt/pillars/top.sls + base: + r11-proxy: + - r11-proxy + + +r11-proxy.sls Includes parameters for connecting to salt-proxy minion + +.. code-block:: 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 + +.. code-block:: 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: + +.. code-block:: none + + / # salt r11-proxy test.ping + r11-proxy: + True + / # + +Examples +^^^^^^^^ + +Example of op-mode: + +.. stop_vyoslinter + +.. code-block:: 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 + / # + +.. start_vyoslinter + +Example of configuration: + +.. stop_vyoslinter + +.. code-block:: 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# + / # + +.. start_vyoslinter + +Example of configuration commands from the file +"/srv/salt/states/commands.txt" + +.. stop_vyoslinter + +.. code-block:: 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# + / # + +.. start_vyoslinter + +.. _salt: https://docs.saltproject.io/en/latest/contents.html +.. stop_vyoslinter +.. _netmiko: https://docs.saltproject.io/en/latest/ref/modules/all/salt.modules.netmiko_mod.html#module-salt.modules.netmiko_mod +.. start_vyoslinter \ No newline at end of file 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/index.rst deleted file mode 100644 index f81820d2..00000000 --- a/docs/automation/terraform/index.rst +++ /dev/null @@ -1,33 +0,0 @@ -: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:: - :maxdepth: 1 - :caption: Guides - - terraformvyos - terraformAWS - terraformAZ - terraformGoogle - terraformvSphere - -.. stop_vyoslinter -.. _Terraform: https://developer.hashicorp.com/terraform/intro -.. _Ansible: https://docs.ansible.com -.. _install: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli -.. start_vyoslinter \ No newline at end of file diff --git a/docs/automation/terraform/md-index.md b/docs/automation/terraform/md-index.md deleted file mode 100644 index dc787db1..00000000 --- a/docs/automation/terraform/md-index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -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/md-terraformAWS.md b/docs/automation/terraform/md-terraformAWS.md deleted file mode 100644 index 488e7926..00000000 --- a/docs/automation/terraform/md-terraformAWS.md +++ /dev/null @@ -1,548 +0,0 @@ ---- -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 `__. - -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 / - 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 `__ in AWS and - downloading your ``.pem`` key. -``` - -### Deploy with Terraform - -Run the following commands on your Terraform instance: - -```none -cd / -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]: diff --git a/docs/automation/terraform/md-terraformAZ.md b/docs/automation/terraform/md-terraformAZ.md deleted file mode 100644 index b1b8fac0..00000000 --- a/docs/automation/terraform/md-terraformAZ.md +++ /dev/null @@ -1,501 +0,0 @@ ---- -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 `__. - -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 / - 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 / -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]: diff --git a/docs/automation/terraform/md-terraformGoogle.md b/docs/automation/terraform/md-terraformGoogle.md deleted file mode 100644 index f9c002a7..00000000 --- a/docs/automation/terraform/md-terraformGoogle.md +++ /dev/null @@ -1,703 +0,0 @@ ---- -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 / -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 / -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]: diff --git a/docs/automation/terraform/md-terraformvSphere.md b/docs/automation/terraform/md-terraformvSphere.md deleted file mode 100644 index abcef5fa..00000000 --- a/docs/automation/terraform/md-terraformvSphere.md +++ /dev/null @@ -1,388 +0,0 @@ ---- -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]() - 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 / -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 / -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]: diff --git a/docs/automation/terraform/rst-index.rst b/docs/automation/terraform/rst-index.rst new file mode 100644 index 00000000..f81820d2 --- /dev/null +++ b/docs/automation/terraform/rst-index.rst @@ -0,0 +1,33 @@ +: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:: + :maxdepth: 1 + :caption: Guides + + terraformvyos + terraformAWS + terraformAZ + terraformGoogle + terraformvSphere + +.. stop_vyoslinter +.. _Terraform: https://developer.hashicorp.com/terraform/intro +.. _Ansible: https://docs.ansible.com +.. _install: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli +.. start_vyoslinter \ No newline at end of file diff --git a/docs/automation/terraform/rst-terraformAWS.rst b/docs/automation/terraform/rst-terraformAWS.rst new file mode 100644 index 00000000..8156fac4 --- /dev/null +++ b/docs/automation/terraform/rst-terraformAWS.rst @@ -0,0 +1,576 @@ +: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. + + +.. image:: /_static/images/aws.* + :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. + +.. image:: /_static/images/keypairs.* + :width: 50% + :align: center + :alt: Network Topology Diagram + +3. Create a security group_ for the new VyOS instance and open all traffic. + +.. image:: /_static/images/sg.* + :width: 50% + :align: center + :alt: Network Topology Diagram + + +.. image:: /_static/images/traffic.* + :width: 50% + :align: center + :alt: Network Topology Diagram + +Terraform +^^^^^^^^^ + +1. Create an UNIX or Windows instance. + +2. Download and install + `Terraform `__. + +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 / + terraform init + +Ansible +^^^^^^^ + + +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_ in AWS and + downloading your ``.pem`` key. + +.. start_vyoslinter + +Deploy with Terraform +^^^^^^^^^^^^^^^^^^^^^ + + +Run the following commands on your Terraform instance: + +.. code-block:: none + + cd / + terraform plan + terraform apply + yes + + +Create an AWS instance and check its configuration +-------------------------------------------------- + +.. code-block:: 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: + +.. code-block:: 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. + + .. 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 +--------------------------------------- + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: none + + terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } + } + +``terraform.tfvars`` + +.. code-block:: 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 +------------------------------------- + +.. code-block:: none + + . + ├── group_vars + └── all + ├── ansible.cfg + ├── mykey.pem + └── instance.yml + + +File contents of Ansible for AWS +-------------------------------- + +``ansible.cfg`` + +.. code-block:: 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`` + +.. code-block:: none + + Copy your key.pem from AWS + + +``instance.yml`` + + + +.. code-block:: 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`` + +.. code-block:: 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. + + +.. stop_vyoslinter +.. _link: https://developer.hashicorp.com/terraform/intro +.. _install: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli +.. _pair: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html +.. _group: https://docs.aws.amazon.com/cli/latest/userguide/cli-services-ec2-sg.html +.. _image: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html +.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/AWS_terraform_ansible_single_vyos_instance-main + +.. start_vyoslinter diff --git a/docs/automation/terraform/rst-terraformAZ.rst b/docs/automation/terraform/rst-terraformAZ.rst new file mode 100644 index 00000000..9e094aea --- /dev/null +++ b/docs/automation/terraform/rst-terraformAZ.rst @@ -0,0 +1,514 @@ +: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 +^^^^^ + +1. Create an `Azure account `__. + +Terraform +^^^^^^^^^ + + +1. Create an UNIX or Windows instance. + +2. Download and install + `Terraform `__. + +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 / + 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`_ + + +Deploy with Terraform +^^^^^^^^^^^^^^^^^^^^^ + + +Run the following commands on your Terraform instance: + +.. code-block:: none + + cd / + 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: + +.. code-block:: none + + terraform destroy + +Structure of files in Terraform for Azure +----------------------------------------- + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: 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" + default = "Vyos0!" + } + + 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`` + +.. code-block:: none + + password = "" # password for Ansible SSH + host = "" # IP of my Ansible + + +Structure of files in Ansible for Azure +--------------------------------------- + +.. code-block:: none + + . + ├── group_vars + └── all + ├── ansible.cfg + └── instance.yml + + +File contents of Ansible for Azure +---------------------------------- + +``ansible.cfg`` + +.. code-block:: none + + [defaults] + inventory = /root/az/ip.txt + host_key_checking= False + remote_user=vyos + + +``instance.yml`` + + +.. code-block:: 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`` + +.. code-block:: 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: Vyos0! + +Source files on GitHub +---------------------- + +All files related to deploying VyOS on Azure with Terraform and Ansible +can be found in the vyos-automation_ repository. + +.. stop_vyoslinter +.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Azure_terraform_ansible_single_vyos_instance-main +.. start_vyoslinter diff --git a/docs/automation/terraform/rst-terraformGoogle.rst b/docs/automation/terraform/rst-terraformGoogle.rst new file mode 100644 index 00000000..eb7e01fe --- /dev/null +++ b/docs/automation/terraform/rst-terraformGoogle.rst @@ -0,0 +1,732 @@ +: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.* + :width: 50% + :align: center + :alt: Network Topology Diagram + +2. Create a service account and download your key (a JSON file). + +.. image:: /_static/images/service.* + :width: 50% + :align: center + :alt: Network Topology Diagram + +.. image:: /_static/images/key.* + :width: 50% + :align: center + :alt: Network Topology Diagram + +The .JSON file downloads automatically after you create it and looks +like the following: + +.. image:: /_static/images/json.* + :width: 50% + :align: center + :alt: Network Topology Diagram + + +Terraform +^^^^^^^^^ + + +1. Create an UNIX or Windows instance. + +2. Download and install + `Terraform `__. + +3. Create the folder. For example, ``/root/google``. + +.. code-block:: none + + mkdir /root/google + +.. stop_vyoslinter +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>`_ + +.. start_vyoslinter + +5. Run the following commands: + + +.. code-block:: none + + cd / + 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`_ + +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: + +.. code-block:: none + + cd / + terraform plan + terraform apply + yes + + +Create a GCP instance and check its configuration +------------------------------------------------- + +.. code-block:: 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: + +.. code-block:: none + + terraform destroy + + +Troubleshooting +--------------- + +1. 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. + +2. If Terraform doesn't connect via SSH to your Ansible instance: + Check the correct login and password in the ``VyOS.tf`` file. + +.. 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 + } + + +Verify that Ansible can ping from Terraform. + +Structure of files in Terraform for Google Cloud +------------------------------------------------ + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: 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 +---------------------------------------------- + +.. code-block:: none + + . + ├── group_vars + └── all + ├── ansible.cfg + └── instance.yml + + +File contents of Ansible for Google Cloud +----------------------------------------- + +``ansible.cfg`` + +.. code-block:: none + + [defaults] + inventory = /root/google/ip.txt + host_key_checking= False + remote_user=vyos + +``instance.yml`` + +.. code-block:: 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`` + +.. code-block:: 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. + +.. stop_vyoslinter +.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Google_terraform_ansible_single_vyos_instance-main +.. start_vyoslinter diff --git a/docs/automation/terraform/rst-terraformvSphere.rst b/docs/automation/terraform/rst-terraformvSphere.rst new file mode 100644 index 00000000..1866fa8e --- /dev/null +++ b/docs/automation/terraform/rst-terraformvSphere.rst @@ -0,0 +1,426 @@ +: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 Azure 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 +^^^^^^^ + + +.. stop_vyoslinter + +1. Add all necessary data to the ``terraform.tfvars`` + `file `__ + and create resources. + +.. start_vyoslinter + +Terraform +^^^^^^^^^ + + +1. Create an UNIX or Windows instance. + +2. Download and install + `Terraform `__. + +3. Create the folder for example ``/root/vsphereterraform``. + +.. code-block:: none + + mkdir /root/vsphereterraform + + +4. 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`_ + +5. Run the following commands: + +.. code-block:: none + + cd / + 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/vsphereterraform/``. + +4. 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`_ + + +Deploy with Terraform +^^^^^^^^^^^^^^^^^^^^^ + + +Run the following commands on your Terraform instance: + +.. code-block:: none + + cd / + 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: +.. code-block:: none + + terraform destroy + + +Structure of files in Terraform for vSphere +------------------------------------------- + +.. code-block:: 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`` + +.. code-block:: 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`` + +.. code-block:: none + + # Copyright (c) HashiCorp, Inc. + # SPDX-License-Identifier: MPL-2.0 + + terraform { + required_providers { + vsphere = { + source = "hashicorp/vsphere" + version = "2.4.0" + } + } + } + +``var.tf`` + +.. code-block:: 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`` + +.. code-block:: 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 +----------------------------------------- + +.. code-block:: none + + . + ├── group_vars + └── all + ├── ansible.cfg + └── instance.yml + + +File contents of Ansible for vSphere +------------------------------------ + +``ansible.cfg`` + +.. code-block:: none + + [defaults] + inventory = /root/vsphere/ip.txt + host_key_checking= False + remote_user=vyos + + +``instance.yml`` + +.. code-block:: 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 cammans 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 + - set system name-server 192.0.2.1 + save: + true + + +``group_vars/all`` + +.. code-block:: 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 vSpherewith Terraform and Ansible +can be found in the vyos-automation_ repository. + + +.. stop_vyoslinter +.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Vsphere_terraform_ansible_single_vyos_instance-main + +.. start_vyoslinter 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 `__. + +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 / + 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 `__ in AWS and + downloading your ``.pem`` key. +``` + +### Deploy with Terraform + +Run the following commands on your Terraform instance: + +```none +cd / +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]: diff --git a/docs/automation/terraform/terraformAWS.rst b/docs/automation/terraform/terraformAWS.rst deleted file mode 100644 index 8156fac4..00000000 --- a/docs/automation/terraform/terraformAWS.rst +++ /dev/null @@ -1,576 +0,0 @@ -: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. - - -.. image:: /_static/images/aws.* - :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. - -.. image:: /_static/images/keypairs.* - :width: 50% - :align: center - :alt: Network Topology Diagram - -3. Create a security group_ for the new VyOS instance and open all traffic. - -.. image:: /_static/images/sg.* - :width: 50% - :align: center - :alt: Network Topology Diagram - - -.. image:: /_static/images/traffic.* - :width: 50% - :align: center - :alt: Network Topology Diagram - -Terraform -^^^^^^^^^ - -1. Create an UNIX or Windows instance. - -2. Download and install - `Terraform `__. - -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 / - terraform init - -Ansible -^^^^^^^ - - -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_ in AWS and - downloading your ``.pem`` key. - -.. start_vyoslinter - -Deploy with Terraform -^^^^^^^^^^^^^^^^^^^^^ - - -Run the following commands on your Terraform instance: - -.. code-block:: none - - cd / - terraform plan - terraform apply - yes - - -Create an AWS instance and check its configuration --------------------------------------------------- - -.. code-block:: 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: - -.. code-block:: 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. - - .. 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 ---------------------------------------- - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: none - - terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 5.0" - } - } - } - -``terraform.tfvars`` - -.. code-block:: 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 -------------------------------------- - -.. code-block:: none - - . - ├── group_vars - └── all - ├── ansible.cfg - ├── mykey.pem - └── instance.yml - - -File contents of Ansible for AWS --------------------------------- - -``ansible.cfg`` - -.. code-block:: 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`` - -.. code-block:: none - - Copy your key.pem from AWS - - -``instance.yml`` - - - -.. code-block:: 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`` - -.. code-block:: 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. - - -.. stop_vyoslinter -.. _link: https://developer.hashicorp.com/terraform/intro -.. _install: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli -.. _pair: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html -.. _group: https://docs.aws.amazon.com/cli/latest/userguide/cli-services-ec2-sg.html -.. _image: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html -.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/AWS_terraform_ansible_single_vyos_instance-main - -.. start_vyoslinter 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 `__. + +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 / + 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 / +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]: diff --git a/docs/automation/terraform/terraformAZ.rst b/docs/automation/terraform/terraformAZ.rst deleted file mode 100644 index 9e094aea..00000000 --- a/docs/automation/terraform/terraformAZ.rst +++ /dev/null @@ -1,514 +0,0 @@ -: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 -^^^^^ - -1. Create an `Azure account `__. - -Terraform -^^^^^^^^^ - - -1. Create an UNIX or Windows instance. - -2. Download and install - `Terraform `__. - -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 / - 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`_ - - -Deploy with Terraform -^^^^^^^^^^^^^^^^^^^^^ - - -Run the following commands on your Terraform instance: - -.. code-block:: none - - cd / - 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: - -.. code-block:: none - - terraform destroy - -Structure of files in Terraform for Azure ------------------------------------------ - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: 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" - default = "Vyos0!" - } - - 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`` - -.. code-block:: none - - password = "" # password for Ansible SSH - host = "" # IP of my Ansible - - -Structure of files in Ansible for Azure ---------------------------------------- - -.. code-block:: none - - . - ├── group_vars - └── all - ├── ansible.cfg - └── instance.yml - - -File contents of Ansible for Azure ----------------------------------- - -``ansible.cfg`` - -.. code-block:: none - - [defaults] - inventory = /root/az/ip.txt - host_key_checking= False - remote_user=vyos - - -``instance.yml`` - - -.. code-block:: 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`` - -.. code-block:: 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: Vyos0! - -Source files on GitHub ----------------------- - -All files related to deploying VyOS on Azure with Terraform and Ansible -can be found in the vyos-automation_ repository. - -.. stop_vyoslinter -.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Azure_terraform_ansible_single_vyos_instance-main -.. start_vyoslinter 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 / +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 / +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]: diff --git a/docs/automation/terraform/terraformGoogle.rst b/docs/automation/terraform/terraformGoogle.rst deleted file mode 100644 index eb7e01fe..00000000 --- a/docs/automation/terraform/terraformGoogle.rst +++ /dev/null @@ -1,732 +0,0 @@ -: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.* - :width: 50% - :align: center - :alt: Network Topology Diagram - -2. Create a service account and download your key (a JSON file). - -.. image:: /_static/images/service.* - :width: 50% - :align: center - :alt: Network Topology Diagram - -.. image:: /_static/images/key.* - :width: 50% - :align: center - :alt: Network Topology Diagram - -The .JSON file downloads automatically after you create it and looks -like the following: - -.. image:: /_static/images/json.* - :width: 50% - :align: center - :alt: Network Topology Diagram - - -Terraform -^^^^^^^^^ - - -1. Create an UNIX or Windows instance. - -2. Download and install - `Terraform `__. - -3. Create the folder. For example, ``/root/google``. - -.. code-block:: none - - mkdir /root/google - -.. stop_vyoslinter -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>`_ - -.. start_vyoslinter - -5. Run the following commands: - - -.. code-block:: none - - cd / - 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`_ - -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: - -.. code-block:: none - - cd / - terraform plan - terraform apply - yes - - -Create a GCP instance and check its configuration -------------------------------------------------- - -.. code-block:: 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: - -.. code-block:: none - - terraform destroy - - -Troubleshooting ---------------- - -1. 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. - -2. If Terraform doesn't connect via SSH to your Ansible instance: - Check the correct login and password in the ``VyOS.tf`` file. - -.. 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 - } - - -Verify that Ansible can ping from Terraform. - -Structure of files in Terraform for Google Cloud ------------------------------------------------- - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: 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 ----------------------------------------------- - -.. code-block:: none - - . - ├── group_vars - └── all - ├── ansible.cfg - └── instance.yml - - -File contents of Ansible for Google Cloud ------------------------------------------ - -``ansible.cfg`` - -.. code-block:: none - - [defaults] - inventory = /root/google/ip.txt - host_key_checking= False - remote_user=vyos - -``instance.yml`` - -.. code-block:: 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`` - -.. code-block:: 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. - -.. stop_vyoslinter -.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Google_terraform_ansible_single_vyos_instance-main -.. start_vyoslinter 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]() + 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 / +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 / +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]: diff --git a/docs/automation/terraform/terraformvSphere.rst b/docs/automation/terraform/terraformvSphere.rst deleted file mode 100644 index 1866fa8e..00000000 --- a/docs/automation/terraform/terraformvSphere.rst +++ /dev/null @@ -1,426 +0,0 @@ -: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 Azure 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 -^^^^^^^ - - -.. stop_vyoslinter - -1. Add all necessary data to the ``terraform.tfvars`` - `file `__ - and create resources. - -.. start_vyoslinter - -Terraform -^^^^^^^^^ - - -1. Create an UNIX or Windows instance. - -2. Download and install - `Terraform `__. - -3. Create the folder for example ``/root/vsphereterraform``. - -.. code-block:: none - - mkdir /root/vsphereterraform - - -4. 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`_ - -5. Run the following commands: - -.. code-block:: none - - cd / - 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/vsphereterraform/``. - -4. 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`_ - - -Deploy with Terraform -^^^^^^^^^^^^^^^^^^^^^ - - -Run the following commands on your Terraform instance: - -.. code-block:: none - - cd / - 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: -.. code-block:: none - - terraform destroy - - -Structure of files in Terraform for vSphere -------------------------------------------- - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: none - - # Copyright (c) HashiCorp, Inc. - # SPDX-License-Identifier: MPL-2.0 - - terraform { - required_providers { - vsphere = { - source = "hashicorp/vsphere" - version = "2.4.0" - } - } - } - -``var.tf`` - -.. code-block:: 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`` - -.. code-block:: 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 ------------------------------------------ - -.. code-block:: none - - . - ├── group_vars - └── all - ├── ansible.cfg - └── instance.yml - - -File contents of Ansible for vSphere ------------------------------------- - -``ansible.cfg`` - -.. code-block:: none - - [defaults] - inventory = /root/vsphere/ip.txt - host_key_checking= False - remote_user=vyos - - -``instance.yml`` - -.. code-block:: 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 cammans 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 - - set system name-server 192.0.2.1 - save: - true - - -``group_vars/all`` - -.. code-block:: 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 vSpherewith Terraform and Ansible -can be found in the vyos-automation_ repository. - - -.. stop_vyoslinter -.. _vyos-automation: https://github.com/vyos/vyos-automation/tree/main/TerraformCloud/Vsphere_terraform_ansible_single_vyos_instance-main - -.. start_vyoslinter 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-ansible.rst b/docs/automation/vyos-ansible.rst deleted file mode 100644 index 12d4e9fb..00000000 --- a/docs/automation/vyos-ansible.rst +++ /dev/null @@ -1,105 +0,0 @@ -: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: - -.. code-block:: none - - . - ├── ansible.cfg - ├── files - │   └── id_rsa_docker.pub - ├── hosts - └── main.yml - - -File contents -------------- - -* ``ansible.cfg`` - -.. code-block:: 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. - -.. code-block:: none - - AAAAB3NzaC1yc2EAAAADAQABAAABAQCoDgfhQJuJRFWJijHn7ZinZ3NWp4hWVrt7HFcvn0kgtP/5PeCtMt - - -* ``hosts`` - -Defines the target VyOS devices and the connection parameters required to reach -them. - -.. code-block:: 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. - -.. code-block:: 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: - -.. code-block:: 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-api.rst b/docs/automation/vyos-api.rst deleted file mode 100644 index e96723e6..00000000 --- a/docs/automation/vyos-api.rst +++ /dev/null @@ -1,601 +0,0 @@ -: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. - -.. code-block:: none - - curl --location --request POST 'https://vyos/retrieve' \ - --form data='{"op": "showConfig", "path": []}' \ - --form key='MY-HTTPS-API-PLAINTEXT-KEY' - -.. code-block:: 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. - -.. code-block:: 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``. - -.. code-block:: 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: - -.. code-block:: 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. - -.. code-block:: 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. - -.. code-block:: 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. - -.. code-block:: 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. - -.. code-block:: 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. - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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. - -.. code-block:: 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. - -.. code-block:: 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. - -.. code-block:: 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: - -.. code-block:: 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``: - -.. code-block:: 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: - -.. code-block:: 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. - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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. - -.. code-block:: 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``. - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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: - -.. code-block:: 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-govyos.rst b/docs/automation/vyos-govyos.rst deleted file mode 100644 index 17e15b0e..00000000 --- a/docs/automation/vyos-govyos.rst +++ /dev/null @@ -1,212 +0,0 @@ -: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 `_: Hosts the source - code. -- `Documentation `_: - Provides the complete API reference, including available types, functions, and - methods. - - -Installation ------------- - -To install Go-VyOS, run: - -.. code-block:: bash - - go install "github.com/ganawaj/go-vyos/vyos" - -Getting started ---------------- - -Import and disable TLS verification -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. stop_vyoslinter - -.. code-block:: none - - import "github.com/ganawaj/go-vyos/vyos" - client := vyos.NewClient(nil).WithToken("AUTH_KEY").WithURL("https://192.168.0.1").Insecure() - -.. start_vyoslinter - -Initialize a VyDevice object -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: 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 -^^^^^^^^^^^^^^^^^^^ - -.. stop_vyoslinter - -.. code-block:: none - - out, resp, err := c.Conf.Set(ctx, "interfaces ethernet eth0 address 192.168.1.1/24") - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - -.. start_vyoslinter - -Show a single object value -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Show.Do(ctx, "interfaces dummy dum1 address") - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - fmt.Printf("Data: %v\n", out.Data) - -Configure, then show object -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Conf.Get(ctx, "interfaces dummy dum1", nil) - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - fmt.Printf("Data: %v\n", out.Data) - -Configure, then show multivalue object -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - options := RetrieveOptions{ - Multivalue: true, - } - - out, resp, err := c.Conf.Get(ctx, "interfaces dummy dum1", options) - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - - -Configure, then delete object -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Conf.Delete(ctx, "interfaces dummy dum1") - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - -Configure, then save -^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Conf.Save(ctx, "") - - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - -Configure, then save file -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Conf.Save(ctx, "/config/test300.config") - - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - -Show object -^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Show.Do(ctx, "system image") - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - fmt.Printf("Data: %v\n", out.Data) - -Generate object -^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Generate.Do(ctx, "pki wireguard key-pair") - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - fmt.Printf("Data: %v\n", out.Data) - -Reset object -^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.Reset.Do(ctx, "ip bgp 192.0.2.11") - if err != nil { - panic("Error: %v", err) - } - - fmt.Println(out.Success) - fmt.Printf("Data: %v\n", out.Data) - -Configure, then load file -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - out, resp, err := c.ConfigFile.Load(ctx, "/config/test300.config") - -.. _go-vyos: https://github.com/ganawaj/go-vyos \ No newline at end of file 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-napalm.rst b/docs/automation/vyos-napalm.rst deleted file mode 100644 index f2f27124..00000000 --- a/docs/automation/vyos-napalm.rst +++ /dev/null @@ -1,155 +0,0 @@ -: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: - -.. code-block:: 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. - -.. code-block:: 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: - -.. code-block:: 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`` - -.. code-block:: 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`` - -.. code-block:: 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: - -.. code-block:: 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: https://napalm.readthedocs.io/en/latest/base.html -.. _NAPALM VyOS driver: https://github.com/napalm-automation-community/napalm-vyos \ No newline at end of file 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-netmiko.rst b/docs/automation/vyos-netmiko.rst deleted file mode 100644 index b94b0129..00000000 --- a/docs/automation/vyos-netmiko.rst +++ /dev/null @@ -1,76 +0,0 @@ -: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. - -.. code-block:: 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 - -.. code-block:: 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-pyvyos.rst b/docs/automation/vyos-pyvyos.rst deleted file mode 100644 index cbd315e5..00000000 --- a/docs/automation/vyos-pyvyos.rst +++ /dev/null @@ -1,156 +0,0 @@ -:lastproofread: 2026-04-14 - -.. _vyos-pyvyos: - -###### -PyVyOS -###### - -PyVyOS is a Python library for configuring and managing VyOS devices through -their API. - -**Key resources:** - -- `Documentation `_: Provides - installation, configuration, and usage instructions. -- `GitHub repository `_: Hosts the - source code. -- `PyPI `_: Hosts distribution packages for - installation via the Python package installer (``pip``). - - -Installation ------------- - -To install PyVyOS via ``pip``, run: - -.. code-block:: bash - - pip install pyvyos - -Getting started ---------------- - -Import and disable warnings for verify=false -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - import urllib3 - urllib3.disable_warnings() - -Use API response class -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - @dataclass - class ApiResponse: - status: int - request: dict - result: dict - error: str - -Initialize a VyDevice object -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: 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 -^^^^^^^^^^^^^^^^^^^ - -.. code-block:: 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 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - response = device.retrieve_return_values(path=["interfaces", "dummy", "dum1", "address"]) - print(response.result) - -Configure, then show object -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - response = device.retrieve_show_config(path=[]) - if not response.error: - print(response.result) - -Configure, then delete object -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - response = device.configure_delete(path=["interfaces", "dummy", "dum1"]) - -Configure, then save -^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - response = device.config_file_save() - -Configure, then save file -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - response = device.config_file_save(file="/config/test300.config") - -Show object -^^^^^^^^^^^ - -.. code-block:: none - - response = device.show(path=["system", "image"]) - print(response.result) - -Generate object -^^^^^^^^^^^^^^^ - -.. code-block:: 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 -^^^^^^^^^^^^ - -.. code-block:: none - - response = device.reset(path=["conntrack-sync", "internal-cache"]) - if not response.error: - print(response.result) - -Configure, then load file -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - response = device.config_file_load(file="/config/test300.config") - - -.. _pyvyos: https://github.com/robertoberto/pyvyos 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]: +[salt]: https://docs.saltproject.io/en/latest/contents.html diff --git a/docs/automation/vyos-salt.rst b/docs/automation/vyos-salt.rst deleted file mode 100644 index 3a5b17d7..00000000 --- a/docs/automation/vyos-salt.rst +++ /dev/null @@ -1,232 +0,0 @@ -: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: - -.. code-block:: none - - set service salt-minion id 'r14' - set service salt-minion master '192.0.2.250' - -Check salt-keys on the salt master - -.. code-block:: none - - / # salt-key --list-all - Accepted Keys: - r11 - Denied Keys: - Unaccepted Keys: - r14 - Rejected Keys: - -Accept minion key - -.. code-block:: 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 - -.. code-block:: none - - / # salt '*' test.ping - r14: - True - r11: - True - -At this step we can get some op-mode information from VyOS nodes: - -.. code-block:: 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: - -.. code-block:: none - - / # cat /etc/salt/master - file_roots: - base: - - /srv/salt/states - - pillar_roots: - base: - - /srv/salt/pillars - -Structure of /srv/salt: - -.. code-block:: none - - / # tree /srv/salt/ - /srv/salt/ - |___ pillars - | |__ r11-proxy.sls - | |__ top.sls - |___ states - |__ commands.txt - -top.sls - -.. code-block:: none - - / # cat /srv/salt/pillars/top.sls - base: - r11-proxy: - - r11-proxy - - -r11-proxy.sls Includes parameters for connecting to salt-proxy minion - -.. code-block:: 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 - -.. code-block:: 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: - -.. code-block:: none - - / # salt r11-proxy test.ping - r11-proxy: - True - / # - -Examples -^^^^^^^^ - -Example of op-mode: - -.. stop_vyoslinter - -.. code-block:: 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 - / # - -.. start_vyoslinter - -Example of configuration: - -.. stop_vyoslinter - -.. code-block:: 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# - / # - -.. start_vyoslinter - -Example of configuration commands from the file -"/srv/salt/states/commands.txt" - -.. stop_vyoslinter - -.. code-block:: 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# - / # - -.. start_vyoslinter - -.. _salt: https://docs.saltproject.io/en/latest/contents.html -.. stop_vyoslinter -.. _netmiko: https://docs.saltproject.io/en/latest/ref/modules/all/salt.modules.netmiko_mod.html#module-salt.modules.netmiko_mod -.. start_vyoslinter \ No newline at end of file -- cgit v1.2.3