Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.


## [v3.0.9] - 2026-03-21

### Added
- **Cloudflare Zero Trust — Secure Agent Communication:** DockFlare Master can now automatically provision a Cloudflare Service Token and a scoped Access Application for the agent API (`/api/v2/agents/`). Once configured, all agent traffic is authenticated at the Cloudflare edge before reaching the server, eliminating the need for a separate private network (Tailscale, VPN, etc.).
- One-click setup and removal from the Agents page — no Cloudflare dashboard visit required.
Expand All @@ -23,6 +23,7 @@ All notable changes to this project will be documented in this file.
- **Agents Table — Visual Polish:** Refreshed header style (uppercase, muted, semibold), consistent cell padding, and a muted `—` dash for missing values.
- **Cloudflared Version Display:** The Cloudflared Version column now shows live data (version + platform sub-line) instead of a hardcoded fallback value.
- **Multi-Server-Agent.md:** Updated the agent deployment guide — `cloudflared` image tag changed from pinned `2025.9.0` to `latest`; one-liner deploy is clearly marked as opt-in; Option A (one-liner) and Option B (manual compose) are presented as distinct paths; removed stale pre-publication note.
- **Mobile UI Optimization:** Converted fixed-width tables across the web UI to responsive card-style layouts on small screens using a CSS `data-label` pattern. Affected pages include the dashboard, settings, access policies, identity providers, and zone policies. Thanks to [@nguyenhuy158](https://github.com/nguyenhuy158) ([#337](https://github.com/ChrispyBacon-dev/DockFlare/pull/337)) — *2026-03-28*

### Fixed
- **Agent `thread_health_status` NameError:** Fixed a crash in the DockFlare Agent where `thread_health_status` and `last_successful_master_contact` were referenced before being declared at module level.
Expand Down
2 changes: 1 addition & 1 deletion dockflare/app/static/css/output.css

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions dockflare/app/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -1593,8 +1593,8 @@ function renderIdPTable(idps) {
};

let tableHTML = `
<table class="table table-zebra table-sm policy-table w-full">
<colgroup>
<table class="table table-zebra table-sm policy-table w-full table-responsive">
<colgroup class="hidden md:table-column-group">
<col class="col-primary">
<col class="col-secondary">
<col class="col-tertiary">
Expand All @@ -1621,18 +1621,18 @@ function renderIdPTable(idps) {

tableHTML += `
<tr>
<td class="p-3">
<td class="p-3" data-label="${t('js.table.provider')}">
<div class="flex items-center gap-3">
<span class="inline-flex items-center justify-center">${icon}</span>
<div class="font-medium">${idpData.name}</div>
</div>
</td>
<td class="p-3 text-xs opacity-70">
<td class="p-3 text-xs opacity-70" data-label="${t('js.table.cloudflare_id')}">
${idpData.cloudflare_id ? `<span class="tooltip" data-tip="${idpData.cloudflare_id}"><code>${idpData.cloudflare_id.slice(0, 8)}...</code></span>` : '-'}
</td>
<td class="p-3 text-sm opacity-80">${idpData.type}</td>
<td class="p-3">${statusBadge}</td>
<td class="p-3 text-right">
<td class="p-3 text-sm opacity-80" data-label="${t('js.table.connector')}">${idpData.type}</td>
<td class="p-3" data-label="${t('js.table.status')}">${statusBadge}</td>
<td class="p-3 text-right" data-label="${t('js.table.actions')}">
<div class="dropdown dropdown-end">
<label tabindex="0" class="btn btn-ghost btn-sm">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
Expand Down
72 changes: 37 additions & 35 deletions dockflare/app/templates/access_policies.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ <h2 class="card-title text-2xl sm:text-3xl">
</select>
</div>
</div>
<div class="flex gap-2 mt-4 sm:mt-0">
<button id="sync-cloudflare-btn" class="btn btn-sm btn-secondary">
<div class="flex flex-col sm:flex-row gap-2 mt-4 sm:mt-0 w-full sm:w-auto">
<button id="sync-cloudflare-btn" class="btn btn-sm btn-secondary w-full sm:w-auto">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 mr-2"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" /></svg>
{{ t('policies.sync_from_cloudflare') }}
</button>
<button id="create-access-group-btn" class="btn btn-sm btn-primary">
<button id="create-access-group-btn" class="btn btn-sm btn-primary w-full sm:w-auto">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 mr-2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg>
{{ t('policies.create_new_group') }}
</button>
Expand All @@ -42,8 +42,8 @@ <h2 class="card-title text-2xl sm:text-3xl">

{% if access_groups and access_groups.items() %}
<div class="overflow-x-auto table-container">
<table class="table table-zebra policy-table w-full" id="access-groups-table">
<colgroup>
<table class="table table-zebra policy-table w-full table-responsive" id="access-groups-table">
<colgroup class="hidden md:table-column-group">
<col class="col-primary">
<col class="col-secondary">
<col class="col-tertiary">
Expand All @@ -68,7 +68,7 @@ <h2 class="card-title text-2xl sm:text-3xl">
{% set policy_type_label = 'system' %}
{% endif %}
<tr data-policy-type="{{ policy_type_label }}" data-group-id="{{ group_id }}">
<td class="px-4 py-3 cell-top">
<td class="px-4 py-3 cell-top" data-label="{{ t('policies.display_name') }}">
<div class="font-medium flex items-center gap-2">
{{ details.display_name }}
</div>
Expand All @@ -84,15 +84,15 @@ <h2 class="card-title text-2xl sm:text-3xl">
</button>
{% endif %}
</td>
<td class="px-4 py-3 cell-top"><code class="badge badge-sm badge-outline">{{ group_id }}</code></td>
<td class="px-4 py-3 text-xs opacity-80 cell-top">
<td class="px-4 py-3 cell-top" data-label="{{ t('policies.group_id_label') }}"><code class="badge badge-sm badge-outline">{{ group_id }}</code></td>
<td class="px-4 py-3 text-xs opacity-80 cell-top" data-label="{{ t('policies.policy_summary') }}">
{% if details.policies %}
{{ t('policies.rules_defined', count=details.policies | length) }}
{% else %}
<span class="italic opacity-60">{{ t('policies.no_rules') }}</span>
{% endif %}
</td>
<td class="px-4 py-3">
<td class="px-4 py-3" data-label="{{ t('policies.policy_type') }}">
{% if details.external_policy %}
<span class="badge badge-sm badge-secondary df-badge">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /></svg>
Expand All @@ -110,7 +110,7 @@ <h2 class="card-title text-2xl sm:text-3xl">
</span>
{% endif %}
</td>
<td class="px-4 py-3 text-right align-top">
<td class="px-4 py-3 text-right align-top" data-label="{{ t('common.actions') }}">
<div class="dropdown dropdown-end">
<label tabindex="0" class="btn btn-ghost btn-sm">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
Expand Down Expand Up @@ -404,28 +404,30 @@ <h3 class="font-bold text-lg mb-4">{{ t('policies.sync_access_policies') }}</h3>
--policy-col-actions: 12%;
}

