diff --git a/changelogs/fragments/user-alpine-on-changed-fix.yaml b/changelogs/fragments/user-alpine-on-changed-fix.yaml
new file mode 100644
index 00000000000..aa7f7d04ff1
--- /dev/null
+++ b/changelogs/fragments/user-alpine-on-changed-fix.yaml
@@ -0,0 +1,2 @@
+bugfixes:
+  - user - on systems using busybox, honor the ``on_changed`` parameter to prevent unnecessary password changing (https://github.com/ansible/ansible/issues/65711)
diff --git a/lib/ansible/modules/system/user.py b/lib/ansible/modules/system/user.py
index 8849f60d050..e25938d0e0f 100644
--- a/lib/ansible/modules/system/user.py
+++ b/lib/ansible/modules/system/user.py
@@ -2796,15 +2796,14 @@ class BusyBox(User):
                             self.module.fail_json(name=self.name, msg=err, rc=rc)
 
         # Manage password
-        if self.password is not None:
-            if info[1] != self.password:
-                cmd = [self.module.get_bin_path('chpasswd', True)]
-                cmd.append('--encrypted')
-                data = '{name}:{password}'.format(name=self.name, password=self.password)
-                rc, out, err = self.execute_command(cmd, data=data)
+        if self.update_password == 'always' and self.password is not None and info[1] != self.password:
+            cmd = [self.module.get_bin_path('chpasswd', True)]
+            cmd.append('--encrypted')
+            data = '{name}:{password}'.format(name=self.name, password=self.password)
+            rc, out, err = self.execute_command(cmd, data=data)
 
-                if rc is not None and rc != 0:
-                    self.module.fail_json(name=self.name, msg=err, rc=rc)
+            if rc is not None and rc != 0:
+                self.module.fail_json(name=self.name, msg=err, rc=rc)
 
         return rc, out, err
 
diff --git a/test/integration/targets/user/tasks/main.yml b/test/integration/targets/user/tasks/main.yml
index b76531c8e02..bee81aabab4 100644
--- a/test/integration/targets/user/tasks/main.yml
+++ b/test/integration/targets/user/tasks/main.yml
@@ -95,6 +95,32 @@
   assert:
     that: "'warnings' not in test_user_encrypt0"
 
+# https://github.com/ansible/ansible/issues/65711
+- name: Test updating password only on creation
+  user:
+    name: ansibulluser
+    password: '*'
+    update_password: on_create
+  register: test_user_update_password
+
+- name: Ensure password was not changed
+  assert:
+    that:
+      - test_user_update_password is not changed
+
+- name: Verify password hash for Linux
+  when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+  block:
+    - name: LINUX | Get shadow entry for ansibulluser
+      getent:
+        database: shadow
+        key: ansibulluser
+
+    - name: LINUX | Ensure password hash was not removed
+      assert:
+        that:
+          - getent_shadow['ansibulluser'][1] != '*'
+
 - block:
     - name: add an plaintext password for user
       user: