I an trying to make a script that launches on boot to connect to my personal VPN.

I have an init file: /etc/init.d/vpnstartup

which calls my vpnon.sh script on boot with the commands:

case "$1" in
        su username -c $VPN_DIR/vpnon.sh

in my script vpnon.sh there are commands that need root permissions to be executed:

sudo iptables -A INPUT -i pptp -j ACCEPT
sudo iptables -A OUTPUT -o pptp -j ACCEPT

I grant permissions of the vpnstartup init file and the vpnon.sh script with chmod 775 when I try out my init file by calling it using ./vpnstartup start

I get the following error when the sudo iptables command gets called

sudo: no tty present and no askpass program specified
sudo: no tty present and no askpass program specified

what I think is happening is the sudo command requires an input password but has no way to get it.

The only solution I found was adding the NOPASSWD :ALL option to the sudoers file under my user name.

I don't want to do this method for security reasons if there is a better solution.

Please let me know if you can help me with this problem; I have spent many hours on it.

  • It seems perverse to su from root in your init script to run a script that then requires you to sudo back to root: can't you organize your script(s) to avoid that? – steeldriver Mar 18 '15 at 5:19
  • @steeldriver thanks for the suggestion. I researched that calling sudo within a script is frowned upon. best to do it outside of the script. – tritium_3 Mar 19 '15 at 7:15

I think something that is a key factor here is that because a script is run with sudo, it can do everything root can do. The problem is that other sudo commands within that script don't necessarily inherit root permissions, but are executed as the controlling user. This can often produce the error you see from sudo, even if the parent script itself is allowed via sudo but the subcommands are not.

What's happening is the nested sudo call within that script is failing because sudo would normally prompt for a password, but there's no controlling shell so it can't. This generates the slightly ambiguous sudo: no tty present and no askpass program specified error that you see.

An easy way to illustrate this is if, like your example, an init script contains internal calls using sudo. Running:

sudo /etc/init.d/startvpn

can fail if your own user doesn't have sudo rights to all the sudo calls within, and might give you the sudo tty error. However, running it like this:

sudo sh /etc/init.d/startvpn

would probably work. In the latter case, sudo sh creates a command shell as root, so anything that is run within that shell actually does execute as root. Root generally has unrestricted sudo permissions so it no longer matters if a command is run with sudo or not.

Some things worth mentioning:

  • As others have pointed out, most of this mess can be avoided by not using sudo within scripts. Often sub-commands that fail when run with sudo can work fine without it (when the parent script is run with sudo).
  • While running the script with sudo sh may solve the issue, again there are security implications to doing so. Consider that sudo behaves this way as a sanity check, to ensure that the contents of the script are not doing something they shouldn't, even if the script itself is allowed.
  • If the user you are running sudo as also has sufficient blanket permissions, you may not see any of these problems. But they can surface later, say if you develop a script with your own privileged account, and in production it's ran as a non-privileged service account.
  • In general you should avoid granting broad sudo permissions to user accounts as a way to solve this kind of issue. If really needed, limit the account access rules to that user and that specific command.

I found the solution to the problem.

I removed all of the individual sudo commands in my vpnon.sh script, and passed in sudo from outside of the script.

In my /etc/init.d/vpnstartup file, I changed the su username -c to sudo $VPN_DIR/vpnon.sh which looks like this now:

case "$1" in
        sudo $VPN_DIR/vpnon.sh

then called sudo update-rc.d vpnstartup defaults and now the VPN connects on startup! :)

  • 1
    You shouldn't need sudo at all since the files in /etc/init.d are run as root – steeldriver Mar 19 '15 at 11:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.