Skip to content

Portable VPS Deployment with Ansible⚓︎

🚀 Cloud VPS Deployment Guide⚓︎

This guide deploys a standardized VPS configuration to any cloud provider (Hetzner, DigitalOcean, Linode, etc.) with monitoring, backups, and automation.

Prerequisites Checklist⚓︎

Before starting, ensure you have:

  • Ubuntu 24.04 VPS deployed on any cloud provider
  • Root or sudo access to VPS
  • Synology NAS accessible via Tailscale
  • VPS connected to Tailscale network
  • Ntfy.sh server configured with authentication tokens

Phase 1: VPS Initial Setup⚓︎

Get VPS IP Address⚓︎

# On the VPS, get public IP address
curl -4 ifconfig.me

Write down the IP: _________________

Create User Account⚓︎

# On VPS as root
adduser unifiadmin
usermod -aG sudo,docker unifiadmin

Deploy SSH Key⚓︎

# From your NAS, deploy the SSH key
cat /volume2/ansible-infrastructure/ssh-keys/ansible_key.pub | ssh unifiadmin@VPS_IP "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

Test SSH access:

ssh -i /volume2/ansible-infrastructure/ssh-keys/ansible_key unifiadmin@VPS_IP

Phase 2: Update Ansible Configuration⚓︎

Update VPS IP in Inventory⚓︎

# Edit this file on your NAS
nano /volume2/ansible-infrastructure/inventory/portable-vps.yml

Change the IP address:

all:
  children:
    vps_servers:
      hosts:
        portable-vps:
          ansible_host: VPS_IP_HERE  # ← Update this line
          ansible_user: unifiadmin
          ansible_ssh_private_key_file: ssh-keys/ansible_key

Phase 3: Deploy VPS Configuration with Ansible⚓︎

Test Connectivity⚓︎

docker run --rm -it \
  -v /volume2/ansible-infrastructure:/ansible \
  -w /ansible \
  cytopia/ansible:latest \
  sh -c "apk add --no-cache openssh-client && ansible -i inventory/portable-vps.yml all -m ping"

Expected output: portable-vps | SUCCESS => {"ping": "pong"}

Optional: Run Discovery⚓︎

docker run --rm -it \
  -v /volume2/ansible-infrastructure:/ansible \
  -w /ansible \
  cytopia/ansible:latest \
  sh -c "apk add --no-cache openssh-client && ansible-playbook -i inventory/portable-vps.yml playbooks/discover-server.yml --ask-become-pass -v"

Test Deployment First⚓︎

# Test deployment in check mode first
docker run --rm -it \
  -v /volume2/ansible-infrastructure:/ansible \
  -w /ansible \
  cytopia/ansible:latest \
  sh -c "apk add --no-cache openssh-client && ansible-playbook -i inventory/portable-vps.yml playbooks/vps-infrastructure.yml --check --diff --ask-become-pass -v"

Deploy Complete VPS Configuration⚓︎

# Deploy complete VPS configuration
docker run --rm -it \
  -v /volume2/ansible-infrastructure:/ansible \
  -w /ansible \
  cytopia/ansible:latest \
  sh -c "apk add --no-cache openssh-client && ansible-playbook -i inventory/portable-vps.yml playbooks/vps-infrastructure.yml --ask-become-pass -v"

When prompted for BECOME password: Enter the unifiadmin sudo password

Note: The deployment uses the vps-applications role with comprehensive defaults and bulletproof variable handling. Both local and VPS deployments are tested and working.

What Ansible Builds Automatically⚓︎

✅ Base System Configuration⚓︎

  • SSH hardening (UFW firewall, Fail2Ban intrusion prevention)
  • Essential packages (curl, wget, git, htop, vim, tree, cifs-utils, etc.)
  • System package updates and security hardening
  • User shell configuration with sudo and docker group access
  • Service management and security policies

✅ Docker Environment⚓︎

  • Docker v27.2.0+ installation with Compose
  • Docker daemon configuration optimized for VPS
  • Docker networks and volumes
  • Docker Compose directory: /home/unifiadmin/docker/compose
  • Container management and monitoring

VPS-Specific Scripts (7 total)⚓︎

  • /usr/local/bin/unifi-backup.sh - Weekly Unifi controller backup
  • /usr/local/bin/backup-golinks.sh - Daily Tailscale Golinks backup
  • /usr/local/bin/internet-connectivity-check.sh - 5-minute connectivity monitoring
  • /usr/local/bin/monitor-exit-node.sh - 5-minute Tailscale exit node monitoring
  • /usr/local/bin/docker-maintenance.sh - Daily Docker updates and cleanup
  • /usr/local/bin/backup-dotfiles.sh - Weekly dotfiles backup to GitHub
  • /usr/local/bin/rclone-nas - NAS backup wrapper script

