# Traefik

Configure AdGuard Home, Traefik, Keepalived and Pocket ID for a self-hosted DNS proxy.

#### References

<ReferenceLinks references={frontmatter.references} />

---

### Directory structure

- root
  - compose.yml (\*)
  - traefik
    - config
      - traefik.yml (\*)
      - dynamic_config.yml (\*)
    - letsencrypt
      - acme.json
  - adguard
    - conf
      - AdGuardHome.yaml (\*)
    - work/
  - keepalived
    - keepalived.conf

1.  ## Initial setup

    ### Make directories

    ```sh wrap preserveIndent
    mkdir -p {{DOCKER_PATH_VAR}}/dns-proxy/traefik/{config,letsencrypt} {{DOCKER_PATH_VAR}}/dns-proxy/pocket-id/data {{DOCKER_PATH_VAR}}/dns-proxy/adguard/{conf,work} {{DOCKER_PATH_VAR}}/dns-proxy/keepalived && cd {{DOCKER_PATH_VAR}}/traefik
    ```

    ### compose.yml

    ```sh
    nano compose.yml
    ```

    ```yml title="compose.yml"
    dockerCompose
    ```

    ### Cloudflare API token

    Generate a scoped API token to automate DNS record management and SSL certificate validation.
    - Go to Dashboard > My Profile > **API Tokens**.
    - **Create Token:** Use the `Edit zone DNS template`.
    - **Permissions:** Select `Zone` | `DNS` | `Edit`.
    - **Zone Resources:** Select `Include` | `Specific zone` | `your-domain.tld`.

    ### .env

    ```sh
    nano .env
    ```

    ```dotenv title=".env"
    env
    ```

2.  ## Traefik

    ### traefik.yml

    ```sh
    nano ./traefik/config/traefik.yml
    ```

    ```yml title="./traefik/config/traefik.yml"
    traefikConfigYml
    ```

    ### dynamic_config.yml

    ```sh
    nano ./traefik/config/dynamic_config.yml
    ```

    ```yml title="./traefik/config/dynamic_config.yml"
    dynamicConfigYml
    ```

    ### acme.json

    ```sh wrap
    touch ./traefik/letsencrypt/acme.json && chmod 600 ./traefik/letsencrypt/acme.json

    ```

3.  ## AdGuardHome.yaml

    ```sh
    nano ./adguard/conf/AdGuardHome.yaml
    ```

    ```yml title="./adguard/conf/AdGuardHome.yaml"
    adguardConfigYml
    ```

4.  ## keepalived.conf

    ```sh
    nano ./keepalived/keepalived.conf
    ```

    ```yml title="./keepalived/keepalived.conf"
    keepalivedConfig
    ```

5.  ## Miscellaneous (optional)

    ### Tailscale

    [Setup Tailscale](/guides/linux/programs/tailscale)

    ### Resolve port 53 conflicts

    If another service on the host is already using port 53, disable the systemd-resolved stub listener before starting AdGuard Home.
   1. #### Disable the stub listener

       ```sh
       sudo nano /etc/systemd/resolved.conf
       ```

       Set `DNSStubListener=no`

   2. #### Restart systemd-resolved

       ```sh
       sudo systemctl restart systemd-resolved
       ```

    ### Router DNS

    Update the **Primary DNS**, often located under LAN, DHCP or DNS Settings.

        - **Primary DNS:** <code>{serverIp}</code> or <code>{virtualIp}</code> _(Your device’s Local LAN IP or virtual IP, not the Tailscale one)_.
        - **Secondary DNS:** `1.1.1.1` _(Fail-safe so your internet still works if your device is turned off)_.

    

6.  ## Start services

    ### Create proxy network

    Create the external Docker network used by Traefik, Pocket ID and the other proxy services.

    ```sh
    docker network create proxy
    ```

    ### adguard

    Start AdGuard Home first so its initial web setup can be completed before the remaining services depend on it.

    ```sh
    docker compose up -d adguard
    ```

    #### Complete web setup
    - Go to <a class="link" href="http://localhost:3000" target="_blank" rel="noopener">http://localhost:3000</a> or <a class="link" href={adguardSetupLink} target="_blank" rel="noopener">{adguardSetupLink}</a>
      - Admin Web Interface.
      - **Listen interface:** Select `All interfaces`.
      - **Port:** Change to `8080`.

    ### adguardhome-sync

    Once the origin and replica AdGuard Home instances are configured and reachable, start the sync service.

    ```sh
    docker compose up -d adguardhome-sync
    ```

    `RUN_ON_START` runs the first synchronization immediately, with subsequent synchronizations running every 10 minutes.

    ### pocket-id and traefik

    Start Pocket ID and Traefik after the proxy network and AdGuard Home are ready.

    ```sh
    docker compose up -d pocket-id traefik
    ```

    #### Complete web setup
   1.  Open <a href={setupUrl} target="_blank" rel="noopener">{setupUrl}</a> in your browser.
   2.  Set up your admin account and register your primary Passkey.
   3.  Go to **Administration** > **OIDC Clients** > **Add OIDC Client**:
        - Name: `Traefik Forward Auth`
        - Callback URL: `https://auth.{{BASE_SUB_DOMAIN_VAR}}/_oauth`
        - Check `Public Client` if secret is not enforced, or copy the `Client ID` and `Client Secret`.
   4.  Paste those credentials into the `PROVIDERS_OIDC_CLIENT_ID` and `PROVIDERS_OIDC_CLIENT_SECRET` environment variables in `.env`.

    ### traefik-forward-auth

    Start the authentication middleware after the Pocket ID OIDC client has been configured.

    ```sh
    docker compose up -d traefik-forward-auth
    ```

    ### keepalived

    Start keepalived after the DNS services and virtual IP configuration are ready.

    ```sh
    docker compose up -d keepalived
    ```
