So let’s set the stage.
You’re writing a blog.
This blog is kept in a Git repository.
“Great!” You think, knowing that you can make changes from any of your computers, and just
git pull on the server to bring everything down.
Because how Nginx works, you don’t need to reload anything, the new content is available immediately.
There’s just one problem: this means you need to SSH into the server to pull everything, which requires SSH into a border server first, tunneling your connection through another one.
While yes, a few tweaks to
~/.ssh will make that work just fine, it’s still a bit of a pain.
Suddenly, an idea strikes you:
Set up a
cron.hourly task to
cd into the directory, run a
git pull, and then finally ask
hugo to rebuild the site.
To test this, you write a little shell script, give it
+x, and run.
Because you were planning to modify
cron files, you’re
You try, and….
Error: add site dependencies: create deps: failed to create file caches from configuration: mkdir /tmp/hugo_cache/root: permission denied
That’s…. strange. Run from your user? Perfectly fine. Root? Error.
Then it hits you: Linux permission flags have two special bits:
setuid will cause you to automatically assume the user that owns the file, and
setgid will do the same but for groups and group ownership.
So in theory, if your fictional user was named
chown blog-update update; chmod u+s update would set
setuid on the update script, and designate
blog-update as the user that owns it.. in theory, anyone who runs
./update would assume the rights and permissions of
No. Try again, same error.
Debug time: add a
whoami to your script. What does it report? Why,
root of course.
If you weren’t already doing your best JonTron impression
, you are now.
So… what gives?
setgid Aren’t as Useful as They Should Be
setgid do change your user and group ID, but with one major, and, in my research, unmentioned exception (until someone at stackoverflow had the answer… obviously): They do not work on scripts!
Yes, both bits work for compiled binary programs, such as
ping needs to be run as root), and so on.
Start your file with a
#!/bin/sh, make it a shell script, and as a security feature, the
setgid bits are flat-out ignored. Lovely!
Now yes, in fairness, it does make sense. But either I’ve not been looking in the right places, or that information is so rare, that it really took a bit of head-scratching for me to even realize what was going on… after I googled the answer as to why.
But.. The Solution?
I just made a
cron script as my user instead, problem solved.
Not super extravagant, but it works.