A containerized deployment of the Motion video surveillance software using Podman and Kubernetes-style YAML definitions. It turns a local webcam into a DVR: motion events are detected and recorded straight to the host filesystem, with a web control panel and live stream exposed on the host network.
- Codec/resolution: MJPG at 1280x720, 30 fps
- Recording: 60-second MKV chunks written directly to the host
- Deployment model: single
podman play kubecommand, no manualpodman runflags
- Podman installed and running on the host machine.
- Hardware: a V4L2-compatible webcam connected to the host (default device path:
/dev/video0). - SELinux: on an enforcing system (e.g. Fedora), the host directories need the
container_file_tcontext or Motion won't be able to read its config or write recordings.
Only config/ and container/ are tracked in this repo. storage/ is runtime output and needs to be created locally — it holds your recordings, so you don't want it in version control.
~/motion/
├── config/
│ └── motion.conf # Motion configuration file
├── container/
│ └── motion-pod.yaml # Kubernetes-style Podman deployment file
└── storage/ # Recordings land here (create this — not in the repo)
1. Clone the repository
git clone https://github.com/sancliffe/pod-motion.git ~/motion
cd ~/motion
mkdir -p storage2. Match the volume paths to your host
container/motion-pod.yaml hard-codes its hostPath volumes to /home/steve/motion/.... If your home directory isn't /home/steve, update both hostPath.path entries (for motion-storage-vol and motion-config-vol) to match your actual clone location, e.g.:
sed -i "s#/home/steve/motion#${HOME}/motion#g" container/motion-pod.yaml3. Apply SELinux context (if applicable)
chcon -Rt container_file_t ~/motion/config ~/motion/storage ~/motion/container4. Deploy the pod
podman play kube ~/motion/container/motion-pod.yamlThis creates the pod (motion-deployment-pod), mounts the config/storage volumes, maps the ports, and pulls docker.io/motionproject/motion:latest if it isn't already present.
5. Confirm it's running
podman pod ps
podman logs motion-deployment-motionThen open http://<host-ip>:7999 for the web control panel and http://<host-ip>:8081 for the live stream.
| Port | Purpose |
|---|---|
7999 |
Web control panel (configuration and admin interface) |
8081 |
Live camera stream |
webcontrol_localhost and stream_localhost are set to off in motion.conf — required for either port to be reachable from outside the pod's network namespace. If you only want local access, flip these back to on and drop the hostPort mappings.
| Host path | Container path | Purpose |
|---|---|---|
~/motion/storage |
/var/lib/motion |
Recorded MKV output |
~/motion/config |
/usr/local/etc/motion |
motion.conf |
/dev/video0 |
/dev/video0 |
Webcam passthrough |
If your webcam isn't at /dev/video0, update both the webcam-device volume and video_device in motion.conf to match (check with v4l2-ctl --list-devices or ls /dev/video*).
podman pod rm -f motion-deployment-podThis stops and removes the pod and its containers. Recordings in ~/motion/storage are left untouched.
podman play kubesucceeds but the pod restarts / camera not found: check the container has access to the device — you may need--security-opt label=disableor to confirm the/dev/video0path exists on the host before deploying.- Web control panel or stream unreachable from another machine: double-check
webcontrol_localhost offandstream_localhost offare actually set inmotion.conf(a stale mount from an old path will silently use Motion's built-in defaults instead). Permission deniedwriting recordings, or Motion can't readmotion.conf: almost always a missedchcon -Rt container_file_ton an SELinux-enforcing host — re-run step 3 above.- Port already in use: something else on the host is bound to 7999 or 8081; change the
hostPortvalues inmotion-pod.yamland the correspondingServiceports.
MIT — see LICENSE.