Skip to content

Releases: mcansem/infra

v0.9.0 — Documentation

Choose a tag to compare

@mcansem mcansem released this 21 Jul 01:23

Ninth release of the infra repository: Documentation. The last two v0.1.0 stubs, plus the roadmap's remaining items - architecture diagrams, operational runbooks, onboarding documentation.

Added

  • docs/architecture.md - real content replacing the v0.1.0 stub: three Mermaid diagrams (component/data-flow, externally-reachable network topology matching scripts/harden-host.sh's role_ports(), CI/CD sequence matching vars/standardDeployPipeline.groovy's stage order), rendered natively by GitHub
  • docs/recovery.md - real content replacing the v0.1.0 stub: the authoritative host-lost runbook, consolidating what was scattered across backup.md/restore.md/platforms/homelab.md, plus explicit RPO (~24h, tied to the daily backup cadence) and RTO (an honest estimate - under two hours - explicitly caveated as untested, not a real SLA)
  • docs/runbooks.md - one playbook per Prometheus alert (HostDown, DiskSpaceLow, ContainerMissing): what it means, likely causes, concrete investigate/fix commands
  • docs/onboarding.md - how a new application repo starts using this infrastructure: Jenkinsfile shape, image/port expectations, what to do if it doesn't fit the existing docker/app/ service shape, new-subdomain certificate bootstrap

Changed

  • docs/project-specification.md's Documentation section gains runbooks.md, onboarding.md

What's next

v1.0.0 - Production Ready Stable Release. Final stabilization pass - the last phase on the current roadmap.

Full changelog: CHANGELOG.md

v0.8.0 — Platform Integration

Choose a tag to compare

@mcansem mcansem released this 21 Jul 01:03

Eighth release of the infra repository: Platform Integration - multi-target deployment guidance. Documentation only, no infrastructure changes, per the phase's own stated constraint.

Added

  • docs/deployment.md - real content replacing the v0.1.0 stub: the general deploy flow (git pull -> docker pull -> compose up -> health check -> rollback), the management/app/agent role vocabulary, links to per-provider host provisioning
  • docs/platforms/aws.md, google-cloud.md, oracle-cloud.md, homelab.md - each covers only what's genuinely provider-specific (getting from nothing to a reachable Ubuntu host); everything past that point is already identical across providers by design, so these docs hand off to the existing scripts/harden-host.sh <role> + docker/*/README.md steps rather than re-describing them
  • docs/platforms/oracle-cloud.md notes the Always Free ARM (Ampere A1) tier is viable for the app role's own images (nginx/postgres, both confirmed multi-arch) but flags the application's own images as a separate build-time concern for that repo's own CI
  • docs/platforms/homelab.md is a migration guide, not a fresh-deploy guide - walks through scripts/backup.sh -> scripts/restore.sh as the actual AWS-to-self-hosted migration mechanism for Jenkins, exercising the v0.6.0 tooling end to end

Changed

  • docs/project-specification.md's Documentation section gains platforms/

What's next

v0.9.0 - Documentation (architecture diagrams, operational runbooks, onboarding documentation, plus completing architecture.md and recovery.md, the two remaining stubs from v0.1.0).

Full changelog: CHANGELOG.md

v0.7.0 — Observability

Choose a tag to compare

@mcansem mcansem released this 21 Jul 00:29

Seventh release of the infra repository: Observability - metrics, dashboards, alerting, and external availability monitoring.

Added

  • docker/monitoring-agent/ - Node Exporter (host metrics) + cAdvisor (per-container metrics), deployed identically on every host role. Both bind to 127.0.0.1 only by default (neither has any authentication) - cross-host Prometheus scraping is a documented, source-IP-scoped manual opt-in, not scripted
  • docker/observability/ - Prometheus, Alertmanager, Grafana, Uptime Kuma on the management host. Prometheus/Alertmanager stay internal-only (no meaningful auth of their own); Grafana/Uptime Kuma get a public URL through the new management proxy
  • Prometheus joins monitoring_agent_net to scrape node-exporter/cadvisor by container name - their 127.0.0.1-published ports aren't reachable from inside another container, so same-host scraping goes over a shared Docker network instead
  • Three default alert rules (host down, disk >85%, container missing) with a no-op Alertmanager receiver - wiring a real notification channel needs deployment-specific credentials that don't belong in this repo
  • Grafana's Prometheus datasource is provisioned as code; dashboards are a documented two-click import (Node Exporter Full, cAdvisor) rather than vendored JSON
  • docker/management-proxy/ - TLS termination and name-based vhost routing (jenkins.<domain>, grafana.<domain>, uptime.<domain>) for every public UI on the management host, replacing the single-vhost jenkins/nginx.conf. Domain names are injected via the official nginx image's envsubst templating, not hardcoded

Changed

  • jenkins/docker-compose.yml: the nginx service moved out to docker/management-proxy/ - jenkins/ is Jenkins-only again, still not published on a host port itself
  • scripts/harden-host.sh: role_ports() documents why the exporter ports are deliberately not in the default UFW allowlist

