Deploy code via FTP/FTPS/SFTP (lftp), or SSH (rsync) and run pre/post commands on remote servers.
365
Deployer 9000 is a small Alpine-based image that syncs a directory to a remote server over FTP / FTPS, SFTP or rsync over SSH, with optional commands before and after the transfer. It was built for GitHub Actions and runs anywhere where a container can reach your server: GitLab CI, a cron job, your laptop.
Unlike its infamous cousin HAL, this unit has one mission: get your code deployed, no backtalk.
PRESERVE_TIMES only the files that changed are uploaded, nothing is stored on the serverdeploy:
image: blackhost/deployer:1
stage: deploy
script: [deployer]
variables:
PROTOCOL: sftp
SERVER: example.com
REMOTE_DIR: public_html
rules:
- if: $CI_COMMIT_BRANCH == "main"
Add USERNAME and PASSWORD (or SSH_KEY) as masked CI/CD variables in Settings → CI/CD → Variables. The job runs inside your checked-out repository, so LOCAL_DIR defaults to the project root.
Two jobs for two targets is just two variables: blocks:
deploy-api:
extends: deploy
variables: { SERVER: api.example.com, PASSWORD: *** }
rules: [{ if: $CI_COMMIT_BRANCH == "api" }]
Keep deploy settings inside the job. Project-wide variables with the same names (PORT, DRY_RUN, DELETE, PARALLEL) are picked up too.
On GitHub? Deployer 9000 is also a GitHub Action, same options written as
with:inputs. Setup guide: GitHub Actions: Setup & Usage.
docker run --rm -v "$PWD:/deploy" \
-e PROTOCOL=sftp -e SERVER=example.com -e REMOTE_DIR=public_html \
-e USERNAME=deploy -e PASSWORD="***" \
blackhost/deployer:1
The image's working directory is /deploy. Mount the folder you want to ship there, or set LOCAL_DIR. Add -e DRY_RUN=true to see the plan first.
Use the action instead of the image directly, inputs map one to one to the variables below:
- uses: Black-HOST/deployer@v1
with:
server: ${{ secrets.FTP_HOST }}
username: ${{ secrets.FTP_USER }}
password: *** secrets.FTP_PASS }}
remote_dir: public_html
Full documentation at https://github.com/Black-HOST/deployer.
Every option is an environment variable. GitHub Actions users write the same names in lowercase under with:.
| Variable | Default | Description |
|---|---|---|
PROTOCOL | ftp | ftp, sftp or rsync |
SERVER | required | Hostname or IP of the target server |
PORT | 21 for ftp, 22 for sftp and rsync | Remote port |
USERNAME | required | Login user |
PASSWORD | Password for FTP, SFTP, rsync, or the passphrase of SSH_KEY | |
SSH_KEY | Private key for SFTP and rsync, the key contents in PEM format | |
HOST_KEY | Public SSH host key of the server, for example ssh-ed25519 AAAA..., one per line. When set, any other host key is refused. SFTP and rsync only | |
LOCAL_DIR | . | Directory to upload, relative to the working directory |
REMOTE_DIR | / | Target directory on the server, relative paths resolve from the login directory |
DELETE | false | Remove remote files that no longer exist locally. Read the warning below |
ONLY_NEWER | false | Skip files whose remote copy has a newer timestamp |
DRY_RUN | false | Log in and print what would be transferred, change nothing |
PRESERVE_TIMES | false | Give every file tracked by git the time of its last commit before the transfer. FTP and SFTP then upload only the files that changed |
SAFEGUARDS | true | Refuse to deploy when DELETE is enabled and there is nothing to deploy, which would wipe REMOTE_DIR |
EXCLUDE | .*,.*/,node_modules/,*.log | Comma or newline separated glob patterns. The default skips dotfiles and dot-directories, so .git and .env never leave the runner. A directory needs a trailing slash |
INCLUDE | Comma or newline separated glob patterns that are deployed even when excluded, for example .htaccess,.well-known/ | |
PRE_SCRIPT | Command(s) run on the server over SSH before the transfer. SFTP and rsync only | |
POST_SCRIPT | Command(s) run on the server over SSH after the transfer. SFTP and rsync only | |
REMOTE_SHELL | /bin/bash -lc | Shell used to run PRE_SCRIPT and POST_SCRIPT |
SECURE | true | FTP only: use FTPS (TLS) |
VERIFY_TLS | true | FTP only: verify the server certificate |
PASSIVE | true | FTP only: passive mode |
PARALLEL | 2 | FTP and SFTP only: parallel transfers, 1 to 5 is safe |
EXTRA_LFTP | FTP and SFTP only: raw lftp commands injected before the transfer. Advanced, and a failing command fails the job |
Boolean values accept true, false, yes, no, 1, 0, on, off.
PRESERVE_TIMES every file looks new and FTP and SFTP upload all of them. Set PRESERVE_TIMES=true in a git checkout to upload only what changed; shallow checkouts are completed automatically.DELETE=true removes files. Anything under REMOTE_DIR that is not in LOCAL_DIR and not excluded is deleted, and that covers dotfiles you list in INCLUDE. Run with DRY_RUN=true first, every time you change the exclude list. With nothing to deploy the job is refused, unless SAFEGUARDS=false.HOST_KEY to trust one key only and refuse everything else.| Tag | Meaning |
|---|---|
1.3.0 | exact release |
1.3 | latest 1.3.x |
1 | latest 1.x, recommended for pipelines |
latest | newest release |
Images are built from tagged releases of the GitHub repository and are also published on ghcr.io/black-host/deployer.
Content type
Image
Digest
sha256:c96c9f942…
Size
14.4 MB
Last updated
about 20 hours ago
docker pull blackhost/deployer