refactor: Network Services rebuilt, DHCP decommissioned, infra cleanup
Network Services page is rebuilt around real API data: GET /api/dns/overview returns provider-aware records; per-service Cloudflare sync is exposed via POST /api/ddns/sync; effective domain is displayed so operators can verify what external name resolves to the cell; NTP status reflects the actual systemd-timesyncd state rather than a hardcoded boolean. DHCP is fully decommissioned: the cell-dhcp container is removed from docker-compose.yml, DHCP methods are stripped from network_manager, the setup_cell script no longer seeds DHCP config, and the Settings DHCP field is gone. DHCP was never a PIC responsibility and the container was consuming resources for no benefit. Dead code removed: api/config.py (superseded by config_manager), the standalone Email/Calendar/Files pages (these are now optional store services and do not need dedicated pages). api/constants.py is introduced to hold RESERVED_SUBDOMAINS in one place rather than scattered literals. Docker resource limits (mem_limit, cpus, pids_limit) are added to all compose services so a runaway process cannot starve the host. Makefile gains a warning before the backup target so operators are not surprised by the archive path. Settings same/accept state fix ensures the Cell Identity section correctly shows the accept/discard banner and does not flash a false-positive change indicator on first load. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+37
@@ -355,6 +355,15 @@ def _restore_cell_wg_peers(cell_links):
|
||||
|
||||
def _apply_startup_enforcement():
|
||||
try:
|
||||
# Regenerate the Caddyfile from current config before anything else so a
|
||||
# stale on-disk file (e.g. one written by an older image, missing the
|
||||
# `admin 0.0.0.0:2019` directive) can't permanently wedge the health
|
||||
# monitor into restarting Caddy every few minutes. Done first so the
|
||||
# later service_store/identity regenerations don't debounce it away.
|
||||
try:
|
||||
caddy_manager.regenerate_with_installed([])
|
||||
except Exception as _cre:
|
||||
logger.warning(f"startup Caddyfile regeneration failed (non-fatal): {_cre}")
|
||||
peers = peer_registry.list_peers()
|
||||
cell_links = cell_link_manager.list_connections()
|
||||
firewall_manager.reconcile_stale_peer_rules(peers)
|
||||
@@ -857,6 +866,34 @@ def connectivity_upload_openvpn():
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/connectivity/exits/sshuttle', methods=['POST'])
|
||||
def connectivity_configure_sshuttle():
|
||||
"""Configure the sshuttle (SSH tunnel) exit. Secrets are never echoed back."""
|
||||
try:
|
||||
data = request.get_json(silent=True) or {}
|
||||
result = connectivity_manager.configure_sshuttle(data)
|
||||
if result.get('ok'):
|
||||
return jsonify({'ok': True})
|
||||
return jsonify({'ok': False, 'error': result.get('error', 'invalid config')}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"connectivity_configure_sshuttle: {e}")
|
||||
return jsonify({'error': 'internal error'}), 500
|
||||
|
||||
|
||||
@app.route('/api/connectivity/exits/proxy', methods=['POST'])
|
||||
def connectivity_configure_proxy():
|
||||
"""Configure the upstream proxy (redsocks) exit. Secrets are never echoed back."""
|
||||
try:
|
||||
data = request.get_json(silent=True) or {}
|
||||
result = connectivity_manager.configure_proxy(data)
|
||||
if result.get('ok'):
|
||||
return jsonify({'ok': True})
|
||||
return jsonify({'ok': False, 'error': result.get('error', 'invalid config')}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"connectivity_configure_proxy: {e}")
|
||||
return jsonify({'error': 'internal error'}), 500
|
||||
|
||||
|
||||
@app.route('/api/connectivity/exits/apply', methods=['POST'])
|
||||
def connectivity_apply_routes():
|
||||
"""Idempotently re-apply all connectivity policy routing rules."""
|
||||
|
||||
Reference in New Issue
Block a user