Notes

  • None of this has been run against a live host yet - the AWS management host was still being provisioned while this was written, so the nginx-to-management-proxy migration had no live traffic to move

What's next

v0.8.0 - Platform Integration (multi-target deployment guidance for AWS/Google Cloud/Oracle Cloud/Homelab, documentation and examples only - infrastructure code stays cloud-agnostic).

Full changelog: CHANGELOG.md

v0.6.0 — Operations

Choose a tag to compare

@mcansem mcansem released this 20 Jul 22:40

Sixth release of the infra repository: Operations - backup, restore, update, cleanup, and manual deploy tooling.

Added

  • scripts/backup.sh - local, verified, rotated backups per host role (pg_dump -Fc for Postgres, volume tars for jenkins_home/portainer_data/registry_data); off-host replication is documented (docs/backup.md), not scripted, since the destination varies per deployment
  • scripts/restore.sh - destructive, so it's a dry run unless --yes-i-am-sure is passed; validates Postgres connectivity and table presence after a restore
  • scripts/update.sh - on-demand apt upgrade + docker compose pull/up per role, image prune, idempotent logrotate config install
  • scripts/cleanup.sh - periodic docker system prune/build-cache prune, never touches volumes
  • scripts/deploy.sh - manual/fallback counterpart to vars/standardDeployPipeline.groovy's SSH deploy stage (pull infra config -> tag rollback images -> pull -> up -> wait-for-healthy -> roll back on failure), for when Jenkins isn't the one triggering deployment
  • scripts/logrotate/infra-nginx.conf for the file-based nginx logs added in v0.5.0
  • Real content for docs/backup.md and docs/restore.md (stubs since v0.1.0), including a disaster-recovery walkthrough

Fixed

  • Two internal-consistency gaps caught while writing this phase: docs/roadmap.md still showed v0.5.0 as "In Progress" after it had already shipped; docs/project-specification.md's Operations section was missing restore.sh/cleanup.sh

Notes

  • None of these scripts have been run against a live host yet - restore.sh and deploy.sh both have their own built-in safety gates for that first real run (explicit confirmation flag, automatic image rollback on failed healthcheck respectively)

What's next

v0.7.0 - Observability (Uptime Kuma, Prometheus, Grafana, Node Exporter, cAdvisor, alerting, monitoring dashboards).

Full changelog: CHANGELOG.md

v0.5.0 — Production Hardening

Choose a tag to compare

@mcansem mcansem released this 20 Jul 19:22

Fifth release of the infra repository: Production Hardening, end to end - container-level, documentation, and host-level.

Added

  • docs/roadmap.md - single source of truth for phase-by-phase scope/status and roadmap revision history (previously duplicated inside project-specification.md), with a Guiding Principles section ("write once, deploy anywhere") and an explicit Out of Scope section (Kubernetes, Terraform, Ansible - deferred to v2.x)
  • scripts/harden-host.sh - role-driven UFW firewall (management/app/agent, each with a different port set), Fail2ban (sshd + nginx-limit-req + nginx-botsearch jails), unattended-upgrades, and an opt-in-only --harden-ssh flag
  • SSH is always allowed - including the current session's actual port, auto-detected - before any default-deny firewall policy, to avoid locking the operator out of a remote host

Changed

  • Container-level hardening applied across all four stacks (docker/portainer/, docker/registry/, jenkins/, docker/app/): healthcheck-based depends_on (condition: service_healthy), stop_grace_period, resource limits, a restart-policy split (stateless unless-stopped/always vs. stateful/expensive-to-crash-loop on-failure:5), and ${VAR:?message} environment validation
  • nginx/app.conf and jenkins/nginx.conf: rate limiting, a Permissions-Policy header, a starter Content-Security-Policy (app only - Jenkins manages its own), and file-based logging so Fail2ban has something to tail
  • README.md and docs/project-specification.md no longer embed the roadmap inline - both point to docs/roadmap.md
  • Roadmap scope expanded per an architecture change request: v0.6.0/v0.7.0/v0.9.0 all gained additional items - see docs/roadmap.md's Revision History

Notes

  • harden-host.sh has not been run against a real host yet - --harden-ssh in particular should only be used after confirming key-based SSH access works, from a second terminal
  • No custom Jenkins-login Fail2ban jail - no bundled filter exists for its log format, and one written without a running Jenkins to test against would be unreliable

What's next

v0.6.0 - Operations (backup.sh, restore.sh, update.sh, cleanup.sh, backup/restore verification, log rotation).

Full changelog: CHANGELOG.md

v0.4.0 — Staging Environment

Choose a tag to compare

@mcansem mcansem released this 20 Jul 00:43

Fourth release of the infra repository: the Staging Environment, plus the self-hosted registry and TLS-fronted Jenkins it depends on.

