# Reproducibility

The goal: after a deploy, the parts of the server the library owns are a function of your script, not of what was there before. Run the same script twice, or run it against a fresh server, and you get the same result.

What that covers:

  • Uploads. upload_file and upload_directory remove the destination first. The remote tree is exactly your local tree minus the ignored patterns. Add mode= and the permissions stop depending on the machine you deploy from too.
  • Venvs. create_venv wipes and rebuilds by default. Packages you stopped declaring disappear, pinned versions really apply, and changing the target Python version actually changes the interpreter — none of which happens in a reused venv.
  • Services. The configuration file of a deployed service is rewritten from the SupervisorService model every time. What you declare is what supervisord reads.

What it does not cover — real gaps, not oversights:

  • System packages and OS state. pacman/apt, users, nginx, databases, firewall, cron. Out of scope; the library doesn't touch them (the one exception is install_supervisor, because services are its job).
  • Files the app creates at runtime. Databases, logs, uploads, caches. They live wherever your app puts them and survive every deploy — which is normally what you want. If one lands inside an upload destination, it gets wiped: keep runtime data outside deploy directories.
  • Services deployed by previous runs. deploy_supervisor_service manages the service you hand it and nothing else. Services from earlier runs stay untouched, and stay running.

# Limitation: orphan services

There is no prune. If you rename a service — say myapp becomes myapp-web — the new configuration is deployed and started, and the old myapp keeps running with the old code, from a venv you may have just rebuilt underneath it. Same if you drop a service from your script: it isn't removed, it just stops being managed.

A prune that deleted every configuration not declared in your script would, on a host shared with other apps, take down services this library never deployed. So removing a service is manual:

conn.sudo("supervisorctl stop myapp")
conn.sudo("rm /etc/supervisor/conf.d/myapp.conf")  # Debian/Ubuntu
# conn.sudo("rm /etc/supervisor.d/myapp.ini")      # Arch
conn.sudo("supervisorctl update")