Reusable, generic cloud-init configuration templates for common server infrastructure patterns. These templates are designed to be included in your own cloud-init configurations via #include
directives.
These templates follow a composable pattern:
- Generic base templates (this repo) - safe to open source
- Your server configurations (private repo) - domain-specific customizations
# your-private-repo/servers/web-server.yaml
#cloud-config-archive
# Environment setup (runs first)
- type: text/cloud-config
content: |
write_files:
- path: /etc/environment.d/90-infrastructure.conf
content: |
ADMIN_EMAIL="[email protected]"
AWS_REGION="us-west-2"
permissions: '0644'
owner: root:root
# Include base templates
- type: text/x-include-url
content: |
#include
https://raw.githubusercontent.com/your-org/cloud-init-templates/main/base/hardening.yaml
https://raw.githubusercontent.com/your-org/cloud-init-templates/main/base/docker.yaml
# Your application-specific configuration
- type: text/cloud-config
content: |
# Your app config here...
Some templates come in multiple variants to support different use cases:
- Node.js: Choose between
nodejs-22.yaml
(LTS) ornodejs-24.yaml
(Latest) based on your application requirements - PostgreSQL: Single template
postgres.yaml
installs latest version from PostgreSQL's official repository
- Purpose: Security hardening for Ubuntu servers
- Features: UFW firewall, fail2ban, automatic security updates, SSH hardening
- Environment Variables: None required
- Use Case: Apply to all production servers
β οΈ CAUTION: This configuration reboots the server at 2AM UTC time if there are updates that required a reboot. You may not want this.
- Purpose: Docker CE installation and configuration
- Features: Latest Docker CE, docker-compose, systemd integration
- Environment Variables: None required
- Use Case: Container-based applications
β οΈ CAUTION: You should look into more secure docker-like replacements, like podman.
- Purpose: Critical system alerts via AWS SES
- Features: Login notifications, disk/system monitoring, service failure alerts
- Environment Variables:
DEVOPS_EMAIL
,ALERTS_EMAIL
,AWS_REGION
- Use Case: Production monitoring and incident response
- Purpose: Node.js runtime installation
- Features: Node.js 22.x or 24.x LTS via NodeSource repository
- Environment Variables: None required
- Use Case: Node.js applications
- Purpose: PostgreSQL database installation
- Features: Latest PostgreSQL from official PostgreSQL repository
- Environment Variables: None required
- Use Case: Database servers
Templates use environment variables loaded from /etc/environment.d/90-infrastructure.conf
for customization without hardcoded values.
You cannot mix #include
with #cloud-config
in the same user-data. Instead, use #cloud-config-archive
to combine multiple formats.
Correct approach with cloud-config-archive:
#cloud-config-archive
# 1. Create environment files first
- type: text/cloud-config
content: |
write_files:
- path: /etc/environment.d/90-infrastructure.conf
content: |
DEVOPS_EMAIL="[email protected]"
permissions: '0644'
owner: root:root
# 2. Include base templates
- type: text/x-include-url
content: |
#include
https://raw.githubusercontent.com/your-org/cloud-init-templates/main/base/email-alerts.yaml
# 3. Additional configuration
- type: text/cloud-config
content: |
merge_how:
- name: list
settings: [append]
- name: dict
settings: [no_replace, recurse_list]
packages: [...]
Why this approach works: Cloud-config-archive processes each section in order, ensuring environment files are created before included templates run.
Create the environment file in your server configuration:
# In your private server configs (using cloud-config-archive)
#cloud-config-archive
- type: text/cloud-config
content: |
write_files:
- path: /etc/environment.d/90-infrastructure.conf
content: |
# Email Configuration
DEVOPS_EMAIL="[email protected]"
ALERTS_EMAIL="[email protected]"
ADMIN_EMAIL="[email protected]"
# Infrastructure
AWS_REGION="us-west-2"
BACKUP_RETENTION_DAYS="14"
permissions: "0644"
owner: root:root
Templates use environment variables for customization. Common variables include DEVOPS_EMAIL
, ALERTS_EMAIL
, AWS_REGION
, and SSH_PORT
.
π Complete reference: See ENVIRONMENT_VARIABLES.md
for all available variables, their purposes, and defaults.
# Create your own copy
gh repo fork your-org/cloud-init-templates
# servers/web-server.yaml
#cloud-config-archive
# Environment setup (runs first)
- type: text/cloud-config
content: |
write_files:
- path: /etc/environment.d/90-infrastructure.conf
content: |
DEVOPS_EMAIL="[email protected]"
ALERTS_EMAIL="[email protected]"
AWS_REGION="us-west-2"
permissions: '0644'
owner: root:root
# Include base templates
- type: text/x-include-url
content: |
#include
https://raw.githubusercontent.com/your-org/cloud-init-templates/main/base/hardening.yaml
https://raw.githubusercontent.com/your-org/cloud-init-templates/main/base/docker.yaml
# Your application-specific config
- type: text/cloud-config
content: |
packages:
- nginx
runcmd:
- systemctl enable nginx
- systemctl start nginx
Most cloud providers accept cloud-init data during instance creation. Point to your server configuration:
# Use raw GitHub URL for your server config
https://raw.githubusercontent.com/your-org/your-servers/main/servers/web-server.yaml
- β No hardcoded secrets - All sensitive values use environment variables
- β Generic configurations - Domain-agnostic settings only
- β Sensible defaults - Safe fallback values provided
- β Open source friendly - Safe to publish publicly
- π Keep private - Contains your domain-specific secrets
- π Environment variables - Store sensitive values in env files
- π Least privilege - Only expose what's necessary for deployment
cloud-init-templates/
βββ README.md # This file
βββ ENVIRONMENT_VARIABLES.md # Environment variable reference
βββ base/ # Base templates
β βββ docker.yaml # Docker installation
β βββ email-alerts.yaml # AWS SES alerting
β βββ hardening.yaml # Security hardening
β βββ nodejs-22.yaml # Node.js 22.x runtime
β βββ nodejs-24.yaml # Node.js 24.x runtime
β βββ postgres.yaml # PostgreSQL from official repo
βββ examples/ # Example server configs
β βββ search-server.yaml # Search server with Meilisearch
β βββ web-server.yaml # Web application server
βββ tests/ # Validation test suite
βββ README.md # Testing documentation
βββ run-all-tests.sh # Comprehensive test runner
βββ test-email-alerts.sh # Email alerting tests
βββ test-hardening.sh # Security hardening tests
βββ test-security.sh # General security tests
βββ utils.sh # Shared testing utilities
- Fork the repository
- Create a feature branch:
git checkout -b feature/new-template
- Follow the template standards:
- Use environment variables for customization
- Provide sensible defaults
- Include comprehensive comments
- Test with multiple distributions
- Submit a pull request
- Environment Loading: All scripts must load env vars:
[ -f /etc/environment.d/90-infrastructure.conf ] && . /etc/environment.d/90-infrastructure.conf
- Sensible Defaults: Always provide fallback values:
EMAIL="${ADMIN_EMAIL:-admin@example.com}"
- Documentation: Clearly document required environment variables
- Security: No hardcoded secrets or domain-specific information
See the examples/
directory for complete server configuration examples showing how to combine multiple base templates.
- Documentation: Cloud-Init Docs
MIT License - see LICENSE file for details.
π§ Infrastructure as Code β’ π Security First β’ π Production Ready