{"id":15341553,"url":"https://github.com/marcaurele/ansible-exoscale-privnet","last_synced_at":"2026-01-07T11:31:17.039Z","repository":{"id":147060961,"uuid":"95220497","full_name":"marcaurele/ansible-exoscale-privnet","owner":"marcaurele","description":"Deploy a DHCP server to configure VMs using their privnet","archived":false,"fork":false,"pushed_at":"2019-01-08T09:27:58.000Z","size":56,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-19T23:04:53.657Z","etag":null,"topics":["ansible","cloudstack","dhcp-server","exoscale","isc-dhcp","playbook"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcaurele.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-23T12:59:43.000Z","updated_at":"2020-04-26T02:29:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"38db97c5-5d74-4d18-aaaf-06f1beaa7c1e","html_url":"https://github.com/marcaurele/ansible-exoscale-privnet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcaurele%2Fansible-exoscale-privnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcaurele%2Fansible-exoscale-privnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcaurele%2Fansible-exoscale-privnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcaurele%2Fansible-exoscale-privnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcaurele","download_url":"https://codeload.github.com/marcaurele/ansible-exoscale-privnet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245901357,"owners_count":20691017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","cloudstack","dhcp-server","exoscale","isc-dhcp","playbook"],"created_at":"2024-10-01T10:40:31.344Z","updated_at":"2026-01-07T11:31:12.013Z","avatar_url":"https://github.com/marcaurele.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ansible playbook to deploy a DHCP server for private networking on Exoscale\n\nOn [Exoscale](https://www.exoscale.ch), you can attach a\n[private network](https://community.exoscale.ch/documentation/compute/privnet/)\nto your VMs, which comes unmanaged. To ease the communication between your\ninstances on this private link, let's setup a DHCP server answering requests on\nthe private interface for all your VMs using this second network. \n\nWe are going to use Ansible to ease the process of deploying one DHCP server\nand 3 sample virtual machines to validate the setup.\n\nIf you're not familiar with [Ansible](https://www.ansible.com), it's an open\nsource automation tool for your infrastructure as a code.\nThe only language you'll need is\n[YAML](https://docs.ansible.com/ansible/latest/YAMLSyntax.html) to write the\nconfiguration files.\n\n## Setup\n\nFirst you have to clone the repository:\n\n    $ git clone https://github.com/marcaurele/ansible-exoscale-privnet.git\n    $ cd ansible-exoscale-privnet\n\nCreate a new [virtual environment for Python](https://virtualenv.pypa.io):\n\n    # For python 2\n    $ virtualenv -p \u003clocation_of_python_2.7\u003e venv\n    # For python 3\n    $ python3 -m venv venv\n    # Activate the virtual environment\n    $ . ./venv/bin/activate\n\nInstall the requirements for the playbook\n([ansible](https://pypi.python.org/pypi/ansible) *(\u003e=2.4)*,\n[cs](https://pypi.python.org/pypi/cs),\n[sshpubkeys](https://pypi.python.org/pypi/sshpubkeys)):\n\n    $ pip install -r requirements.txt\n\nIn your shell you need to export those 3 variables, as per\n[cs documentation](https://github.com/exoscale/cs/):\n\n  - `export CLOUDSTACK_ENDPOINT=https://api.exoscale.ch/compute`\n  - `export CLOUDSTACK_KEY=\u003cyour-api-key\u003e`\n  - `export CLOUDSTACK_SECRET=\u003cyour-api-secret-key\u003e`\n\nOr if you're alread using a `.cloudstack.ini` file, you only need to export:\n\n  - `export CLOUDSTACK_REGION=\u003csection_name\u003e`\n\n*Your API key can be found at https://portal.exoscale.ch/account/profile/api.*\n\nNow you are all set to run the playbook. To verify the setup, from your\nterminal run:\n\n    $ cs listZones\n\nYou should get a JSON output of the current zones available on Exoscale.\n\n```json\n{\n  \"count\": 3, \n  \"zone\": [\n    {\n      \"allocationstate\": \"Enabled\", \n      \"dhcpprovider\": \"VirtualRouter\", \n      \"id\": \"1128bd56-b4d9-4ac6-a7b9-c715b187ce11\", \n      \"localstorageenabled\": true, \n      \"name\": \"ch-gva-2\", \n      \"networktype\": \"Basic\", \n      \"securitygroupsenabled\": true, \n      \"tags\": [], \n      \"zonetoken\": \"ccb0a60c-79c8-3230-ab8b-8bdbe8c45bb7\"\n    }, \n    {\n      \"allocationstate\": \"Enabled\", \n      \"dhcpprovider\": \"VirtualRouter\", \n      \"id\": \"91e5e9e4-c9ed-4b76-bee4-427004b3baf9\", \n      \"localstorageenabled\": true, \n      \"name\": \"ch-dk-2\", \n      \"networktype\": \"Basic\", \n      \"securitygroupsenabled\": true, \n      \"tags\": [], \n      \"zonetoken\": \"fe63f9cb-ff75-31d3-8c46-3631f7fcd533\"\n    }, \n    {\n      \"allocationstate\": \"Enabled\", \n      \"dhcpprovider\": \"VirtualRouter\", \n      \"id\": \"4da1b188-dcd6-4ff5-b7fd-bde984055548\", \n      \"localstorageenabled\": true, \n      \"name\": \"at-vie-1\", \n      \"networktype\": \"Basic\", \n      \"securitygroupsenabled\": true, \n      \"tags\": [], \n      \"zonetoken\": \"26d84c22-f66d-377e-93ab-987ef477cab3\"\n    }\n  ]\n}\n```\n\n## Quick run\n\nI will discuss the playbook setup afterwards. If you're eager to run the playbook\nand see the result, run:\n\n    $ ansible-playbook deploy-privnet-dhcp.yml\n\nIf you wish to deploy those virtual machines in another zone/region, for example\n`de-fra-1` you can overwrite the `zone` variable on the command line:\n\n    $ ansible-playbook deploy-privnet-dhcp.yml -e \"zone=de-fra-1\"\n\n## Playbook roles\n\n### Common\n\nThis role creates an SSH key \"privnet\" to be used on all virtual machines\ndeployed by this playbook to authenticate, instead of using a password. This\nnew key generated by CloudStack is saved under `~/.ssh/id_rsa_privnet` on your\nlocal machine.\n\n### Infra\n\nThis role provisions the VMs on Exoscale, as well as a new SSH key, security\ngroups, and adds the private networking interface to each of them. What you\nmight not see often is the `user_data` provided for the VM deployment in\n[`create_vm.yml`](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/infra/tasks/create_vm.yml)\nwhich is used to let cloud-init manage the hostname nicely as done when starting\na VM from Exsocale portal:\n\n```yaml\n    user_data: |\n      #cloud-config\n      manage_etc_hosts: true\n      fqdn: {{ zone }}-{{ dhcp_name }}\n```\n\nThe private networking interface is added through\n[`create_private_nic.yml`](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/infra/tasks/create_private_nic.yml)\nusing Ansible\n[`cs_instance_nic`](http://docs.ansible.com/ansible/latest/cs_instance_nic_module.html)\nmodule:\n\n```yaml\n- name: \"dhcp server : add privnet nic\"\n  local_action:\n    module: cs_instance_nic\n    network: \"{{ private_network }}\"\n    vm: \"{{ zone }}-{{ dhcp_name }}\"\n    zone: \"{{ zone }}\"\n```\n\nIt can also be directly attached to the VM on the deployment step in\n[`create_vm.yml`](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/infra/tasks/create_vm.yml)\nwith the `networks` attribute:\n\n```yaml\n- name: \"dhcp server : create\"\n  local_action:\n    module: cs_instance\n    name: \"{{ zone }}-{{ dhcp_name }}\"\n    template: \"{{ template }}\"\n    root_disk_size: \"{{ root_disk_size }}\"\n    service_offering: \"{{ instance_type }}\"\n    ssh_key: \"{{ ssh_key }}\"\n    security_groups: [ '{{ security_group_name }}' ]\n    networks:\n      - \"{{ private_network }}\"\n    user_data: |\n      #cloud-config\n      manage_etc_hosts: true\n      fqdn: {{ zone }}-{{ dhcp_name }}\n    zone: \"{{ zone }}\"\n```\nThis instructs Ansible to attach a new NIC to VM `{{ dhcp_name }}` in the\n`{{zone }}` zone on the `privNetForBasicZone` network. A new `eth1` interface\ncomes up on your Linux Ubuntu box for the DHCP server to bind to.\n\n### DHCP/server\n\nThis role configures the DHCP server. We configure a static IP address for\nits privnet interface `eth1` in\n[`configure_private_nic.yml`](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/dhcp/server/tasks/configure_private_nic.yml)\nand activate the interface:\n\n```yaml\n- name: upload network interface configuration\n  template:\n    src: privnet.cfg.j2\n    dest: /etc/network/interfaces.d/01-privnet.cfg\n    force: yes\n  register: privnet_cfg\n\n- name: enable privnet interface\n  shell: \"ifup eth1\"\n  when: privnet_cfg.changed\n```\n\nIn [`setup_dhcp_server.yml`](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/dhcp/server/tasks/setup_dhcp_server.yml)\nwe install ISC DHCP server with a basic configuration to serve IP addresses\nin the range `10.11.12.2` - `10.11.12.30`:\n\n```yaml\n- name: install packages\n  apt:\n    name:\n      - isc-dhcp-server\n    state: present\n\n- name: set listening interfaces\n  lineinfile:\n    path: /etc/default/isc-dhcp-server\n    line: \"INTERFACES=\\\"eth1\\\"\"\n    regexp: \"^INTERFACES\"\n  notify: restart dhcp server\n\n- name: set configuration\n  template:\n    dest: /etc/dhcp/dhcpd.conf\n    src: dhcpd.conf.j2\n    owner: root\n    group: root\n  notify: restart dhcp server\n```\n\n### DHCP/client\n\nThis role is the simplest through\n[`configure_private_nic.yml`](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/dhcp/client/tasks/configure_private_nic.yml): it uploads the\n[network interface configuration file](https://github.com/marcaurele/ansible-exoscale-privnet/blob/master/roles/dhcp/client/files/privnet.cfg)\nfor the privnet and enables it:\n\n```yaml\n- name: copy network interface configuration\n  copy:\n    src: privnet.cfg\n    dest: /etc/network/interfaces.d/01-privnet.cfg\n    force: yes\n  register: privnet_cfg\n\n- name: enable privnet interface\n  shell: \"ifup eth1\"\n  when: privnet_cfg.changed\n```\n\n## Going further\n\nThis setup could be extended to also configure the DHCP server with static\nDHCP mappings for your VMs based on their private interface MAC address.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcaurele%2Fansible-exoscale-privnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcaurele%2Fansible-exoscale-privnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcaurele%2Fansible-exoscale-privnet/lists"}