Skip to content
DevelopmiPublic

About

Layered Ansible infrastructure automation for bare-metal & VPS. NIST 800-53 baseline, CIS Level 1, Tailscale zero-trust mesh, CrowdSec defense, and SOPS/age secrets.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

121 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Developmi Hardened logo

Developmi Hardened

A layered infrastructure stack built with Ansible, Docker and Zero Trust principles.

Python 3.14 Ansible Core 2.21.1 Docker Ready Standard NIST 800-53 Status In Development License MIT CI GitHub Actions Maintainer Miguel Lozano Role Cloud & Infrastructure Engineer

The script is free. Peace of mind is not.

This repository delivers a reproducible hardening baseline, zero-trust access patterns, and optional containerized application bundles for managed infrastructure.


Table of Contents


Overview

Developmi Hardened is an Ansible-based infrastructure automation project focused on establishing a secure, auditable, and repeatable baseline across mixed-host environments.

It is designed to standardize the security posture of:

  • Brain nodes for central services, ingress, and observability.
  • Muscle nodes for workload execution and optional edge services.
  • Application stacks under apps/ are operator-managed and deploy first-class via native Docker Compose (git pull + docker compose up on public_net); Portainer (Edge agent) is an optional manager when enable_portainer: true (ADR-07).

The project aligns to NIST 800-53 controls and emphasizes secrets handling, least privilege, hardened networking, and operational repeatability.


Features

  • 🛡️ Security-first hardening with SSH restrictions, firewall controls, audit logging, CrowdSec integration, and Vault-backed secrets.
  • 🔐 Zero-trust networking through Tailscale ACL-driven access and minimized public exposure.
  • 🧱 Modular architecture using Ansible roles for security, Docker orchestration, observability, compliance, ingress, and Portainer edge operations.
  • 📦 Optional application bundles for Chatwoot, Metabase, n8n, OpenWebUI, Twenty CRM, and Uptime Kuma.
  • 📈 Operational visibility with exporter and observability stack support when capacity allows.
  • 🧪 Validation gates executed through Make targets (uv-backed) for linting, syntax checks, and secret scanning.
  • 🧭 Documented operating model with commands centralized in docs/operations/OPERATIONS_RUNBOOK.md.

Value Snapshot for CTO/CFO

In less than 30 seconds:

  • Cost Control: Designed for self-hosted operation on VPS/Bare Metal to avoid linear SaaS cost growth.
  • Security Baseline: NIST-aligned hardening with zero-trust networking and auditable controls.
  • Data Sovereignty: Sensitive workloads stay in infrastructure you control.
  • Cloud-Exit Ready: Portable Ansible playbooks and provider-agnostic architecture reduce lock-in.
  • Operational Predictability: Pull-based management model and Make-driven runbooks reduce change risk.

FinOps Case Study (Nuntu)

This project pattern has been applied to a real-world migration scenario (codenamed Nuntu) focused on sovereignty, security, and OpEx reduction.

Business problem

  • SaaS sprawl with linear OpEx growth by headcount.
  • Data processed in third-party multi-tenant platforms.
  • Vendor/API dependence creating operational fragility.

Implemented approach

  • Sovereign self-hosted stack on high-performance VPS fleet.
  • Pull-based operations model (Portainer Edge pattern).
  • Caddy + WAF perimeter with hardened default-deny posture.
  • Security automation and compliance-oriented runbooks.

Measured outcomes (reported case)

Metric Before (SaaS Sprawl) After (Sovereign Self-Hosted) Impact
Annual Software OpEx $X (baseline) $0.3X -70%
Platform Uptime (Prod) ~99.5% 99.8% Higher reliability
Data Sovereignty 0% 100% Full control
WAF Efficacy N/A >99% block rate, <1% false positives Enterprise-grade perimeter
Incident Response Time Hours/Days Minutes Stronger resilience
Vendor Risk Critical Negligible Supply-chain risk reduced

Scope note: This case study is a field implementation narrative and not a vendor benchmark report. Results depend on workload, architecture, and governance discipline.


Field Validation Evidence

Current documented execution evidence in this repository corresponds to a lab/staging scope with:

  • 1 Brain node
  • 2 Muscle nodes

This is intentionally presented as operational proof-of-execution while broader fleet rollouts are scheduled.

Deployment proof screenshots

Base hardening deployment evidence

Monitoring deployment evidence


Compliance & Standards

This repository is not just "NIST-themed". It includes implementation-grounded compliance references with auditable mappings and evidence workflows.

