|
| 1 | +# USB Sync & Move2USB |
| 2 | + |
| 3 | +Photobooth offers two ways to get your photos and videos onto a USB stick: |
| 4 | + |
| 5 | +| Feature | Purpose | Trigger | |
| 6 | +|---------|---------|---------| |
| 7 | +| **USB Sync** | Automatic background sync at a regular interval | Runs continuously while Photobooth is open | |
| 8 | +| **Move2USB** | One-shot copy **or** move of all media | Manual — HTTP endpoint, socket.io command, or hardware button | |
| 9 | + |
| 10 | +Both features share the same USB device identifier (Adminpanel → **USB Sync → USB device identifier**) and the same Linux mount permissions. |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +- **Linux only** — Windows is not supported. |
| 17 | +- **rsync** must be installed (`sudo apt install rsync`). |
| 18 | +- A **USB stick** formatted as **FAT32** or **exFAT** (recommended for cross-platform compatibility). The volume label should match the identifier configured in the admin panel (default: `photobooth`). |
| 19 | +- Mount permissions for the `www-data` user (see [Permissions setup](#permissions-setup) below). |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## Permissions setup |
| 24 | + |
| 25 | +The web-server user (`www-data`) needs permission to mount and unmount USB drives. |
| 26 | +Photobooth ships two complementary mechanisms that are installed via the **Photobooth Setup Wizard**: |
| 27 | + |
| 28 | +1. **Polkit rule** — allows `www-data` to call `udisksctl mount` / `udisksctl unmount` without a password. |
| 29 | +2. **sudoers rule** (`/etc/sudoers.d/021_www-data-usb-sync`) — passwordless `sudo mount`, `sudo umount` and `sudo mkdir -p /media/*` as fallback when udisksctl is unavailable. |
| 30 | + |
| 31 | +### Installing via the Setup Wizard |
| 32 | + |
| 33 | +Download and run the Setup Wizard: |
| 34 | + |
| 35 | +``` |
| 36 | +wget -O install-photobooth.sh https://raw.githubusercontent.com/PhotoboothProject/photobooth/dev/install-photobooth.sh |
| 37 | +sudo bash install-photobooth.sh |
| 38 | +``` |
| 39 | + |
| 40 | +Then choose: |
| 41 | + |
| 42 | +- **6 Permissions → 4 USB Sync policy** |
| 43 | + |
| 44 | +The wizard will: |
| 45 | + |
| 46 | +- Install the Polkit rule for udisksctl. |
| 47 | +- Install the sudoers rule for mount/umount/mkdir. |
| 48 | +- Try to disable desktop auto-mount (pcmanfm volume handling) to avoid permission conflicts. |
| 49 | +- Remove any legacy `020_www-data-usb` sudoers file. |
| 50 | + |
| 51 | +Run the same menu entry again after OS upgrades to re-apply the rules. |
| 52 | + |
| 53 | +### Removing permissions |
| 54 | + |
| 55 | +Run **6 Permissions → 4 USB Sync policy** again and answer **No** when asked to set up the policy. The wizard removes Polkit rules, sudoers rules, and the legacy files. |
| 56 | + |
| 57 | +--- |
| 58 | + |
| 59 | +## USB Sync (automatic) |
| 60 | + |
| 61 | +USB Sync runs as a background Node.js process (`sync-to-drive.js`) that is started automatically when Photobooth is opened in the browser (provided the feature is enabled). |
| 62 | + |
| 63 | +### How it works |
| 64 | + |
| 65 | +1. The process looks for a USB device matching the configured identifier (label, device path, or device name). |
| 66 | +2. It mounts the device if it is not already mounted: |
| 67 | + - First via `udisksctl mount`. |
| 68 | + - Fallback: `sudo mount` to `/media/<label>` with automatic FAT32/exFAT uid/gid options. |
| 69 | +3. It runs `rsync` to incrementally copy new `jpg`, `gif`, `mp4` files from the Photobooth data directory to the USB stick. |
| 70 | +4. Deleted images are backed up into a `deleted/` folder on the USB stick (rsync `--backup-dir`). |
| 71 | +5. After sync completes, the process sleeps for the configured interval and starts over. |
| 72 | + |
| 73 | +### Device detection |
| 74 | + |
| 75 | +The device is matched (case-insensitive) by: |
| 76 | + |
| 77 | +- **Volume label** (recommended) — e.g. `photobooth` |
| 78 | +- **Block device path** — e.g. `/dev/sda1` |
| 79 | +- **Device short name** — e.g. `sda1` |
| 80 | + |
| 81 | +If `lsblk` does not report the label (e.g. in LXC containers or after a USB reconnect), Photobooth falls back to `blkid` which reads the label directly from the block device. |
| 82 | + |
| 83 | +### Configuration |
| 84 | + |
| 85 | +Open the Admin Panel → **USB Sync**: |
| 86 | + |
| 87 | +| Setting | Description | |
| 88 | +|---------|-------------| |
| 89 | +| **Enable** | Turn automatic USB Sync on or off. | |
| 90 | +| **Automated syncing interval** | Seconds between sync attempts (default: 300). | |
| 91 | +| **USB device identifier** | The value used to find the USB stick — typically the volume label (default: `photobooth`). | |
| 92 | + |
| 93 | +### File types synced |
| 94 | + |
| 95 | +`jpg`, `gif`, `mp4` (and the internal `chk` verification files). |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +## Move2USB (manual copy / move) |
| 100 | + |
| 101 | +Move2USB lets you copy — or move — **all** current photos and videos to the USB stick with a single action. |
| 102 | + |
| 103 | +### Modes |
| 104 | + |
| 105 | +| Mode | Behaviour | |
| 106 | +|------|-----------| |
| 107 | +| **copy** | Copies all media to the USB stick. Originals remain on the Photobooth. | |
| 108 | +| **move** | Copies all media to the USB stick **and** deletes the originals plus the Photobooth image database after a successful, verified sync. | |
| 109 | + |
| 110 | +### Enabling Move2USB |
| 111 | + |
| 112 | +1. Adminpanel → **Hardware Button → Enable Hardware Buttons** must be active. |
| 113 | +2. Adminpanel → **Hardware Button → Move2USB mode** — choose `copy` or `move` (set to `disabled` to hide the feature). |
| 114 | +3. The **USB device identifier** under USB Sync must point to a valid USB stick. |
| 115 | + |
| 116 | +### Triggering Move2USB |
| 117 | + |
| 118 | +- **HTTP endpoint:** `http://<IP>:<Port>/commands/start-move2usb` |
| 119 | +- **Socket.io:** emit `photobooth-socket` → `move2usb` |
| 120 | +- **Hardware button:** assign a key code to the Move2USB action (same input-device mechanism as picture/collage/print). |
| 121 | + |
| 122 | +### Copy verification |
| 123 | + |
| 124 | +Move2USB creates a `copy.chk` marker file in the Photobooth data folder before rsync and expects it to appear on the USB stick after sync. If the marker is missing on the USB stick after rsync, the sync is treated as **failed** and no files are deleted (even in `move` mode). |
| 125 | + |
| 126 | +### What gets deleted in "move" mode |
| 127 | + |
| 128 | +Only after a verified successful sync: |
| 129 | + |
| 130 | +1. All `jpg`, `gif`, `mp4` files in the Photobooth data directory. |
| 131 | +2. The Photobooth image database file (`<dbname>.txt`). |
| 132 | + |
| 133 | +--- |
| 134 | + |
| 135 | +## Mount strategy (both features) |
| 136 | + |
| 137 | +Photobooth uses a layered approach to mount USB drives: |
| 138 | + |
| 139 | +1. **udisksctl** — preferred, works with the Polkit rule. |
| 140 | +2. **findmnt check** — if udisksctl output was ambiguous, verify via `findmnt`. |
| 141 | +3. **sudo mount** — fallback using the sudoers rule; mounts to `/media/<label>`. |
| 142 | + |
| 143 | +For **FAT32** (`vfat`) and **exFAT** volumes the mount options `umask=0000,uid=<www-data>,gid=<www-data>` are set automatically so the web-server process can write to the stick. |
| 144 | + |
| 145 | +If a drive is already mounted but **not writable** (e.g. auto-mounted by the desktop with different uid/gid), Photobooth unmounts and re-mounts it with the correct options. |
| 146 | + |
| 147 | +Unmounting follows the same order: udisksctl first, `sudo umount` as fallback. |
| 148 | + |
| 149 | +--- |
| 150 | + |
| 151 | +## Preparing a USB stick |
| 152 | + |
| 153 | +1. Format the stick as **FAT32** (for sticks ≤ 32 GB) or **exFAT** (for larger sticks). |
| 154 | +2. Set the volume label to `photobooth` (or whatever you configure as the USB device identifier). |
| 155 | + - Linux: `sudo fatlabel /dev/sdX1 photobooth` (FAT32) or `sudo exfatlabel /dev/sdX1 photobooth` (exFAT). |
| 156 | + - Windows: right-click the drive → Rename. |
| 157 | + - macOS: Disk Utility → rename the volume. |
| 158 | +3. Plug the stick into the Photobooth host. |
| 159 | + |
| 160 | +--- |
| 161 | + |
| 162 | +## Troubleshooting |
| 163 | + |
| 164 | +### USB stick not detected |
| 165 | + |
| 166 | +- Verify the label: `lsblk -o NAME,LABEL,FSTYPE,MOUNTPOINT` — the label must match the configured identifier (case-insensitive). |
| 167 | +- If `lsblk` shows no label, try `blkid` — Photobooth uses this as a fallback. |
| 168 | +- Confirm the device is a **USB** device (`lsblk -o NAME,SUBSYSTEMS` should contain `usb`). |
| 169 | + |
| 170 | +### Permission errors / mount failures |
| 171 | + |
| 172 | +- Re-run the Setup Wizard → **Permissions → USB Sync policy**. |
| 173 | +- Check that Polkit and sudoers are in place: |
| 174 | + - `ls -l /etc/polkit-1/localauthority/50-local.d/photobooth.pkla` or `/etc/polkit-1/rules.d/photobooth.rules` |
| 175 | + - `ls -l /etc/sudoers.d/021_www-data-usb-sync` |
| 176 | +- Disable desktop auto-mount (e.g. pcmanfm volume handling) — it can race with Photobooth and mount with the wrong uid. |
| 177 | + |
| 178 | +### Sync not running / nothing copied |
| 179 | + |
| 180 | +- Is USB Sync enabled in the Admin Panel? |
| 181 | +- Check the server logs at the Debug panel: [http://localhost/admin/debugpanel](http://localhost/admin/debugpanel). |
| 182 | +- Look for `[synctodrive]` log lines — they show device detection, mount status, and rsync output. |
| 183 | + |
| 184 | +### Move2USB fails or does not delete files |
| 185 | + |
| 186 | +- Check Debug panel for `[remotebuzzer]` log lines mentioning `move2usb`. |
| 187 | +- If the log says "sync verification failed (copy.chk missing)", the rsync did not complete successfully — check USB stick space and permissions. |
| 188 | +- Files are only deleted in `move` mode **and** only after verified sync. |
| 189 | + |
| 190 | +### FAT32 / exFAT write issues |
| 191 | + |
| 192 | +- Ensure the stick is not write-protected (physical switch on some USB sticks). |
| 193 | +- Re-format the stick and re-label it. |
| 194 | +- If mounted by another process, Photobooth will unmount and re-mount with proper options — check the log for "not writable, unmounting" messages. |
0 commit comments