@@ -37,7 +37,7 @@ public function handle(): void
37
37
38
38
// Attempt recovery
39
39
$ this ->attemptRecovery ();
40
-
40
+
41
41
// Re-throw exception for job retry mechanism
42
42
throw $ e ;
43
43
}
@@ -89,15 +89,24 @@ protected function validatePrerequisites(): void
89
89
90
90
if (!is_writable ($ configDir )) {
91
91
throw new \Exception ("Caddy config directory is not writable: {$ configDir }" );
92
- }
93
-
94
- // Check if log directory exists and is writable
92
+ } // Check if log directory exists and is writable
95
93
if (!is_dir ($ caddyLogPath )) {
96
- if (!mkdir ($ caddyLogPath , 0755 , true )) {
94
+ if (!mkdir ($ caddyLogPath , 0777 , true )) {
97
95
throw new \Exception ("Cannot create Caddy log directory: {$ caddyLogPath }" );
98
96
}
99
- } if (!is_writable ($ caddyLogPath )) {
100
- throw new \Exception ("Caddy log directory is not writable: {$ caddyLogPath }" );
97
+ // Ensure caddy user can write to the log directory with broader permissions
98
+ shell_exec ("chown -R caddy:caddy {$ caddyLogPath }" );
99
+ shell_exec ("chmod -R 777 {$ caddyLogPath }" );
100
+ }
101
+
102
+ if (!is_writable ($ caddyLogPath )) {
103
+ // Try to fix permissions with broader access (777) for multi-user write access
104
+ shell_exec ("chown -R caddy:caddy {$ caddyLogPath }" );
105
+ shell_exec ("chmod -R 777 {$ caddyLogPath }" );
106
+
107
+ if (!is_writable ($ caddyLogPath )) {
108
+ throw new \Exception ("Caddy log directory is not writable: {$ caddyLogPath }" );
109
+ }
101
110
}
102
111
}
103
112
@@ -200,12 +209,10 @@ protected function generateCaddyfile(): void
200
209
201
210
// Reload Caddy configuration
202
211
shell_exec ('systemctl reload caddy ' );
203
- }
204
-
205
- private function createCaddyBlock (Domain $ domain , $ apacheHttpPort ): ?array
212
+ } private function createCaddyBlock (Domain $ domain , $ apacheHttpPort ): ?array
206
213
{
207
- if ($ domain ->status === Domain::STATUS_SUSPENDED ||
208
- $ domain ->status === Domain::STATUS_DEACTIVATED ||
214
+ if ($ domain ->status === Domain::STATUS_SUSPENDED ||
215
+ $ domain ->status === Domain::STATUS_DEACTIVATED ||
209
216
$ domain ->status === Domain::STATUS_BROKEN ) {
210
217
return null ;
211
218
}
@@ -216,9 +223,7 @@ private function createCaddyBlock(Domain $domain, $apacheHttpPort): ?array
216
223
'enable_ssl ' => true ,
217
224
'enable_www ' => true ,
218
225
];
219
- }
220
-
221
- private function createMasterDomainCaddyBlock (MasterDomain $ masterDomain , $ apacheHttpPort ): ?array
226
+ } private function createMasterDomainCaddyBlock (MasterDomain $ masterDomain , $ apacheHttpPort ): ?array
222
227
{
223
228
if (empty ($ masterDomain ->domain )) {
224
229
return null ;
@@ -229,46 +234,47 @@ private function createMasterDomainCaddyBlock(MasterDomain $masterDomain, $apach
229
234
'proxy_to ' => "127.0.0.1: {$ apacheHttpPort }" ,
230
235
'enable_ssl ' => true ,
231
236
'enable_www ' => true ,
232
- 'is_master ' => true , ];
233
- } /**
237
+ 'is_master ' => true ,
238
+ ];
239
+ }/**
234
240
* Validate generated configuration before applying
235
241
*/
236
242
protected function validateGeneratedConfig (): void
237
243
{
238
244
$ caddyConfigPath = '/etc/caddy/Caddyfile ' ;
239
245
$ caddyBinary = '/usr/bin/caddy ' ;
240
-
246
+
241
247
if (!file_exists ($ caddyConfigPath )) {
242
248
throw new \Exception ("Generated Caddyfile not found at: {$ caddyConfigPath }" );
243
249
}
244
-
250
+
245
251
// Format Caddyfile to fix inconsistencies if Caddy binary is available
246
252
if (is_executable ($ caddyBinary )) {
247
253
$ formatCommand = "{$ caddyBinary } fmt --overwrite {$ caddyConfigPath } 2>&1 " ;
248
254
$ formatOutput = shell_exec ($ formatCommand );
249
255
$ formatExitCode = shell_exec ("echo $? " );
250
-
256
+
251
257
if (trim ($ formatExitCode ) === '0 ' ) {
252
258
\Log::info ('Caddyfile formatted successfully ' );
253
259
} else {
254
260
\Log::warning ('Caddyfile formatting failed: ' . $ formatOutput );
255
261
}
256
-
262
+
257
263
// Validate syntax using Caddy binary
258
264
$ command = "{$ caddyBinary } validate --config {$ caddyConfigPath } 2>&1 " ;
259
265
$ output = shell_exec ($ command );
260
266
$ exitCode = shell_exec ("echo $? " );
261
-
267
+
262
268
if (trim ($ exitCode ) !== '0 ' ) {
263
269
throw new \Exception ("Caddyfile validation failed: {$ output }" );
264
270
}
265
-
271
+
266
272
\Log::info ('Caddyfile validation passed ' );
267
273
} else {
268
274
\Log::warning ('Caddy binary not found, skipping syntax validation and formatting ' );
269
275
}
270
276
}
271
-
277
+
272
278
/**
273
279
* Apply Caddy configuration and reload service
274
280
*/
@@ -277,14 +283,14 @@ protected function applyCaddyConfiguration(): void
277
283
try {
278
284
// Create backup of current configuration
279
285
$ this ->backupCurrentConfig ();
280
-
286
+
281
287
// Reload Caddy service to apply new configuration
282
288
$ this ->reloadCaddyService ();
283
-
289
+
284
290
\Log::info ('Caddy configuration applied successfully ' );
285
291
} catch (\Exception $ e ) {
286
292
\Log::error ('Failed to apply Caddy configuration: ' . $ e ->getMessage ());
287
-
293
+
288
294
// Restore backup on failure
289
295
$ this ->restoreConfigBackup ();
290
296
throw $ e ;
@@ -297,12 +303,12 @@ protected function backupCurrentConfig(): void
297
303
{
298
304
$ caddyConfigPath = '/etc/caddy/Caddyfile ' ;
299
305
$ backupPath = $ caddyConfigPath . '.backup. ' . date ('Y-m-d-H-i-s ' );
300
-
306
+
301
307
if (file_exists ($ caddyConfigPath )) {
302
308
if (!copy ($ caddyConfigPath , $ backupPath )) {
303
309
throw new \Exception ("Failed to create configuration backup at: {$ backupPath }" );
304
310
}
305
-
311
+
306
312
\Log::info ("Configuration backup created: {$ backupPath }" );
307
313
}
308
314
}
@@ -313,13 +319,13 @@ protected function restoreConfigBackup(): void
313
319
{
314
320
$ caddyConfigPath = '/etc/caddy/Caddyfile ' ;
315
321
$ backupDir = dirname ($ caddyConfigPath );
316
-
322
+
317
323
// Find the most recent backup
318
324
$ backups = glob ($ backupDir . '/Caddyfile.backup.* ' );
319
325
if (!empty ($ backups )) {
320
326
rsort ($ backups ); // Sort by name (newest first)
321
327
$ latestBackup = $ backups [0 ];
322
-
328
+
323
329
if (copy ($ latestBackup , $ caddyConfigPath )) {
324
330
\Log::info ("Configuration restored from backup: {$ latestBackup }" );
325
331
$ this ->reloadCaddyService ();
@@ -328,50 +334,51 @@ protected function restoreConfigBackup(): void
328
334
}
329
335
}
330
336
}
331
-
337
+
332
338
/**
333
339
* Reload Caddy service
334
340
*/
335
341
protected function reloadCaddyService (): void
336
342
{
337
343
$ commands = [
338
344
'systemctl reload caddy ' ,
339
- 'systemctl restart caddy ' , // Fallback if reload fails
345
+ 'systemctl restart caddy ' ,
346
+
340
347
];
341
-
348
+
342
349
foreach ($ commands as $ command ) {
343
350
$ output = shell_exec ("{$ command } 2>&1 " );
344
351
$ exitCode = shell_exec ("echo $? " );
345
-
352
+
346
353
if (trim ($ exitCode ) === '0 ' ) {
347
354
\Log::info ("Caddy service reloaded successfully using: {$ command }" );
348
355
return ;
349
356
}
350
-
357
+
351
358
\Log::warning ("Command failed: {$ command }, output: {$ output }" );
352
359
}
353
-
360
+
354
361
throw new \Exception ("Failed to reload Caddy service " );
355
362
}
356
-
363
+
357
364
/**
358
365
* Attempt recovery on job failure
359
366
*/
360
367
protected function attemptRecovery (): void
361
368
{
362
369
try {
363
370
\Log::info ('Attempting Caddy configuration recovery ' );
364
-
371
+
365
372
// Try to restore from backup
366
373
$ this ->restoreConfigBackup ();
367
-
374
+
368
375
// Check if service is still running
369
376
$ status = shell_exec ('systemctl is-active caddy 2>/dev/null ' );
370
377
if (trim ($ status ) !== 'active ' ) {
371
378
\Log::warning ('Caddy service is not active, attempting to start ' );
372
379
shell_exec ('systemctl start caddy 2>&1 ' );
373
380
}
374
-
381
+
375
382
\Log::info ('Recovery attempt completed ' );
376
383
} catch (\Exception $ e ) {
377
384
\Log::error ('Recovery attempt failed: ' . $ e ->getMessage ());
@@ -385,12 +392,12 @@ protected function cleanupOldBackups(): void
385
392
$ caddyConfigPath = '/etc/caddy/Caddyfile ' ;
386
393
$ backupDir = dirname ($ caddyConfigPath );
387
394
$ maxBackups = 10 ;
388
-
395
+
389
396
$ backups = glob ($ backupDir . '/Caddyfile.backup.* ' );
390
397
if (count ($ backups ) > $ maxBackups ) {
391
398
rsort ($ backups ); // Sort by name (newest first)
392
399
$ oldBackups = array_slice ($ backups , $ maxBackups );
393
-
400
+
394
401
foreach ($ oldBackups as $ backup ) {
395
402
if (unlink ($ backup )) {
396
403
\Log::info ("Removed old backup: {$ backup }" );
0 commit comments