NAS Integration⚓︎

  • CIFS mount to /mnt/Backup with secure credentials
  • Automated backup destination configuration
  • NAS connectivity verification and mounting

✅ Monitoring & Notifications⚓︎

  • Ntfy.sh integration with separate authentication tokens:
    • Server monitoring notifications
    • Container update notifications
    • Healthcheck notifications
  • Healthcheck.io integration for critical services:
    • Exit node monitoring
    • Unifi backup verification
    • Golinks backup verification
  • Error handling with automatic notifications

✅ Scheduled Automation (6 cron jobs)⚓︎

  • Unifi Backup: Sunday 1:00 AM with healthcheck
  • Golinks Backup: Daily 4:00 AM with healthcheck
  • Internet Connectivity: Every 5 minutes
  • Exit Node Monitor: Every 5 minutes with healthcheck
  • Docker Maintenance: Daily 2:30 AM
  • Dotfiles Backup: Monday 3:00 AM

✅ Directory Structure⚓︎

  • /home/unifiadmin/.config/appdata - Application data
  • /home/unifiadmin/docker/compose - Docker Compose files
  • /home/unifiadmin/github/docker - Docker configurations
  • /home/unifiadmin/github/configurations - Server configurations
  • /home/unifiadmin/github/configurations/golink-backup - Golinks backup storage
  • /mnt/Backup - NAS mount point

Phase 4: Post-Deployment Configuration⚓︎

Verify VPS Services⚓︎

# SSH to the VPS
ssh -i /volume2/ansible-infrastructure/ssh-keys/ansible_key unifiadmin@VPS_IP

