diff --git a/changelog.d/5970.docker b/changelog.d/5970.docker new file mode 100644 index 0000000000..c9d04da9cd --- /dev/null +++ b/changelog.d/5970.docker @@ -0,0 +1 @@ +Avoid changing UID/GID if they are already correct. diff --git a/docker/start.py b/docker/start.py index 40a861f200..260f2d9943 100755 --- a/docker/start.py +++ b/docker/start.py @@ -41,8 +41,8 @@ def generate_config_from_template(config_dir, config_path, environ, ownership): config_dir (str): where to put generated config files config_path (str): where to put the main config file environ (dict): environment dictionary - ownership (str): ":" string which will be used to set - ownership of the generated configs + ownership (str|None): ":" string which will be used to set + ownership of the generated configs. If None, ownership will not change. """ for v in ("SYNAPSE_SERVER_NAME", "SYNAPSE_REPORT_STATS"): if v not in environ: @@ -105,24 +105,24 @@ def generate_config_from_template(config_dir, config_path, environ, ownership): log("Generating log config file " + log_config_file) convert("/conf/log.config", log_config_file, environ) - subprocess.check_output(["chown", "-R", ownership, "/data"]) - # Hopefully we already have a signing key, but generate one if not. - subprocess.check_output( - [ - "su-exec", - ownership, - "python", - "-m", - "synapse.app.homeserver", - "--config-path", - config_path, - # tell synapse to put generated keys in /data rather than /compiled - "--keys-directory", - config_dir, - "--generate-keys", - ] - ) + args = [ + "python", + "-m", + "synapse.app.homeserver", + "--config-path", + config_path, + # tell synapse to put generated keys in /data rather than /compiled + "--keys-directory", + config_dir, + "--generate-keys", + ] + + if ownership is not None: + subprocess.check_output(["chown", "-R", ownership, "/data"]) + args = ["su-exec", ownership] + args + + subprocess.check_output(args) def run_generate_config(environ, ownership): @@ -130,7 +130,7 @@ def run_generate_config(environ, ownership): Args: environ (dict): env var dict - ownership (str): "userid:groupid" arg for chmod + ownership (str|None): "userid:groupid" arg for chmod. If None, ownership will not change. Never returns. """ @@ -149,9 +149,6 @@ def run_generate_config(environ, ownership): log("Creating log config %s" % (log_config_file,)) convert("/conf/log.config", log_config_file, environ) - # make sure that synapse has perms to write to the data dir. - subprocess.check_output(["chown", ownership, data_dir]) - args = [ "python", "-m", @@ -170,12 +167,33 @@ def run_generate_config(environ, ownership): "--open-private-ports", ] # log("running %s" % (args, )) - os.execv("/usr/local/bin/python", args) + + if ownership is not None: + args = ["su-exec", ownership] + args + os.execv("/sbin/su-exec", args) + + # make sure that synapse has perms to write to the data dir. + subprocess.check_output(["chown", ownership, data_dir]) + else: + os.execv("/usr/local/bin/python", args) def main(args, environ): mode = args[1] if len(args) > 1 else None - ownership = "{}:{}".format(environ.get("UID", 991), environ.get("GID", 991)) + desired_uid = int(environ.get("UID", "991")) + desired_gid = int(environ.get("GID", "991")) + if (desired_uid == os.getuid()) and (desired_gid == os.getgid()): + ownership = None + else: + ownership = "{}:{}".format(desired_uid, desired_gid) + + log( + "Container running as UserID %s:%s, ENV (or defaults) requests %s:%s" + % (os.getuid(), os.getgid(), desired_uid, desired_gid) + ) + + if ownership is None: + log("Will not perform chmod/su-exec as UserID already matches request") # In generate mode, generate a configuration and missing keys, then exit if mode == "generate": @@ -227,16 +245,12 @@ def main(args, environ): log("Starting synapse with config file " + config_path) - args = [ - "su-exec", - ownership, - "python", - "-m", - "synapse.app.homeserver", - "--config-path", - config_path, - ] - os.execv("/sbin/su-exec", args) + args = ["python", "-m", "synapse.app.homeserver", "--config-path", config_path] + if ownership is not None: + args = ["su-exec", ownership] + args + os.execv("/sbin/su-exec", args) + else: + os.execv("/usr/local/bin/python", args) if __name__ == "__main__":