I wrote a simple playbook, open-links.yml, that is meant to run a script on one of my remote hosts:

- name: Run Bash script
  hosts: myhosts
  gather_facts: false
    au: "j"
    - name: Copy and run a script that opens a link
      script: /home/{{ au }}/CS/SoftwareDevelopment/MySoftware/Bash/ansible/open-links.sh

open-links.sh is a script that is meant to open a link in a browser:


# Link to open

doas -u oumaima echo "From ${0}, $(whoami): It works, doesn't it"|tee ~/debug.log
doas -u oumaima brave-browser "${link_to_open}" > /dev/null 2>&1 &
#doas -u oumaima DISPLAY=:0 brave-browser "${link_to_open}" > /dev/null 2>&1 &
#doas -u oumaima DISPLAY=:0.0 brave-browser ${link_to_open} > /dev/null 2>&1 &
#neither of these two work, whatever the value of DISPLAY

Although running ansible-playbook -u root -i inventory.ini open-links.yml gives me the following output

PLAY [Run Bash script] **********************************************************************************

TASK [Copy and run a script that opens a link] ***********************************************************
changed: [fe80::cc08:9465:8dba:15a9%wlp4s0]

PLAY RECAP **********************************************************************************************
fe80::cc08:9465:8dba:15a9%wlp4s0 : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

No link gets opened. The location of debug.log is /root/, and its content, From /root/.ansible/tmp/ansible-tmp-1702325377.165474-2513875-125933755232488/open-links.sh, root: It works, doesn't it, both of them suggest to me that if any link does get opened, then it probably happens for root. When I am logged in with ssh to the remote host and manually run

doas -u oumaima brave-browser "${link_to_open}" > /dev/null 2>&1 &

then the browser does open the link as specified for the user oumaima. I know that the link is open because the remote host is in the same room and I can seen the browser from the user account oumaima. Forwarding to my control station of what is happening in the GUI of oumaima is not what I want and let it be outside of the scope of this question. I just want the link to be opened. Why doesn't this happen when the script is run with ansible-playbook -u root -i inventory.ini open-links.yml

I know that I could just work around that by allowing non-root logins to the remote host and running the playbook as oumaima, like so: ansible-playbook -u oumaima -i inventory.ini open-links.yml. Let such solutions be outside of the scope of this question. I'd like to fix the issue when running the playbook as root.

About the hosts: a laptop in the same room, on the same LAN, as my control station. Ubuntu Desktop 22.04 LTS on both the control station and the remote host.

  • 2
    Before running any commands, bash evaluates the command and substitutes everything that needs to be substituted. So ~ gets substituted with the home of the user running the cvommand, root, which is /root/. Also, the doas-user is only valid until the pipe. After that, doas is done, the tee runs as root. The logfile propably belongs root.
    – rathier
    Dec 11, 2023 at 22:05
  • 1
    For the second problem, I guess it's DISPLAY. Can you open a graphical program as root` Like xterm or xclock via ansible? If that works, can you open the program with doas as your user via ansible? If that works, my guess would be wrong and it is not the display-setting.
    – rathier
    Dec 11, 2023 at 22:09
  • 2
    Maybe, if you don't redirect stdout and stderr to /dev/null but to your log instead, you might see, if brave has problems starting up and what these problems are.
    – rathier
    Dec 11, 2023 at 22:11
  • @rathier Spot on. I replaced doas -u oumaima brave-browser "${link_to_open}" > /dev/null 2>&1 & with doas -u oumaima brave-browser "${link_to_open}" and now my script works. Do you have any idea why that might be?
    – John Smith
    Dec 12, 2023 at 9:09
  • Is there already an instance of the brave-browser running as user oumaima on the remote host, or does it need to be started from scratch? As far as I know, most browsers will attempt to detect if an instance of them is already running, and prefer sending a request to open a URL to the existing instance rather than starting a new one. Depending on exactly how Brave does that, signaling the existing instance may be successful while starting a new one fails because of e.g. missing DISPLAY variable. doas will apparently provide a very minimal environment by default.
    – telcoM
    Dec 12, 2023 at 9:41

1 Answer 1


To use a X11 display, you'll normally need two things:

  • a Xauthority file (either ~/.Xauthority or a file pointed to by the XAUTHORITY environment variable) with a valid session cookie for the display you want to use,
  • and a DISPLAY environment variable specifying the display you want to use.

If you run a SSH session with X11 forwarding, and the local end satisfies the X11 use requirements locally, and the remote end has the xauth command available, then the remote sshd will automatically set up both of these requirements for you in such a way that the display will end up to the local screen at wherever you started the SSH client.

If you run a X11 program remotely and set DISPLAY to :0 for it, it means you are attempting to make it display its window(s) on the display that's directly connected to the remote system, which might be useful if you are using the system as a billboard, but probably not immediately visible for you. For it to succeed, the remote system should already have a logged-in GUI session with whatever user account you're using to run the X11 program, so that the Xauthority file will be present and up to date.

When Ansible uses SSH, it probably won't request X11 forwarding by default, unless you explicitly configure it to do so.

  • I added more information in response to your worthy answer. The remote host in my case is just another desktop PC - forwarding to my control station of what is happening in the GUI of oumaima is not what I want.
    – John Smith
    Dec 12, 2023 at 8:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .