| 1 | #!/usr/bin/env python3 |
| 2 | import json |
| 3 | import os |
| 4 | from pathlib import Path |
| 5 | import re |
| 6 | import subprocess |
| 7 | import sys |
| 8 | |
| 9 | |
| 10 | data = json.load(sys.stdin) |
| 11 | root = Path(data["hostRoot"]) / "cfg" |
| 12 | service = Path(data["hostRoot"]).name |
| 13 | secret = json.loads(subprocess.check_output( |
| 14 | ["nomad", "var", "get", "-out=json", f"nomad/jobs/{service}"], |
| 15 | text=True, stderr=subprocess.DEVNULL, |
| 16 | ))["Items"]["idp_header"] |
| 17 | if not re.fullmatch(r"[0-9a-f]{32}", secret): |
| 18 | raise ValueError("invalid Copyparty identity secret") |
| 19 | config = Path(__file__).with_name("copyparty.conf").read_text() |
| 20 | if config.count("STUDIO_IDP_HEADER") != 1: |
| 21 | raise ValueError("expected one Copyparty identity header marker") |
| 22 | config = config.replace("STUDIO_IDP_HEADER", "X-Studio-Idp-" + secret) |
| 23 | if config.count("STUDIO_MIN_FREE_GB") != 1: |
| 24 | raise ValueError("expected one Copyparty free-space marker") |
| 25 | capacity = os.statvfs(data["hostRoot"]) |
| 26 | reserve = max(1, min(16, capacity.f_blocks * capacity.f_frsize // (4 * 10**9))) |
| 27 | config = config.replace("STUDIO_MIN_FREE_GB", str(reserve)) |
| 28 | target = root / "copyparty.conf" |
| 29 | if not target.exists() or target.read_text() != config: |
| 30 | pending = root / ".copyparty.conf.pending" |
| 31 | pending.write_text(config) |
| 32 | os.chmod(pending, 0o600) |
| 33 | os.chown(pending, data["uid"], data["uid"]) |
| 34 | os.replace(pending, target) |
| 35 | os.chmod(target, 0o600) |
| 36 | os.chown(target, data["uid"], data["uid"]) |