diff --git a/daemons/execd/remoted_pidone.c b/daemons/execd/remoted_pidone.c
index e8d7c7690d..96fee90c07 100644
--- a/daemons/execd/remoted_pidone.c
+++ b/daemons/execd/remoted_pidone.c
@@ -1,298 +1,301 @@
 /*
  * Copyright 2017-2023 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <stdio.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <crm/crm.h>
 #include "pacemaker-execd.h"
 
 static pid_t main_pid = 0;
 
 static void
 sigdone(void)
 {
     exit(CRM_EX_OK);
 }
 
 static void
 sigreap(void)
 {
     pid_t pid = 0;
     int status;
 
     do {
         /*
          * Opinions seem to differ as to what to put here:
          *  -1, any child process
          *  0,  any child process whose process group ID is equal to that of the calling process
          */
         pid = waitpid(-1, &status, WNOHANG);
         if (pid == main_pid) {
             /* Exit when pacemaker-remote exits and use the same return code */
             if (WIFEXITED(status)) {
                 exit(WEXITSTATUS(status));
             }
             exit(CRM_EX_ERROR);
         }
     } while (pid > 0);
 }
 
 static struct {
     int sig;
     void (*handler)(void);
 } sigmap[] = {
     { SIGCHLD, sigreap },
     { SIGINT,  sigdone },
 };
 
 /*!
  * \internal
  * \brief Check a line of text for a valid environment variable name
  *
  * \param[in]  line  Text to check
  * \param[out] first  First character of valid name if found, NULL otherwise
  * \param[out] last   Last character of valid name if found, NULL otherwise
  *
  * \return TRUE if valid name found, FALSE otherwise
  * \note It's reasonable to impose limitations on environment variable names
  *       beyond what C or setenv() does: We only allow names that contain only
  *       [a-zA-Z0-9_] characters and do not start with a digit.
  */
 static bool
 find_env_var_name(char *line, char **first, char **last)
 {
     // Skip leading whitespace
     *first = line;
     while (isspace(**first)) {
         ++*first;
     }
 
     if (isalpha(**first) || (**first == '_')) { // Valid first character
         *last = *first;
         while (isalnum(*(*last + 1)) || (*(*last + 1) == '_')) {
             ++*last;
         }
         return TRUE;
     }
 
     *first = *last = NULL;
     return FALSE;
 }
 
 static void
 load_env_vars(const char *filename)
 {
     /* We haven't forked or initialized logging yet, so don't leave any file
      * descriptors open, and don't log -- silently ignore errors.
      */
     FILE *fp = fopen(filename, "r");
 
     if (fp != NULL) {
         char line[LINE_MAX] = { '\0', };
 
         while (fgets(line, LINE_MAX, fp) != NULL) {
             char *name = NULL;
             char *end = NULL;
             char *value = NULL;
             char *quote = NULL;
 
             // Look for valid name immediately followed by equals sign
             if (find_env_var_name(line, &name, &end) && (*++end == '=')) {
 
                 // Null-terminate name, and advance beyond equals sign
                 *end++ = '\0';
 
                 // Check whether value is quoted
                 if ((*end == '\'') || (*end == '"')) {
                     quote = end++;
                 }
                 value = end;
 
                 if (quote) {
                     /* Value is remaining characters up to next non-backslashed
                      * matching quote character.
                      */
                     while (((*end != *quote) || (*(end - 1) == '\\'))
                            && (*end != '\0')) {
                         end++;
                     }
                     if (*end == *quote) {
                         // Null-terminate value, and advance beyond close quote
                         *end++ = '\0';
                     } else {
                         // Matching closing quote wasn't found
                         value = NULL;
                     }
 
                 } else {
                     /* Value is remaining characters up to next non-backslashed
                      * whitespace.
                      */
                     while ((!isspace(*end) || (*(end - 1) == '\\'))
                            && (*end != '\0')) {
                         ++end;
                     }
 
                     if (end == (line + LINE_MAX - 1)) {
                         // Line was too long
                         value = NULL;
                     }
                     // Do NOT null-terminate value (yet)
                 }
 
                 /* We have a valid name and value, and end is now the character
                  * after the closing quote or the first whitespace after the
                  * unquoted value. Make sure the rest of the line is just
                  * whitespace or a comment.
                  */
                 if (value) {
                     char *value_end = end;
 
                     while (isspace(*end) && (*end != '\n')) {
                         ++end;
                     }
                     if ((*end == '\n') || (*end == '#')) {
                         if (quote == NULL) {
                             // Now we can null-terminate an unquoted value
                             *value_end = '\0';
                         }
 
                         // Don't overwrite (bundle options take precedence)
                         setenv(name, value, 0);
 
                     } else {
                         value = NULL;
                     }
                 }
             }
 
             if ((value == NULL) && (strchr(line, '\n') == NULL)) {
                 // Eat remainder of line beyond LINE_MAX
                 if (fscanf(fp, "%*[^\n]\n") == EOF) {
                     value = NULL; // Don't care, make compiler happy
                 }
             }
         }
         fclose(fp);
     }
 }
 
 void
 remoted_spawn_pidone(int argc, char **argv, char **envp)
 {
     sigset_t set;
 
     /* This environment variable exists for two purposes:
      * - For testing, setting it to "full" enables full PID 1 behavior even
      *   when PID is not 1
      * - Setting to "vars" enables just the loading of environment variables
      *   from /etc/pacemaker/pcmk-init.env, which could be useful for testing or
      *   containers with a custom PID 1 script that launches pacemaker-remoted.
      */
-    const char *pid1 = (getpid() == 1)? "full" : getenv("PCMK_remote_pid1");
+    const char *pid1 = "full";
 
-    if (pid1 == NULL) {
-        return;
+    if (getpid() != 1) {
+        pid1 = pcmk__env_option(PCMK__ENV_REMOTE_PID1);
+        if (pid1 == NULL) {
+            return;
+        }
     }
 
     /* When a container is launched, it may be given specific environment
      * variables, which for Pacemaker bundles are given in the bundle
      * configuration. However, that does not allow for host-specific values.
      * To allow for that, look for a special file containing a shell-like syntax
      * of name/value pairs, and export those into the environment.
      */
     load_env_vars("/etc/pacemaker/pcmk-init.env");
 
     if (strcmp(pid1, "full")) {
         return;
     }
 
     /* Containers can be expected to have /var/log, but they may not have
      * /var/log/pacemaker, so use a different default if no value has been
      * explicitly configured in the container's environment.
      */
     if (pcmk__env_option(PCMK__ENV_LOGFILE) == NULL) {
         pcmk__set_env_option(PCMK__ENV_LOGFILE, "/var/log/pcmk-init.log", true);
     }
 
     sigfillset(&set);
     sigprocmask(SIG_BLOCK, &set, 0);
 
     main_pid = fork();
     switch (main_pid) {
         case 0:
             sigprocmask(SIG_UNBLOCK, &set, NULL);
             setsid();
             setpgid(0, 0);
 
             // Child remains as pacemaker-remoted
             return;
         case -1:
             crm_err("fork failed: %s", pcmk_rc_str(errno));
     }
 
     /* Parent becomes the reaper of zombie processes */
     /* Safe to initialize logging now if needed */
 
 #  ifdef HAVE_PROGNAME
     /* Differentiate ourselves in the 'ps' output */
     {
         char *p;
         int i, maxlen;
         char *LastArgv = NULL;
         const char *name = "pcmk-init";
 
         for (i = 0; i < argc; i++) {
             if (!i || (LastArgv + 1 == argv[i]))
                 LastArgv = argv[i] + strlen(argv[i]);
         }
 
         for (i = 0; envp[i] != NULL; i++) {
             if ((LastArgv + 1) == envp[i]) {
                 LastArgv = envp[i] + strlen(envp[i]);
             }
         }
 
         maxlen = (LastArgv - argv[0]) - 2;
 
         i = strlen(name);
 
         /* We can overwrite individual argv[] arguments */
         snprintf(argv[0], maxlen, "%s", name);
 
         /* Now zero out everything else */
         p = &argv[0][i];
         while (p < LastArgv) {
             *p++ = '\0';
         }
         argv[1] = NULL;
     }
 #  endif // HAVE_PROGNAME
 
     while (1) {
         int sig;
         size_t i;
 
         sigwait(&set, &sig);
         for (i = 0; i < PCMK__NELEM(sigmap); i++) {
             if (sigmap[i].sig == sig) {
                 sigmap[i].handler();
                 break;
             }
         }
     }
 }
diff --git a/include/crm/common/options_internal.h b/include/crm/common/options_internal.h
index a7e2006ff9..dbac1344f4 100644
--- a/include/crm/common/options_internal.h
+++ b/include/crm/common/options_internal.h
@@ -1,128 +1,129 @@
 /*
  * Copyright 2006-2023 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__OPTIONS_INTERNAL__H
 #  define PCMK__OPTIONS_INTERNAL__H
 
 #  ifndef PCMK__CONFIG_H
 #    define PCMK__CONFIG_H
 #    include <config.h>   // _Noreturn
 #  endif
 
 #  include <glib.h>     // GHashTable
 #  include <stdbool.h>  // bool
 
 _Noreturn void pcmk__cli_help(char cmd);
 
 
 /*
  * Environment variable option handling
  */
 
 const char *pcmk__env_option(const char *option);
 void pcmk__set_env_option(const char *option, const char *value, bool compat);
 bool pcmk__env_option_enabled(const char *daemon, const char *option);
 
 
 /*
  * Cluster option handling
  */
 
 typedef struct pcmk__cluster_option_s {
     const char *name;
     const char *alt_name;
     const char *type;
     const char *values;
     const char *default_value;
 
     bool (*is_valid)(const char *);
 
     const char *description_short;
     const char *description_long;
 
 } pcmk__cluster_option_t;
 
 const char *pcmk__cluster_option(GHashTable *options,
                                  const pcmk__cluster_option_t *option_list,
                                  int len, const char *name);
 
 gchar *pcmk__format_option_metadata(const char *name, const char *desc_short,
                                     const char *desc_long,
                                     pcmk__cluster_option_t *option_list,
                                     int len);
 
 void pcmk__validate_cluster_options(GHashTable *options,
                                     pcmk__cluster_option_t *option_list,
                                     int len);
 
 bool pcmk__valid_interval_spec(const char *value);
 bool pcmk__valid_boolean(const char *value);
 bool pcmk__valid_number(const char *value);
 bool pcmk__valid_positive_number(const char *value);
 bool pcmk__valid_quorum(const char *value);
 bool pcmk__valid_script(const char *value);
 bool pcmk__valid_percentage(const char *value);
 
 // from watchdog.c
 long pcmk__get_sbd_timeout(void);
 bool pcmk__get_sbd_sync_resource_startup(void);
 long pcmk__auto_watchdog_timeout(void);
 bool pcmk__valid_sbd_timeout(const char *value);
 
 // Constants for environment variable names
 #define PCMK__ENV_BLACKBOX                  "blackbox"
 #define PCMK__ENV_CALLGRIND_ENABLED         "callgrind_enabled"
 #define PCMK__ENV_CLUSTER_TYPE              "cluster_type"
 #define PCMK__ENV_DEBUG                     "debug"
 #define PCMK__ENV_FAIL_FAST                 "fail_fast"
 #define PCMK__ENV_LOGFACILITY               "logfacility"
 #define PCMK__ENV_LOGFILE                   "logfile"
 #define PCMK__ENV_LOGPRIORITY               "logpriority"
 #define PCMK__ENV_NODE_START_STATE          "node_start_state"
 #define PCMK__ENV_PHYSICAL_HOST             "physical_host"
+#define PCMK__ENV_REMOTE_PID1               "remote_pid1"
 #define PCMK__ENV_REMOTE_PORT               "remote_port"
 #define PCMK__ENV_RESPAWNED                 "respawned"
 #define PCMK__ENV_SERVICE                   "service"
 #define PCMK__ENV_SHUTDOWN_DELAY            "shutdown_delay"
 #define PCMK__ENV_STDERR                    "stderr"
 #define PCMK__ENV_VALGRIND_ENABLED          "valgrind_enabled"
 
 // @COMPAT Drop at 3.0.0; likely last used in 1.1.24
 #define PCMK__ENV_MCP                       "mcp"
 
 // @COMPAT Drop at 3.0.0; added unused in 1.1.9
 #define PCMK__ENV_QUORUM_TYPE               "quorum_type"
 
 // Constants for cluster option names
 #define PCMK__OPT_NODE_HEALTH_BASE          "node-health-base"
 #define PCMK__OPT_NODE_HEALTH_GREEN         "node-health-green"
 #define PCMK__OPT_NODE_HEALTH_RED           "node-health-red"
 #define PCMK__OPT_NODE_HEALTH_STRATEGY      "node-health-strategy"
 #define PCMK__OPT_NODE_HEALTH_YELLOW        "node-health-yellow"
 
 // Constants for meta-attribute names
 #define PCMK__META_ALLOW_UNHEALTHY_NODES    "allow-unhealthy-nodes"
 
 // Constants for enumerated values for various options
 #define PCMK__VALUE_CLUSTER                 "cluster"
 #define PCMK__VALUE_CUSTOM                  "custom"
 #define PCMK__VALUE_FENCING                 "fencing"
 #define PCMK__VALUE_GREEN                   "green"
 #define PCMK__VALUE_LOCAL                   "local"
 #define PCMK__VALUE_MIGRATE_ON_RED          "migrate-on-red"
 #define PCMK__VALUE_NONE                    "none"
 #define PCMK__VALUE_NOTHING                 "nothing"
 #define PCMK__VALUE_ONLY_GREEN              "only-green"
 #define PCMK__VALUE_PROGRESSIVE             "progressive"
 #define PCMK__VALUE_QUORUM                  "quorum"
 #define PCMK__VALUE_RED                     "red"
 #define PCMK__VALUE_UNFENCING               "unfencing"
 #define PCMK__VALUE_YELLOW                  "yellow"
 
 #endif // PCMK__OPTIONS_INTERNAL__H