Added

  • Private Docker Registry (docker/registry/) - self-hosted, htpasswd-authenticated, TLS-terminated; deliberately no Docker Hub/GHCR dependency
  • ssl/obtain-cert.sh - shared Let's Encrypt (webroot) / self-signed certificate helper, domain-parametrized, used by every TLS-terminating service in this repo
  • Jenkins fronted by TLS-terminating Nginx (jenkins/nginx.conf) - GitHub webhooks now have a real HTTPS endpoint; Jenkins no longer publishes a host port directly
  • vars/standardDeployPipeline.groovy's Docker Build stage now also pushes to the private registry (registryUrl/registryCredentialsId params)
  • Staging/production app stack (docker/app/): Nginx + PostgreSQL + Next.js + .NET API deployed as one unit - first real use of the base + docker-compose.staging.yml/docker-compose.production.yml override pattern decided back at v0.1.0
  • nginx/app.conf: TLS termination, gzip, security headers, /api/ routed to the .NET API, everything else to Next.js

Fixed

  • ShellCheck CI job now scans all **/*.sh repo-wide instead of only scripts/**/*.sh
  • Added .gitattributes forcing LF line endings - Windows git was about to ship shell scripts with CRLF, which breaks the shebang on the Linux hosts this repo targets

Notes

  • App images (nextjs, dotnet-api) are pulled from the private registry, never built in this repo, per the app/infra separation principle - healthchecks assume conventional ports/paths (3000, /health) until the real app images exist to confirm against
  • Postgres backup/restore automation is out of scope here - that's v0.6.0 (Operations)

What's next

v0.5.0 - Production Environment (Oracle Cloud deployment, hardened Nginx, real production config, healthchecks).

Full changelog: CHANGELOG.md

v0.3.0 — CI/CD (Jenkins)

Choose a tag to compare

@mcansem mcansem released this 19 Jul 23:44

Third release of the infra repository: CI/CD foundation via a Dockerized, config-as-code Jenkins.

Added

  • Jenkins server stack (jenkins/docker-compose.yml, jenkins/Dockerfile) - jenkins/jenkins:lts-jdk17 + Docker CLI for Docker-outside-of-Docker builds against the host daemon
  • Jenkins configured entirely via JCasC (jenkins/casc.yaml): admin user from env vars, setup wizard disabled, plugin set pinned in jenkins/plugins.txt
  • Jenkins Shared Library (vars/standardDeployPipeline.groovy): Checkout -> Build -> Docker Build -> Deploy via SSH, parametrized by targetHost/targetEnv/imageName so the same pipeline will serve AWS/Google/Oracle/Homelab deploy targets later
  • Registered as the infra-shared-library global pipeline library, ready for app repos (e.g. portfolio/) to consume with a 2-line Jenkinsfile

Notes

  • Deploy SSH credentials are intentionally not in this repo - added manually via the Jenkins UI after first boot
  • No build triggers (webhook/polling) yet; those are configured per app repo once onboarded, and webhooks become the natural choice once Nginx/SSL fronts Jenkins (v0.4.0+)

What's next

v0.4.0 - Staging Environment (Nginx, PostgreSQL, Next.js, .NET API, SSL).

Full changelog: CHANGELOG.md

v0.2.0 — Docker Infrastructure

Choose a tag to compare

@mcansem mcansem released this 19 Jul 22:58
4cc1606

Second release of the infra repository: Docker management foundation via Portainer.

Added

  • Portainer CE server stack (docker/portainer/docker-compose.yml) — deployed once on the management host (AWS EC2, per the Short Term roadmap)
  • Portainer Agent stack (docker/portainer/agent-compose.yml) — deployed on each remote Docker host to be managed, fulfilling the "one Portainer instance manages multiple hosts" requirement
  • Both images pinned to 2.39.5-alpine (required for a working Docker healthcheck — the default scratch-based image ships no shell/wget)
  • docker/README.md documenting the per-concern stack layout and deploy steps

Fixed

  • markdownlint CI failures (fenced code block languages, heading structure, CHANGELOG/spec doc rule tuning)

What's next

v0.3.0 — CI/CD (Jenkins in Docker, declarative pipeline: GitHub → Build → Docker Build → Deploy via SSH).

Full changelog: CHANGELOG.md

v0.1.0 — Repository Foundation

Choose a tag to compare

@mcansem mcansem released this 19 Jul 22:18

First release of the infra repository: the foundational skeleton for a reusable, multi-application DevOps infrastructure platform.

This release does not deploy anything yet — it establishes the structure, conventions, and roadmap that every future phase (v0.2.0 → v1.0.0) builds on.

Added

  • Repository skeleton: scripts/, docker/, jenkins/, nginx/, ssl/, docs/, .github/
  • README.md — project vision, philosophy, and roadmap
  • CONTRIBUTING.md — commit conventions and release process
  • LICENSE (MIT)
  • .gitignore, .editorconfig
  • Documentation stubs for architecture, deployment, backup, restore, and disaster recovery
  • GitHub Actions lint workflow (ShellCheck + markdownlint)
  • Issue and pull request templates

What's next

v0.2.0 — Docker Infrastructure (Compose base + per-environment overrides, healthchecks, named volumes, Portainer).

Full changelog: CHANGELOG.md