mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-29 14:50:59 +01:00
MINOR: systemd: support for systemd socket activation via setenv-sd-listen-fds
Adds the setenv-sd-listen-fds configuration option to automatically set or clear environment variables based on systemd's LISTEN_FDS and LISTEN_FDNAMES. When enabled, HAProxy will expose file descriptors using environment variable names prefixed with FD_ followed by the uppercase FileDescriptorName defined in the systemd socket unit. This feature simplifies socket activation in containerized environments and allows binding to inherited file descriptors without relying on NAT or network initialization. Default behavior is off, which ensures the environment variables are unset.
This commit is contained in:
parent
d48585199b
commit
61937cf2e1
@ -1775,6 +1775,7 @@ The following keywords are supported in the "global" section :
|
||||
- set-dumpable
|
||||
- set-var
|
||||
- setenv
|
||||
- setenv-sd-listen-fds
|
||||
- ssl-default-bind-ciphers
|
||||
- ssl-default-bind-ciphersuites
|
||||
- ssl-default-bind-client-sigalgs
|
||||
@ -3120,6 +3121,49 @@ setenv <name> <value>
|
||||
the configuration file sees the new value. See also "presetenv", "resetenv",
|
||||
and "unsetenv".
|
||||
|
||||
setenv-sd-listen-fds [ on | off ]
|
||||
Sets environment variables automatically using the LISTEN_FDS and
|
||||
LISTEN_FDNAMES environment variables described in the systemd documentation.
|
||||
|
||||
These 2 variables are set by systemd.socket. Systemd is able to listen to a
|
||||
TCP socket by itself and pass the socket to the service using the
|
||||
ListenStream keyword. When using FileDescriptorName, it is possible to assign
|
||||
a name to the corresponding FD which will be inherited by haproxy.
|
||||
|
||||
When set to "on", environment variables are created with the prefix "FD_",
|
||||
followed by the uppercase version of FileDescriptorName from systemd.
|
||||
|
||||
When set to off, the FD_ environment variables derived from
|
||||
FileDescriptorName are unset.
|
||||
|
||||
Limitations:
|
||||
- FileDescriptorName may contain alphanumerical characters and underscores.
|
||||
- variables name cannot exceed 254 characters
|
||||
|
||||
This feature is particularly useful when running HAProxy in a container, as
|
||||
it allows you to avoid constraints from NATing or start containers without
|
||||
network access.
|
||||
|
||||
Example:
|
||||
|
||||
haproxy.socket:
|
||||
[Socket]
|
||||
ListenStream=80
|
||||
FileDescriptorName=http1
|
||||
|
||||
ListenStream=443
|
||||
FileDescriptorName=https1
|
||||
|
||||
haproxy.cfg:
|
||||
global
|
||||
setenv-sd-listen-fds on
|
||||
|
||||
frontend
|
||||
bind fd@${FD_HTTP1}
|
||||
bind fd@${FD_HTTPS1} ssl ...
|
||||
|
||||
Default value is off.
|
||||
|
||||
shm-stats-file <name> [ EXPERIMENTAL ]
|
||||
When this directive is set, it enables the use of shared memory for storing
|
||||
stats counters. <name> is used as argument to shm_open() to open the shared
|
||||
|
||||
@ -7,4 +7,7 @@ int sd_notifyf(int unset_environment, const char *format, ...);
|
||||
int sd_listen_fds_with_names(int unset_environment, char ***names);
|
||||
int sd_listen_fds(int unset_environment);
|
||||
|
||||
void setenv_listen_fds();
|
||||
void unsetenv_listen_fds();
|
||||
|
||||
#endif
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <haproxy/protocol.h>
|
||||
#include <haproxy/stats-file.h>
|
||||
#include <haproxy/stress.h>
|
||||
#include <haproxy/systemd.h>
|
||||
#include <haproxy/tools.h>
|
||||
|
||||
int cluster_secret_isset;
|
||||
@ -1594,6 +1595,33 @@ static int cfg_parse_global_env_opts(char **args, int section_type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cfg_parse_global_listen_fds(char **args, int section_type,
|
||||
struct proxy *curpx, const struct proxy *defpx,
|
||||
const char *file, int line, char **err)
|
||||
{
|
||||
if (strcmp(args[0], "setenv-sd-listen-fds") == 0) {
|
||||
if (too_many_args(1, args, err, NULL))
|
||||
return -1;
|
||||
if (*(args[1]) == 0) {
|
||||
memprintf(err, "'%s' expects a 'on' or 'off' argument.\n",
|
||||
args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(args[1], "on") == 0) {
|
||||
setenv_listen_fds();
|
||||
} else if (strcmp(args[1], "off") == 0) {
|
||||
unsetenv_listen_fds();
|
||||
} else {
|
||||
memprintf(err, "'%s' expects 'on' or 'off' as argument.\n", args[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cfg_parse_global_shm_stats_file(char **args, int section_type,
|
||||
struct proxy *curpx, const struct proxy *defpx,
|
||||
const char *file, int line, char **err)
|
||||
@ -1852,6 +1880,7 @@ static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
{ CFG_GLOBAL, "quiet", cfg_parse_global_mode, KWF_DISCOVERY },
|
||||
{ CFG_GLOBAL, "resetenv", cfg_parse_global_env_opts, KWF_DISCOVERY },
|
||||
{ CFG_GLOBAL, "setenv", cfg_parse_global_env_opts, KWF_DISCOVERY },
|
||||
{ CFG_GLOBAL, "setenv-sd-listen-fds", cfg_parse_global_listen_fds },
|
||||
{ CFG_GLOBAL, "shm-stats-file", cfg_parse_global_shm_stats_file },
|
||||
{ CFG_GLOBAL, "shm-stats-file-max-objects", cfg_parse_global_shm_stats_file_max_objects },
|
||||
{ CFG_GLOBAL, "stress-level", cfg_parse_global_stress_level },
|
||||
|
||||
@ -255,3 +255,63 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Automatically sets environment variables based on LISTEN_FDS and LISTEN_FDNAMES.
|
||||
*
|
||||
* When cleanup is set, unset those environment variables instead.
|
||||
*/
|
||||
static void __setenv_listen_fds(int cleanup)
|
||||
{
|
||||
char **names = NULL;
|
||||
char **p;
|
||||
char d[255] = "FD_";
|
||||
int fd = 3;
|
||||
const char *fdstr = NULL;
|
||||
int i;
|
||||
|
||||
sd_listen_fds_with_names(0, &names);
|
||||
|
||||
p = names;
|
||||
while (names && *names) {
|
||||
char *n;
|
||||
|
||||
/* start to write after FD_ (i = 3) */
|
||||
for (n = *names, i = 3; *n && i < sizeof(d); i++, n++) {
|
||||
if (!isalnum((int)*n) && *n != '_')
|
||||
break;
|
||||
d[i] = toupper(*n);
|
||||
}
|
||||
d[i] = '\0';
|
||||
|
||||
if (!cleanup)
|
||||
fdstr = ultoa(fd);
|
||||
|
||||
if (cleanup)
|
||||
unsetenv(d);
|
||||
else
|
||||
setenv(d, fdstr, 1);
|
||||
names++;
|
||||
fd++;
|
||||
}
|
||||
|
||||
/* free names allocated by sd_listen_fds_with_names() */
|
||||
names = p;
|
||||
while (names && *names) {
|
||||
free(*names);
|
||||
names++;
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
/* Automatically sets environment variables based on LISTEN_FDS and LISTEN_FDNAMES. */
|
||||
void setenv_listen_fds()
|
||||
{
|
||||
__setenv_listen_fds(0);
|
||||
}
|
||||
|
||||
/* Automatically UNsets environment variables based on LISTEN_FDS and LISTEN_FDNAMES. */
|
||||
void unsetenv_listen_fds()
|
||||
{
|
||||
__setenv_listen_fds(1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user