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.
🚀 Getting Started¶
From zero to your first deploy, step by step. The example deploys a PHP (Laravel) app to an Ubuntu server with Nginx/Apache + PHP-FPM; other stacks follow the same steps with a different builds section (see the Configuration Reference).
- Prerequisites
- Prepare the server
- Create the configuration
- Check everything before deploying
- First deploy
- Everyday use
- Go or Python apps: run them as a service
1. Prerequisites¶
On your machine (where you run versa)¶
- versa installed: see INSTALL.md.
- Git: versa deploys the last commit of the repository you run it from.
- The build tools your project uses, in
PATH:composerfor PHP,npm/pnpm/yarnfor frontend,gofor Go. Builds run locally, not on the server. (Python dependencies are the exception: they're installed on the server.) - Windows: hooks that run locally (
pre_deploy_local) usesh. Install Git for Windows and addC:\Program Files\Git\bintoPATH. - An SSH key that can log in to the server.
On the server¶
- Linux with SSH and SFTP enabled. Old distributions (e.g. CentOS 5) work too, see
legacy_algorithms. tarandgzip(present on virtually every distribution).- A user that can write to the deploy directory.
2. Prepare the server¶
[!TIP] Let versa do it. With root SSH access, the TUI Services view does this whole section for you: deploy user with your key, directory, sudoers, web server vhost, PHP, database, SSL and firewall.
Palone prepares a fresh server for deploy. See SERVICES.md. The steps below are for preparing it by hand.
2.1 Deploy user and SSH key¶
From your machine, copy your public key to the server and accept its host key once:
ssh-copy-id deploy@your-server.com # or append the .pub file to ~/.ssh/authorized_keys on the server
ssh deploy@your-server.com # answer "yes" so the server is saved in ~/.ssh/known_hosts
[!TIP] Connecting once with
sshsaves the server in~/.ssh/known_hosts, which versa uses to verify the server. Without it versa still connects but warnsHost key NOT verified.
2.2 Deploy directory¶
sudo mkdir -p /var/www/my-app
sudo chown -R deploy:www-data /var/www/my-app
versa creates releases/, shared/ and the current symlink inside it.
2.3 Shared files¶
Files that must survive between releases (like .env) live in shared/. Create them before the first deploy; versa would otherwise create them as empty directories:
mkdir -p /var/www/my-app/shared
nano /var/www/my-app/shared/.env
2.4 Web server¶
Each release is stored as releases/<version>/app/, and current points to the active release. Your web root is therefore /var/www/my-app/current/app/<public dir>.
Nginx: use $realpath_root so PHP resolves the real release path, not the symlink:
server {
root /var/www/my-app/current/app/public;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
}
}
Apache:
<VirtualHost *:80>
DocumentRoot /var/www/my-app/current/app/public
<Directory /var/www/my-app/current/app/public>
Options +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Don't serve stale static files from the kernel cache after a switch
EnableSendfile Off
EnableMMAP Off
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
2.5 Allow reloading services without a password¶
PHP-FPM caches where current points, so it must be reloaded after each deploy (versa does it through services_reload). Allow the deploy user to do that without a password, with sudo visudo -f /etc/sudoers.d/deploy:
deploy ALL=(ALL) NOPASSWD: /bin/systemctl reload php8.2-fpm
deploy ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx
3. Create the configuration¶
In the root of your repository:
versa init
Choose 1 (server with SSH). This creates a commented deploy.yml. Edit it; a minimal Laravel setup looks like:
project: "my-app"
environments:
production:
ssh:
host: "your-server.com"
user: "deploy"
key_path: "~/.ssh/id_rsa"
remote_path: "/var/www/my-app"
builds:
php:
enabled: true
frontend:
enabled: true
npm_command: "npm ci"
compile_command: "npm run build"
shared_paths:
- ".env"
- "storage"
services_reload:
- "sudo systemctl reload php8.2-fpm"
post_deploy:
- "php artisan migrate --force"
- "php artisan config:cache"
Commit deploy.yml (and everything you want deployed): versa only deploys committed files.
4. Check everything before deploying¶
versa config validate production # the file is valid (no connection)
versa info production # SSH, host key, SFTP and server details
Fix whatever these report before going on; TROUBLESHOOTING.md covers the usual errors.
5. First deploy¶
The server has no deploy.lock yet, so tell versa this is the first deploy:
versa deploy production --initial-deploy
versa builds the project, uploads it, links shared_paths, switches current, and reloads PHP-FPM. Before running the post_deploy hooks it asks for confirmation: check that shared/.env is right, then answer y.
6. Everyday use¶
git commit -am "New feature"
versa deploy production # builds and ships only if something changed
| I want to… | Command |
|---|---|
| See what would be deployed | versa diff production |
| See releases on the server | versa status production |
| Go back to the previous release | versa rollback production |
| Go back to a specific release | versa rollback production --to 20261001-183807 |
| Redeploy even though nothing changed | versa deploy production --force |
| Follow the app log | versa logs production |
| Run a command on the server | versa exec production "php artisan queue:restart" |
| Check / restart a Go or Python service | versa service production [restart] |
| Do all of this from a full-screen interface | versa |
7. Go or Python apps: run them as a service¶
A PHP app is served by PHP-FPM, but a Go binary or a Python server is a process that has to be running. Declare it under services and versa takes care of the rest: it installs it in the server's init system (systemd, or /etc/init.d on old servers), starts it at boot, restarts it on every deploy and rollback, and rolls the deploy back if it doesn't stay up.
Go API:
environments:
production:
# ssh, remote_path …
builds:
go:
enabled: true
target_os: "linux"
target_arch: "amd64"
binary_name: "api"
deploy_path: "bin"
shared_paths:
- ".env"
services:
- name: "myapi"
env_file: ".env" # /var/www/my-app/shared/.env
environment:
PORT: "8080"
Python (FastAPI) API: dependencies are installed on the server, in a virtualenv per release. The server needs python3 and python3-venv.
builds:
python:
enabled: true
web_server: true
web_framework: "fastapi"
entry_point: "main.py" # main.py defines `app`
web_port: 8000
services:
- name: "myapi"
env_file: ".env"
Then:
versa service production setup | ssh root@203.0.113.10 sh # once, as root: installs the services + sudoers
versa info production # confirms sudo is OK
versa deploy production
versa service production # is it running?
versa service production logs # follow its output
Put a reverse proxy (Nginx) in front of the port if the service must be reachable from outside. All options: Services.
Next steps¶
- CLI Reference: every command and flag.
- Configuration Reference: hooks, health checks, notifications, incremental uploads, local mode.