diff --git a/apps/portfolio/kustomization.yaml b/apps/portfolio/kustomization.yaml index 6dc8abe..941ed87 100644 --- a/apps/portfolio/kustomization.yaml +++ b/apps/portfolio/kustomization.yaml @@ -17,6 +17,15 @@ configMapGenerator: - name: portfolio-site files: - index.html=site/index.html + - resume.html=site/resume.html + - kubernetes.html=site/kubernetes.html + - microsoft.html=site/microsoft.html + - automation.html=site/automation.html + - observability.html=site/observability.html + - styles.css=site/styles.css + - architecture.svg=site/architecture.svg + - favicon.svg=site/favicon.svg + - robots.txt=site/robots.txt - name: portfolio-nginx files: - default.conf=nginx/default.conf diff --git a/apps/portfolio/nginx/default.conf b/apps/portfolio/nginx/default.conf index 227ef5f..84b5cb1 100644 --- a/apps/portfolio/nginx/default.conf +++ b/apps/portfolio/nginx/default.conf @@ -6,6 +6,7 @@ server { root /usr/share/nginx/html; index index.html; server_tokens off; + charset utf-8; access_log /dev/stdout; error_log /dev/stderr warn; @@ -13,8 +14,11 @@ server { add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; - add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; - add_header Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + add_header Cross-Origin-Resource-Policy "same-origin" always; + add_header X-Robots-Tag "noindex, nofollow" always; + add_header Content-Security-Policy "default-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; script-src 'none'; connect-src 'none'; object-src 'none'; frame-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests" always; location = /healthz { access_log off; @@ -22,7 +26,17 @@ server { return 200 "ok\n"; } + location ~* \.(css|svg)$ { + expires 7d; + try_files $uri =404; + } + + location ~* \.html$ { + expires -1; + try_files $uri =404; + } + location / { - try_files $uri $uri/ /index.html; + try_files $uri $uri/ $uri.html /index.html; } } diff --git a/apps/portfolio/site/architecture.svg b/apps/portfolio/site/architecture.svg new file mode 100644 index 0000000..949b6eb --- /dev/null +++ b/apps/portfolio/site/architecture.svg @@ -0,0 +1,105 @@ + + Portfolio GitOps architecture + A Git repository flows through Argo CD and Kustomize into a restricted Kubernetes namespace, then through ingress and TLS to the browser. Security and observability controls surround the workload. + + + + + + + + + + + + + + + + + + + + + GitOps delivery path + The site architecture is part of the demonstration. + + + + + Git repository + Desired state + Reviewable changes + + + + + Argo CD + Reconciliation + Self-healing + + + + + Kustomize + Manifest rendering + ConfigMap hashes + + + + + Kubernetes namespace + 2 web replicas + Non-root · read-only + No API token + Default-deny network + + + + + Browser + NGINX ingress + TLS + + + + + + + + + + + + + Guardrails around the workload + + + + Pod Security + Restricted v1.36 + + + + NetworkPolicy + Ingress only + + + + AppProject + Namespace scoped + + + + Resource controls + Quota · limits · PDB + + + + Observability + Metrics · logs · alerts + + + + + diff --git a/apps/portfolio/site/automation.html b/apps/portfolio/site/automation.html new file mode 100644 index 0000000..5d58d1a --- /dev/null +++ b/apps/portfolio/site/automation.html @@ -0,0 +1,27 @@ + + + + + + + Infrastructure Automation Case Study | Jay Phillips + + + + +
+
Case study 03 · Repeatable operations

Infrastructure automation.

Turning repetitive administration and hard-won troubleshooting knowledge into scripts, declarative configuration, version-controlled workflows, and reusable deployment patterns.

+
+
+

PowerShell for enterprise administration

PowerShell is the primary automation language for Windows and Active Directory work.

  • Query and export computer and user data from Active Directory.
  • Normalize input files and enrich records with logon names, email, title, and department.
  • Automate group membership, local-account removal, firewall configuration, domain operations, and server inventory.
  • Install prerequisites for System Center products and validate server readiness.
  • Collect reboot history, health information, and deployment results from remote systems.
+

GitOps as operational automation

The Kubernetes environment treats Git as the desired state. Argo CD reconciles applications, reports drift, retries failures, prunes removed resources, and provides a visible deployment history.

  • App-of-apps repository structure.
  • Kustomize-rendered application manifests.
  • Automated image digest updates for selected workloads.
  • Sealed Secrets for encrypted secret workflows.
  • Validation, commit, push, sync, rollout, and smoke tests packaged into complete Bash scripts.
+

Infrastructure as code

Terraform, Ansible, and Packer are used in the home lab to explore repeatable virtual-machine provisioning, configuration, and image creation. The objective is to move from manually assembled systems toward reproducible environments with clear inputs and versioned changes.

+

Design principles

  • Safe defaults: scripts stop on errors, validate prerequisites, and avoid overwriting unknown state.
  • Idempotence: repeated execution should converge or exit cleanly.
  • Complete deliverables: full scripts and configuration files reduce copy-and-paste mistakes.
  • Evidence: every automation ends with verification output rather than assuming success.
  • Rollback: Git history and declarative state make changes reviewable and reversible.
+
+ +
+

See how the platform is observed.

Continue with metrics, logs, uptime, and alert delivery.

Observability case study
+
+ + + diff --git a/apps/portfolio/site/favicon.svg b/apps/portfolio/site/favicon.svg new file mode 100644 index 0000000..26ba778 --- /dev/null +++ b/apps/portfolio/site/favicon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + JP + diff --git a/apps/portfolio/site/index.html b/apps/portfolio/site/index.html index 15f1a89..ddd5bc8 100644 --- a/apps/portfolio/site/index.html +++ b/apps/portfolio/site/index.html @@ -3,596 +3,270 @@ - - Jay Phillips | Infrastructure Portfolio - + + + + + Jay Phillips | Infrastructure Engineer -
-