Provisioning a New VPS
Step-by-step guide for bootstrapping a fresh EC2 instance using the Provision VPS GitHub Actions workflow.
Prerequisites
- EC2 instance running Ubuntu 24.04 with a public IP
- SSH access as your configured
ssh_user(ubuntufor EC2 Ubuntu 24.04,rootfor most other providers) - All required GitHub Secrets set (see tables below)
Step 1 — Update VPS_IP
Go to Settings → Secrets and variables → Actions in GitHub and set:
VPS_IP = <new EC2 public IP>
Step 2 — Set up SSH access for GitHub Actions
The workflow needs to SSH into the new instance. Choose one option:
- Option A — AWS key pair (.pem)
- Option B — New deploy key
Paste the .pem file contents as the VPS_SSH_PRIVATE_KEY GitHub Secret:
cat ~/your-key.pem # paste the output into the secret
AWS automatically places the corresponding public key in ~ubuntu/.ssh/authorized_keys at launch — no manual step needed.
SSH into the instance first using your .pem key, then generate a dedicated deploy key:
ssh -i ~/your-key.pem ubuntu@<EC2_PUBLIC_IP>
On the instance, generate a key pair and authorise it:
ssh-keygen -t ed25519 -f ~/.ssh/deploy -N ""
cat ~/.ssh/deploy.pub >> ~/.ssh/authorized_keys
Copy the private key and set it as the VPS_SSH_PRIVATE_KEY GitHub Secret:
cat ~/.ssh/deploy # paste the output into the secret
Lightsail instances use a custom key pair set at creation time (LIGHTSAIL_KEY_PAIR_NAME). The private key can only be downloaded once — if it's lost, recover access via the Lightsail browser SSH console and add a new key manually.
1. Generate a new key pair locally:
ssh-keygen -t ed25519 -f ~/.ssh/ops4life -N ""
2. Open browser SSH — Lightsail console → instance → Connect using SSH
3. Authorise the new public key on the instance:
echo "$(cat ~/.ssh/ops4life.pub)" >> ~/.ssh/authorized_keys
4. Update ~/.ssh/config to use the new key:
Host <INSTANCE_IP>
HostName <INSTANCE_IP>
User ubuntu
IdentityFile ~/.ssh/ops4life
IdentitiesOnly yes
5. Test local access:
ssh ubuntu@<INSTANCE_IP>
6. Update VPS_SSH_PRIVATE_KEY GitHub Secret with the new private key:
cat ~/.ssh/ops4life # paste into the secret
Step 3 — Set all provision-time secrets
The following secrets are passed as Ansible extra vars. Set them all in Settings → Secrets and variables → Actions before running the workflow.
Always required
| Secret | Description |
|---|---|
VPS_SSH_PRIVATE_KEY | Private SSH key for the runner to reach the VPS |
VPS_IP | Public IP of the target EC2 instance |
TRAEFIK_HOST | Base domain (e.g. ops4life.com) |
ACME_EMAIL | Email for Let's Encrypt certificate registration |
GH_PAT | GitHub Personal Access Token — used for repo access and API calls |
ANSIBLE_VAULT_PASSWORD | Password for ansible/secrets.yml |
Core App Secrets
| Secret | Used by |
|---|---|
AUTHENTIK_SECRET_KEY | authentik |
AUTHENTIK_PG_PASS | authentik (PostgreSQL password) |
AUTHENTIK_BOOTSTRAP_PASSWORD | authentik |
AUTHENTIK_BOOTSTRAP_EMAIL | authentik |
GH_OAUTH_CLIENT_ID | authentik |
GH_OAUTH_CLIENT_SECRET | authentik |
PG_N8N_PASS | n8n |
PG_PASS | postgres (global admin) |
PGADMIN_PASSWORD | pgadmin |
GF_ADMIN_PASSWORD | monitoring (Grafana) |
SMTP_PASS | listmonk (Resend/SMTP) |
Step 4 — Run the Provision VPS workflow
Go to Actions → Provision VPS → Run workflow and accept the defaults:
| Input | Default | Notes |
|---|---|---|
ssh_user | root | EC2 Ubuntu 24.04 AMIs default to ubuntu — change this input to ubuntu for EC2 |
verbosity | -v | Increase to -vv or -vvv for more detail |
tags | all | Specific tags to run (e.g. system,docker) |
What the playbook does
- System: Installs packages (Node.js, Docker, Python, etc.) and configures swap.
- RDP: Sets up remote desktop with XFCE4 and Chrome.
- Repo: Clones
vps-appsto/opt/vps-apps. - Networks: Creates external Docker networks (
traefik-net,postgres-net). - Environment: Decrypts
ansible/secrets.ymland writes.envfiles for all apps. - Deploy: Orchestrates
docker compose up -dfor all services in dependency order. - Configuration: Runs post-deploy scripts for Authentik, Listmonk, Kuma, etc.
- Sync: Syncs any dynamically generated secrets on the VPS back to
ansible/secrets.yml.
Step 5 — Verify Deployment
Once the workflow finishes:
- Check the Uptime Kuma dashboard at
https://kuma.<your-domain>. - Verify Authentik is accessible at
https://authentik.<your-domain>. - Test SSO by logging into Guacamole or Grafana.