Add terraform files
This commit is contained in:
commit
ad77d0317a
27 changed files with 524 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.vagrant
|
28
README.md
Normal file
28
README.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
|
||||
## Web SSH terminal
|
||||
|
||||
* sshwifty (go)
|
||||
* webssh (python)
|
||||
https://hub.docker.com/r/snsyzb/webssh
|
||||
* Guacamole
|
||||
* Bastillion
|
||||
https://github.com/bastillion-io/Bastillion
|
||||
* SSHy
|
||||
https://github.com/stuicey/SSHy
|
||||
* ssh-web-console
|
||||
https://github.com/genshen/ssh-web-console
|
||||
* webssh2
|
||||
https://github.com/billchurch/webssh2
|
||||
* webssh
|
||||
https://github.com/huashengdun/webssh
|
||||
* https://github.com/gravitational/teleport
|
||||
* https://github.com/roke22/PHP-SSH2-Web-Client
|
||||
* https://www.shellvault.io/
|
||||
* https://github.com/huashengdun/webssh
|
||||
* https://github.com/xtermjs/xterm.js/
|
||||
|
||||
## Terraform + Ansible
|
||||
|
||||
https://www.digitalocean.com/community/tutorials/how-to-use-ansible-with-terraform-for-configuration-management
|
||||
|
52
Vagrantfile
vendored
Normal file
52
Vagrantfile
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby sw=2 st=2 et :
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
SERVERS_COUNT=3
|
||||
|
||||
Vagrant.configure('2') do |config|
|
||||
# Common settings for virtual machines
|
||||
config.vm.box = 'debian/bullseye64'
|
||||
config.vm.box_check_update = false
|
||||
|
||||
##
|
||||
## gateway: Guacamole proxy + entrypoint
|
||||
##
|
||||
config.vm.define 'gateway' do |machine|
|
||||
machine.vm.hostname = 'gateway'
|
||||
machine.vm.network 'private_network', ip: '192.168.50.250'
|
||||
machine.vm.network 'forwarded_port', guest: 80, host: 1080
|
||||
machine.vm.network 'forwarded_port', guest: 8080, host: 8080
|
||||
machine.vm.provider 'virtualbox' do |vb|
|
||||
vb.memory = '4000'
|
||||
vb.gui = false
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
## serverX : host servers with mongo, etc
|
||||
##
|
||||
server_ip = ->(index) { "192.168.50.#{10 + index * 10}" }
|
||||
SERVERS_COUNT.times do |index|
|
||||
config.vm.define "server#{index}" do |machine|
|
||||
machine.vm.hostname = "server#{index}"
|
||||
machine.vm.network 'private_network', ip: server_ip.call(index)
|
||||
machine.vm.provider 'virtualbox' do |vb|
|
||||
vb.memory = '3000'
|
||||
vb.gui = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
config.vm.provision 'ansible' do |ansible|
|
||||
ansible.playbook = 'ansible/playbook.yml'
|
||||
# ansible.verbose = true
|
||||
ansible.config_file = 'ansible/ansible.cfg'
|
||||
ansible.groups = {
|
||||
'app_sshwifty' => ['gateway'],
|
||||
'app_mongo' => SERVERS_COUNT.times.map { |i| "server#{i}" },
|
||||
'all_groups:children' => ['app_mongo']
|
||||
}
|
||||
end
|
||||
end
|
3
ansible/ansible.cfg
Normal file
3
ansible/ansible.cfg
Normal file
|
@ -0,0 +1,3 @@
|
|||
[ssh_connection]
|
||||
ssh_args=-o ControlMaster=auto -o ControlPersist=7200s
|
||||
pipelining=True
|
2
ansible/group_vars/all/vars.yml
Normal file
2
ansible/group_vars/all/vars.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
sshwifty_shared_key: admin
|
1
ansible/inventories/terraform
Symbolic link
1
ansible/inventories/terraform
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../terraform/outputs/inventory
|
1
ansible/inventories/vagrant
Symbolic link
1
ansible/inventories/vagrant
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory
|
26
ansible/playbook.yml
Normal file
26
ansible/playbook.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
- hosts: app_sshwifty
|
||||
become: true
|
||||
tasks:
|
||||
- include_tasks: tasks/setup_base.yml
|
||||
- include_tasks: tasks/setup_docker.yml
|
||||
- include_tasks: tasks/setup_sshwifty.yml
|
||||
- include_tasks: tasks/setup_caddy.yml
|
||||
- include_tasks: tasks/setup_sshaccess.yml
|
||||
|
||||
roles:
|
||||
- role: caddy_ansible.caddy_ansible
|
||||
caddy_setcap: 'yes'
|
||||
caddy_systemd_network_dependency: false
|
||||
caddy_systemd_capabilities_enabled: true
|
||||
caddy_config: "{{ lookup('template', 'templates/Caddyfile.j2') }}"
|
||||
|
||||
- hosts: app_mongo
|
||||
become: true
|
||||
tasks:
|
||||
- include_tasks: tasks/setup_base.yml
|
||||
- include_tasks: tasks/setup_docker.yml
|
||||
- include_tasks: tasks/setup_mongo.yml
|
||||
- include_tasks: tasks/setup_sshaccess.yml
|
||||
|
||||
#
|
6
ansible/requirements.yml
Normal file
6
ansible/requirements.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
roles:
|
||||
- name: caddy_ansible.caddy_ansible
|
||||
src: https://github.com/caddy-ansible/caddy-ansible
|
||||
type: git
|
||||
version: master
|
20
ansible/tasks/setup_base.yml
Normal file
20
ansible/tasks/setup_base.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
|
||||
- name: Sync time
|
||||
ansible.builtin.shell:
|
||||
cmd: ntpdate 0.debian.pool.ntp.org
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Install required system packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- vim
|
||||
- ntpdate
|
||||
state: latest
|
||||
update_cache: true
|
||||
|
||||
- name: Sync time
|
||||
ansible.builtin.command:
|
||||
cmd: ntpdate 0.debian.pool.ntp.org
|
||||
|
||||
#
|
0
ansible/tasks/setup_caddy.yml
Normal file
0
ansible/tasks/setup_caddy.yml
Normal file
59
ansible/tasks/setup_docker.yml
Normal file
59
ansible/tasks/setup_docker.yml
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
- name: Install required system packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- software-properties-common
|
||||
- python3-pip
|
||||
- virtualenv
|
||||
- python3-setuptools
|
||||
state: latest
|
||||
update_cache: true
|
||||
|
||||
- name: Create keyring directory
|
||||
ansible.builtin.file:
|
||||
dest: /etc/apt/keyrings
|
||||
state: directory
|
||||
|
||||
- name: Add signing key
|
||||
ansible.builtin.get_url:
|
||||
url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg"
|
||||
dest: /etc/apt/keyrings/docker.gpg_armored
|
||||
|
||||
- name: De-Armor Docker GPG key
|
||||
shell: >
|
||||
gpg --dearmor
|
||||
< /etc/apt/keyrings/docker.gpg_armored
|
||||
> /etc/apt/keyrings/docker.gpg
|
||||
# no_log: true
|
||||
args:
|
||||
creates: /etc/apt/keyrings/docker.gpg
|
||||
|
||||
- name: Get DEB architecture
|
||||
shell: dpkg --print-architecture
|
||||
register: deb_architecture
|
||||
|
||||
- name: Add repository into sources list
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "deb [arch={{ deb_architecture.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
|
||||
state: present
|
||||
filename: docker
|
||||
|
||||
- name: Install Docker
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-compose-plugin
|
||||
- docker-compose
|
||||
state: latest
|
||||
update_cache: true
|
||||
|
||||
- name: Install Docker Module for Python
|
||||
pip:
|
||||
name: docker
|
||||
|
||||
#
|
0
ansible/tasks/setup_mongo.yml
Normal file
0
ansible/tasks/setup_mongo.yml
Normal file
12
ansible/tasks/setup_sshaccess.yml
Normal file
12
ansible/tasks/setup_sshaccess.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
# Password needs to be encrypted. Use the following command to change password
|
||||
# python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'
|
||||
- name: Add the user 'debian'
|
||||
ansible.builtin.user:
|
||||
name: debian
|
||||
password: '$6$7SKND.wc64QSchcm$eGS36vIXypLHSd.PQM0gIq6ILx9QiRQxWNej3Gb32sKk2MuLrRlceXCJmidYATNZeJTbBXNf3c5qTmm7BB.EA1'
|
||||
shell: /bin/bash
|
||||
state: present
|
||||
update_password: always
|
||||
|
||||
#
|
30
ansible/tasks/setup_sshwifty.yml
Normal file
30
ansible/tasks/setup_sshwifty.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
- name: Install required system packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- vim
|
||||
state: latest
|
||||
update_cache: true
|
||||
|
||||
- name: Deploy SSHwifty configuration
|
||||
template:
|
||||
src: templates/sshwifty.conf.j2
|
||||
dest: /etc/sshwifty.conf
|
||||
|
||||
- name: Create SSHwifty directory
|
||||
file:
|
||||
path: /var/lib/sshwifty
|
||||
state: directory
|
||||
|
||||
- name: Deploy SSHwifty configuration
|
||||
template:
|
||||
src: templates/docker-compose.yml.j2
|
||||
dest: /var/lib/sshwifty/docker-compose.yml
|
||||
|
||||
- name: Run SSHwifty
|
||||
community.docker.docker_compose:
|
||||
project_src: /var/lib/sshwifty
|
||||
recreate: smart
|
||||
state: present
|
||||
|
||||
#
|
11
ansible/templates/Caddyfile.j2
Normal file
11
ansible/templates/Caddyfile.j2
Normal file
|
@ -0,0 +1,11 @@
|
|||
http://0.0.0.0:80 {
|
||||
log
|
||||
|
||||
reverse_proxy http://localhost:8080 {
|
||||
header_up Host {http.request.host}
|
||||
header_up X-Real-IP {http.request.remote.host}
|
||||
header_up X-Forwarded-For {http.request.remote.host}
|
||||
header_up X-Forwarded-Port {http.request.port}
|
||||
header_up X-Forwarded-Proto {http.request.scheme}
|
||||
}
|
||||
}
|
21
ansible/templates/docker-compose.yml.j2
Normal file
21
ansible/templates/docker-compose.yml.j2
Normal file
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# vim: set ts=2 sw=2 et ft=yaml :
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
sshwifty:
|
||||
image: niruix/sshwifty:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 8080:8182
|
||||
environment:
|
||||
SSHWIFTY_SHAREDKEY: admin
|
||||
SSHWIFTY_CONFIG: /etc/sshwifty.conf
|
||||
volumes:
|
||||
- /etc/sshwifty.conf:/etc/sshwifty.conf
|
||||
|
||||
volumes: {}
|
||||
|
||||
networks: {}
|
||||
|
||||
#
|
48
ansible/templates/sshwifty.conf.j2
Normal file
48
ansible/templates/sshwifty.conf.j2
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
{# "HostName": "localhost", #}
|
||||
"SharedKey": "{{ sshwifty_shared_key }}",
|
||||
"DialTimeout": 10,
|
||||
"Servers": [
|
||||
{
|
||||
"ListenInterface": "0.0.0.0",
|
||||
"ListenPort": 8182,
|
||||
"InitialTimeout": 3,
|
||||
"ReadTimeout": 60,
|
||||
"WriteTimeout": 60,
|
||||
"HeartbeatTimeout": 20,
|
||||
"ReadDelay": 10,
|
||||
"WriteDelay": 10 {# , #}
|
||||
{# "TLSCertificateFile": "", #}
|
||||
{# "TLSCertificateKeyFile": "" #}
|
||||
}
|
||||
],
|
||||
"Presets": [
|
||||
{
|
||||
"Title": "Gateway",
|
||||
"Type": "SSH",
|
||||
"Host": "{{ansible_facts.all_ipv4_addresses | ansible.netcommon.ipaddr('192.168.50.0/24') | first }}:22",
|
||||
"Meta": {
|
||||
"User": "debian",
|
||||
"Encoding": "utf-8",
|
||||
"Password": "debian",
|
||||
"Authentication": "Password" {# , #}
|
||||
{# "Private Key": "file:///home/user/.ssh/private_key", #}
|
||||
{# "Fingerprint": "SHA256:bgO...." #}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Title": "SDF.org Unix Shell",
|
||||
"Type": "SSH",
|
||||
"Host": "sdf.org:22",
|
||||
"Meta": {
|
||||
"User": "debian",
|
||||
"Encoding": "utf-8",
|
||||
"Password": "debian",
|
||||
"Authentication": "Password" {# , #}
|
||||
{# "Private Key": "file:///home/user/.ssh/private_key", #}
|
||||
{# "Fingerprint": "SHA256:bgO...." #}
|
||||
}
|
||||
}
|
||||
],
|
||||
"OnlyAllowPresetRemotes": true
|
||||
}
|
4
terraform/.gitignore
vendored
Normal file
4
terraform/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
.terraform
|
||||
.terraform.lock.hcl
|
||||
outputs/*
|
||||
*.tfstate*
|
18
terraform/domains.tf
Normal file
18
terraform/domains.tf
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
resource "gandi_livedns_record" "gateways_exploreko_org" {
|
||||
count = var.mongo_groups_count
|
||||
zone = var.domain_name
|
||||
name = "gateway${count.index}.teaching"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
values = [openstack_compute_instance_v2.mongo_gateway[count.index].access_ip_v4]
|
||||
}
|
||||
|
||||
resource "gandi_livedns_record" "mongos_exploreko_org" {
|
||||
count = var.mongo_replicas_count * var.mongo_groups_count
|
||||
zone = var.domain_name
|
||||
name = "mongo${count.index}.teaching"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
values = [openstack_compute_instance_v2.mongo_servers[count.index].access_ip_v4]
|
||||
}
|
68
terraform/instances.tf
Normal file
68
terraform/instances.tf
Normal file
|
@ -0,0 +1,68 @@
|
|||
|
||||
# Création d'une ressource de paire de clés SSH
|
||||
resource "openstack_compute_keypair_v2" "provision_keypair" {
|
||||
provider = openstack.ovh
|
||||
name = "provision_keypair"
|
||||
public_key = file(var.ssh_public_key)
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "mongo_gateway" {
|
||||
count = var.mongo_groups_count
|
||||
name = "prod-gateway${count.index}" # Nom de l'instance
|
||||
provider = openstack.ovh # Nom du fournisseur
|
||||
image_name = "Debian 11" # Nom de l'image
|
||||
flavor_name = "s1-2" # Nom du type d'instance
|
||||
# flavor_name = "s1-8" # Nom du type d'instance
|
||||
# flavor_name = "d2-8" # Nom du type d'instance
|
||||
# Nom de la ressource openstack_compute_keypair_v2 nommée test_keypair
|
||||
key_pair = openstack_compute_keypair_v2.provision_keypair.name
|
||||
|
||||
metadata = {
|
||||
ansible-group = "gateways"
|
||||
mongo-group-id = count.index
|
||||
}
|
||||
|
||||
# Ajoute le composant réseau pour atteindre votre instance
|
||||
network {
|
||||
name = "Ext-Net"
|
||||
}
|
||||
|
||||
# provisioner "local-exec" {
|
||||
# command = "ansible-playbook -i inventories/terraform --private-key ${var.ssh_private_key} -e 'pub_key=${var.ssh_public_key}' playbook.yml --limit ${self.name}"
|
||||
# working_dir = "../ansible"
|
||||
# environment = {
|
||||
# ANSIBLE_HOST_KEY_CHECKING = "False"
|
||||
# }
|
||||
|
||||
# }
|
||||
}
|
||||
|
||||
# Création d'une instance
|
||||
resource "openstack_compute_instance_v2" "mongo_servers" {
|
||||
count = var.mongo_replicas_count * var.mongo_groups_count
|
||||
name = "prod-server${count.index}" # Nom de l'instance
|
||||
provider = openstack.ovh # Nom du fournisseur
|
||||
image_name = "Debian 11" # Nom de l'image
|
||||
flavor_name = "s1-2" # Nom du type d'instance
|
||||
# flavor_name = "s1-8" # Nom du type d'instance
|
||||
# flavor_name = "d2-8" # Nom du type d'instance
|
||||
# Nom de la ressource openstack_compute_keypair_v2 nommée test_keypair
|
||||
key_pair = openstack_compute_keypair_v2.provision_keypair.name
|
||||
|
||||
metadata = {
|
||||
ansible-group = "mongos"
|
||||
mongo-group-id = floor(count.index / var.mongo_replicas_count)
|
||||
mongo-group-index = count.index % var.mongo_replicas_count
|
||||
}
|
||||
# Ajoute le composant réseau pour atteindre votre instance
|
||||
network {
|
||||
name = "Ext-Net"
|
||||
}
|
||||
|
||||
# provisioner "local-exec" {
|
||||
# command = "cd ../ansible && ansible-playbook -i inventories/terraform --private-key ${var.ssh_private_key} -e 'pub_key=${var.ssh_public_key}' playbook.yml --limit ${self.name}"
|
||||
# environment = {
|
||||
# ANSIBLE_HOST_KEY_CHECKING = "False"
|
||||
# }
|
||||
# }
|
||||
}
|
12
terraform/output.tf
Normal file
12
terraform/output.tf
Normal file
|
@ -0,0 +1,12 @@
|
|||
resource "local_file" "ansible_inventory" {
|
||||
content = templatefile("templates/inventory.tmpl",
|
||||
{
|
||||
mongo_gateways = openstack_compute_instance_v2.mongo_gateway.*
|
||||
mongo_servers = openstack_compute_instance_v2.mongo_servers.*
|
||||
mongo_groups_count = var.mongo_groups_count
|
||||
mongo_replicas_count = var.mongo_replicas_count
|
||||
}
|
||||
)
|
||||
filename = "outputs/inventory"
|
||||
file_permission = "0644"
|
||||
}
|
0
terraform/outputs/.empty
Normal file
0
terraform/outputs/.empty
Normal file
37
terraform/provider.tf
Normal file
37
terraform/provider.tf
Normal file
|
@ -0,0 +1,37 @@
|
|||
terraform {
|
||||
required_version = ">= 0.14.0" # Prend en compte les versions de terraform à partir de la 0.14.0
|
||||
required_providers {
|
||||
openstack = {
|
||||
source = "terraform-provider-openstack/openstack"
|
||||
version = "~> 1.42.0"
|
||||
}
|
||||
|
||||
ovh = {
|
||||
source = "ovh/ovh"
|
||||
version = ">= 0.13.0"
|
||||
}
|
||||
|
||||
gandi = {
|
||||
source = "go-gandi/gandi"
|
||||
version = "~> 2.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "gandi" {
|
||||
key = "${var.gandi_key}"
|
||||
}
|
||||
|
||||
provider "openstack" {
|
||||
auth_url = "https://auth.cloud.ovh.net/v3/" # URL d'authentification
|
||||
domain_name = "default" # Toujours à "default" pour OVHcloud
|
||||
alias = "ovh" # Un alias
|
||||
|
||||
region = "GRA5"
|
||||
}
|
||||
|
||||
provider "ovh" {
|
||||
endpoint = "ovh-eu" # Provider entry point
|
||||
alias = "ovh" # Provider alias
|
||||
}
|
||||
|
4
terraform/provisionners.tf
Normal file
4
terraform/provisionners.tf
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
# provisioner "local-exec" {
|
||||
# command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i outputs/inventory --private-key ${var.private_key} -e 'pub_key=${var.pub_key}' playbook.yml"
|
||||
# }
|
40
terraform/templates/inventory.tmpl
Normal file
40
terraform/templates/inventory.tmpl
Normal file
|
@ -0,0 +1,40 @@
|
|||
%{ for index, instance in mongo_gateways ~}
|
||||
${ instance.name } ansible_user=debian ansible_host=${instance.network[0].fixed_ip_v4}
|
||||
%{ endfor ~}
|
||||
%{ for index, instance in mongo_servers ~}
|
||||
${ instance.name } ansible_user=debian ansible_host=${instance.network[0].fixed_ip_v4}
|
||||
%{ endfor ~}
|
||||
|
||||
[stage_development]
|
||||
|
||||
[stage_testing]
|
||||
|
||||
[stage_production]
|
||||
%{ for index, instance in mongo_gateways ~}
|
||||
${ instance.name }
|
||||
%{ endfor ~}
|
||||
%{ for index, instance in mongo_servers ~}
|
||||
${ instance.name }
|
||||
%{ endfor ~}
|
||||
|
||||
[role_gateway]
|
||||
%{ for index, instance in mongo_gateways ~}
|
||||
${ instance.name }
|
||||
%{ endfor ~}
|
||||
|
||||
[role_mongo]
|
||||
%{ for index, instance in mongo_servers ~}
|
||||
${ instance.name }
|
||||
%{ endfor ~}
|
||||
|
||||
[all_groups:children]
|
||||
role_gateway
|
||||
role_mongo
|
||||
stage_development
|
||||
stage_testing
|
||||
stage_production
|
||||
|
||||
[all:vars]
|
||||
mongo_groups_count = ${ mongo_groups_count }
|
||||
mongo_replicas_count = ${ mongo_replicas_count }
|
||||
|
20
terraform/variables.tf
Normal file
20
terraform/variables.tf
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
variable "mongo_groups_count" {
|
||||
default = "1"
|
||||
description = "How many replicas per mongo"
|
||||
}
|
||||
|
||||
variable "mongo_replicas_count" {
|
||||
default = "2"
|
||||
description = "How many replicas per mongo group"
|
||||
}
|
||||
|
||||
variable "ssh_private_key" {}
|
||||
|
||||
variable "ssh_public_key" {}
|
||||
|
||||
variable "gandi_key" {}
|
||||
|
||||
variable "domain_name" {}
|
||||
|
||||
|
Loading…
Reference in a new issue