Table of Contents
- Development Server Deployment
- Overview
- Configuration
- Organization Variables (required)
- Organization Variable (optional)
- Repository Variable (optional)
- Organization Secrets (credentials)
- Authentication logic
- Port resolution
- Remote path
- Manual dispatch
- Repository health checks
- Examples
- Example 1 — SSH key with passphrase, custom port
- Example 2 — SSH key, port embedded in host
- Example 3 — Password only, default port
- Example 4 — Multiple repos, same server
- Troubleshooting
- Permission denied
- No credentials configured
- Key authentication failed, no fallback
- Missing source directory
- Connection refused
- Related documentation
- Metadata
- Revision History
← Home
Development Server Deployment
Automated SFTP deployment of the src/ directory to the development server.
Overview
The deploy-dev.yml workflow pushes the contents of src/ to a development server over SFTP only when:
- A commit is pushed to
dev/**,alpha/**,beta/**,rc/**,develop, ordevelopmentbranches (andsrc/**changed) - A pull request targeting those branches is merged (skips
chore/branches) - Triggered manually via workflow dispatch
Access control: jmiller and gitea-actions[bot] are always authorized. Other actors need admin or maintain role.
Skips when: DEV_FTP_SUFFIX variable is not set, or the branch starts with chore/.
Configuration
Organization Variables (required)
Configure at the organization level in Settings → Secrets and variables → Actions → Variables:
| Variable | Example | Description |
|---|---|---|
DEV_FTP_HOST |
dev.example.com |
Dev server hostname. May include an explicit port suffix — dev.example.com:2222. |
DEV_FTP_PATH |
/var/www/html |
Base remote path where files are deployed. |
DEV_FTP_USERNAME |
deployuser |
SFTP username for authentication. |
Organization Variable (optional)
| Variable | Example | Description |
|---|---|---|
DEV_FTP_PORT |
2222 |
Explicit port override. See Port resolution below. |
Repository Variable (optional)
| Variable | Example | Description |
|---|---|---|
DEV_FTP_SUFFIX |
my-module |
Appended to DEV_FTP_PATH to form the final deploy path: DEV_FTP_PATH/DEV_FTP_SUFFIX. Useful for deploying multiple repos to the same server. |
Organization Secrets (credentials)
At least one of the following must be set:
| Secret | Description |
|---|---|
DEV_FTP_KEY |
Preferred. SSH private key (any format supported by OpenSSH). |
DEV_FTP_PASSWORD |
SFTP password. Also used as the key passphrase when set alongside DEV_FTP_KEY. |
Authentication logic
The workflow determines the connection method at runtime:
| Secrets present | Behaviour |
|---|---|
DEV_FTP_KEY + DEV_FTP_PASSWORD |
Key auth with DEV_FTP_PASSWORD as the key passphrase. If key auth fails, retries with DEV_FTP_PASSWORD alone as an SFTP password. |
DEV_FTP_KEY only |
Key auth (no passphrase). Fails hard on auth error — no password fallback. |
DEV_FTP_PASSWORD only |
Password auth directly. |
| Neither | Workflow fails with an error message. |
Port resolution
The SFTP port is determined in the following order — the first match wins:
DEV_FTP_PORTvariable — explicit override, highest priority.- Port suffix in
DEV_FTP_HOST— if the host value contains:, the suffix is extracted and the bare hostname is used (e.g.dev.example.com:2222→ hostdev.example.com, port2222). - Default — port 22 is assumed when neither of the above is present.
Remote path
The final remote path is constructed as:
DEV_FTP_PATH/DEV_FTP_SUFFIX
DEV_FTP_SUFFIX is optional. When set, exactly one / is inserted between the base path and the value regardless of trailing/leading slashes in the values.
Manual dispatch
- Go to Actions → Deploy to Dev Server (SFTP).
- Click Run workflow.
- Optionally override the source directory (default:
src) or enable Dry run to list files without uploading.
Repository health checks
The check_repo_health.php script scores deployment readiness as part of the overall health report. When --repo owner/repo is supplied, it also calls the GitHub API to verify secrets and variables are configured.
Deployment category checks
| Check | Points | Requires --repo |
|---|---|---|
deploy-dev.yml workflow exists |
5 | No |
DEV_FTP_HOST variable configured |
3 | Yes |
DEV_FTP_PATH variable configured |
3 | Yes |
DEV_FTP_USERNAME variable configured |
2 | Yes |
SFTP credentials configured (DEV_FTP_KEY or DEV_FTP_PASSWORD) |
2 | Yes |
Variables and secrets are checked at both the org level and repo level — a check passes if the item exists at either scope.
Examples
Example 1 — SSH key with passphrase, custom port
Org variables:
DEV_FTP_HOST = dev.example.com
DEV_FTP_PORT = 2222
DEV_FTP_PATH = /var/www/html
DEV_FTP_USERNAME = deployuser
Org secrets:
DEV_FTP_KEY = <passphrase-protected SSH private key>
DEV_FTP_PASSWORD = mysecretphrase
Behaviour: Key loaded with mysecretphrase as passphrase. If key auth fails, retries with mysecretphrase as the SFTP password.
Example 2 — SSH key, port embedded in host
Org variables:
DEV_FTP_HOST = dev.example.com:2222
DEV_FTP_PATH = /var/www/html
DEV_FTP_USERNAME = deployuser
Org secret:
DEV_FTP_KEY = <unprotected SSH private key>
Behaviour: Port 2222 extracted from host. Key used without passphrase; no password fallback.
Example 3 — Password only, default port
Org variables:
DEV_FTP_HOST = dev.example.com
DEV_FTP_PATH = /var/www/html
DEV_FTP_USERNAME = deployuser
Org secret:
DEV_FTP_PASSWORD = secretpass
Behaviour: Port defaults to 22. Connects with password directly.
Example 4 — Multiple repos, same server
Each repo sets its own DEV_FTP_SUFFIX:
| Repo | Suffix | Deploys to |
|---|---|---|
project-a |
/project-a |
/var/www/html/project-a |
project-b |
/project-b |
/var/www/html/project-b |
Troubleshooting
Permission denied
❌ Deployment requires admin or maintain role.
Only org/repo administrators and maintainers may deploy. Contact your org administrator.
No credentials configured
❌ No SFTP credentials configured.
Set DEV_FTP_KEY (preferred) or DEV_FTP_PASSWORD as an org-level secret.
Set at least one of DEV_FTP_KEY or DEV_FTP_PASSWORD in Org Settings → Secrets.
Key authentication failed, no fallback
RuntimeError: Key authentication failed and no password fallback is available: ...
The SSH private key was rejected and DEV_FTP_PASSWORD is not set. Check the key is correct and authorized on the server, or add DEV_FTP_PASSWORD as a fallback.
Missing source directory
⚠️ Source directory 'src' not found — skipping deployment
Expected behaviour for repos without a src/ directory. No files are uploaded; the workflow exits successfully.
Connection refused
[Errno 111] Connection refused
- Verify
DEV_FTP_HOSTis correct. - Check the resolved port (shown in the Resolve SFTP host and port step log).
- Confirm the server firewall allows inbound SFTP on that port.
Related documentation
Metadata
| Field | Value |
|---|---|
| Document Type | Guide |
| Domain | Operations |
| Applies To | All Repositories |
| Jurisdiction | Tennessee, USA |
| Owner | Moko Consulting |
| Repo | https://git.mokoconsulting.tech/MokoConsulting/moko-platform |
| Path | /docs/workflows/dev-deployment.md |
| Version | 04.06.00 |
| Status | Active |
| Last Reviewed | 2026-04-07 |
| Reviewed By | Documentation Team |
Revision History
| Date | Author | Change |
|---|---|---|
| 2026-03-12 | Moko Consulting | Rewrote for SFTP-only workflow; added auth fallback, port resolution, health check docs |
| 2026-01-28 | Moko Consulting | Standardized metadata and revision history |
| 2026-01-17 | Moko Consulting | Initial dev deployment workflow documentation |
Repo: moko-platform · moko-platform wiki
| Field | Value |
|---|---|
| Minimum Version | 04.07.00 |
| Platform | all |
| Applies To | All repositories |
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-08 | Moko Consulting | Initial version |