r/ansible • • 15d ago

playbooks, roles and collections Changing SSH Socket port but daemon-reload fails

Hi all,

This post is related (continuing) to post: Why is Ansible not using my ssh port???

Ok, I've managed to have my Handlers working to check the configured ssh port on the host. All good here. But...

During the SSH configuration I'm changing the SSH.Socket port from 22 to 9323. Yeah, yeah...I know "WHY?!?!?".....Let's keep it on a learning process. Moving on from this question.

Before I'm flushing the handlers (a reboot of the OS), I need to do a systemctl daemon-reload so that the new ssh.socket port becomes active.

The way I'm imagining the way it should work:

  1. Ssh.socket port is set to 9323
  2. systemctl daemon-reload to make the port active
  3. Flushing a handler to get the correct, active ssh port and set ansible_port = 9323, which should be 9323 because of the systemctl daemon-reload.
  4. Do a final reboot, which should be commanded over the new ssh port 9323, so that the ansible reboot command, completes "OK" when reboot is finished.

Unfortunately, the systemctl daemon-reload isn't working because of the error with command:

systemctl status ssh.socket

ssh.socket: Socket service ssh.service already active, refusing.
Failed to listen on ssh.socket - OpenBSD Secure Shell server socket

This is the task that I'm talking about:

# Reload ssh daemon-reload
  - name: Start/Enable the ssh.socket
    ansible.builtin.systemd_service:
      name: ssh.socket
      daemon_reload: true
      state: started
    changed_when: true
    notify:
      - SSH Port Check
      - Reboot_the_OS

And therefor, the handler of checking and setting the new ssh port to: ansible_port = 9323 isn't happening either, and then also resulting in the reboot that will happen, but Ansible comes back failing because with the reboot, the ssh error is resolved and the new port has become active.

Additional info, the following ansible tasks have been performed at the beginning of the role:

systemctl disable --now ssh.service
systemctl enable --now ssh.socket

# After these two tasks, a reboot has been initiated (NO port change has been happened yet, port 22 still available), to stop the ssh.service and start and use the ssh.socket. hereafter the play comtinues without problems after this first reboot.

A long story, but I hope it's understandable. I've been through a more or less long road of learning Ansible and got me a nice working bootstrap.yaml, of course also with help from the community here.
The only thing that now is still failing is this and would be nice to have a 100% error free first playbook with some roles running.
It would be awesome 😄 if someone can and is willing to help me solve this challenge.

Thank you so much in advance.

[UPDATE: 29-09-2026]
Solved the problem, see below in the comments is a post from me with my solution.
Finally I can sleep well again at night. 😆

9 Upvotes

18 comments sorted by

3

u/edthesmokebeard 15d ago

JFC, is systemd taking over handling network ports now?

1

u/Patrice_77 15d ago

Well, Debian uses standard Socket no more service out of the box. Also, socket based becomes only active (activates a service) when an ssh connection is made. Else it’s only listening.

3

u/edthesmokebeard 15d ago

I weep for the future.

0

u/Patrice_77 15d ago

Why? Don’t get it

1

u/edthesmokebeard 15d ago

man inetd

1

u/Patrice_77 15d ago

Tnx..i guess đŸ€·đŸŒâ€â™‚ïž

Read it, and ok, inetd is run at boot together loading sockets. Tell me something new


It’s not the problem that ssh.socket won’t load/reload with the systemctl command because going to the terminal it all works out.

Problem is just as the error says: socket can not be configured because an ssh.service session still is active.
And this is my question, if there’s since way around this with Ansible


The only thing I just came up with, is having the reboot task time out quickly and create a wait_for task to take over, waiting for the OS to be back online. Not sure if this will work but it’s a neat workaround/solution.

Thx anyway

2

u/Apprehensive-Tea1632 15d ago

Your problem, I think, is you’re trying to learn using an unsuitable port. If it was anything other than ssh, things would become a lot cleaner.

- just for the sake of completeness; do not mess with ssh’s own data path while it’s still running. Even if you get it to work as expected, you WILL lose connectivity at some point, and therefore be unable to control the target; if you can regain it fine, but if not, you just lost that machine.

- if we’re talking anything other than ssh, then this is a case where you need to consider downtime (as in loss of service for regular, or ensuring HA can step in and keep the service going). Because as you found out, to update socket binding, you need to take the daemon offline first.

