> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devhelm.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from Dashboard

> Move from UI-managed monitors to DevHelm monitoring-as-code with zero downtime

By the end of this guide, you'll have adopted your existing Dashboard-managed resources into YAML and transitioned to a code-managed workflow with no disruption to your monitoring.

<Accordion title="Prerequisites">
  * DevHelm CLI installed
  * An API token — see [Authentication](/authentication)
  * Existing monitors created through the Dashboard
</Accordion>

## Migration strategy

The goal is to transition from "click-to-create" to "commit-to-deploy" without any monitoring gaps. There is no bulk export — adoption happens **per resource** with `devhelm import`. The process:

1. Declare your existing resources in a `devhelm.yml` file
2. Import each resource into the deploy state so DevHelm adopts it instead of recreating it
3. Verify the plan shows no changes, then commit the YAML to your repository
4. Let future changes go through code instead of the Dashboard

## Step-by-step migration

<Steps>
  <Step title="Inventory current resources">
    List your monitors and capture their configuration as a reference for writing the YAML:

    ```bash theme={null}
    devhelm monitors list -o json > current-monitors.json
    ```

    Do the same for alert channels (`devhelm alert-channels list`) and any other resources you plan to migrate.
  </Step>

  <Step title="Declare resources in devhelm.yml">
    Write a `devhelm.yml` that mirrors what's running, using the JSON output from the previous step. Double-check:

    * Monitor names and URLs are correct
    * Frequencies and regions match expectations
    * Alert channel types are right
    * Tags are present

    Use `${VAR}` references for secret values like webhook URLs — never paste credentials into the YAML:

    ```yaml theme={null}
    alertChannels:
      - name: Engineering Slack
        config:
          channelType: slack
          webhookUrl: ${SLACK_WEBHOOK_URL}
    ```

    Set the secrets:

    ```bash theme={null}
    devhelm secrets create --key SLACK_WEBHOOK_URL --value https://hooks.slack.com/services/...
    ```
  </Step>

  <Step title="Import resources into the deploy state">
    `devhelm import <type> <name>` adopts one named API resource into the local deploy state, so the next deploy updates it in place instead of creating a duplicate. Import each resource you declared:

    ```bash theme={null}
    devhelm import monitor "API Health Check"
    devhelm import alertChannel "Engineering Slack"
    devhelm import notificationPolicy "Critical alerts"
    ```

    Supported types: `monitor`, `tag`, `environment`, `secret`, `alertChannel`, `notificationPolicy`, `webhook`, `resourceGroup`, `dependency`, `statusPage`.

    Inspect the resulting state at any time:

    ```bash theme={null}
    devhelm state show
    ```
  </Step>

  <Step title="Validate and plan">
    Check that the YAML is syntactically valid:

    ```bash theme={null}
    devhelm validate devhelm.yml
    ```

    Preview what would change:

    ```bash theme={null}
    devhelm plan -f devhelm.yml
    ```

    Since the YAML mirrors the current state and each resource was imported, the plan should show **no changes** (or minimal differences from secret handling). If you see unexpected creates or deletes, review the YAML against the Dashboard and check that every resource was imported.
  </Step>

  <Step title="Deploy">
    Apply the YAML to take ownership:

    ```bash theme={null}
    devhelm deploy -f devhelm.yml --yes
    ```

    This makes DevHelm's config-as-code system the source of truth. Dashboard changes will now show as drift in `devhelm plan`.
  </Step>

  <Step title="Commit to your repository">
    ```bash theme={null}
    git add devhelm.yml
    git commit -m "chore: import monitoring config from Dashboard"
    git push
    ```
  </Step>

  <Step title="Set up CI/CD">
    Add a GitHub Actions workflow to deploy on push. See [CI/CD pipeline guide](/guides/ci-cd-pipeline).
  </Step>
</Steps>

## Handling drift

After migration, if someone edits a resource through the Dashboard:

```bash theme={null}
devhelm plan -f devhelm.yml
```

The plan shows the drift. The next `devhelm deploy` overwrites the Dashboard changes with the YAML definition. Make this expectation clear to your team: **YAML is the source of truth**.

## Incremental migration

You don't have to migrate everything at once. Start with a subset:

1. Declare and import only your critical production monitors
2. Deploy and validate
3. Gradually add more resources to the YAML, importing each one as you go
4. Eventually adopt alert channels and notification policies too

Resources not in the YAML file are left untouched — DevHelm only manages resources declared in the file.

## Next steps

<CardGroup cols={2}>
  <Card title="Monitoring as Code tutorial" icon="file-code" href="/guides/monitoring-as-code">
    Full YAML format and workflow guide.
  </Card>

  <Card title="Multi-environment config" icon="code-branch" href="/guides/multi-environment-config">
    Manage staging and production separately.
  </Card>

  <Card title="CI/CD pipeline" icon="rotate" href="/guides/ci-cd-pipeline">
    Automate deploys from GitHub Actions.
  </Card>
</CardGroup>
