Ansible ad-hoc command with direct host specified - no hosts matched - linux

I am running a 16.04 Ubuntu desktop machine using VirtualBox. This VM has Ansible 2.4.0 installed. I am trying to run an ad-hoc ansible command just to prove it works (I am doing an online course). To simulate a small server farm, I use lxc (linux containters) and have three of them running:
root#tomasz-VirtualBox:/home/tomasz/ansible# lxc-ls --fancy
NAME STATE AUTOSTART GROUPS IPV4 IPV6
db1 RUNNING 0 - 10.0.3.248 -
web1 RUNNING 0 - 10.0.3.110 -
web2 RUNNING 0 - 10.0.3.226 -
I can SSH to any of these servers, however when I try to run a one-off ansible command, for example:
root#tomasz-VirtualBox:/home/tomasz/ansible# ansible 10.0.3.248 -m ping -u ubuntu
I get the following errors, that no inventory has been matched:
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.3.248
[WARNING]: No hosts matched, nothing to do
I am puzzled, to be honest, and as an Ansible novice, I have no idea how to move this forward. Seems such a simple issue, have not come across any similar thing here on stackoverflow. Many thanks for any hints!

I provide this host's IP address directly in the command. In this very case, according to my understanding, the inventory file is irrelevant.
Wrong. You specify host pattern, which should match hosts in your inventory. Inventory is a must for Ansible.
There's an option to specify "inline" inventory. For your case:
ansible all -i '10.0.3.248,' -m ping -u ubuntu
in this example: host pattern is all, inventory is a list of a single host 10.0.3.248.
Note comma at the end – it is important, this way Ansible understand that it is inline inventory, and not path to file.

Related

How to set up custom hostnames and ports for servers (eg node.js) running in WSL 2

