I am a newbie to Ansible. I have managed to write playbooks that set up Apache, Tomcat and others, all on localhost. I am now trying to move this to other servers to test the playbooks.
I have done the following:
1. Added a section [webservers] in /etc/ansible/hosts and put the public IP for that instance there.
2. I invoked ansible-playbook like so:
ANSIBLE_KEEP_REMOTE_FILES=1 ansible-playbook -vvvv -s serverSetup.yml
My questions:
1. Where do I store the public SSH key for the target server?
2. How do I specify which public key to use?
There are a number of other ways it is possible: ansible.cfg, set_fact, environment vars.
ansible.cfg
You can have an Ansible Config file within your project folder which can state which key to use, using the following:
private_key_file = /path/to/key/key1.pem
You can see an example of an ansible.cfg file here: https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg
set_fact
You can add the key using the set_fact module within your playbook, this can be hardcoded as below or templated:
- name: Use particular private key for this playbook
set_fact: ansible_private_ssh_key=/path/to/key/key1.pem
http://docs.ansible.com/ansible/set_fact_module.html
environment vars
See this stackoverflow post's answer for more information:
how to define ssh private key for servers fetched by dynamic inventory in files
Where do I store the public SSH key for the target server?
Wherever makes sense. Since these are keys that I may use to directly connect to the machine, I usually store them in ~/.ssh/ with my other private keys. For projects where I'm working on multiple computers or with other users, I store them in Ansible Vault and have a playbook that extracts them and stores them on the local machine.
How do I specify which public key to use?
group_vars is a good place to specify ansible_private_ssh_key.
ansible uses a user to connect to the target machine.
So if your user is ubuntu (-u ubuntu in ansible flags) the key will be ~ubuntu/.ssh/authorized_keys on target machine).
And from the ansible --help command you have
--private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE use this file to authenticate the connection
Related
I'm trying to merge from Salt to Ansible.
What is Ansible equivalent to Salt's top file?
In Ansible you build inventory, put your hosts into groups and then you run playbooks, that will bring your hosts to the desired state (e.g. ensure that software is installed, files are present, etc) on those groups. Note that there is no agent software with Ansible, it uses SSH to do things on remote hosts,
I am trying to set up a passwordless login (copy id_rsa.pub from server A to server B) from server A to server B while running a playbook from controller machine C. The playbook:
cannot have an inventory file. The host IP will be passed from the command line to the playbook as:
ansible-playbook -i , test.yml
Server A DNS name or IP address will be hardcoded in my playbook.
I have tried:
Using fetch module, I tried fetching ssh key(id_rsa_serverA.pub) from server A to controller C and then using copy module to copy the ssh_key(id_rsa_ServerA) to Server B. While it did the work, it does not adhere to the project guidelines I am working on.
Tried 'synchronize' module with ansible 2.5. Fails.
I did a similar thing,
i use user module on serverA with option generate_ssh_key: yes and user register: user_pubkey
then i use authorized_key module with delegate_to serverB, setting the key to "{{ user_pubkey.stdout }}" for the neededuser:`
you can pass #IP of serverB as extra_vers at launch time : ansible-playbook ... ... ... -e serverB=serverB_#IP
hope this helps
cheers
I have a inventory within the hosts file called [WEB], it consists of the servers below.
[WEB]
WEB01
WEB02
WEB03
When I declare hosts: WEB, it will iterate through each server and run locally on that respective server to do what it needs.
How can I take the same inventory but run what I want to do on the local Ansible server when running ansible-playbook FILE.YML? For example, I want to run a URI command that has the web server name as a parameter but as said, run it on the local Ansible server to POST to a external website. This doesn't need to run on the web servers themselves but I want to take the webserver names (WEB01, WEB02, WEB03) and run the URI module to post to a site.
Thanks!
You can loop through the host name vars using with items and delegate that to local host .
OR
If you don't want to perform any action on the hosts in the web group then you can define that in a variable in the inventory then apply with items. specify hosts as hosts: localhost
The real scenario, want to get a resource id of sqs in AWS, which will be returned after the execution of a playbook. So, using this variable in files to configure the application.
Persisting variables from one playbook to another
checking out the documentation, modules like set_fact and register have scope only for that specific host. There are many purpose of using the variables from one host to another.
Alternatives I can think of:
using Command module and echoing the variables to a file. Later, using the variable file using vars section or include.
Setting the env variables and then accessing it but this will be difficult.
So what is the solution?
If you're gathering facts, you can access hostvars via the normal jinja2 + variable lookup:
e.g.
- hosts: serverA.example.org
gather_facts: True
...
tasks:
- set_fact:
taco_tuesday: False
and then, if this has run, on another host:
- hosts: serverB.example.org
...
tasks:
- debug: var="{{ hostvars['serverA.example.org']['ansible_memtotal_mb'] }}"
- debug: var="{{ hostvars['serverA.example.org']['taco_tuesday'] }}"
Keep in mind that if you have multiple Ansible control machines (where you call ansible and ansible-playbook from), you should take advantage of the fact that Ansible can store its facts/variables in a cache (currently Redis and json), that way the control machines are less likely to have different hostvars. With this, you could set your control machines to use a file in a shared folder (which has its risks -- what if two control machines are running on the same host at the same time?), or set/get facts from a Redis server.
For my uses of Amazon data, I prefer to just fetch the resource each time using a tag/metadata lookup. I wrote an Ansible plugin that allows me to do this a little more easily as I prefer this to thinking about hostvars and run ordering (but your mileage may vary).
You can pass variables On The Command Line: http://docs.ansible.com/ansible/playbooks_variables.html#passing-variables-on-the-command-line
ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
You can use local connection to run playbook = get variable and apply it to another playbook:
- hosts: 127.0.0.1
connection: local
- shell: ansible-playbook -i ...
register: sqs_id
- shell: ansible-playbook -i ... -e "sqs_id={{sqs_id.stdout}}"
Also delegation might be useful in this scenario:
http://docs.ansible.com/ansible/playbooks_delegation.html#delegation
Also you can store output in the local file and use (http://docs.ansible.com/ansible/playbooks_delegation.html#delegation):
- name: take a sqs id
local_action: command cat ~/sqs_id
PS:
I don't understand why you can't write complex playbook where will be included many roles that will share variables?
You can write "common" variables to a host_vars or group_vars this way all the servers has access to it.
Another way may be to create a custom ansible module/lookup plugin to hide all the boilerplate code and get an easy and flexible access to the variables you need.
I had a similar issue with azure DevOps pipelines.
I created VM:s with terraform, ssh-keys and windows username/password was generated by terraform and stored it in a KeyVault.
So I then needed to query KeyVault before running Ansible on all created VM:s. I ended up using Azure python SDK to get all secrets. I also generate an inventory file and a host_vars folder with a file for each VM.
The actual play-book is now very basic and does the job perfectly. All variables for terraform and ansible is in a json file. And the python script is less than 30 lines.
I'm new to configuration management tool.
I want to use Ansible.
I'd like to set proxy to several GNU/Linux Debian (in fact several Raspbian).
I'd like to append
export http_proxy=http://cache.domain.com:3128
to /home/pi/.bashrc
I also want to append
Acquire::http::Proxy "http://cache.domain.com:3128";
to /etc/apt.conf
I want to set DNS to IP X1.X2.X3.X4 creating a
/etc/resol.conf file with
nameserver X1.X2.X3.X4
What playbook file should I write ? How should I apply this playbook to my servers ?
Start by learning a bit about Ansible basics and familiarize yourself with playbooks. Basically you ensure you can SSH in to your Raspian machines (using keys) and that the user Ansible invokes on these machines can run sudo. (That's the hard bit.)
The easy bit is creating the playbook for the tasks at hand, and there are plenty of pointers to example playbooks in the documentation.
If you really want to add a line to a file or two, use the lineinfile module, although I strongly recommend you create templates for the files you want to push to your machines and use those with the template module. (lineinfile can get quite messy.)
I second jpmens. This is a very basic problem in Ansible, and a very good way to get started using the docs, tutorials and example playbooks.
However, if you're stuck or in a hurry, you can solve this like this (everything takes place on the "ansible master") :
Create a roles structure like this :
cd your_playbooks_directory
mkdir -p roles/pi/{templates,tasks,vars}
Now create roles/pi/tasks/main.yml :
- name: Adds resolv.conf
template: src=resolv.conf.j2 dest=/etc/resolv.conf mode=0644
- name: Adds proxy env setting to pi user
lineinfile: dest=~pi/.bashrc regexp="^export http_proxy" insertafter=EOF line="export http_proxy={{ http_proxy }}"
Then roles/pi/templates/resolv.conf.j2 :
nameserver {{ dns_server }}
then roles/pi/vars/main.yml :
dns_server: 8.8.8.8
http_proxy: http://cache.domain.com:3128
Now make a top-level playbook to apply roles, at your playbook root, and call it site.yml :
- hosts : raspberries
roles:
- { role: pi }
You can apply your playbook using :
ansible-playbook site.yml
assuming your machines are in the raspberries group.
Good luck.