feat: Settings changes now apply to real service config files and restart containers

Each service manager now has apply_config() that writes to the actual config:
- network: dhcp_range → dnsmasq.conf (reload cell-dhcp), ntp_servers → chrony.conf
  (restart cell-ntp), domain → dnsmasq.conf domain= line
- email: domain → mailserver.env OVERRIDE_HOSTNAME + POSTMASTER_ADDRESS,
  restart cell-mail
- wireguard: port/address/private_key → wg0.conf ListenPort/Address/PrivateKey,
  restart cell-wireguard
- calendar: port → radicale config hosts=, restart cell-radicale

PUT /api/config now calls apply_config() after persisting JSON, and returns
{restarted: [...], warnings: [...]} so Settings UI can show which containers
were restarted. _restart_container() helper added to BaseServiceManager.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 04:27:22 -04:00
parent ae73246878
commit 87ff50c378
7 changed files with 237 additions and 12 deletions
+14 -4
View File
@@ -317,13 +317,23 @@ function Settings() {
useEffect(() => { loadAll(); }, [loadAll]);
const _applyResult = (res, label) => {
const { restarted = [], warnings = [] } = res.data || {};
if (restarted.length > 0) {
toast(`${label} saved — restarted: ${restarted.join(', ')}`);
} else {
toast(`${label} saved`);
}
warnings.forEach((w) => toast(w, 'warning'));
};
// identity save
const saveIdentity = async () => {
setIdentitySaving(true);
try {
await cellAPI.updateConfig(identity);
const res = await cellAPI.updateConfig(identity);
setIdentityDirty(false);
toast('Cell identity saved');
_applyResult(res, 'Cell identity');
} catch {
toast('Failed to save identity', 'error');
} finally {
@@ -335,9 +345,9 @@ function Settings() {
const saveService = async (key) => {
setServiceSaving((s) => ({ ...s, [key]: true }));
try {
await cellAPI.updateConfig({ [key]: serviceConfigs[key] });
const res = await cellAPI.updateConfig({ [key]: serviceConfigs[key] });
setServiceDirty((d) => ({ ...d, [key]: false }));
toast(`${key} configuration saved`);
_applyResult(res, key);
} catch {
toast(`Failed to save ${key} config`, 'error');
} finally {