Recommended path: Bootstrap a VPS → provision a Bedrock site with site-bedrock.yml → wire reusable-deploy-bedrock.yml (full path below). Laravel apps use the reusable deploy workflow; nginx vhost is manual until site-nginx.yml is implemented.
- Ansible 2.14+ on your laptop
- SSH access to the target server (root on a fresh VPS, or sudo user)
- Python 3 on the target (Ubuntu images include it)
# Ubuntu/Debian
sudo apt install ansible
# Or pip
pip install ansible
# Ansible collection for UFW module
cd ansible
ansible-galaxy collection install -r requirements.yml-
Copy example config files:
cp ansible/inventory/hosts.example.yml ansible/inventory/hosts.yml cp ansible/inventory/group_vars/all.example.yml ansible/inventory/group_vars/all.yml
-
Set variables in
inventory/group_vars/all.yml:platform_admin_user— sudo user that will SSH in (must already exist on first run if not using root-only bootstrap)platform_ssh_allowed_users— usernames allowed insshd_configplatform_ufw_allow_web— open 80/443 if this server serves HTTP(S)
-
Run the playbook:
cd ansible ansible-playbook -i inventory/hosts.yml playbooks/bootstrap-server.yml -
Test SSH in a new terminal before closing your current session.
On a brand-new VPS, create your admin user first (from linux-server-utils or manually), copy your SSH key to your laptop, then run bootstrap with that user in platform_ssh_allowed_users.
Order matters:
- Create sudo user + SSH keys
- Verify login works
- Run
bootstrap-server.yml(disables root SSH, enables firewall, etc.)
-
Prepare the app directory (see setup-app-directory.sh):
sudo /usr/local/src/linux-server-utils/web/setup-app-directory.sh /var/www/myapp william
-
Copy
templates/nginx-site.conf.j2to/etc/nginx/sites-available/myapp.conf -
sudo ln -s ... sites-enabled/andsudo certbot --nginx -d myapp.example.com -
Wire app repo to
reusable-deploy-laravel.ymlor add a custom workflow -
Add GitHub Actions deploy key secrets to the app repo
An Ansible site-nginx playbook is on the roadmap.
Production example: wiltsu.dev (mydevsite).
-
Copy and edit Bedrock vars:
cp ansible/inventory/group_vars/site_bedrock.example.yml ansible/inventory/group_vars/site_bedrock.yml # bedrock_domain: wiltsu.dev # bedrock_deploy_path: /var/www/wiltzsu (must match deploy.yml deploy_path)
-
Provision the shell:
cd ansible ansible-playbook -i inventory/hosts.yml playbooks/site-bedrock.yml -K -
Add
deploy.ymlin the Bedrock repo:jobs: deploy: uses: Wiltzsu/platform/.github/workflows/reusable-deploy-bedrock.yml@master with: deploy_path: /var/www/wiltzsu # must match bedrock_deploy_path secrets: SSH_KEY: ${{ secrets.SSH_KEY }} HOST: ${{ secrets.HOST }} USER: ${{ secrets.USER }}
-
After first deploy + DB import:
wp search-replacewith--path=web/wp, thensudo certbot --nginx -d wiltsu.dev -d www.wiltsu.dev.
bedrock_domain must match the domain you registered. The folder name on disk (e.g. /var/www/wiltzsu) can differ — optional symlink for nginx: ln -s /var/www/wiltzsu /var/www/wiltsu.
| Secret | Description |
|---|---|
SSH_KEY |
Private deploy key (no passphrase) — see below |
HOST |
Server IP or hostname (origin server, not CDN) |
USER |
SSH username (same user for every app on that server) |
Use the same HOST, USER, and SSH_KEY in every app repo that deploys to the same VPS. Each app workflow only differs by deploy_path.
This is separate from the passphrase-protected key created by create-user.sh for laptop login. GitHub Actions cannot enter a key passphrase, so CI needs its own key.
SSH in as your deploy user (or root) and run:
sudo /usr/local/src/linux-server-utils/user/setup-github-deploy-key.sh williamOr, if you are already logged in as william:
~/path/to/linux-server-utils/user/setup-github-deploy-key.shThe script creates ~/.ssh/github_actions_deploy, appends the public key to authorized_keys, and prints the private key path.
Open Settings → Secrets and variables → Actions and add:
| Secret | Value |
|---|---|
USER |
SSH username (e.g. william) |
HOST |
Server IP |
SSH_KEY |
Full private key from cat ~/.ssh/github_actions_deploy |
Include the -----BEGIN OPENSSH PRIVATE KEY----- / -----END ...----- lines. Do not commit this key to git.
From your laptop (after saving the private key locally):
chmod 600 ~/.ssh/github_actions_deploy
ssh -i ~/.ssh/github_actions_deploy -o IdentitiesOnly=yes william@YOUR_SERVER_IP "echo SSH OK"You should see SSH OK. Then push to master (or re-run the deploy workflow).
If you disable root login or rename the deploy user, update all of the following:
AllowUsersin/etc/ssh/sshd_configincludes the deploy user- GitHub secret
USERmatches that username - The deploy public key is still in that user's
authorized_keys - App directories are owned by
user:www-data(seesetup-app-directory.sh)
SSH authenticates the user, not the site. One deploy key on the server can deploy to /var/www/grapplingtracker, /var/www/mydevsite, and so on — each app workflow sets its own deploy_path. Use separate keys per app only if you want tighter isolation when a repo secret leaks.