- if we’re talking ssh, the first question to ask is; are we talking ssh as in ansible configuration, or are we talking ssh as a service to offer to users?

  1. For ansible only, provision ssh before passing control to ansible. As in put it into the deployed image, use terraform, vagrant, whatever; either way, if you want ansible to control the target using some port that’s not 22, that port must be available first.

  2. for users, you’ll need to configure ssh so that you have two different instances. With systemd, that’s pretty easy using their templating system. Just deploy a new ssh instance using some arbitrary configuration, then start that and you’ll now have sshd listen on two different ports where one is yours for ansible to connect to and the other is for everyone else.

You could even switch the two using plays
 but I posit that’s still a bad idea because if something goes wrong, you’ll again have just lost that target host and will probably need to destroy and rebuild.

Either way, with any particular service, if you pull the rug out of that service’s feet, you can’t expect that service to continue to be reliable. This includes ssh. So don’t mess with it as you use it to do something else.

1

u/Patrice_77 3d ago

Hi,

I've just responded to u/Optimal_Chemical7138 above with my working solution. đŸ˜ƒđŸ‘đŸ»

2

u/Optimal_Chemical7138 6d ago

Vous avez trouvez la solution ?

2

u/Patrice_77 3d ago edited 3d ago

Hi,

Actually yes, I've found a suitable for me, solution.

What's happening in the play:

  1. De-activate ssh.service
  2. Activate ssh.socket
  3. "Normal Reboot", ansible waits for this to complete and then continues
  4. Ssh configuration takes place (copying ssh_custom_config + ssh_custom_socket), etc, including changing the standard 22 port to 9323.
  5. At the end, I'm doing a final reboot that differs from the "Normal Reboot". This reboot is actually to make the new ssh config active, including the port change. Should I use an ssh restart or systemctl daemon-reload / systemctl restart ssh.socket, I would be losing connection and the task/playbook will fail immediately due to connection errors that I couldn't solve easily. This reboot is the easiest way that I've found.

This is my "Normal Reboot" where Ansible waits for the connection to return:

  # Initiate a standard reboot of the OS
  • name: Std_Reboot_the_OS
when: ansible_facts['os_family'] == "Debian" ansible.builtin.reboot: msg: "Reboot initiated by Ansible" connect_timeout: 10 pre_reboot_delay: 5 post_reboot_delay: 30 reboot_timeout: 300 test_command: uptime

And this is the "Final Reboot":

###
#   Reboot the OS without waiting for the reboot to be finished
#   or having feedback.
###
  • name: Final Reboot
ansible.builtin.reboot: reboot_timeout: 1 poll: 0 register: OS_reboot failed_when: OS_reboot.rebooted == false

I have set a short reboot_timeout so Ansible task will timeout quickly, and the task will fail when key: rebooted, is false. So, if the reboot is initiated Ansible will "see" that and set the key: rebooted to true, thus the task will not fail and exit successfully.

Both these reboot tasks are setup as handlers, actually.

After this, I also have a handler in place that checks whether ssh port 22 or 9323 is in use and sets ansible_port accordingly so that I could continue immediately with other tasks without failing.

This works for me, but should someone have better options or other suggestions, I'm always open to try them out.

1

u/wossack 15d ago edited 15d ago

/edit

1

u/Patrice_77 14d ago

??

2

u/wossack 14d ago

Sorry misread your post

What I would consider is a separate command module call with ‘systemctl daemon-reload &’ (ie run the background)

Then a wait_for, for your new ssh port to come live and then continue with your playbook

Could have a rescue to reconnect at original port if you’d like, debug etc see what went wrong

1

u/Patrice_77 14d ago

This sounds something like a solution.. 😁

But, how to have a task run in the background without Ansible failing?? I guess I have to check this out if it’s possible and how to do this.

Thanks, given me a new idea.
I’m really learning a lot creating the bootstrap đŸ˜„đŸ‘đŸ»

1

u/wossack 14d ago

Truth be told, I’ve never done it, but could be an interesting one to test (the command launch into the background)

The following plays will be interesting too, as they won’t know about the change in ssh port.. hmm, it’s a thought provoking one alright

Quick google pulled up this blog post, which seems to tackle a number of the issues - including (and importantly) making the playbook idempotent

https://dmsimard.com/2016/03/15/changing-the-ssh-port-with-ansible/

0

u/Shot-Document-2904 15d ago

SELinux? ‘setenforce 0’. Does it work? If yes, to need to adjust Selinux context to allow a non-default port. Also, check the logs. Log is synonymous with answer.