pulumi-reolink
Manage your Reolink camera and doorbell settings as Infrastructure as Code with Pulumi — declarative, versioned, and drift-corrected. It connects directly to your cameras/doorbells over HTTP using reolink-aio — the same library that powers Home Assistant's official Reolink integration.
See specs/spec.md for the full technical specification.
Installation
pip install pulumi-reolink
Getting Started
1. Bootstrap your existing cameras
From your Pulumi project directory, run the interactive bootstrap CLI against each camera you want to manage:
python -m pulumi_reolink.bootstrap
You'll be prompted for the camera's host/IP, admin username, and admin password. It connects once to query the camera's current settings and its own configured name, then prompts for Camera Name with that name pre-filled — press Enter to accept it, or type a different one. The secret config key isn't prompted for; it's derived automatically from the name (e.g. front-doorbell-password).
The tool appends an entry to cameras.yaml in the current directory and prints the command to store the password securely:
pulumi config set --secret front-doorbell-password "<password>"
The plaintext password is only held in memory long enough to connect and print that command — it is never written to cameras.yaml or to disk.
2. Load cameras in your Pulumi program
import pulumi
import yaml
from pulumi_reolink import ReolinkDevice
config = pulumi.Config()
with open("cameras.yaml") as f:
cameras = yaml.safe_load(f)["cameras"]
for camera in cameras:
ReolinkDevice(
camera["name"],
host=camera["host"],
username=camera["username"],
password=config.require_secret(camera["password_key"]),
settings=camera.get("settings", {}),
)
See example/ for a complete, runnable Pulumi project built this way.
3. Preview and deploy
pulumi preview
pulumi up
4. Detect and correct drift
If a setting was changed out-of-band (e.g. via the Reolink phone/desktop app), refresh Pulumi's state and re-apply your desired configuration:
pulumi refresh
pulumi up
Limitations & Out-of-Scope Configurations
To prevent network lockouts and state desynchronization, the following must be managed out-of-band, not through this provider:
- Initial network onboarding — join factory-reset/new cameras to your network and set their initial admin credentials with the official Reolink app first.
- Active network settings — changing the Wi-Fi SSID, Wi-Fi password, or subnet configuration via Pulumi is not supported; it can drop the camera's connection mid-transaction.
- Admin password rotation — rotate admin passwords out-of-band; a failed in-band rotation risks locking the provider out of the device.
- Firmware updates — flashing firmware is a long-running, connectivity-disrupting operation and is not supported.
- Battery-powered cameras (e.g. the Argus series) — these sleep to conserve power and disable their local HTTP API. Only plugged-in (PoE or DC-powered) cameras and doorbells are supported.
FAQ
Does this require Home Assistant?
No — it connects directly to your camera over its local HTTP API via reolink-aio, the same library Home Assistant's integration uses, but entirely standalone.
Why not use Pulumi's generic REST API provider?
Reolink's API is a single POST /cgi-bin/api.cgi RPC endpoint with stateful session-token authentication — a Login command returns a token that must be appended to every subsequent request, then a Logout command releases it — not RESTful resource paths. A generic REST provider has no way to model that session lifecycle, so this uses a custom Pulumi Dynamic Provider instead.
Does this support NVRs or multiple cameras behind one host?
Not yet. Each ReolinkDevice manages a single camera (channel 0); multi-channel NVR support is out of scope for now.
Does this work with battery-powered cameras (e.g. the Argus series)? No — they sleep to conserve power and disable their local HTTP API while asleep, so there's nothing to connect to. Only plugged-in (PoE or DC-powered) cameras and doorbells are supported.
Can I change Wi-Fi settings or rotate the admin password through this? No, deliberately. Both carry a real risk of locking the provider out of the device mid-deployment — manage them out-of-band via the Reolink app instead.
What happens if I remove a camera from my Pulumi program?
Nothing on the camera itself. delete is a no-op by design — removing a ReolinkDevice from your code stops Pulumi from managing it, but never mutates or resets the physical device.
What happens if a setting is changed outside Pulumi (e.g. via the Reolink app)?
Run pulumi refresh to detect the drift, then pulumi up to re-apply your declared configuration.
Which settings can I manage? A stable set of built-in names, plus best-effort support for others via runtime reflection on the connected camera's API. An unknown or model-unsupported setting fails the deployment with a clear error rather than silently doing nothing. The built-in names:
status_ledir_lightspush_notificationsrecordingmotion_sensitivityptz_guard_enabledftp_recordingemail_notificationshdrdaynight_modeaudio_recordingprivacy_maskbuzzerspeaker_volumeai_animal_sensitivityai_person_sensitivitybaby_cry_sensitivityauto_trackingguard_return_timeprivacy_modesiren_on_event
Is this affiliated with or endorsed by Reolink? No — this is an independent, community project built on Reolink's local HTTP API, not an official Reolink product.
Development Environment
Nix Shell
Activate the Nix developer shell to load project tools: Python, uv, pulumi, just, git, and gh. It also runs uv sync and activates the resulting .venv, so pulumi_reolink, pulumi, and pyyaml are immediately importable. example/ relies on this shell's environment rather than managing its own dependencies:
nix-shell
Task Runner (Justfile)
just: List all available tasks.just format: Format code withruff format.just lint: Lint code withruff check.just typecheck: Type-checkpulumi_reolinkwithmypy.just test: Run the unit test suite with coverage enforcement (pytest --cov-fail-under=90).just validate: Run the full pipeline (format check, lint, type check, tests).
Metadata
Release files for pulumi-reolink 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pulumi_reolink-0.1.0.tar.gz | 151.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pulumi_reolink-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.9 kB
Release files / pulumi_reolink-0.1.0.tar.gz
| Download URL | pulumi_reolink-0.1.0.tar.gz |
|---|---|
| Size | 151.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e448be7fb25a22e66149be411437a1fb2376dcb3d3287c907644c6f37c5aa21b
|
|
BLAKE2b-256 checksum How to use checksums |
478c20642c91481efd04cfe3beb2490043e77f9d8b5f5b5705fc599122094669
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.
Transparency logRelease files / pulumi_reolink-0.1.0-py3-none-any.whl
| Download URL | pulumi_reolink-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4e296017b54ca735721daaea858015dfb580c0a57e007ca93f7ddd6bbeb3470c
|
|
BLAKE2b-256 checksum How to use checksums |
5e732f5a4863e92c41eb0ebed34d07a5c11d26e436950dde39fce6b866a1c802
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.
Transparency log