diff --git a/ansible/environments/laptop/host_vars/odofreebsd b/ansible/environments/laptop/host_vars/odofreebsd
index 2e2ac18..aecf6d0 100644
--- a/ansible/environments/laptop/host_vars/odofreebsd
+++ b/ansible/environments/laptop/host_vars/odofreebsd
@@ -30,6 +30,7 @@ users:
       - name: video
       - name: u2f
       - name: operator # To be able to shutdown without root
+      - name: webcamd
     authorized_keys:
       - yubikey
       - main_fido
diff --git a/ansible/playbook.yaml b/ansible/playbook.yaml
index 885c7ba..8ba9079 100644
--- a/ansible/playbook.yaml
+++ b/ansible/playbook.yaml
@@ -43,6 +43,7 @@
     - poudriere
     - android
     - latex
+    - webcam
 
 - hosts: nat_dhcp:homeserver_nat_dhcp
   vars:
diff --git a/ansible/roles/webcam/files/cuse_loader.conf b/ansible/roles/webcam/files/cuse_loader.conf
new file mode 100644
index 0000000..040ca03
--- /dev/null
+++ b/ansible/roles/webcam/files/cuse_loader.conf
@@ -0,0 +1 @@
+cuse_load="YES"
diff --git a/ansible/roles/webcam/files/webcamd_rc.conf b/ansible/roles/webcam/files/webcamd_rc.conf
new file mode 100644
index 0000000..fafc0dd
--- /dev/null
+++ b/ansible/roles/webcam/files/webcamd_rc.conf
@@ -0,0 +1 @@
+webcamd_enable="YES"
diff --git a/ansible/roles/webcam/tasks/common.yaml b/ansible/roles/webcam/tasks/common.yaml
new file mode 100644
index 0000000..fef1101
--- /dev/null
+++ b/ansible/roles/webcam/tasks/common.yaml
@@ -0,0 +1,15 @@
+- import_tasks: tasks/freebsd.yaml
+  when: 'os_flavor == "freebsd"'
+
+- import_tasks: tasks/linux.yaml
+  when: 'os_flavor == "linux"'
+
+- include_tasks:
+    file: tasks/peruser.yaml
+    apply:
+      become: yes
+      become_user: "{{ initialize_user }}"
+  when: users is defined
+  loop: "{{ users | dict2items | community.general.json_query('[?value.initialize==`true`].key') }}"
+  loop_control:
+    loop_var: initialize_user
diff --git a/ansible/roles/webcam/tasks/freebsd.yaml b/ansible/roles/webcam/tasks/freebsd.yaml
new file mode 100644
index 0000000..adf188f
--- /dev/null
+++ b/ansible/roles/webcam/tasks/freebsd.yaml
@@ -0,0 +1,26 @@
+- name: Install packages
+  package:
+    name:
+      - webcamd
+      - pwcview # For testing webcam
+    state: present
+
+- name: Install loader.conf
+  copy:
+    src: "files/{{ item }}_loader.conf"
+    dest: "/boot/loader.conf.d/{{ item }}.conf"
+    mode: 0644
+    owner: root
+    group: wheel
+  loop:
+    - cuse
+
+- name: Install service configuration
+  copy:
+    src: "files/{{ item }}_rc.conf"
+    dest: "/etc/rc.conf.d/{{ item }}"
+    mode: 0644
+    owner: root
+    group: wheel
+  loop:
+    - webcamd
diff --git a/ansible/roles/webcam/tasks/linux.yaml b/ansible/roles/webcam/tasks/linux.yaml
new file mode 100644
index 0000000..43ba876
--- /dev/null
+++ b/ansible/roles/webcam/tasks/linux.yaml
@@ -0,0 +1,29 @@
+# - name: Build aur packages
+#   register: buildaur
+#   become_user: "{{ build_user.name }}"
+#   command: "aurutils-sync --no-view {{ item }}"
+#   args:
+#     creates: "/var/cache/pacman/custom/{{ item }}-*.pkg.tar.*"
+#   loop:
+#     - foo
+
+# - name: Update cache
+#   when: buildaur.changed
+#   pacman:
+#     name: []
+#     state: present
+#     update_cache: true
+    
+# - name: Install packages
+#   package:
+#     name:
+#       - foo
+#     state: present
+
+# - name: Enable services
+#   systemd:
+#     enabled: yes
+#     name: "{{ item }}"
+#     daemon_reload: yes
+#   loop:
+#     - foo.service
diff --git a/ansible/roles/webcam/tasks/main.yaml b/ansible/roles/webcam/tasks/main.yaml
new file mode 100644
index 0000000..6805b9d
--- /dev/null
+++ b/ansible/roles/webcam/tasks/main.yaml
@@ -0,0 +1,2 @@
+- import_tasks: tasks/common.yaml
+  # when: foo is defined
diff --git a/ansible/roles/webcam/tasks/peruser.yaml b/ansible/roles/webcam/tasks/peruser.yaml
new file mode 100644
index 0000000..111e886
--- /dev/null
+++ b/ansible/roles/webcam/tasks/peruser.yaml
@@ -0,0 +1,29 @@
+- include_role:
+    name: per_user
+
+# - name: Create directories
+#   file:
+#     name: "{{ account_homedir.stdout }}/{{ item }}"
+#     state: directory
+#     mode: 0700
+#     owner: "{{ account_name.stdout }}"
+#     group: "{{ group_name.stdout }}"
+#   loop:
+#     - ".config/foo"
+
+# - name: Copy files
+#   copy:
+#     src: "files/{{ item.src }}"
+#     dest: "{{ account_homedir.stdout }}/{{ item.dest }}"
+#     mode: 0600
+#     owner: "{{ account_name.stdout }}"
+#     group: "{{ group_name.stdout }}"
+#   loop:
+#     - src: foo.conf
+#       dest: .config/foo/foo.conf
+
+- import_tasks: tasks/peruser_freebsd.yaml
+  when: 'os_flavor == "freebsd"'
+
+- import_tasks: tasks/peruser_linux.yaml
+  when: 'os_flavor == "linux"'
diff --git a/ansible/roles/webcam/tasks/peruser_freebsd.yaml b/ansible/roles/webcam/tasks/peruser_freebsd.yaml
new file mode 100644
index 0000000..e69de29
diff --git a/ansible/roles/webcam/tasks/peruser_linux.yaml b/ansible/roles/webcam/tasks/peruser_linux.yaml
new file mode 100644
index 0000000..e69de29