Skip to content
Closed
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.

- Traefik's built-in dashboard is now exposed at `https://traefik.test`, surfacing misconfigured routers directly instead of only in the container logs. Existing installations pick this up after `dde system:down && dde system:up` (a plain restart is not enough — the labels and static `traefik.yml` only apply when the container is recreated).

### Fixed

- `dde system:install` no longer aborts the "Configuring DNS resolver" step with a cryptic `Permission denied` rename error. A resolver file left behind by dde v1 (which lacked a trailing newline) is now recognised as already configured, so upgrading needs no root. When the file genuinely has to be created, dde prints the exact `sudo` command to run instead of a raw exception.

## [2.0.0-beta.2] - 2026-06-01

### Added
Expand Down
22 changes: 17 additions & 5 deletions src/Service/DnsmasqService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Manager\DockerManager;
use App\Model\ContainerConfig;
use App\Util\ProcessFactory;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;

final class DnsmasqService extends AbstractSystemService
Expand Down Expand Up @@ -114,7 +115,8 @@ public function buildImage(bool $pull = false): void
*
* On macOS: writes a resolver file to /etc/resolver/test.
* On Linux: configures systemd-resolved or NetworkManager.
* Both require root privileges (the installer script runs with sudo).
* Both require root; when dde cannot write the file it explains the
* manual command to run instead.
*
* @throws \RuntimeException if the platform is not supported
*/
Expand Down Expand Up @@ -219,14 +221,24 @@ private function configureDnsMacOs(): void
{
$resolverDir = '/etc/resolver';
$resolverFile = $resolverDir.'/test';

$content = $this->getResolverContent();

if ($this->filesystem->exists($resolverFile) && $this->filesystem->readFile($resolverFile) === $content) {
// A dde v1 resolver file is content-equivalent but lacks the trailing
// newline; treat it as already configured so upgrades need no root.
if ($this->filesystem->exists($resolverFile) && trim($this->filesystem->readFile($resolverFile)) === trim($content)) {
return;
}

$this->filesystem->mkdir($resolverDir);
$this->filesystem->dumpFile($resolverFile, $content);
try {
$this->filesystem->mkdir($resolverDir);
$this->filesystem->dumpFile($resolverFile, $content);
} catch (IOException $ioException) {
throw new \RuntimeException(sprintf(
"Could not write %s, which requires root. Create it manually and re-run 'dde system:install':\n echo '%s' | sudo tee %s",
$resolverFile,
rtrim($content, "\n"),
$resolverFile,
), $ioException->getCode(), previous: $ioException);
}
}
}
Loading