# Check deployed scripts
ls -la /usr/local/bin/*.sh

# Verify cron jobs
crontab -l

# Check NAS mount
mount | grep /mnt/Backup

# Test connectivity monitoring
/usr/local/bin/internet-connectivity-check.sh

# Check Docker environment
docker --version
docker compose version

Configure Docker Applications⚓︎

# Navigate to Docker Compose directory
cd /home/unifiadmin/docker/compose

# Deploy your Docker applications
# (Place your docker-compose.yml files here)

# Start services
docker compose up -d

Phase 5: Monitoring Verification⚓︎

Test Notification System⚓︎

# Test ntfy notifications (replace with your actual token)
curl -H "Authorization: Bearer tk_8eaxrky4sbnki665w6m4aybokafi5" \
     -H "Title: VPS Deployment Test" \
     -d "VPS deployment completed successfully!" \
     "https://ntfy.levine.io/server-monitoring"

Verify Healthchecks⚓︎

# Test healthcheck endpoints
curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/d48e3f5b-1ac3-42a8-87cb-382b55038a6b

Complete Deployment Timeline⚓︎

  1. VPS Provisioning: 5-10 minutes (cloud provider dependent)
  2. User Setup: 2-3 minutes
  3. Ansible Deployment: 8-12 minutes
  4. Application Deployment: 5-15 minutes (depending on containers)
  5. Verification: 3-5 minutes

VPS-Specific Configuration Details⚓︎

Security Hardening⚓︎

  • UFW Firewall: Configured with essential ports only
  • Fail2Ban: SSH brute force protection
  • SSH Hardening: Key-only authentication, root login disabled
  • User Management: Non-root user with minimal required privileges

Backup Strategy⚓︎

  • NAS Integration: Direct CIFS mount to Synology NAS
  • Automated Backups: Unifi, Golinks, and dotfiles
  • Backup Verification: Healthcheck integration for critical backups
  • Backup Destination: /mnt/Backup (NAS mount)

Monitoring Architecture⚓︎

  • Real-time Monitoring: Internet connectivity and Tailscale exit node
  • Scheduled Monitoring: Docker maintenance and system backups
  • Notification Channels: Ntfy.sh with topic-specific tokens
  • Health Verification: Healthcheck.io integration for critical services

Common Issues & Solutions⚓︎

Variable Loading Issues⚓︎

Solution: The VPS role now has comprehensive defaults that ensure all variables are available, preventing undefined variable errors.

NAS Mount Issues⚓︎

Symptom: /mnt/Backup not accessible Solution:

# Check mount status
mount | grep /mnt/Backup

# Remount if needed
sudo mount -a

# Check credentials
sudo cat /etc/samba/credentials

Ntfy Notification Failures⚓︎

Symptom: Notifications not received Solution:

# Test ntfy connectivity
curl -v https://ntfy.levine.io/server-monitoring

# Verify token in script
grep -r "tk_" /usr/local/bin/

Docker Maintenance Issues⚓︎

Symptom: Docker maintenance script fails Solution:

# Check Docker Compose directory
ls -la /home/unifiadmin/docker/compose/

# Test Docker Compose manually
cd /home/unifiadmin/docker/compose
docker compose pull
docker compose up -d

Tailscale Connectivity Issues⚓︎

Symptom: Exit node monitoring fails Solution:

# Check Tailscale status
sudo tailscale status

# Verify connectivity target
ping 100.102.180.92

Emergency Commands Reference⚓︎

Quick VPS Info⚓︎

# System info
hostnamectl
df -h
free -h
docker --version
docker compose version
sudo tailscale status

Service Management⚓︎

# Check critical services
systemctl status docker
systemctl status cron
systemctl status ufw
systemctl status fail2ban

# Check logs
journalctl -u docker -f
tail -f /var/log/auth.log

Manual Script Execution⚓︎

# Test individual scripts
sudo -u unifiadmin /usr/local/bin/internet-connectivity-check.sh
sudo -u unifiadmin /usr/local/bin/monitor-exit-node.sh
sudo -u unifiadmin /usr/local/bin/docker-maintenance.sh

Dry Run Mode (Testing)⚓︎

# Test all changes without applying them
docker run --rm -it \
  -v /volume2/ansible-infrastructure:/ansible \
  -w /ansible \
  cytopia/ansible:latest \
  sh -c "apk add --no-cache openssh-client && ansible-playbook -i inventory/portable-vps.yml playbooks/vps-infrastructure.yml --check --diff --ask-become-pass -v"

Success Verification Checklist⚓︎

VPS is fully deployed when:

  • SSH access works with key authentication
  • UFW firewall is active and configured
  • Fail2Ban is running and monitoring SSH
  • Docker and Docker Compose are installed and running
  • All 7 VPS scripts are deployed and executable
  • All 6 cron jobs are scheduled and running
  • NAS is mounted at /mnt/Backup
  • Ntfy notifications are working
  • Healthcheck endpoints are responding
  • Internet connectivity monitoring is active
  • Tailscale exit node monitoring is functional

Emergency Resources⚓︎

Ansible Project Location: /volume2/ansible-infrastructure
SSH Keys Location: /volume2/ansible-infrastructure/ssh-keys
VPS Inventory: /volume2/ansible-infrastructure/inventory/portable-vps.yml
VPS Playbook: /volume2/ansible-infrastructure/playbooks/vps-infrastructure.yml
NAS Backup Location: /mnt/Backup (on VPS)

VPS Architecture:

  • Ansible: Infrastructure foundation with bulletproof variable handling
  • Docker: Application containerization and orchestration
  • Tailscale: Secure networking and connectivity
  • NAS Integration: Centralized backup and storage
  • Monitoring: Real-time alerts and health verification

Post-Deployment Tasks⚓︎

  1. Deploy Docker applications in /home/unifiadmin/docker/compose
  2. Test all monitoring and notification systems
  3. Verify backup operations are working correctly
  4. Update DNS records if needed for applications
  5. Document any provider-specific configurations
  6. Schedule regular maintenance and updates

Key Advantages of This VPS Approach⚓︎

✅ Complete Portability⚓︎

  • Cloud-agnostic: Works on any Ubuntu 24.04 VPS
  • Standardized configuration: Consistent across providers
  • Automated deployment: No manual configuration required

✅ Comprehensive Monitoring⚓︎

  • Real-time alerts: Connectivity and service monitoring
  • Health verification: Automated backup and service checks
  • Multi-channel notifications: Ntfy.sh and Healthcheck.io integration

✅ Robust Automation⚓︎

  • Scheduled maintenance: Docker updates and cleanup
  • Automated backups: Unifi, Golinks, and dotfiles
  • Bulletproof variable handling: Prevents deployment failures

✅ Security Hardening⚓︎

  • Firewall protection: UFW with minimal required ports
  • Intrusion prevention: Fail2Ban monitoring
  • Secure access: SSH key-only authentication
  • Network security: Tailscale mesh networking

✅ Scalable Architecture⚓︎

  • Multi-VPS support: Deploy to multiple cloud providers
  • Centralized management: Single Ansible configuration
  • Consistent monitoring: Unified notification system

VPS deployment completed successfully! 🚀