Primary control coverage

  • NIST SP 800-53: AC-2, CM-7, SC-7, SI-4, AU-12, and SC-28 (partial for full disk encryption).
  • NIST SP 800-207 (Zero Trust): overlay-network control path, identity/tag-based access, and pull-based management pattern.
  • CIS Level 1 (generic Ubuntu/Debian alignment): SSH baseline, firewall posture, brute-force mitigation, and audit telemetry.
  • DORA/ENS contextual mapping: documented as technical-functional alignment for resilience and governance discussions.

Where to audit compliance details

Important: This project provides implementation evidence and technical mappings. Formal certification readiness still requires organization-specific legal, scope, and auditor validation.


Quick Start

Prerequisites

  • uv for Python dependency and environment management.
  • Python 3.14 or newer.
  • SSH access to the target hosts.
  • Ansible Galaxy network access for collection installation.
  • Docker Compose only if you plan to run optional app bundles.

Setup

git clone https://github.com/Developmi/hardened.git
cd hardened
make sync
make install-collections

Inventory

Create or customize your inventory before deployment:

[brain]
brain-1 ansible_host=YOUR_PUBLIC_IP ansible_user=root public_ip=YOUR_PUBLIC_IP

[muscle]
muscle-1 ansible_host=YOUR_PUBLIC_IP ansible_user=ubuntu public_ip=YOUR_PUBLIC_IP

Secrets

Populate the SOPS-encrypted secrets file and encrypt it before deployment (SOPS + age replaces the old Ansible Vault workflow; the Tailscale auth/ACL keys remain vaulted until expiry):

# 1. Generate the age keypair and back it up OFFLINE
age-keygen -o age/keys.txt
# 2. Replace the age1<PLACEHOLDER> recipient in .sops.yaml with your public key
# 3. Create + fill + encrypt the secrets file
make sops-init
make sops-encrypt

Deploy

make check-toolchain
make deploy-hardening
make deploy-engine
make deploy-edge BACKEND=caddy TARGET=<brain>
make deploy-portainer
make run PLAYBOOK=playbooks/l3/stack.yml TAGS='l3-observability,stack'

Note: The canonical command surface lives in docs/operations/OPERATIONS_RUNBOOK.md. Use make targets instead of raw playbook calls when possible.


Operations with Make

Make is the official command interface for this project. Day-to-day operations should run through Make targets.

High-frequency operator commands

make help
make sync
make install-collections
make check-toolchain
make deploy-hardening
make deploy-engine
make deploy-edge BACKEND=caddy TARGET=<brain>
make deploy-portainer
make run PLAYBOOK=playbooks/l3/stack.yml TAGS='l3-observability,stack'
make verify-tailscale
make verify-crowdsec
make verify-observability

Advanced and safety workflows

make run PLAYBOOK=playbooks/site.yml TAGS='nist,sc-7'
make run PLAYBOOK=playbooks/site.yml SKIP_TAGS='tailscale,vpn'
make deploy-compliance
make nuke CONFIRM=DESTROY_ALL_INFRASTRUCTURE
make audit-full

Operational reference index:


Architecture

Simplified Tree

.
├── playbooks/site.yml                 # Base hardening entry point
├── playbooks/l1/                      # L1 - OS baseline
├── playbooks/l2/                      # L2 - Compliance, hardening
├── playbooks/l3/                      # L3 - Observability, exporters
├── playbooks/l4/                      # L4 - Networking/Edge proxy
├── playbooks/l6/                      # L6 - Runtime (Engine, Portainer, backups)
├── playbooks/ops/                     # Operational playbooks (nuke, bootstrap, validate)
├── inventory/               # Target host inventory definitions
├── group_vars/              # Shared and group-specific variables
├── roles/                   # Ansible roles for platform capabilities
├── apps/                    # L5 application profiles (profile, vars)
├── docs/                    # Operational, compliance, and project documentation
└── scripts/                 # Bootstrap and monitoring helpers

Execution Flow

flowchart LR
  Operator[Operator] --> Make[Make Targets]
  Make --> Ansible[Ansible Playbooks]
  Ansible --> SOPS[Encrypted Secrets]
  Ansible --> Hosts[Brain and Muscle Hosts]
  Hosts --> Docker[Optional Docker Compose Bundles]
  Hosts --> Security[Hardening, Compliance, and Monitoring]
Loading

The role structure is intentionally separated so security controls, Docker orchestration, observability, and ingress can evolve independently without coupling the baseline hardening path.


Docker & Deployment

Docker is used for application stacks and observability services, not as the primary automation runtime.

Deploy Applications

All 8 application profiles (Chatwoot, Metabase, n8n, NocoDB, OpenWebUI, Twenty CRM, Uptime Kuma, FastAPI) deploy as Docker Compose stacks from structured profiles under apps/, rendered by the L6 runtime. Compose does not depend on Portainer (ADR-07): with the optional manager enabled (enable_portainer: true), the same stacks can be managed through Portainer's UI (Edge agent); with the default enable_portainer: false, a compose-only deploy needs zero portainer_* variables. See ARCHITECTURE.md §Application Profiles for the full schema.

