Página en inglés
Esta página de referencia todavía no está traducida al español. Las guías (Primeros pasos, Flujos, Videos, Ejemplos) sí lo están.
📖 CLI Reference¶
Every versa command, its arguments and flags, and what it does on your machine and on the server.
- Conventions
- Global flags
- Choosing the configuration file
- Commands
- Setup:
init·config validate·ssh-test/info - Deploying:
deploy·diff·rollback·status - Operating the server:
exec·logs·hooks·services-reload·service - The tool itself:
version·self-update - Interactive TUI
- Which commands work in local mode
- Exit codes and error output
Conventions¶
versa <command> <environment> [arguments] [flags]
<environment>is a key underenvironments:in your config file (production,staging, …). It is required by every command that touches a server.- Run
versafrom the root of your Git repository. versa deploys the repository in the current directory and looks for the config file there. versa <command> --helpprints the built-in help for any command.
Global flags¶
Available on every command.
| Flag | Default | Description |
|---|---|---|
--config <path> |
deploy.yml |
Configuration file to use. Disables auto-discovery (see below). |
--verbose |
false |
More detailed output. |
--debug |
false |
Debug output (internal steps, remote commands). |
--log-file <path> |
— | Also write the log to this file. Handy to keep a history: --log-file deploy.log. |
--no-gui |
false |
With no command, print help instead of launching the TUI. |
--gui |
false |
Launch the TUI. Kept for backward compatibility: plain versa already does this. |
-v, --version |
— | Print the version (same as versa version). |
-h, --help |
— | Help for any command. |
Choosing the configuration file¶
Unless you pass --config, versa looks in the current directory for files matching any of these names (.yml or .yaml):
deploy.yml deploy_*.yml versa_deploy.yml versa_deploy_*.yml *_deploy.yml *_deploy_*.yml
| Files found | What happens |
|---|---|
| None | deploy.yml is used (and the command fails if it doesn't exist). |
| One | That file is used. |
| Several | versa lists them and asks you to pick one by number. |
For scripts and CI, always pass --config so versa never stops to ask:
versa deploy production --config versa_deploy_frontend.yml
[!NOTE]
versa initdoes not auto-discover: it always writes to the--configpath (defaultdeploy.yml).
versa init¶
Creates a commented starter configuration in the current directory.
versa init # asks: [1] VPS/server over SSH, [2] local hosting without SSH
versa init --local # skip the question, generate a local-mode config
versa init --config deploy_staging.yml
| Flag | Default | Description |
|---|---|---|
--local |
false |
Generate a local-mode environment without asking. |
Fails if the target file already exists. Edit the generated file, then run versa config validate.
versa config validate¶
Parses and validates the config file without connecting to any server.
versa config validate # validate every environment
versa config validate production # also print a summary of one environment
It checks required fields, that ssh.key_path exists (and on Linux/macOS, that it is chmod 600), that remote_path is absolute, that at least one build is enabled and that each enabled build has its required fields. With an environment name it prints:
✅ deploy.yml is valid (2 environment(s): production, staging)
Environment "production":
mode: ssh
ssh: deploy@10.0.0.5:22
remote_path: /var/www/app
builds: php, frontend
hooks: pre_deploy_local=1 pre_deploy_server=0 post_deploy=2
versa ssh-test (versa info)¶
info is an alias of ssh-test. Connects to the server, prints what it finds, and checks that SFTP works.
versa info production
🔍 Testing SSH connection to production (deploy@10.0.0.5)...
✅ SSH connection established successfully!
🔍 Probing server...
Host: web01
OS: Ubuntu 22.04.4 LTS
Kernel: 5.15.0-105-generic x86_64
Init / libc: systemd / glibc
CPU: Intel(R) Xeon(R) (4 cores)
RAM: 2.1G / 7.8G
Disk (deploy): 12G / 40G (30%)
php: 8.2.18
node: —
tools: tar gzip timeout perl ...
🔍 Testing SFTP subsystem...
✅ SFTP subsystem working.
Run this first on a new server: it surfaces SSH, host-key and permission problems before a real deploy. When the environment has services, it also checks that the SSH user can restart them with passwordless sudo. It warns if tar is missing on the server, because deploys need it. The probe is plain POSIX and works on old servers too (RHEL/CentOS 5, busybox).
versa deploy¶
Builds the committed state of your repository and deploys it to one or more environments.
versa deploy production
versa deploy production --initial-deploy # first deploy to this environment
versa deploy production --dry-run # show what would change; deploy nothing
versa deploy production --force # redeploy even with no changes
versa deploy staging,production # several environments, one after another
| Flag | Default | Description |
|---|---|---|
--initial-deploy |
false |
Allow deploying when the server has no deploy.lock yet (first deploy). Also asks for confirmation before running post_deploy hooks, so you can put .env etc. in place. |
--dry-run |
false |
Connect, detect changes and list them, then stop. Nothing is built or uploaded and pre_deploy_local hooks are not run. |
--force |
false |
Deploy even when no file changed since the last deploy (e.g. to redeploy after a rollback). |
--skip-dirty-check |
false |
Don't refuse to deploy when the working tree has uncommitted changes. Those changes are still not deployed: versa always deploys the last commit (HEAD). |
What a deploy does¶
- Local checks: build tools are in
PATH, the directory is a Git repository,pre_deploy_localhooks pass, and the working tree is clean (unless--skip-dirty-check). - Clone:
HEADis cloned to a temporary directory. Only committed files are deployed. - Connect and lock: opens SSH and creates
<remote_path>/.versa.lockso two deploys can't run at once. - Change detection: SHA256 hashes of every file are compared with the server's
deploy.lock. With no changes, versa printsNo changes detectedand stops (unless--force). - Pre-flight: probes the server (OS,
tar, and for Go builds, whether the target fits the server's kernel/arch). - Build: runs the enabled builders (PHP/Go/Frontend/Python) concurrently.
- Upload: compresses the release into chunks and uploads them over SFTP in parallel, into
releases/<version>/. Withincremental_upload: true, only changed files are sent. - Prepare: links
shared_paths, reuses dependencies from the previous release (vendor,node_modules,.venv…) via hardlinks, restorespreserved_paths, and for Python creates the virtualenv on the server when it couldn't be reused. - Activate: runs
pre_deploy_serverhooks, atomically switchescurrent → releases/<version>, runsservices_reload, runspost_deployhooks, installs and restartsservices(checking they stay up), then thehealth_check. - Finish: writes the new
deploy.lock, deletes old releases beyondreleases_to_keep, sends the webhook notification, and releases the lock.
If a post_deploy hook, a service or the health check fails, current is switched back to the previous release (and services are restarted on it). See DEPLOY.md for the hook rules.
Multiple environments¶
versa deploy staging,production deploys to each environment in order, with a separate build per environment, and stops at the first failure. To build once and ship the same artifact to several servers (one config file per server), use multi-deploy in the TUI (Switch Config view).
Local-mode environments¶
For an environment with local: true, deploy builds the project and writes a complete release to local_path (replacing what was there), then runs post_deploy hooks locally. Upload the contents of local_path/app to your hosting yourself.
versa diff¶
Lists the files a deploy would ship: the committed HEAD compared with the server's deploy.lock.
versa diff production
It is a dry-run deploy that also skips the dirty check (uncommitted changes don't matter, since only HEAD is compared). The output groups files by type (PHP, Twig, Go, Frontend, Python, Other) and says which dependency manifests changed (composer, package.json, go.mod, Python requirements, routes) and will trigger a rebuild. Only for SSH environments.
versa rollback¶
Points current back to an earlier release that is still on the server.
versa rollback production # to the newest release older than the active one
versa rollback production --to 20261001-183807 # to a specific release
| Flag | Default | Description |
|---|---|---|
--to <release> |
— | Release to activate. Release names are UTC timestamps YYYYMMDD-HHMMSS; list them with versa status. |
- Rollback only switches the symlink: nothing is rebuilt and
post_deployhooks are not run. Database migrations are not reverted. services_reloadruns andservicesare restarted after switching, so PHP-FPM and your Go/Python processes serve the restored release right away.- Only releases still on the server can be restored (see
releases_to_keep). A deploy that fails after the switch (post_deploy, services or health check) rolls back and deletes its own release, so it can't be restored by mistake. - Without
--to, a second rollback goes further back, never forward to a newer release. deploy.lockis not changed. If you then want to redeploy the same commit, useversa deploy <env> --force.
versa status¶
Shows the active release and every release on the server.
versa status production
[INFO] Status for production:
[INFO] Current release: 20261001-183807
[INFO] Available releases: 3
[INFO] 20260930-101500
[INFO] 20260930-170212
[INFO] → 20261001-183807
→ marks the release current points to.
versa history¶
Lists the deploys recorded on the server, newest first — failed ones too — or prints one deploy's full log.
versa history production # last 20 (--limit N)
versa history production 20261108-150140 # the log of that deploy
ID STATUS TIME COMMIT TAG BY
20261108-153012 success 48s a41f09c3 v1.2.0 ana@laptop
20261108-150140 FAILED 31s c93a11f0 ana@laptop
└ post-deploy hook failed (rolled back to 20261107-101203): …
The server keeps the last 100 deploys and the logs of the last 20 in <remote_path>/history/ (details). Deploys made before versa 1.15.0 aren't listed.
versa exec¶
Runs a command on the server over SSH and prints its output.
versa exec production "df -h"
versa exec production "sudo systemctl status php8.2-fpm"
versa exec production "tail -50 /var/log/nginx/error.log | grep 502"
- Everything after the environment is joined with spaces into one command. Quote it so your local shell doesn't interpret pipes, redirections or
&&. - It runs in the SSH user's login shell, starting in their home directory (not in the release). Use
cd /var/www/app/current/app && …if you need the app directory. - Limited to
hook_timeoutseconds (default 300).
versa logs¶
Follows a log file on the server (tail -f). Press Ctrl+C to stop.
versa logs production # <remote_path>/current/app/storage/logs/laravel.log
versa logs production /var/log/nginx/error.log
versa logs production /var/log/syslog --lines 200
| Argument / flag | Default | Description |
|---|---|---|
[path] |
<remote_path>/current/app/storage/logs/laravel.log |
Absolute path of the file on the server. |
--lines <n> |
50 |
Lines of history to show before following. |
The default path is Laravel's log. For other frameworks, always pass the path.
versa hooks¶
Runs the post_deploy hooks again on the active release, without deploying.
versa hooks production # all post_deploy hooks, in order
versa hooks production 0 2 # only hooks #0 and #2 (0-based, in the order they appear in the config)
Hooks run in <active release>/app, with hook_timeout. A parallel: block counts as one index. Unlike during a deploy, a failure here stops the command but does not roll back.
versa services-reload¶
Runs the environment's services_reload commands (e.g. reload PHP-FPM and the web server) without deploying.
versa services-reload production
Each command has a 30 s timeout. Failures are reported as warnings. Useful when PHP keeps serving stale code, or after changing the server's PHP/web server config.
versa service¶
Manages the processes listed under services (a Go API, a Python web server…). Deploys already install, enable and restart them; use this to check on them or act by hand.
versa service production # status of every service (default action)
versa service production restart
versa service production logs --name api # follow the log; Ctrl+C to stop
versa service production setup | ssh root@SERVER sh # once, as root: install the services + sudoers
| Action | What it does |
|---|---|
status |
Whether each service is running (systemctl status, or the init script's status). Default. |
start |
Start, wait start_wait seconds and check it's still running. |
stop |
Stop. |
restart |
Restart and check it stays up. |
reload |
Run the service's reload command if it is up (no dropped requests), else restart; then check it stays up. What deploys and rollbacks do. |
logs |
Follow the log: journalctl -u <name> on systemd, /var/log/<name>.log otherwise. |
install |
Rewrite the service files and enable them at boot, without deploying. As a non-root SSH user it only checks that root installed the current version (else: needs root setup). |
uninstall |
Stop, disable at boot and remove from the init system. |
setup |
Print the script root runs once on the server (versa service <env> setup \| ssh root@SERVER sh): installs and enables the services and writes /etc/sudoers.d/versa-<project>. Run it again after changing a service's name, user, env_file or stop_timeout. |
sudoers |
Print the sudoers lines the SSH user needs, with this server's binary paths. |
| Flag | Default | Description |
|---|---|---|
--name <n> |
all | Act on one service. Required for logs when there are several. |
--lines <n> |
50 |
logs: lines of history before following. |
Unless ssh.user is root, the commands run with sudo -n: see Permissions.
versa version¶
versa version # versaDeploy 1.7.0
versa self-update¶
Checks the latest GitHub release and, if it is newer, downloads the binary for your OS/architecture, verifies its SHA256 checksum when one is published, and replaces the running versa.
versa self-update
You need write permission on the folder where versa is installed (on Linux, sudo if it's in /usr/local/bin).
Interactive TUI¶
Running versa with no command opens a full-screen interface (versa --no-gui prints help instead). It loads the config file from the current directory if there is one; otherwise use the Switch Config view to choose one. The SSH connection to an environment opens the first time you need it.
Everywhere
| Key | Action |
|---|---|
← / → |
Previous / next view |
Tab |
Focus the sidebar (pick a view or environment) |
↑ / ↓, Enter |
Move, select |
F5 |
Refresh the current view |
c |
Connect / reconnect to the active environment |
D |
Go to Operations to deploy |
q, Ctrl+C |
Quit |
Mouse: click a tab to open it, click an environment in the sidebar to switch to it, and use the wheel to scroll (lists move their selection). While the TUI uses the mouse, most terminals select text with Shift + drag.
Views
| View | What it shows | Keys |
|---|---|---|
| Dashboard | Server info (same as versa info), active release, runtimes and tools, security alerts |
F5 refresh |
| Releases | Releases on the server, active one marked | Enter browse its files · R roll back to it (asks y/n; runs services_reload and restarts services) |
| Files | Remote file browser (follows symlinks) | Enter open dir / view file · e edit the viewed text file (Ctrl+S save, keeps its mode; Esc cancel) · Backspace up · d download · u upload (Space select files, Enter open dir) · Delete delete · Esc close |
| Shared | Contents of <remote_path>/shared, the preserved_paths (e.g. config.json) and shared_paths not created yet |
Enter open dir / file (then e edits .env, config.json…; applying it) |
| Operations | Deploy options and live log | ↑/↓ + Enter toggle Dry run, Force, Initial deploy, Skip dirty check, Debug, log file · D deploy · R rollback · s SSH test · t status and the last 10 deploys · h re-run hooks · l services reload · u self-update · Esc close log |
| Terminal | Remote shell on the server | Enter start typing (until then ←/→ pass through) · Tab completion · Esc stop typing, again to leave |
| Services | Server stack: installed services, versions, updates, security, sites, SSL (SERVICES.md) | Space select · Enter edit / next version · I install · P prepare for deploy · U upgrade · S security updates · Ctrl+R apt update · L logs · B backup now · X reset DB password · w save provision · a add services_reload |
| Config | The loaded config file | e edit · Ctrl+S save · Esc cancel |
| Switch Config | Config files found in the directory | Enter load · Space select several · m multi-deploy the selected configs with a single build · Esc back |
Which commands work in local mode¶
Environments with local: true have no server, so only these commands apply to them:
| Command | Local mode |
|---|---|
deploy |
✅ Builds and writes the release to local_path |
config validate |
✅ |
diff, rollback, status, history, exec, hooks, services-reload, service, logs, ssh-test/info |
❌ SSH environments only |
Exit codes and error output¶
versa exits with 0 on success and 1 on any error, so it can be used in CI and scripts. Known errors are printed with a code, the underlying details and, when possible, a suggested fix:
[ERROR] Deployment lock already held
Code: CONFIG_INVALID
Details: sftp: "Failure" (SSH_FX_FAILURE)
Suggestion: Another deployment is currently in progress. If you are sure no one else
is deploying, manually remove the directory: /var/www/app/.versa.lock
See TROUBLESHOOTING.md for common errors.