-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
certbot-apache: use httpd by default for CentOS/RHEL #9402
Conversation
Code looks solid, have you already tested it on CentOS/RHEL 8/9 in practice? |
This seems like it will now leave On all versions of CentOS, RHEL and Fedora it is fine to restart httpd using The special case needed is if you want to do something other than control the daemon, e.g. |
Ah, thanks for the clarification @notroj, turns out I misunderstood the RHEL changelog! Updating the PR |
A change in RHEL 9 is causing apachectl to error out when used with additional arguments, resulting in certbot errors. The CentOS configurator now uses httpd instead for RHEL 9 (and later) derived distros.
36cebb1
to
6a7d876
Compare
] | ||
new = util.parse_loose_version(os_version) >= util.parse_loose_version('9') | ||
if rhel_derived and new: | ||
self.options.ctl = 'httpd' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this sets the value of --apache-ctl
(see certbot --help apache
) with no way for the user to override it while continuing to list the default value as apachectl
in the help output on RHEL 9+. Is that right?
If so, I think we may want to do something like what we do here and define a new override class with static defaults.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true, though i was hoping to leave all the finicky distro-specific details out of get_configurator()
and instead handle it within CentOSConfigurator
.
one issue w/ relying on static defaults is that _prepare_options()
always sets options.restart_cmd
's binary to options.ctl
(https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/configurator.py#L184-L187), so even if our CentOS 9 defaults have httpd
for one and apachectl
for the other, they'll both end up as httpd
unless we intervene. what about something like:
diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py
index 82b3dcaec..8d7d4eb3a 100644
--- a/certbot-apache/certbot_apache/_internal/configurator.py
+++ b/certbot-apache/certbot_apache/_internal/configurator.py
@@ -178,14 +178,14 @@ class ApacheConfigurator(common.Configurator):
# Config options use dashes instead of underscores
if self.conf(o.replace("_", "-")) is not None:
setattr(self.options, o, self.conf(o.replace("_", "-")))
+ # If the user overrides apachectl, update the various cmds as well
+ if o == "ctl":
+ self.options.version_cmd[0] = self.options.ctl
+ self.options.restart_cmd[0] = self.options.ctl
+ self.options.conftest_cmd[0] = self.options.ctl
else:
setattr(self.options, o, getattr(self.OS_DEFAULTS, o))
- # Special cases
- self.options.version_cmd[0] = self.options.ctl
- self.options.restart_cmd[0] = self.options.ctl
- self.options.conftest_cmd[0] = self.options.ctl
this way, we can just give CentOS 9 a different set of OS_DEFAULTS and leave its _prepare_options()
alone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Digging into this further, I noticed that we also have an --apache-bin
option:
$ certbot --help apache
usage:
certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...
...
--apache-ctl APACHE_CTL
Full path to Apache control script (default: apachectl)
--apache-bin APACHE_BIN
Full path to apache2/httpd binary (default: None)
I feel like in the long term if not now, we should make use of this here instead of telling our code that the name of apachectl
is httpd
. There are different ways to structure this, but I personally think we should try to keep these two options true to their intended usage and update other commands based on their values. By that I mean I'm essentially imagining logic that at least effectively does something like:
if self.options.version_cmd[0] == self.OS_DEFAULTS.ctl:
self.options.version_cmd[0] = self.options.ctl
else:
self.options.version_cmd[0] = self.options.bin
What do you think?
Also, on RHEL 9+ and friends, are these values from higher up in this file correct? Do we want to be using apachectl
at all?
restart_cmd=['apachectl', 'graceful'],
restart_cmd_alt=['apachectl', 'restart'],
conftest_cmd=['apachectl', 'configtest'],
I notice we leave them unmodified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, on RHEL 9+ and friends, are these values from higher up in this file correct? Do we want to be using
apachectl
at all?
Authoritatively: yes, you should use apachectl restart
or graceful
to restart the daemon on all versions of RHEL, and will be supported in all future versions. This is supported as a thin wrapper around systemctl $action httpd
to manipulate the systemd service. apachectl configtest
should also work for all versions since it's so widely used. The thing we don't support is passing arguments in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went w/ @bmw's suggestion and reworked this to use two different configurator classes for the different scenarios (i.e. older CentOSy OSes vs. new RHEL-derived OSes). this ended up adding some more complexity to get_configurator()
, but in the end i think it makes more sense this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wgreenberg, sorry for the conflicting suggestions between my first and second comments in the thread here. What do you think about what I said in that second post though at #9402 (comment) about using the apache_bin option instead of configuring our code to believe that the name to the Apache control script is httpd
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is getting close! Based on your answers to some of my inline questions, I think we may want to consider keeping a single CentOS override class and doing the command overriding conditionally by inspecting the OS again like you did in the initial version of this PR. I'm not tied to this specific design, although I do think it may allow us to simplify/undo some of the other changes here.
I think we should also add a changelog entry about this but other than that and my inline comments, this LGTM!
As of RHEL 9, apachectl can't be passed flags like "-t -D", so instead | ||
use options.bin (i.e. httpd) | ||
""" | ||
if not self.options.bin: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call super()._override_cmds()
here so values like self.options.restart_cmd[0]
get set based on the ctl
value and then in addition set self.options.version_cmd[0] = self.options.bin
below?
super()._prepare_options() | ||
if not self.options.restart_cmd_alt: # pragma: no cover | ||
raise ValueError("OS option restart_cmd_alt must be set for CentOS.") | ||
self.options.restart_cmd_alt[0] = self.options.ctl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to do this for RHEL 9+? If not, do you know what changed between new and old versions?
"amazon": override_centos.CentOSConfigurator, | ||
"gentoo": override_gentoo.GentooConfigurator, | ||
"gentoo base system": override_gentoo.GentooConfigurator, | ||
"opensuse": override_suse.OpenSUSEConfigurator, | ||
"suse": override_suse.OpenSUSEConfigurator, | ||
"sles": override_suse.OpenSUSEConfigurator, | ||
"scientific": override_centos.CentOSConfigurator, | ||
"scientific linux": override_centos.CentOSConfigurator, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I worry about removing entries from this dict due to the code at
certbot/certbot-apache/certbot_apache/_internal/entrypoint.py
Lines 60 to 63 in 529942f
os_like = util.get_systemd_os_like() | |
if os_like: | |
for os_name in os_like: | |
override_class = OVERRIDE_CLASSES.get(os_name) |
What do you think?
@bmw i reworked this into a single class, ready for review again! |
self.options.get_includes_cmd[0] = self.options.bin | ||
self.options.get_defines_cmd[0] = self.options.bin | ||
else: | ||
super()._override_cmds() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may want to unconditionally call this at the top of this function so values like self.options.restart_cmd[0]
get set to a possibly custom self.options.ctl
value. Otherwise, this PR LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack, yup!
CHANGELOG entry needs to be moved from 1.25.0 to 1.32.0. |
d'oh, good catch @alexzorin. fixed here: #9444 |
Yeah thanks for catching this Alex. This recurring issue motivates me a bit to take another look at #8272. |
Fixes #9386
CentOS and RHEL 9 now use
httpd
instead ofapachectl
, so that's now the default for that configurator. There's now a special case for older CentOS/RHEL versions to use apachectl, as well as for older Fedora (<28).