An Ansible automation project for deploying a Node.js quiz application with user management across multiple servers using GitHub Actions and Secrets.
This project automates the deployment of:
- Server1 (homework): User management server with SSH key deployment
- Server2 (github): Node.js application server with Nginx reverse proxy
┌─────────────────┐ ┌─────────────────┐
│ Server1 │ │ Server2 │
│ 192.168.11.86 │ │ 192.168.11.87 │
│ │ │ │
│ •User Management│ │ • Node.js App │
│ •SSH Keys │ │ • PM2 Process │
│ │ │ • Nginx Proxy │
└─────────────────┘ └─────────────────┘
- Creates development users dynamically from GitHub secrets
- Deploys SSH public keys for passwordless authentication
- Configures bash shell and home directories
- Supports flexible user configuration via JSON
- Deploys Node.js quiz application from GitHub
- Sets up PM2 process management
- Configures Nginx reverse proxy
- Manages environment variables securely
- Automatic dependency installation
ansible_Deploy/
├── README.md
├── inventory.ini # Server inventory
├── site.yml # Main playbook
└── roles/
├── homework/
│ ├── tasks/main.yml # User management tasks
│ ├── vars/main.yml # User definitions & SSH key
│ └── handlers/main.yml # SSH service handlers
└── github/
├── defaults/main.yml # App configuration
├── tasks/main.yml # App deployment tasks
├── handlers/main.yml # Service handlers
└── templates/
├── env.j2 # Environment template
└── nginx.conf.j2 # Nginx config template
Configure the following secrets in your GitHub repository (Settings → Secrets and variables → Actions):
| Secret Name | Description | Example Value |
|---|---|---|
ADMIN_PASSWORD |
Admin panel password | your_secure_admin_password |
SESSION_SECRET |
Express session secret | your_super_secret_session_key |
OPENROUTER_API_KEY |
AI API key for quiz generation | sk-or-v1-xxxxxxxxxxxxx |
| Secret Name | Description | Example Value |
|---|---|---|
USERS_JSON |
JSON array of users to create | [{"name": "dev1"}, {"name": "dev2"}, {"name": "dev3"}] |
SSH_PUBLIC_KEY |
SSH public key for user authentication | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... |
- Navigate to your repository on GitHub
- Go to Settings → Secrets and variables → Actions
- Click "New repository secret"
- Add each secret with the exact names listed above
[
{"name": "dev1"},
{"name": "dev2"},
{"name": "dev3"},
{"name": "staging"},
{"name": "production"}
]# Generate new SSH key (if needed)
ssh-keygen -t ed25519 -C "[email protected]"
# Display your public key
cat ~/.ssh/id_ed25519.pubEdit inventory.ini to match your server details:
[homework]
192.168.11.86 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
[github]
192.168.11.87 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsaKey settings in roles/github/defaults/main.yml:
- Repository:
https://github.com/aacc1on/quiz_MVC.git - Domain:
quizzzzz.camdvr.org - Port:
3000 - Admin Credentials: Retrieved from GitHub secrets
- Ansible installed
- SSH access to target servers
- Private key configured (
~/.ssh/id_rsa)
- Ubuntu/Debian-based systems
- Root SSH access
- Internet connectivity for package installation
- All required secrets configured
- GitHub Actions enabled (if using CI/CD)
# Export secrets as environment variables
export ADMIN_PASSWORD="your_admin_password"
export SESSION_SECRET="your_session_secret"
export OPENROUTER_API_KEY="your_api_key"
export USERS_JSON='[{"name": "dev1"}, {"name": "dev2"}]'
export SSH_PUBLIC_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5..."
# Test connectivity
ansible all -i inventory.ini -m ping
# Run the full deployment
ansible-playbook -i inventory.ini site.ymlCreate .github/workflows/deploy.yml:
name: Deploy with Ansible
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Ansible
run: |
pip install ansible
- name: Deploy to servers
env:
ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD }}
SESSION_SECRET: ${{ secrets.SESSION_SECRET }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
USERS_JSON: ${{ secrets.USERS_JSON }}
SSH_PUBLIC_KEY: ${{ secrets.SSH_PUBLIC_KEY }}
run: |
ansible-playbook -i inventory.ini site.yml# Deploy only user management (Server1)
ansible-playbook -i inventory.ini site.yml --limit homework
# Deploy only application (Server2)
ansible-playbook -i inventory.ini site.yml --limit github- Never commit secrets to version control
- Use different secrets for different environments
- Rotate secrets regularly, especially API keys
- Use strong passwords with mixed characters
- Limit secret access to necessary team members only
- Users are created dynamically from the
USERS_JSONsecret - SSH public key authentication is enabled for all users
- Users are added to the root group for administrative access
- Bash shell is configured for all users
- Environment variables sourced from GitHub secrets
- Session management with configurable secrets
- Nginx proxy for additional security layer
- Process isolation with PM2
After deployment, the quiz application will be available at:
- URL:
http://quizzzzz.camdvr.org - Admin Panel: Login with credentials from GitHub secrets
- Port: Application runs on port 3000, proxied through Nginx
The application uses these environment variables (sourced from GitHub secrets):
PORT=3000
NODE_ENV=development
ADMIN_USERNAME=admin # Default value
ADMIN_PASSWORD=${ADMIN_PASSWORD} # From GitHub secret
SESSION_SECRET=${SESSION_SECRET} # From GitHub secret
OPENROUTER_API_KEY=${OPENROUTER_API_KEY} # From GitHub secretThe Node.js application is managed by PM2:
# Check application status
pm2 list
# View logs
pm2 logs myapp
# Restart application
pm2 restart myappMissing Environment Variables
# Check if secrets are properly set
echo $ADMIN_PASSWORD
echo $SESSION_SECRET
# Verify users JSON format
echo $USERS_JSON | python -m json.toolSSH Connection Failed
# Test SSH connectivity
ssh -i ~/.ssh/id_rsa [email protected]
# Verify SSH public key format
ssh-keygen -l -f ~/.ssh/id_ed25519.pubApplication Not Starting
# Check PM2 status
pm2 list
pm2 logs myapp
# Check environment file
cat /var/www/myapp/.envDomain Not Resolving
- Ensure DNS is configured for
quizzzzz.camdvr.org - Check Nginx configuration:
sudo nginx -t
Update the USERS_JSON secret with additional users:
[
{"name": "dev1"},
{"name": "dev2"},
{"name": "dev3"},
{"name": "newuser"},
{"name": "staging"}
]Edit roles/github/defaults/main.yml or override with additional secrets:
app_domain: "your-domain.com"
app_env:
PORT: "8080"
# ... other settingsCreate different secret sets for different environments:
PROD_ADMIN_PASSWORD,STAGING_ADMIN_PASSWORDPROD_SESSION_SECRET,STAGING_SESSION_SECRET- etc.
- curl
- git
- nginx
- Node.js 20.x
- npm
- pm2
ansible.builtinansible.posix
- Never expose secrets in logs or console output
- Use HTTPS in production environments
- Regularly update dependencies and system packages
- Monitor access logs for suspicious activity
- Backup configurations before making changes