(I've provided a simple working solution in response)
I recently moved from macOS to WSL 2. I have two node servers running within WSL 2 (Ubuntu distro). Each must be accessible through a custom hostname for development vs production purposes. I've had difficulty accessing the node servers via custom hostnames (ie set in some ../etc/hosts file) especially given WSL 2's dynamic IP that changes per WSL/pc 'boot'. How does one go about setting custom hostnames in WSL 2?
Scenario:
Each node.js app server (again running within WSL 2) must be accessed from the browser with the following urls/custom hostnames:
www.app1.com:3010
www.app2.com:3020
After searching around I have found the following relatively simple process works. I thought I'd share and save some time and headache for those new to WSL 2. Note, although I'm using node as the server stack, this process should more or less be the same for other app/web server stacks.
Note the following SE post is the basis of the solution. It's also worthwhile to examine MSFT's reference on WSL vs WSL 2. Also note, I haven't provided deep rationale on why these steps are required, why we might need custom hostnames, ipv6 options in ../etc/hosts, the meaning of 127.0.0.1, loopback addresses, WSL 2 and distro management, etc. These are subjects beyond the scope of this post.
Simple scenario:
nodeApp1: node application server with custom hostname: 'www.app1.com' on port 3010 (or whatever)
nodeApp2: node application serverwith custom hostname: 'www.app2.com' on port 3020 (or whatever)
Each node.js app server (again running within wsl 2) can be accessed from the browser with the following urls:
www.app1.com:3010
www.app2.com:3020
Two key items:
The correct etc/hosts files to be modified is on the Windows side (not WSL distro) at: C:\Windows\System32\drivers\etc\hosts (yes in Windows folders). This is a 'hot' update so no need for WSL 2 reboot. The content for this scenario is:
127.0.0.1 localhost
127.0.0.1 www.app1.com
127.0.0.1 www.app2.com
255.255.255.255 broadcasthost
::1 localhost www.app1.com www.app2.com
Please add C:\Users\"you"\.wslconfig with the following content (yes in Windows folders):
[wsl2]
localhostForwarding=true
Note: there's a reference to this in WSL 2 Ubuntu distro's /etc/hosts.
Also note, this requires WSL shutdown and reboot. Shutting down your terminal is insufficient. Also total machine boot is not
required. Simply run:
wsl --shutdown (in Powershell) or
wsl.exe --shutdown (within Ubuntu)
Then restart the Windows Terminal app (or any WSL terminal) to access the updated WSL 2 environment. The apps with custom urls/hostnames will now work in the browser permanently and WSL 2's dynamic IP is circumvented.

WSL2 use "localhost" to access Windows service

I'm using WSL2 on Windows 10.
My dev stack is using a local webserver (localwp or wamp) on the host OS.
I use WSL2 as the main terminal (SSH, Git, SASS, automation tools, ...).
What I need is a way to connect to my host services (MySql) from the WSL2 system using a server name instead of a random IP address.
It is already possible for the Windows host to connect to WSL2 services with "localhost". Is there a solution to do it the other way?
You should use hostname.local to access Windows from WSL2 because that will use the correct IP. Note that hostname should be replaced with the result of the hostname command run in WSL2.
You can check the IP by running ping $(hostname).local from WSL2.
You also need to add a firewall rule to allow traffic from WSL2 to Windows. In an elevated PowerShell prompt run this:
New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow
The command above should allow you to access anything exposed by Windows from WSL, no matter what port, however bear in mind that any apps you've launched get an automated rule created for them when you first launch them, blocking access from public networks (this is when you get a prompt from Windows Firewall, asking whether the app should be allowed to accept connections from public networks).
If you don't explicitly allow, they will be blocked by default, which also blocks connections from WSL. So you might need to find that inbound rule, and change it from block to allow (or just delete it).
See info here:
https://github.com/microsoft/WSL/issues/4585#issuecomment-610061194
Well, your title and your question body don't seem quite aligned.
The question title says "use localhost", but then in the body you say "using a server name."
Accessing the Windows 10 service via the name "localhost" from WSL2? Let's just go with "no". I can think of a possibility of how to make it work, but it would be complicated.
But I think the second is really what you are looking for, so a couple of options that I can think of for accessing the Windows host services by hostname in WSL2:
First, and hopefully the easiest, WSL2 supports mDNS (WSL1 did not), so you should be able to access the Windows host as {hostname}.local (where {hostname} is the name of the Windows host (literally, in bash, ping $(hostname).local, since the assigned WSL2 hostname is that of the host Windows 10 computer). That works for me. While I don't recall having to do anything special to enable this, this Super User answer seems to indicate that you have to turn it on manually.
The second option would be to add your Windows host IP to /etc/hosts. If your Windows IP is static, then you could just add it manually to /etc/hosts and be done. If it's dynamic, then you might want to script it. You can retrieve it from inside WSL2 via:
powershell.exe "(Test-Connection -ComputerName (hostname) -Count 1).IPV4Address.IPAddressToString" (and other methods) and then use something like sed to change /etc/hosts.
Add the following code to ~/.bashrc or ~/.zshrc, and then use winhost to access the host ip。
sed -i -e '/winhost/d' /etc/hosts
win_ip=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
win_host="$win_ip winhost"
echo $win_host >> /etc/hosts
The last time I was facing this issue,
I downgraded to WSL1, and all the connections started working perfectly.
You can use:
wsl --set-version Ubuntu 1
This is the easiest approach to fix all connection related issues in WSL2.

Sandboxing to allow multiple processes open the same port

Background
I have a command-line application that I use to connect to a remote device on port 1234. I cannot change the port number, and I do not have access to the source to rebuild this tool. I'm currently working in a lab where all ports except SSH are blocked. To get around this, I create a tunnel, i.e.:
ssh -L 1234:remotehost:1234 sshuser#remotehost
Now, I can just point my CLI program at localhost:1234 to connect with my CLI tool to the desired host.
Problem
This CLI tool needs to run for about an hour straight, and I have about 200 remote hosts to test with it. I would like to parallelize this task. Unfortunately, I can only create a single tunnel on my local machine using port 1234.
Question
Is there a (trivial/simple/automated) way to jail/sandbox my CLI tool so that I can launch 100 instances in parallel (i.e. via a shell script) so that each instance "thinks" it's talking to port 1234? For example, does Docker or KVM provide some sort of anonymous/on-demand compute node feature that I could setup rapidly? I'd rather not have to resort to manually deploying and managing a slew of VirtulBox hosts via vagrant.
The simple answer is that you can use multiple IP addresses locally. Each local IP address on the client will allow you to create another tunnel. Currently, you are using localhost. But your client also has an IP address. You can prove my point by trying this syntax:
ssh -f -N -L 127.0.0.1:1234:remotehost1:1234 sshuser#remotehost1 # this is default
ssh -f -N -L <local-IP1>:1234:remotehost2:1234 sshuser#remotehost2 # specifying non-default value <local-IP1>
Now, you just need to figure out how to give your client multiple IP addresses (secondary addresses). Then you can expand this beyond 2 parallel sessions.
I've also added -f and -N to your ssh syntax to put ssh into the background (-f) and to not issue any commands.
Using -R tunnels in the past, I've found that I need to enable GatewayPorts on the server (/etc/ssh/sshd_config). In the case of -L , I don't see the need. However, the ssh man-page explicitly mentioned GatewayPorts associated with the -L function. You may need to play around a bit. I just tried this out on my Mac and I was able to get it going without any GatewayPorts considerations.

Setting the ip of a RHEL box from a Vagrant script

I have a RHEL image already preconfigured, I don't know how it was originally setup.
By default, it is configured with a local network interface on the ip 192.168.50.50. What I am trying to do is configure its ip from the Vagrant script.
This doesn't seem to do anything:
config.vm.network "private_network", ip: "192.168.50.10"
This does change the ip:
sudo nmcli con mod bond0 ipv4.addresses 192.168.50.10/24
service network restart
But after that apparently Vagrant doesn't automatically detect the ip to connect to, so I need to add:
config.ssh.host = LOCAL_IP
But here's the problem: on the first time, the ip is the default one (.50.50). So I can't already set config.ssh.host to my desired ip. If I omit the config.ssh.host line, it runs the first time but not after, and vagrant ssh fails as well.
Is there a way to set the box ip without editing the Vagrant script between the first and second vagrant up?
Edit: Result of vagrant up --debug command: http://pastebin.com/BTccc4NT
Edit: The problem was that the Vagrant file from the default box (on Windows, it's at C:\Users\user\.vagrant.d\boxes\nameofbox\virtualbox\Vagrantfile) itself had this line:
config.vm.network "private_network", ip: "192.168.50.50", auto_config: false
hum, its weird, it creates 2 interfaces
DEBUG network: Normalized configuration: {:adapter_ip=>"192.168.50.1", :auto_config=>false, :ip=>"192.168.50.50", :mac=>nil, :name=>nil, :netmask=>"255.255.255.0", :nic_type=>nil, :type=>:static, :adapter=>2}
INFO network: Searching for matching hostonly network: 192.168.50.50
INFO subprocess: Starting process: ["C:/Program Files/Oracle/VirtualBox/VBoxManage.exe", "list", "hostonlyifs"]
......
DEBUG network: Normalized configuration: {:adapter_ip=>"192.168.50.1", :auto_config=>true, :ip=>"192.168.50.10", :mac=>nil, :name=>nil, :netmask=>"255.255.255.0", :nic_type=>nil, :type=>:static, :adapter=>3}
INFO network: Searching for matching hostonly network: 192.168.50.10
INFO subprocess: Starting process: ["C:/Program Files/Oracle/VirtualBox/VBoxManage.exe", "list", "hostonlyifs"]
so on on adapter2 you have 192.168.50.50 and on adapter3 you have 192.168.50.10
The possible reason for this is that the box you're using has a specific Vagrantfile which defines already a network on the static address.
I am not fully familiar with windows but on mac, the box definition is under ~/.vagrant/boxes/<yourbox>/<theprovider>/Vagrantfile (note this is not the Vagrantfile from your project, this is really a Vagrantfile which will be applied to any VM built from this box); check the file and remove the network configuration if you see it
As documented the Vagrantfile are merged from the different locations
At each level, settings set will be merged with previous values. What this exactly means depends on the setting. For most settings, this means that the newer setting overrides the older one. However, for things such as defining networks, the networks are actually appended to each other. By default, you should assume that settings will override each other. If the behavior is different, it will be noted in the relevant documentation section.
so by default Vagrant will create additional network interface and will not replace the one coming from the box Vagrantfile.

Run a command in remote server

What would be the best way to run commands in remote servers? I am thinking of using SSH, but is there a better way than that?
I used Red Hat Linux and I want to run the command in one of the servers, specify what other servers I want to have my command run, and it has to do the exact same thing in the servers specified. Puppet couldn't solely help, but I might be able to combine some other tool with Puppet to do the job for me.
It seems you are able to log on to the other servers without entering a password. I assume this is based on SSH keys, as described here: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s2-ssh-configuration-keypairs.html
You say another script is producing a list of servers. You can now use the following simple script to loop over the list:
for server in `./server-list-script`; do
echo $server:
ssh username#$server mkdir /etc/dir/test123
done >logfile 2>&1
The file "logfile" will collect the output. I'm pretty sure Puppet is able to do this as well.
Your solution will almost definitely end up involving ssh in some capacity.
You may want something to help manage the execution of commands on multiple servers; ansible is a great choice for something like this.
For example, if I want to install libvirt on a bunch of servers and make sure libvirtd is running, I might pass a configuration like this to ansible-playbook:
- hosts: all
tasks:
- yum:
name: libvirt
state: installed
- service:
name: libvirtd
state: running
enabled: true
This would ssh to all of the servers in my "inventory" (a file -- or command -- that provides ansible with a list of servers), install the libvirt package, start libvirtd, and then arrange for the service to start automatically at boot.
Alternatively, if I want to run puppet apply on a bunch of servers, I could just use the ansible command to run an ad-hoc command without requiring a configuration file:
ansible all -m command -a 'puppet apply'

Resources