.policy-table {
table-layout: fixed;
}
@media (min-width: 769px) {
.policy-table {
table-layout: fixed;
}

.policy-table col.col-primary {
width: var(--policy-col-primary);
}
.policy-table col.col-primary {
width: var(--policy-col-primary);
}

.policy-table col.col-secondary {
width: var(--policy-col-secondary);
}
.policy-table col.col-secondary {
width: var(--policy-col-secondary);
}

.policy-table col.col-tertiary {
width: var(--policy-col-tertiary);
}
.policy-table col.col-tertiary {
width: var(--policy-col-tertiary);
}

.policy-table col.col-status {
width: var(--policy-col-status);
}
.policy-table col.col-status {
width: var(--policy-col-status);
}

.policy-table col.col-actions {
width: var(--policy-col-actions);
.policy-table col.col-actions {
width: var(--policy-col-actions);
}
}

.policy-table th,
Expand Down Expand Up @@ -911,8 +913,8 @@ <h3 class="font-bold text-lg mb-4">{{ t('policies.sync_access_policies') }}</h3>
return;
}

let html = '<div class="overflow-x-auto table-container"><table class="table table-zebra policy-table w-full">';
html += '<colgroup>';
let html = '<div class="overflow-x-auto table-container"><table class="table table-zebra policy-table w-full table-responsive">';
html += '<colgroup class="hidden md:table-column-group">';
html += '<col class="col-primary">';
html += '<col class="col-secondary">';
html += '<col class="col-tertiary">';
Expand All @@ -929,14 +931,14 @@ <h3 class="font-bold text-lg mb-4">{{ t('policies.sync_access_policies') }}</h3>

zonePolicies.forEach(zone => {
html += '<tr>';
html += `<td class="px-4 py-3 font-medium">${zone.zone_name}</td>`;
html += `<td class="px-4 py-3 font-medium" data-label="{{ t('policies.zone_name') }}">${zone.zone_name}</td>`;
if (zone.zone_id) {
html += `<td class="px-4 py-3 text-xs opacity-70"><span class=\"tooltip\" data-tip=\"${zone.zone_id}\"><code>${zone.zone_id.slice(0, 8)}...</code></span></td>`;
html += `<td class="px-4 py-3 text-xs opacity-70" data-label="{{ t('policies.zone_id') }}"><span class=\"tooltip\" data-tip=\"${zone.zone_id}\"><code>${zone.zone_id.slice(0, 8)}...</code></span></td>`;
} else {
html += '<td class="px-4 py-3 text-xs opacity-70">-</td>';
html += '<td class="px-4 py-3 text-xs opacity-70" data-label="{{ t('policies.zone_id') }}">-</td>';
}
html += `<td class="px-4 py-3"><code class="text-sm">*.${zone.zone_name}</code></td>`;
html += '<td class="px-4 py-3">';
html += `<td class="px-4 py-3" data-label="{{ t('policies.wildcard_hostname') }}"><code class="text-sm">*.${zone.zone_name}</code></td>`;
html += '<td class="px-4 py-3" data-label="{{ t('common.status') }}">';

if (zone.has_default_policy) {
html += '<span class="badge badge-sm badge-success df-badge">';
Expand All @@ -946,7 +948,7 @@ <h3 class="font-bold text-lg mb-4">{{ t('policies.sync_access_policies') }}</h3>
html += '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /></svg>{{ t('policies.not_protected') }}</span>';
}

html += '</td><td class="px-4 py-3 text-right">';
html += '</td><td class="px-4 py-3 text-right" data-label="{{ t('common.actions') }}">';

if (!zone.has_default_policy) {
html += `<div class="dropdown dropdown-end">
Expand Down
Loading
Loading