mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2026-03-04 00:01:12 -05:00
Upgrade through Dashboard fails if AGH service is run as non-root user #1104
Labels
No labels
P1: Critical
P2: High
P3: Medium
P4: Low
UI
bug
cannot reproduce
compatibility
dependencies
docker
documentation
duplicate
enhancement
enhancement
external libs
feature request
good first issue
help wanted
infrastructure
invalid
localization
needs investigation
performance
potential-duplicate
question
recurrent
research
snap
waiting for data
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/AdGuardHome#1104
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @kinggrowler on GitHub (Nov 22, 2019).
Originally assigned to: @szolin on GitHub.
When an update for AdGuard Home is available, the dashboard displays a notice about the available upgrade along with an "Upgrade now" button.
Clicking the button does nearly everything correctly: the old binary is archived, the new one downloaded, the systemd service is restarted.
However, when the service is run as a non-root user, the "setcap" command must be manually executed again.
sudo setcap CAP_NET_BIND_SERVICE=+eip /opt/AdGuardHome/AdGuardHomeMy question: is this expected behaviour, and if so, is there a better way I can handle this than manually logging in and running the command?
Expected Behavior
Ideally, AGH would handle setting of the CAP_NET_BIND_SERVICE capability. Baring that, AGH should display a warning message before upgrading via Dashboard.
Actual Behavior
AGH fails to restart after upgrade due to inability to bind to a privileged port.
Screenshots
Additional Information
$ cat /etc/systemd/system/AdGuardHome.service
@ameshkov commented on GitHub (Nov 25, 2019):
I am not sure if we can handle this without root.
As an alternative solution, we can simply disable automatic updates, replace "Update now" with "Learn how to update" button and lead users to the update manual.
@kinggrowler commented on GitHub (Nov 25, 2019):
I have a workaround for this simply by changing slightly the systemd service file for AdGuardHome.service.
Adding the line:
ExecStartPre=+/sbin/setcap CAP_NET_BIND_SERVICE=+eip /opt/AdGuardHome/AdGuardHomeWill run the setcap command each time the service is bounced, and run only that command as root user. I have tested this a number of times upgrading from 0.99.2 to 0.99.3 and it works without issue. The downside is we run this command each time the service is restarted, but it certainly doesn't cause issue to do so (as far as I know).
See this note about systemd.service "Special executable prefixes:
( The "+" modifier was introduced in version 231.)
Attached is my complete systemd service file, which differs from the one in my orignal comment by only this line:
@ameshkov commented on GitHub (Nov 25, 2019):
Huh, interesting!
So it seems it would be enough to change the documentation on how to run AdGuard Home without root.
@kinggrowler commented on GitHub (Nov 25, 2019):
My workaround definitely works but I'm not an expert with systemd so I don't know if there is a better way. It certainly seems like a nice solution since there is no change to the AGH binary and only adding one line to the service file, and only for those users that wish to run as non-root user.
@OMICRON3069 commented on GitHub (Dec 25, 2019):
Maybe you can add this two line to your systemd services file
so it will be like
@kinggrowler commented on GitHub (Dec 28, 2019):
@OMICRON3069 , can you explain a bit more about what these two lines do?
@OMICRON3069 commented on GitHub (Dec 28, 2019):
No problem, and you can read systemd manual in detail at https://www.freedesktop.org/software/systemd/man/systemd.exec.html
CapabilityBoundingSet=
AmbientCapabilities=
Also, you can get those answers by searching
systemd allow bind portwith google. I think google should always be the first to ask about those technical problems.@kinggrowler commented on GitHub (Dec 28, 2019):
Very interesting, thanks! What was your experience doing an upgrade?
I don't disagree but found in my IT career, when creating or updating a ticket, it was a powerful choice to include all information in the ticket so as to prevent people needing to click elsewhere for answers. It's one thing to say "do this" but it's more helpful to include why.
But I'm retired now and no longer do IT work so I don't know what the hot trends are regarding this. Cheers!
@OMICRON3069 commented on GitHub (Dec 29, 2019):
Things are little different in my situation. I compile those code (not just only AGH) on my local machine, and sync those binaries to my server through syncthing.
Indeed, it makes sense to include additional information to prevent people for further searching, maybe I will try it in the future!
@simonbcn commented on GitHub (Jan 21, 2020):
Any of those solutions doesn't work in a new install. AdGuardHome always wants to run as root the first time.
@ameshkov commented on GitHub (Jan 21, 2020):
@simonbcn the thing is that AdGuard Home detects the first installation by checking for
AdGuardHome.yamlpresence. If you create this file by yourself before running AGH, it won't check for root access.@simonbcn commented on GitHub (Jan 21, 2020):
@ameshkov I've tried to create a empty file with that name but it doesn't work:
@szolin commented on GitHub (Jan 21, 2020):
@simonbcn You should exec AGH under root for the first time. After you finish the installation wizard you'll have a yaml config file. Now you can use this file even on a new PC - root user isn't required anymore.
@simonbcn commented on GitHub (Jan 21, 2020):
@szolin but the installation wizard asks for user/password in "Authentication" and this is should be configured for the final user.
I think the start of Adguardhome is wrong because it doesn't check if it really has write access to save that configuration file before it wants to run as root always.
@szolin commented on GitHub (Jan 21, 2020):
We don't do that indeed, but we don't have to. What's the use-case here?
The user is AGH administrator - we currently assume that he has root access.
In other words, your use-case is not common. And allowing to start under a normal user will lead to problems for the most users during installation wizard steps - when they choose 53 and 80 ports. Can you maybe propose a good solution to this whole behaviour?
@simonbcn commented on GitHub (Jan 21, 2020):
Why AGH needs root rights?
@szolin commented on GitHub (Jan 21, 2020):
And I've just explained that:
@simonbcn commented on GitHub (Jan 21, 2020):
So the problem is not that the configuration file does not exist, it is that it needs sudo rights to access those ports. Therefore your proposed solution (to provide a default AGH. config file) would not work.
@szolin commented on GitHub (Jan 21, 2020):
Why not? It will if you set different port numbers there. You won't be able to listen on ports <1024 without special system configuration, as explained by the thread starter.
@simonbcn commented on GitHub (Jan 21, 2020):
That is the problem, this application assumes many things and that is why it calls for sudo rights but it should not be like that. At least, not if we want this program to be portable to any distro linux safely.
setcap CAP_NET_BIND_SERVICEis the solution if I don't want run this program as root. But AGH doesn't test anything before ask for sudo rights.Perhaps it should do a test after the user configures the URLs and ports and if a problem occurs indicate to the user the need to run as root.
On the other hand, wouldn't it require root rights whenever the program is restarted to open the <1024 ports?
@ameshkov commented on GitHub (Jan 21, 2020):
That's why there is #723.
@simonbcn besides using ports 53 and 80, AGH also offers to set static IP and that also requires root access.
If we want to make AGH run without root, we'll have to move the initial setup logic to the package, i.e. come up with a bash script that will ask the very same questions (prompt for ports, admin user/password, offer to set static IP), then build the
AdGuardHome.yaml, runsetcap CAP_NET_BIND_SERVICE, and finally, run AGH itself.I think that building
AdGuardHome.yamlis the most problematic part of this. We could add a command-line option that will do this, something like this:./AdGuardHome --init --web-port=80 --dns-port=53 --username=admin --password=adminWhat do you think?
@simonbcn commented on GitHub (Jan 22, 2020):
The problem is not just the configuration file, it is all the files and folders that the initialization process creates with the root user:
@ameshkov commented on GitHub (Jan 22, 2020):
The point is that you should not run AGH with root access at all.
You should instead place the
AdGuardHome.yamlfile near the binary and run AGH under the user you're intending to use after that.@simonbcn commented on GitHub (Jan 22, 2020):
The problem is in the application as it is designed now. I have to run it for the first time as root but that implies that all files/folders created at that time belong to the root user.
I cannot create a generic configuration file for any user who installs this application. That has to be configured by everyone when they first run it.