Introduction
I use Dropbox to back up my smartphone photos in full resolution to my home server, allowing me to avoid paying for high-capacity cloud services just to transfer files. Since my server curie has plenty of local storage, I only need a reliable cloud platform to serve as a middle layer. The basic 2GB free tier of Dropbox is perfect for this when paired with its “Camera Uploads” mobile feature. The photos sync immediately to the server, and a script sweeps them into permanent storage, keeping our Dropbox usage well under the 2GB limit.
However, running the headless Dropbox daemon 24/7 creates a secondary issue: it keeps the local storage array spinning all day, causing unnecessary disk wear, power draw, and noise. The solution is to stop the always-on services and run Dropbox in short windows a few times per day using systemd. This uses the official Linux daemon and command line interface, see Dropbox for Linux install and Dropbox Linux CLI.
Create a windowed Dropbox service
First, I created a template service, /etc/systemd/system/dropbox-window@.service. This runs the official daemon at /opt/dropbox/dropboxd for a limited time, 30 minutes, then stops it automatically via RuntimeMaxSec. The %i token acts as a placeholder for the username, making it incredibly easy to scale to a multi-user setup. See systemd.service.
[Unit] Description=Run Dropbox for a limited window for %i After=network-online.target Wants=network-online.target [Service] Type=simple User=%i ExecStart=/opt/dropbox/dropboxd # Stop the process automatically after 30 minutes RuntimeMaxSec=1800 # SIGINT lets Dropbox shut down gracefully, similar to pressing Ctrl-C. KillSignal=SIGINT # Ensures that when systemd stops the service, it sends the stop signal to all processes in the same control group KillMode=control-group # Gives Dropbox up to 60 seconds to stop gracefully after receiving SIGINT before further action is taken. TimeoutStopSec=60 # If the service still does not stop after TimeoutStopSec, systemd will send SIGKILL to forcibly terminate it. SendSIGKILL=yes # Commands that run after the main process stops. These are cleanup actions. Kills any leftover Dropbox processes # matching /opt/dropbox/.../dropbox for that user ExecStopPost=/usr/bin/pkill -u %i -f '/opt/dropbox/.*/dropbox'
Setting KillMode=control-group ensures the entire process tree receives the termination signal. As an extra failsafe for a multi-user environment, the ExecStopPost command uses a precise pkill target limited to that specific user account (-u %i). This ensures user instances do not interfere with each other or leave orphan processes behind.
Schedule the window every six hours
Then I created a timer unit, /etc/systemd/system/dropbox-window@.timer. This uses monotonic timers to start the service every 6 hours, see systemd.timer:
[Unit] Description=Start Dropbox window for %i every 6 hours [Timer] OnBootSec=5min OnUnitActiveSec=6h Persistent=true [Install] WantedBy=timers.target
If you want the window to be 15 minutes instead of 30, set RuntimeMaxSec=900. For a calendar schedule instead of a fixed interval, use OnCalendar= in the timer unit.
Enable the timers
Now I could enable the service for the respective users on the server:
sudo systemctl enable --now dropbox-window@tjansson.timer sudo systemctl enable --now dropbox-window@user2.timer
Systemd handles the execution windows independently for each account, ensuring everything stays isolated and highly maintainable.
Looking at my system thread monitoring metrics below, you can see how this optimization helped. Instead of a continuous high thread count baseline, the server now shows distinct, sharp spikes only when the Dropbox windows open every 6 hours, leaving the system (and the disks) completely at peace in between. Part of the problem was also that dropboxd was failing as it was not up to date, but see how that is resolved below.

Moving files into permanent storage
With the sync windows running on a predictable cycle, we need to regularly pull files out of the incoming Dropbox/Camera Uploads directory. Relocating these files locally forces Dropbox to delete them from the cloud during the next sync window, keeping your 2GB quota permanently open.
Here is the bash script I run to move the images to my permanent media directory (/home/tjansson/bin/move-dropbox-images-tjansson.sh):
#!/bin/bash shopt -s nullglob # don't return literal glob if matching fails DIR_FROM="/home/tjansson/Dropbox/Camera Uploads" DIR_DEST="/home/tjansson/Media/Pictures/Thomas-phone-pictures/" # Only try to move the files if there are any files present FROM_FILES=("$DIR_FROM"/*.*) if [[ ${#FROM_FILES[@]} > 1 ]]; then mv "$DIR_FROM"/*.* "$DIR_DEST" fi
Note the shopt -s nullglob line—this is important so that if the folder is empty, bash doesn’t try to literally move a file named *.*, which would result in an error. Simply set this script to run once a day (e.g., every day at 4 in the morning) via your user’s crontab:
00 4 * * * /home/tjansson/bin/move-dropbox-images-tjansson.sh
You can easily set up a similar script and cron job for the second user (e.g., user2) to move their photos into their respective permanent storage folder.
Automating Dropbox Updates
The headless Dropbox binaries must be kept up to date as otherwise, the client eventually refuses to authenticate and stops syncing entirely. Since we are no longer dealing with simple, static service names, our automated update workflow needs to gracefully pause the active systemd window components before updating the binary directory at /opt/dropbox.
I keep this script at /opt/update-dropbox.sh and run it once a day at 3:30 in the morning through cron:
#!/usr/bin/env sh # 1. Stop the running Dropbox instances to prevent conflicts during the update. # We redirect standard output to /dev/null so cron stays silent on a successful stop. sudo systemctl stop dropbox-window@tjansson.service > /dev/null sudo systemctl stop dropbox-window@user2.service > /dev/null sleep 1 # 2. Download the latest Dropbox Linux package. # The '-nv' (non-verbose) flag turns off the progress bar, but will still output # a message if the download completely fails (triggering a cron email). sudo wget -nv "https://www.dropbox.com/download?plat=lnx.x86_64" -O dropbox-linux.tar.gz # 3. Extract the downloaded package. # It will now extract silently unless the archive itself is corrupted. sudo tar xzf dropbox-linux.tar.gz --strip 1 -C /opt/dropbox # 4. Delete the downloaded tarball to clean up disk space. sudo rm -f dropbox-linux.tar.gz # 5. Restart the Dropbox instances with the newly updated files. # Output is sent to /dev/null to keep successful startups quiet. sudo systemctl start dropbox-window@tjansson.service > /dev/null sudo systemctl start dropbox-window@user2.service > /dev/null
Conclusion
By shifting from an always-on configuration to a windowed sync architecture, we address two operational challenges at once. We retain a completely seamless, multi-user mobile backup workflow that avoids expensive cloud storage tiers, while also ensuring that our server’s hard drives aren’t being forced to stay awake 24/7 by a restless background daemon. The disks get to spin down quietly, our hardware lifespan is extended, and our backups remain perfectly up to date.
Notes and references
If you are setting up from scratch on a server, follow the headless flow described on the official install page, then keep the daemon in /opt/dropbox.
