# Quickstart


You'll set up ddup to manage one domain, `app.example.com`, served by two web servers. When one of the servers stops responding, ddup removes its IP from DNS, and adds it back when the server recovers.

## Prerequisites

- A DNS zone hosted by one of the [supported DNS providers](/providers.md), and API credentials for it. Each provider's page explains how to create them.
- Two or more servers with a URL that ddup can request to check their health. It must return a 2xx status code when the server is healthy (you can [change the status code](/docs/health-checks.md#expected-status-code)).
- Docker or Podman. To run ddup without containers, see [Installation](/docs/installation.md).

## Step 1: Create the configuration file

Create a folder for the configuration:

```sh
mkdir -p $HOME/.ddup
```

In that folder, create a file named `config.yaml`, replacing the IPs and URLs with the ones of your servers:

```yaml
# How often to check the endpoints
interval: 30s

domains:
  - recordName: "app.example.com"
    # Name of the provider, defined in the "providers" section below
    provider: "my-dns"
    endpoints:
      - name: "web1"
        url: "http://192.0.2.10/healthz"
        ip: "192.0.2.10"
      - name: "web2"
        url: "http://192.0.2.11/healthz"
        ip: "192.0.2.11"

# Enable the dashboard
server:
  enabled: true
  # Needed to reach the dashboard from outside the container
  bind: "0.0.0.0"
```

Then add a `providers` section at the end of the file, with the settings for your DNS provider:

<div class="content-tabs" data-content-tabs data-tabs-label="Content tabs">
  

<section class="content-tab" data-tab-title="AWS Route 53">
  <div class="content-tab-heading">AWS Route 53</div>
  <div class="content-tab-body">
    <div class="code-block">
    <button class="code-copy" type="button" aria-label="Copy code to clipboard" title="Copy code" data-copy-code>
      <svg class="code-copy-icon code-copy-icon-copy" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
        <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M20 6 9 17l-5-5"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-failed" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M18 6 6 18"/>
        <path d="m6 6 12 12"/>
      </svg>
    </button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">my-dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">awsRoute53</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">hostedZoneId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Z0123456789ABCDEFGHIJ&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">accessKeyId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-access-key-id&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">secretAccessKey</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-secret-access-key&#34;</span></span></span></code></pre></div></div><p>See <a href="/providers/aws-route53">AWS Route 53</a> to find the hosted zone ID and create the access key, or to use an IAM role instead.</p>
  </div>
</section>


<section class="content-tab" data-tab-title="Azure DNS">
  <div class="content-tab-heading">Azure DNS</div>
  <div class="content-tab-body">
    <div class="code-block">
    <button class="code-copy" type="button" aria-label="Copy code to clipboard" title="Copy code" data-copy-code>
      <svg class="code-copy-icon code-copy-icon-copy" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
        <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M20 6 9 17l-5-5"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-failed" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M18 6 6 18"/>
        <path d="m6 6 12 12"/>
      </svg>
    </button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">my-dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">azure</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">subscriptionId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;00000000-0000-0000-0000-000000000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">resourceGroupName</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;my-dns-rg&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">zoneName</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;example.com&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">tenantId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;00000000-0000-0000-0000-000000000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">clientId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;00000000-0000-0000-0000-000000000000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">clientSecret</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-client-secret&#34;</span></span></span></code></pre></div></div><p>See <a href="/providers/azure-dns">Azure DNS</a> to create the service principal and allow it to change the zone, or to use a managed identity instead.</p>
  </div>
</section>


<section class="content-tab" data-tab-title="Cloudflare">
  <div class="content-tab-heading">Cloudflare</div>
  <div class="content-tab-body">
    <div class="code-block">
    <button class="code-copy" type="button" aria-label="Copy code to clipboard" title="Copy code" data-copy-code>
      <svg class="code-copy-icon code-copy-icon-copy" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
        <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M20 6 9 17l-5-5"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-failed" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M18 6 6 18"/>
        <path d="m6 6 12 12"/>
      </svg>
    </button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">my-dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cloudflare</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiToken</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-api-token&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">zoneId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-zone-id&#34;</span></span></span></code></pre></div></div><p>See <a href="/providers/cloudflare">Cloudflare</a> to create the API token and find the zone ID.</p>
  </div>
</section>


<section class="content-tab" data-tab-title="Google Cloud DNS">
  <div class="content-tab-heading">Google Cloud DNS</div>
  <div class="content-tab-body">
    <div class="code-block">
    <button class="code-copy" type="button" aria-label="Copy code to clipboard" title="Copy code" data-copy-code>
      <svg class="code-copy-icon code-copy-icon-copy" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
        <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M20 6 9 17l-5-5"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-failed" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M18 6 6 18"/>
        <path d="m6 6 12 12"/>
      </svg>
    </button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">my-dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">googleCloudDns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">projectId</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;my-project&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">managedZone</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;example-com&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># The key file, in the same folder as config.yaml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">credentialsFile</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;/etc/ddup/ddup-key.json&#34;</span></span></span></code></pre></div></div><p>See <a href="/providers/google-cloud-dns">Google Cloud DNS</a> to find the managed zone name and create the service account key.</p>
  </div>
</section>


<section class="content-tab" data-tab-title="OVHcloud">
  <div class="content-tab-heading">OVHcloud</div>
  <div class="content-tab-body">
    <div class="code-block">
    <button class="code-copy" type="button" aria-label="Copy code to clipboard" title="Copy code" data-copy-code>
      <svg class="code-copy-icon code-copy-icon-copy" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
        <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M20 6 9 17l-5-5"/>
      </svg>
      <svg class="code-copy-icon code-copy-icon-failed" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <path d="M18 6 6 18"/>
        <path d="m6 6 12 12"/>
      </svg>
    </button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">my-dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ovh</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiKey</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-application-key&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiSecret</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-application-secret&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">consumerKey</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;your-consumer-key&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">zoneName</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;example.com&#34;</span></span></span></code></pre></div></div><p>See <a href="/providers/ovh">OVHcloud</a> to create the API keys.</p>
  </div>
</section>



</div>


> [!TIP]
> You can keep secrets such as API tokens out of the configuration file and read them from other files instead. See [Secrets](/docs/configuration.md#secrets).

## Step 2: Start ddup

```sh
# For Podman, replace "docker" with "podman"
docker run -d \
  --name ddup \
  --read-only \
  --restart unless-stopped \
  -v $HOME/.ddup:/etc/ddup:ro \
  -p 127.0.0.1:7401:7401 \
  ghcr.io/italypaleale/ddup:v0
```

The `-p` flag makes the dashboard available on port 7401 of your machine, only from the machine itself. The dashboard has no authentication, so don't expose it on a network you don't trust.

## Step 3: Check that it works

ddup checks all endpoints as soon as it starts. Look at its logs:

```sh
docker logs -f ddup
```

For each domain, you should see a line with the message `Updated DNS records`, which lists the IPs that ddup published. If the records already matched, the message is `DNS records already up to date` instead. If something is wrong, such as invalid credentials, the logs show the error.

Open `http://localhost:7401` in a browser to see the [dashboard](/docs/dashboard.md), and look up the domain to see the records:

```sh
dig +short app.example.com
```

## Step 4: Try a failover

Stop the web server on one of the machines. By default, ddup removes an endpoint after it fails 2 checks in a row, so with a 30-second interval its IP disappears from DNS within about a minute. The logs show `Endpoint health check failed` for each failed check, then `Updated DNS records` with the remaining IPs.

Start the web server again. On the next check, ddup adds its IP back.

## Next steps

- [Installation](/docs/installation.md): run ddup with Docker Compose, or as a service without containers
- [Configuration](/docs/configuration.md): every configuration option
- [Health checks](/docs/health-checks.md): control how endpoints are checked, and how quickly they're removed and added back
- [Failover with priorities](/docs/failover-priorities.md): keep backup servers out of DNS until the main ones fail

