fix(control-panel/sftp): create shared fpm group before useradd
Provisioning failed on a stock host because `useradd -g <fpm_gid>` (82, the alpine www-data gid) requires a group at that gid, which no host baseline creates. Add ensure_fpm_group(): create a `heleos-web` group at fpm_gid if absent, before the SFTP user is created. Idempotent; resolves the open item noted in site-templates/README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
a90d07875d
commit
638fb24593
1 changed files with 20 additions and 0 deletions
|
|
@ -19,6 +19,11 @@ from .runner import Runner
|
||||||
|
|
||||||
SSHD_DROPIN = "/etc/ssh/sshd_config.d/sftp-{customer}.conf"
|
SSHD_DROPIN = "/etc/ssh/sshd_config.d/sftp-{customer}.conf"
|
||||||
|
|
||||||
|
# Host group (at fpm_gid) shared by php-fpm and every customer's SFTP user. The
|
||||||
|
# alpine images run www-data as uid/gid 82, but a stock host has no group at that
|
||||||
|
# gid, so useradd -g <fpm_gid> would fail. Created once per host.
|
||||||
|
FPM_GROUP_NAME = "heleos-web"
|
||||||
|
|
||||||
|
|
||||||
def _user_exists(runner: Runner, user: str) -> bool:
|
def _user_exists(runner: Runner, user: str) -> bool:
|
||||||
if runner.dry_run:
|
if runner.dry_run:
|
||||||
|
|
@ -27,6 +32,20 @@ def _user_exists(runner: Runner, user: str) -> bool:
|
||||||
return out.strip().isdigit()
|
return out.strip().isdigit()
|
||||||
|
|
||||||
|
|
||||||
|
def _group_exists(runner: Runner, gid: int) -> bool:
|
||||||
|
if runner.dry_run:
|
||||||
|
return False
|
||||||
|
out = runner.run(["getent", "group", str(gid)], check=False, capture=True)
|
||||||
|
return bool(out.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_fpm_group(runner: Runner, cfg: Config) -> None:
|
||||||
|
"""Ensure a group with gid == fpm_gid exists so the SFTP user's primary group
|
||||||
|
(and the setgid web root) can share it with php-fpm. Idempotent."""
|
||||||
|
if not _group_exists(runner, cfg.fpm_gid):
|
||||||
|
runner.run(["groupadd", "-g", str(cfg.fpm_gid), FPM_GROUP_NAME])
|
||||||
|
|
||||||
|
|
||||||
def set_web_ownership(runner: Runner, cfg: Config, site: Site) -> None:
|
def set_web_ownership(runner: Runner, cfg: Config, site: Site) -> None:
|
||||||
web = context.webroot(cfg, site)
|
web = context.webroot(cfg, site)
|
||||||
runner.run(["chown", "-R", f"{cfg.fpm_uid}:{cfg.fpm_gid}", web])
|
runner.run(["chown", "-R", f"{cfg.fpm_uid}:{cfg.fpm_gid}", web])
|
||||||
|
|
@ -45,6 +64,7 @@ def ensure_customer_account(runner: Runner, cfg: Config, customer: str,
|
||||||
home = f"{cfg.customers_root}/{customer}"
|
home = f"{cfg.customers_root}/{customer}"
|
||||||
created = not _user_exists(runner, user)
|
created = not _user_exists(runner, user)
|
||||||
if created:
|
if created:
|
||||||
|
ensure_fpm_group(runner, cfg) # useradd -g <fpm_gid> needs this group
|
||||||
runner.run([
|
runner.run([
|
||||||
"useradd", "-M", "-N",
|
"useradd", "-M", "-N",
|
||||||
"-g", str(cfg.fpm_gid), # primary group = fpm group
|
"-g", str(cfg.fpm_gid), # primary group = fpm group
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue