Breaking changes
- The global
validate_certsoption inmotioneye.confhas been removed. All HTTPS connections made by motionEye now verify server certificates. Certificate verification can instead be switched off individually, for remote motionEye cameras, FTPS/WebDAV/S3 upload services, webhooks, and email notifications, where a self-signed certificate is used. A leftovervalidate_certsline only causes a one-time startup warning. SMTP server certificates for email notifications with TLS enabled were never validated before. If your setup relies on this, e.g. a mailserver with self-signed certificate, or entered by IP, you need to switch off the new "Verify certificate" toggle now: - The display preferences (layout columns/rows, fit frames vertically, framerate/resolution dimmers, camera order) are now stored per browser, instead of server-side in
prefs.json, which is no longer used nor included in backups. Every browser starts with default values once. By default, the number of layout columns now follows the window width, and the single-column layout below 1200px is gone:- #3502 @JamBalaya56562
- Taken over from #1570 @digiltd
- The obsolete
updateandversionAPI endpoints, and theServerHTTP response header, have been removed: - The additional sections/configs machinery,
tzctl/wifictl, and thepushConfigRebootoption have been removed, which were unused: motiondoes not log to file by default anymore. A newlog_to_filesetting has been added, which defaults tofalse, and is honored by motionEye as well asmotion. It is overridden by the-lCLI flag, and enabled as well when running motionEye in daemon mode via-bflag. By default,motionlogs to syslog/journal now, or STDERR if no syslog is available, e.g. todocker logsin Docker containers. Sincemotiondoes not log custom event command output to syslog, if needed for "Run a command", without file logging, output needs to be handled in a script. For the commonmotioneye.servicesetup,/var/log/motioneyeis now unused, and could be removed:- Failed logins are now rate-limited per client, across usernames. After five failed attempts, further logins are delayed, starting at 5 seconds and doubling up to 15 minutes, and a 429 response with a wait message is shown. If motionEye runs behind a reverse proxy, set the new
trusted_proxiesoption inmotioneye.conf, otherwise all users share the proxy's address: - The
meyectl sendmailandmeyectl sendtelegramcommands now only take themotioncamera ID and event timestamp. For motion notifications, which internally make use of these commands, access information and credentials are read from the camera config files instead. This way, they do not appear in themeyectlcommand line and debugmotion.loganymore. Camera configurations are migrated automatically on motionEye start for this change, but any custom scripts making use of these commands might need to be adjusted: - When adding a camera from a remote motionEye instance, the local hub won't follow redirects anymore. Assure to use the final URL for network cameras on the remote. A new wiki page has been added to describe the remote motionEye feature, changes, and compatibility between motionEye versions:
New features
- Authentication for the
motioncontrol interface can now be enabled via the newmotion_control_authenticationoption (username:password) inmotioneye.conf. For this to be safe,motioneye_initnow installsmotioneye.confasroot:motionwith mode0640, so motionEye can read but not change it: - The FTP upload service has a new "Use TLS (FTPS)" switch:
- New "remove files after upload" option for upload services:
- New
eventstartandeventendactions, and buttons in the camera GUI to trigger motion events and toggle motion detection: - The order of cameras in the live view can now be customized:
- The session lifetime of the normal (surveillance) user is now configurable:
- 12-hour/AM-PM
strftimespecifiers (%I,%p,%l) can now be used in file names: - The resolution of HTTP network cameras can be set with
motion4.4+: - motionEye can now be installed more easily into a Python venv, via the new
--meyectloption ofmotioneye_init, which is now the default documented installation method: - motionEye in our official Docker images does not run as root user anymore. The desired user can instead be passed with
docker run --user, and the Docker Composeuserkey respectively: - Added FreeBSD support: local drives are listed using
geom, andmotioneye_initnow installs anrc.dservice script:- #3508 @JamBalaya56562
- Taken over from #1616 @ascl00
- motionEye Docker images for
ppc64leands390xare provided on Docker Hub and the GitHub Docker Registry now:
Enhancements
- Webhooks now send a
User-Agentheader: - Media files are now passed on relative to the camera dir, and mounted drives are listed even without write access:
- Camera settings are refused when no storage device is available, and an unmounted local disk does not break the settings anymore:
- The camera list is now loaded faster, by asking remote cameras at the same time, and errors reported by remote motionEye instances are handled as failures:
- Telegram notifications are now sent out faster, by limiting the requested list of pictures to the event time span. Pictures are sent sorted, with oldest first, and sending the message is retried once on failure if no data could be sent:
- Event commands are logged to syslog, where
motionmutes them: - Notifications are sent even when the picture listing fails:
- Translations are embedded into the page, avoiding a delayed page load:
- Passwords which are set are no longer sent to the frontend, instead of being masked:
- Motion is now tracked by its process instead of a PID file.
/var/run/motioneyeis hence not needed anymore in the commonmotioneye.servicesetup: - Some config handling is more tolerant: unparsable commands, other
netcam_paramsentries, and camera configs lacking newer upload settings no longer cause failures: - Camera lists are now filtered by user role, so normal users only see the camera fields they need:
- MJPEG stream URLs are now withheld until the user has logged in, and the live view starts automatically after login:
- The upload services state file is now created with
0600permissions: - Requests from a remote (peer) motionEye can no longer read or change the main configuration:
- A motionEye hub now treats everything a remote motionEye or a camera sends as untrusted:
- Camera names and messages are shown as plain text, and the remote camera id is validated.
- Remote JSON answers are checked, and redirects from a remote are rejected.
- Remote zip and timelapse downloads are only accepted with known types, and remote movies are cached per camera and path.
- Error messages are sanitized, and the storage webhook URL is now validated like the other webhook URLs.
- Cookies are read by their exact name, and every response now carries
X-Content-Type-Options: nosniff. - 0e09e21 @free-cup-holder-exe
- df9d70e @free-cup-holder-exe
- Camera names are now shown as plain text when settings are applied and in the camera frame:
Fixes
- The Google Drive upload service has been fixed: Obtaining an authorization key was not possible, since Google blocked the intended redirect. The steps are now outlined on the motionEye dialog, and imply copying the URL address from the browser tab after being redirected by Google:
- Using a different listen address than
0.0.0.0and127.0.0.1does not break the motionEye relay API anymore: - Mask editing now uses whole-pixel rectangles and builds the grid at the capture size. This solves an issue where the masked drifted on every load/save cycle:
- v4l2 cameras now show boolean controls and use correct control names, and a failed control listing is warned about and not cached:
- Boolean
netcam_paramsare translated correctly: - Admin-only camera settings are preserved when omitted from a save:
- A failed-connection placeholder is no longer stored as a remote camera's settings:
- Camera tests report MJPEG connection errors, check RTSP Basic credentials, and no longer fail with a timeout exception:
- Saving email notification settings with an empty From address works again, an email is no longer reported as failed when closing the SMTP connection fails, and the test mail no longer raises a second exception on SMTP errors:
- Dropbox access test has been fixed:
- The upload test success message no longer contains a stray
object: - Timelapse movies now apply the configured framerate:
- An unknown
log_levelno longer enables debug logging: - Python 3.14 fix: the
forkmultiprocessing start method is kept: - CIFS mounts no longer trigger an
ntlmkernel warning: - Media dialog playback handlers no longer stack up:
- UI fixes: layout rows fit the window again, action buttons are arranged properly with the camera overlay shown, and a camera in error keeps its aspect ratio:
- Mask files are written to the configured
conf_path: - Removing old media files lists each folder once, and stops at the target dir when removing empty folders. This speeds up the old media files cleanup job significantly:
- The movie cache dir is created when caching, instead of on import:
- A manual motion detection change is kept until the schedule changes:
- Camera configs now record the motionEye version which saved them, so migrations can be done based on the previous motionEye version, rather than on every startup:
Other changes
- The
pausesetting ofmotion4.4+ is used now if motion detection is disabled, which avoids an additional API request at motionEye start, and assures that no motion event can be triggered during the early startup sequence: - Tests and CI/CD: hub/remote compatibility checks across motionEye versions, new tests, CI updates, and regular pre-commit autoupdates:
- Code quality, typing, and linter/Bandit annotations, removal of unnecessary imports and
shell=Truecalls: - Background cleanup moved from a process loop to tasks, with follow-up enhancements:
- Frontend: inline scripts and handlers moved out of the templates, a CSP response header is now set to guard against XSS, and
list_mediacan filter by time window: - Camera configs are migrated after logging is configured:
- Documentation: README now covers Docker images and
motioneye_init, Docker build section fixed: - As always: several translations have been updated. Many thanks to all @weblate contributors! ❤️