refactor: introduce two-user daemon architecture with socket-based communication
- Add daemon/ module with aiohttp server, sync client, and handler registry - Add daemon/handlers/ for privileged operations (acme, dnsmasq, firewall, logs, nginx, wireguard) - Add system/acme-deploy.py, vacuum-walld sudoers and systemd service - Update API routes to use daemon client instead of lib/ directly - Update lib/, tests/, and webui/ for new architecture - Update docs and deployment scripts
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
<tbody id="interface-list">
|
||||
{% for iface in (interfaces or []) %}
|
||||
<tr>
|
||||
<td><strong>{{ iface.get('name', 'unknown') }}</strong></td>
|
||||
<td><strong>{{ iface.get('display_name', iface.get('name', 'unknown')) }}</strong></td>
|
||||
<td class="text-muted">{{ iface.get('mac', 'N/A') }}</td>
|
||||
<td>
|
||||
{% for ip in iface.get('ips', []) %}
|
||||
@@ -32,16 +32,16 @@
|
||||
{% if not iface.get('ips') %}N/A{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="status-dot {{ 'status-up' if iface.get('state') == 'up' else 'status-down' }}"></span>
|
||||
{{ 'Up' if iface.get('state') == 'up' else 'Down' }}
|
||||
<span class="status-dot {{ 'status-up' if iface.get('state') == 'UP' else 'status-down' }}"></span>
|
||||
{{ 'Up' if iface.get('state') == 'UP' else 'Down' }}
|
||||
</td>
|
||||
<td>
|
||||
{% if zones %}
|
||||
<select
|
||||
hx-on::change="fetch('/api/firewall/zones/'+encodeURIComponent(this.value)+'/interfaces',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({interfaces:['{{ iface.name }}']})}).then(r=>{if(!r.ok)throw r}).then(r=>r.ok?(showSuccessToast('{{ iface.name }} assigned to '+this.value),refreshTable('/api/firewall/interfaces',document.getElementById('interface-list'),renderInterfaces)):r.json().then(j=>{throw new Error(j.error||r.statusText)})).catch(e=>{showErrorToast(e.message);this.selectedIndex=0})"
|
||||
hx-on::change="fetch('/api/firewall/zones/'+encodeURIComponent(this.value)+'/interfaces',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({interfaces:['{{ iface.name }}']})}).then(r=>{if(!r.ok)throw r}).then(r=>r.ok?(showSuccessToast('{{ iface.display_name }} assigned to '+this.value),refreshTable('/api/firewall/interfaces',document.getElementById('interface-list'),renderInterfaces)):r.json().then(j=>{throw new Error(j.error||r.statusText)})).catch(e=>{showErrorToast(e.message);this.selectedIndex=0})"
|
||||
>
|
||||
{% for zone in zones %}
|
||||
<option value="{{ zone.get('name', '') }}" {% if zone.get('name') == iface.get('zone') %}selected{% endif %}>{{ zone.get('name', '') }}</option>
|
||||
{% for zname in zones %}
|
||||
<option value="{{ zname }}" {% if zname == iface.get('zone') %}selected{% endif %}>{{ zname }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
|
||||
@@ -102,19 +102,19 @@
|
||||
{% set all_forwards = [] %}
|
||||
{% for zone in (zones or []) %}
|
||||
{% for fwd in zone.get('forward_ports', []) %}
|
||||
{% set _ = all_forwards.append({'zone': zone.get('name'), 'proxy-protocol': fwd.get('proxy-protocol'), 'port': fwd.get('port'), 'to-addr': fwd.get('to-addr'), 'to-port': fwd.get('to-port')}) %}
|
||||
{% set _ = all_forwards.append({'zone': zone.get('name'), 'proto': fwd.get('proto'), 'port': fwd.get('port'), 'toaddr': fwd.get('toaddr'), 'toport': fwd.get('toport')}) %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for fwd in all_forwards %}
|
||||
<tr>
|
||||
<td><strong>{{ fwd.zone }}</strong></td>
|
||||
<td><span class="badge badge-info">{{ fwd['proxy-protocol'] }}</span></td>
|
||||
<td><span class="badge badge-info">{{ fwd.proto }}</span></td>
|
||||
<td>{{ fwd.port }}</td>
|
||||
<td>{{ fwd['to-addr'] }}</td>
|
||||
<td>{{ fwd['to-port'] }}</td>
|
||||
<td>{{ fwd.toaddr }}</td>
|
||||
<td>{{ fwd.toport }}</td>
|
||||
<td>
|
||||
<form hx-delete="/api/firewall/forward-port/{{ fwd.zone }}/{{ fwd.port }}/{{ fwd['proxy-protocol'] }}" hx-swap="none" hx-on::after-request="if(evt.detail.successful){ refreshTable('/api/firewall/config', document.getElementById('forward-rows'), renderForwardsFromConfig); showSuccessToast('Rule removed'); }">
|
||||
<button type="submit" class="btn btn-sm btn-danger" hx-confirm="Remove forward rule {{ fwd.port }}/{{ fwd['proxy-protocol'] }} → {{ fwd['to-addr'] }}:{{ fwd['to-port'] }}?">Remove</button>
|
||||
<form hx-delete="/api/firewall/forward-port/{{ fwd.zone }}/{{ fwd.port }}/{{ fwd.proto }}" hx-swap="none" hx-on::after-request="if(evt.detail.successful){ refreshTable('/api/firewall/config', document.getElementById('forward-rows'), renderForwardsFromConfig); showSuccessToast('Rule removed'); }">
|
||||
<button type="submit" class="btn btn-sm btn-danger" hx-confirm="Remove forward rule {{ fwd.port }}/{{ fwd.proto }} → {{ fwd.toaddr }}:{{ fwd.toport }}?">Remove</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user