Security Notes

  • Prefer publishing services through the hardened ingress layer instead of exposing broad host ports.
  • Use the provided SOPS workflow for sensitive runtime values.
  • Application stacks are intended to run behind the project's reverse proxy and network segmentation model.
  • App configuration is operator-managed: each app has a pinned docker-compose.yml plus a .env (template: apps/<name>/.env.example). The old Ansible-managed apps/<name>/vars.yml was removed (2026-07-31).

Configuration & Secrets

This project does not require a root .env.example. Runtime secrets are encrypted with SOPS + age and loaded transparently by the community.sops vars plugin from group_vars/all/secrets.sops.yml and group_vars/all/managers/portainer.sops.yml (the Tailscale auth/ACL keys remain in the Ansible Vault until expiry). Application-specific configuration is operator-managed via apps/<name>/.env, templated from apps/<name>/.env.example. See ARCHITECTURE.md §App Profiles for the profile schema.

Core Secrets Template

# group_vars/all/secrets.yml.example (fill into secrets.sops.yml, then: make sops-encrypt)
vault_github_token: "GITHUB_TOKEN_GOES_HERE"
caddy_acme_email: "ops@example.com"
# Portainer edge keys live in group_vars/all/managers/portainer.sops.yml:
#   portainer_edge_keys_by_node:
#     brain-1: "PORTAINER_EDGE_KEY_FOR_BRAIN_1"
#     muscle-1: "PORTAINER_EDGE_KEY_FOR_MUSCLE_1"

Optional Observability Values

These are required only when the observability stack is enabled:

  • observability_stack_host_ip
  • observability_grafana_admin_user
  • observability_grafana_admin_password
  • observability_grafana_root_url

App Configuration

Application variables are managed through the Ansible variable hierarchy (5-tier precedence). Each app has:

  • apps/<name>/docker-compose.yml - pinned compose stack; env via apps/<name>/.env.example (operator-managed)
  • apps/<name>/profile.yml - metadata (version, DB type, backup schedule, monitoring)

Apps deploy as Compose stacks (optionally managed via Portainer). See OPERATIONS_RUNBOOK.md §3 for the full deployment guide.


Validation & Quality Gates

The repository is validated through uv-managed tooling and Ansible-native checks.

make sync
make install-collections
make check-toolchain
make lint PLAYBOOK=playbooks/site.yml
make precommit-run

Current quality gates include:

  • YAML formatting validation.
  • Ansible playbook syntax checks.
  • Role and playbook linting.
  • Secret detection with a tracked baseline.

Operational note: make lint is intentionally strict and should be used before changes are promoted to shared environments.


🧪 Tests

This project is validated through Make-driven quality gates. For production-grade role testing, use molecule or ansible-test with a local inventory:

make check-toolchain
make lint PLAYBOOK=playbooks/site.yml
make precommit-run

CI pipeline: All playbooks pass syntax check and linting on every PR via GitHub Actions. A dedicated security-audit.yml workflow runs on version tags for release gating.

Note: Automated role-level integration testing (e.g., Molecule) is on the roadmap. Current validation focuses on syntax, linting, idempotency dry-runs, and secret scanning - all exercised through make targets and CI.


🔒 Security

This project follows a coordinated disclosure policy. If you discover a vulnerability, do not open a public issue. See SECURITY.md for reporting instructions, supported versions, and response timelines.


📋 Changelog

See CHANGELOG.md for the full version history. The project follows Keep a Changelog and Semantic Versioning.


🤝 Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening a pull request. This project follows Conventional Commits and the Developmi engineering standard.


📄 License

Copyright © 2026 Miguel Lozano | Developmi. All rights reserved. Licensed under the MIT License.


Documentation Guide

For the full documentation index including architecture, compliance, operations, and project docs, see docs/README.md.


Contact & Support

  • Maintained by: Miguel Lozano | Developmi
  • Role: Cloud & Infrastructure Engineer | FinOps & Bare Metal Specialist | AI Sovereignty Strategist under NIST/DORA Standards
  • Philosophy: Security is not a feature; it is the baseline.
  • Website: Developmi
  • GitHub: Miguel-DevOps
  • LinkedIn: Miguel Lozano

© 2026 Miguel Lozano | Developmi. All rights reserved.

Related Documents

About

Layered Ansible infrastructure automation for bare-metal & VPS. NIST 800-53 baseline, CIS Level 1, Tailscale zero-trust mesh, CrowdSec defense, and SOPS/age secrets.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages