fix(deploy): apply Caddyfile changes on update (dir mount + recreate)
A single-file bind mount of the Caddyfile kept the original inode, so a git pull that replaces the file never reached a running caddy, and up -d does not recreate it for a content-only change — Caddy fixes (e.g. the 0.9.18 WebSocket fix) silently never deployed. Mount the docker/caddy directory instead (reflects the live file) and force-recreate the caddy container on every install/update so Caddyfile changes reliably take effect. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>feat/v1-foundation v0.9.19
parent
92969eb0dc
commit
a61feb1bef
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -13,6 +13,17 @@ getaggte Releases (Kanal `stable`, optional `beta`) — niemals Entwicklungs-Bui
|
|||
|
||||
_Keine offenen Änderungen — der nächste Stand wird hier gesammelt und als `vX.Y.Z` getaggt._
|
||||
|
||||
## [0.9.19] - 2026-06-19
|
||||
|
||||
### Behoben
|
||||
- **Caddyfile-Änderungen wurden bei einem Update nicht übernommen.** Die Caddy-Config war als
|
||||
**einzelne Datei** gemountet; ein `git pull` ersetzt die Datei (neue Inode), aber der laufende
|
||||
Container hängt weiter an der alten — und `docker compose up -d` baut Caddy bei reiner
|
||||
Inhaltsänderung nicht neu. Dadurch kamen Caddy-Fixes (z. B. der WebSocket-Fix aus 0.9.18) ohne
|
||||
manuelles Eingreifen nie an. Jetzt wird das **Verzeichnis** `docker/caddy` gemountet (spiegelt die
|
||||
Datei live) und `install.sh` baut den Caddy-Container bei jedem Deploy gezielt neu
|
||||
(`up -d --force-recreate caddy`), sodass Caddyfile-Änderungen zuverlässig wirksam werden.
|
||||
|
||||
## [0.9.18] - 2026-06-19
|
||||
|
||||
### Behoben
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
// First tagged release is v0.1.0 (semantic, not -dev).
|
||||
'version' => '0.9.18',
|
||||
'version' => '0.9.19',
|
||||
|
||||
// Deployed commit + branch. install.sh bakes these into .env from the host's .git (the prod
|
||||
// image ships no .git); the Versions page prefers them and falls back to a live .git read in
|
||||
|
|
|
|||
|
|
@ -86,7 +86,11 @@ services:
|
|||
# its X-Forwarded-Proto. Leave as 127.0.0.1/32 when Caddy terminates TLS itself.
|
||||
TRUSTED_PROXY_CIDR: "${TRUSTED_PROXY_CIDR:-127.0.0.1/32}"
|
||||
volumes:
|
||||
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
# Mount the DIRECTORY (not the single Caddyfile): a single-file bind mount keeps the
|
||||
# original inode, so a `git pull` that REPLACES the file would not reach a running
|
||||
# container. A directory mount always reflects the current file, so `caddy reload` /
|
||||
# a recreate picks up Caddyfile changes on update.
|
||||
- ./docker/caddy:/etc/caddy:ro
|
||||
- caddy-data:/data # ACME account + certs — MUST persist across recreate
|
||||
- caddy-config:/config
|
||||
depends_on:
|
||||
|
|
|
|||
|
|
@ -240,6 +240,9 @@ esac
|
|||
# ── [5/9] stack ──────────────────────────────────────────────────────
|
||||
phase 5/9 "Stack starten"
|
||||
$COMPOSE up -d
|
||||
# Caddyfile changes ship as edits to a bind-mounted file; `up -d` does NOT recreate caddy for a
|
||||
# content-only change, so force it to re-read the (possibly updated) Caddyfile on every deploy.
|
||||
$COMPOSE up -d --force-recreate caddy >/dev/null 2>&1 || true
|
||||
info "Container gestartet"
|
||||
|
||||
# ── host watchers (restart + update sentinels) — idempotent, best-effort ────
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@
|
|||
namespace Tests\Feature;
|
||||
|
||||
use App\Http\Middleware\PanelScheme;
|
||||
use App\Livewire\System\Index as SystemIndex;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Services\DeploymentService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Livewire\Livewire;
|
||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Tests\TestCase;
|
||||
|
|
@ -100,6 +103,17 @@ class ExternalTlsModeTest extends TestCase
|
|||
$this->runPanelScheme(Request::create('http://evil.example.com/dashboard'));
|
||||
}
|
||||
|
||||
public function test_status_card_does_not_claim_lets_encrypt_in_external_mode(): void
|
||||
{
|
||||
$this->actingAs(User::factory()->create(['must_change_password' => false]));
|
||||
Setting::put('panel_domain', 'panel.example.com');
|
||||
app(DeploymentService::class)->setTlsMode('external');
|
||||
|
||||
Livewire::test(SystemIndex::class)
|
||||
->assertSee(__('system.tls_active_external_title'))
|
||||
->assertDontSee('Let\'s Encrypt');
|
||||
}
|
||||
|
||||
public function test_reverb_client_uses_wss_on_443_for_the_active_domain(): void
|
||||
{
|
||||
Setting::put('panel_domain', 'panel.example.com');
|
||||
|
|
|
|||
Loading…
Reference in New Issue