From 7681c34bc1c0ae68638ba7aafd32121bf2f72f8a Mon Sep 17 00:00:00 2001 From: Daniel LaForce Date: Sun, 27 Apr 2025 16:02:11 -0600 Subject: [PATCH] feat: Integrate static argobox pages and update theme --- package-lock.json | 10 + package.json | 1 + src/components/Header.astro | 1 + src/components/MiniKnowledgeGraph.astro | 364 ++--- src/pages/ansible-docs.html | 1075 ++++++++++++++ src/pages/ansible-help.html | 615 ++++++++ src/pages/ansible-sandbox.html | 1696 ++++++++++++++++++++++ src/pages/ansible/docs.astro | 627 ++++++++ src/pages/ansible/help.astro | 323 ++++ src/pages/ansible/sandbox.astro | 625 ++++++++ src/pages/api/contact.ts | 98 ++ src/pages/dashboard.astro | 448 ++++++ src/pages/dashboard.html | 0 src/pages/homelab.astro | 838 +++++++++++ src/pages/homelab.html | 1067 ++++++++++++++ src/pages/index.astro | 1299 ++++++----------- src/pages/projects.astro | 620 ++++++++ src/pages/projects/github.astro | 192 +++ src/pages/projects/obsidian.astro | 237 +++ src/pages/projects/services.astro | 292 ++++ src/pages/projects/tech-stack.astro | 492 +++++++ src/pages/resources.astro | 441 ++++++ src/pages/resources/config-files.astro | 393 +++++ src/pages/resources/docker-compose.astro | 462 ++++++ src/pages/resources/iac.astro | 424 ++++++ src/pages/resources/kubernetes.astro | 604 ++++++++ src/pages/resources/tutorials.astro | 538 +++++++ src/pages/tech-stack.astro | 688 +++++++++ src/styles/card-animations.css | 224 +++ src/styles/theme.css | 428 ++++-- 30 files changed, 13974 insertions(+), 1148 deletions(-) create mode 100644 src/pages/ansible-docs.html create mode 100644 src/pages/ansible-help.html create mode 100644 src/pages/ansible-sandbox.html create mode 100644 src/pages/ansible/docs.astro create mode 100644 src/pages/ansible/help.astro create mode 100644 src/pages/ansible/sandbox.astro create mode 100644 src/pages/api/contact.ts create mode 100644 src/pages/dashboard.astro create mode 100644 src/pages/dashboard.html create mode 100644 src/pages/homelab.astro create mode 100644 src/pages/homelab.html create mode 100644 src/pages/projects.astro create mode 100644 src/pages/projects/github.astro create mode 100644 src/pages/projects/obsidian.astro create mode 100644 src/pages/projects/services.astro create mode 100644 src/pages/projects/tech-stack.astro create mode 100644 src/pages/resources.astro create mode 100644 src/pages/resources/config-files.astro create mode 100644 src/pages/resources/docker-compose.astro create mode 100644 src/pages/resources/iac.astro create mode 100644 src/pages/resources/kubernetes.astro create mode 100644 src/pages/resources/tutorials.astro create mode 100644 src/pages/tech-stack.astro create mode 100644 src/styles/card-animations.css diff --git a/package-lock.json b/package-lock.json index 6732594..6b20479 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@astrojs/sitemap": "latest", "@astrojs/tailwind": "latest", "astro": "latest", + "nodemailer": "^6.10.1", "tailwindcss": "^3.0.24" }, "devDependencies": { @@ -5167,6 +5168,15 @@ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "license": "MIT" }, + "node_modules/nodemailer": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz", + "integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", diff --git a/package.json b/package.json index a6092b5..768a199 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@astrojs/sitemap": "latest", "@astrojs/tailwind": "latest", "astro": "latest", + "nodemailer": "^6.10.1", "tailwindcss": "^3.0.24" }, "devDependencies": { diff --git a/src/components/Header.astro b/src/components/Header.astro index 44539f9..41793dc 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -7,6 +7,7 @@ const navItems = [ { name: 'Home', url: '/' }, { name: 'Blog', url: '/blog' }, { name: 'Projects', url: '/projects' }, + { name: 'Tech Stack', url: '/tech-stack' }, { name: 'Home Lab', url: 'https://argobox.com' }, { name: 'Resources', url: '/resources' }, { name: 'About', url: 'https://laforceit.com' }, diff --git a/src/components/MiniKnowledgeGraph.astro b/src/components/MiniKnowledgeGraph.astro index bc49e1f..1165c52 100644 --- a/src/components/MiniKnowledgeGraph.astro +++ b/src/components/MiniKnowledgeGraph.astro @@ -16,115 +16,128 @@ export interface GraphEdge { } interface Props { - currentPost: any; + currentPost?: any; // Made optional relatedPosts?: any[]; + graphData?: { nodes: GraphNode[], edges: GraphEdge[] }; // New optional prop for pre-defined graph data + height?: string; // Optional height prop for customizing the graph height } -const { currentPost, relatedPosts = [] } = Astro.props; +const { currentPost, relatedPosts = [], graphData: initialGraphData, height = "200px" } = Astro.props; // Generate unique ID for the graph container const graphId = `mini-cy-${Math.random().toString(36).substring(2, 9)}`; -// Ensure currentPost has necessary properties -const safeCurrentPost = { - id: currentPost.slug || 'current-post', - title: currentPost.data?.title || 'Current Post', - tags: currentPost.data?.tags || [], - category: currentPost.data?.category || 'Uncategorized', -}; - // Prepare graph data -const nodes: GraphNode[] = []; -const edges: GraphEdge[] = []; +let nodes: GraphNode[] = []; +let edges: GraphEdge[] = []; const addedTagIds = new Set(); const addedPostIds = new Set(); -// Add current post node -nodes.push({ - id: safeCurrentPost.id, - label: safeCurrentPost.title, - type: 'post', - url: `/posts/${safeCurrentPost.id}/` -}); -addedPostIds.add(safeCurrentPost.id); +// Check if we have pre-defined graph data +if (initialGraphData && initialGraphData.nodes && initialGraphData.edges) { + // Use the provided graph data + nodes = initialGraphData.nodes; + edges = initialGraphData.edges; +} else if (currentPost) { + // Generate graph data from currentPost and relatedPosts + // Ensure currentPost has necessary properties + const safeCurrentPost = { + id: currentPost.slug || 'current-post', + title: currentPost.data?.title || 'Current Post', + tags: currentPost.data?.tags || [], + category: currentPost.data?.category || 'Uncategorized', + }; -// Add tags from current post -safeCurrentPost.tags.forEach((tag: string) => { - const tagId = `tag-${tag}`; - - // Only add if not already added - if (!addedTagIds.has(tagId)) { - nodes.push({ - id: tagId, - label: tag, - type: 'tag', - url: `/tag/${tag}/` - }); - addedTagIds.add(tagId); - } - - // Add edge from current post to tag - edges.push({ - source: safeCurrentPost.id, - target: tagId, - type: 'post-tag' + // Add current post node + nodes.push({ + id: safeCurrentPost.id, + label: safeCurrentPost.title, + type: 'post', + url: `/posts/${safeCurrentPost.id}/` }); -}); + addedPostIds.add(safeCurrentPost.id); -// Add related posts and their connections -if (relatedPosts && relatedPosts.length > 0) { - relatedPosts.forEach(post => { - if (!post) return; + // Add tags from current post + safeCurrentPost.tags.forEach((tag: string) => { + const tagId = `tag-${tag}`; - const postId = post.slug || `post-${Math.random().toString(36).substring(2, 9)}`; - - // Skip if already added or is the current post - if (addedPostIds.has(postId) || postId === safeCurrentPost.id) { - return; + // Only add if not already added + if (!addedTagIds.has(tagId)) { + nodes.push({ + id: tagId, + label: tag, + type: 'tag', + url: `/tag/${tag}/` + }); + addedTagIds.add(tagId); } - // Add related post node - nodes.push({ - id: postId, - label: post.data?.title || 'Related Post', - type: 'post', - url: `/posts/${postId}/` - }); - addedPostIds.add(postId); - - // Add edge from current post to related post + // Add edge from current post to tag edges.push({ source: safeCurrentPost.id, - target: postId, - type: 'post-post' - }); - - // Add shared tags and their connections - const postTags = post.data?.tags || []; - postTags.forEach((tag: string) => { - // Only add connections for tags that the current post also has - if (safeCurrentPost.tags.includes(tag)) { - const tagId = `tag-${tag}`; - - // Add edge from related post to shared tag - edges.push({ - source: postId, - target: tagId, - type: 'post-tag' - }); - } + target: tagId, + type: 'post-tag' }); }); + + // Add related posts and their connections + if (relatedPosts && relatedPosts.length > 0) { + relatedPosts.forEach(post => { + if (!post) return; + + const postId = post.slug || `post-${Math.random().toString(36).substring(2, 9)}`; + + // Skip if already added or is the current post + if (addedPostIds.has(postId) || postId === safeCurrentPost.id) { + return; + } + + // Add related post node + nodes.push({ + id: postId, + label: post.data?.title || 'Related Post', + type: 'post', + url: `/posts/${postId}/` + }); + addedPostIds.add(postId); + + // Add edge from current post to related post + edges.push({ + source: safeCurrentPost.id, + target: postId, + type: 'post-post' + }); + + // Add shared tags and their connections + const postTags = post.data?.tags || []; + postTags.forEach((tag: string) => { + // Only add connections for tags that the current post also has + if (safeCurrentPost.tags.includes(tag)) { + const tagId = `tag-${tag}`; + + // Add edge from related post to shared tag + edges.push({ + source: postId, + target: tagId, + type: 'post-tag' + }); + } + }); + }); + } } -// Generate graph data +// Generate final graph data const graphData = { nodes, edges }; + +// Determine if we have a valid central node (first node) +const hasCentralNode = nodes.length > 0; --- @@ -142,7 +155,7 @@ const graphData = { nodes, edges }; .mini-knowledge-graph { position: relative; width: 100%; - height: 200px; + height: auto; /* Height will be set by the inline style */ } .mini-cy { @@ -155,7 +168,7 @@ const graphData = { nodes, edges }; } - + + + + + + \ No newline at end of file diff --git a/src/pages/ansible-help.html b/src/pages/ansible-help.html new file mode 100644 index 0000000..a3f24ae --- /dev/null +++ b/src/pages/ansible-help.html @@ -0,0 +1,615 @@ + + + + + + Ansible Sandbox Help | Argobox + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Back to Ansible Sandbox + +

Ansible Sandbox Help Guide

+

+ Learn how to use and get the most out of the Ansible Sandbox environment +

+
+ +
+

Getting Started

+ +
+
1
+
Select a Playbook
+
+

The sandbox offers various Ansible playbooks showcasing different infrastructure automation scenarios. Choose one from the left panel based on your interests.

+

Each playbook comes with a description and information about its complexity level and typical run time.

+
+
+ +
+
2
+
Explore the Playbook Code
+
+

View the Ansible YAML code to understand how the automation works. The code is syntax-highlighted for readability.

+

Hover over different sections to see what each part of the playbook does.

+
+
+ +
+
3
+
Configure Parameters
+
+

Switch to the "Configuration" tab to customize various parameters for your deployment. These might include:

+
    +
  • Domain names
  • +
  • Directory paths
  • +
  • Feature toggles
  • +
  • VM template selection
  • +
  • Resource allocation
  • +
+
+
+ +
+
4
+
Deploy the Environment
+
+

Click the "Deploy" button to launch the automation process. The system will:

+
    +
  1. Create necessary virtual machines
  2. +
  3. Run the selected Ansible playbook
  4. +
  5. Configure all services
  6. +
  7. Provide access to the deployed environment
  8. +
+
+
+ +
+
5
+
Monitor Progress
+
+

Watch the deployment process in real-time on the "Output" tab, which shows the Ansible execution log.

+

Once deployment completes, you'll see a success message with details on how to access the deployed environment.

+
+
+ +
+
6
+
Explore the Environment
+
+

After deployment, you can:

+
    +
  • View the VM status and details in the "VM Status" tab
  • +
  • Access deployed applications via provided URLs
  • +
  • See resource utilization metrics
  • +
  • Monitor the environment's remaining active time
  • +
+
+
+ +
+
+ + Pro Tip +
+

+ Sandbox environments automatically shut down after 30 minutes to conserve resources. You'll see a countdown timer showing the remaining time. Make sure to complete your exploration before time runs out! +

+
+
+ +
+

Frequently Asked Questions

+ +
+
What is an Ansible playbook?
+
+ An Ansible playbook is a YAML file that describes a set of tasks to be executed on remote servers. Playbooks define the desired state of systems and can configure applications, deploy software, and orchestrate advanced IT workflows. +
+
+ +
+
Is the sandbox environment isolated?
+
+ Yes, each sandbox environment is completely isolated. Your deployments and configurations won't affect other users or any production systems. This provides a safe space to experiment with infrastructure automation. +
+
+ +
+
Can I save or download the playbooks?
+
+ Yes, you can copy the playbook code to use in your own environments. Each code segment can be selected and copied to your clipboard. For a more organized approach, visit the Documentation page for downloadable versions of all playbooks. +
+
+ +
+
What happens if I need more time with an environment?
+
+ Currently, all sandbox environments are limited to 30 minutes. If you need more time, you can always redeploy the environment after it expires, which will give you a fresh 30-minute window to continue your exploration. +
+
+ +
+
Can I modify the playbooks?
+
+ The playbook code displayed is read-only to ensure consistent and reliable deployments. However, you can customize many aspects of the deployment through the Configuration tab, which allows you to adjust key parameters without modifying the underlying code. +
+
+ +
+
What if I encounter an error during deployment?
+
+ If an error occurs during deployment, the Output tab will display the specific error message from Ansible. You can use the "Reset" button to clear the environment and try again, potentially with different configuration options. +
+
+
+ +
+

Key Terms

+ +

+ Playbook - A YAML file defining a series of Ansible tasks and configurations. +

+ +

+ Task - An individual action Ansible executes on a managed host, such as installing a package or creating a file. +

+ +

+ Role - A reusable, self-contained unit of tasks, variables, files, templates, and modules that can be shared across playbooks. +

+ +

+ Inventory - A list of hosts that Ansible will manage, grouped logically for targeted execution. +

+ +

+ Handler - A special type of task that only runs when notified by another task that made a change. +

+ +

+ Variable - A value that can be set and referenced in playbooks, making them more flexible and reusable. +

+ +

+ Template - A text file that uses variables to create dynamic configuration files. +

+
+ + +
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/src/pages/ansible-sandbox.html b/src/pages/ansible-sandbox.html new file mode 100644 index 0000000..0f7acef --- /dev/null +++ b/src/pages/ansible-sandbox.html @@ -0,0 +1,1696 @@ + + + + + + ArgoBox | Ansible Sandbox + + + + + + + +
+
+
+ +
+
+
+ + +
+
+
+ +
+ + +
+ +
+ Simulation Mode + + Active +
+ + +
+
+ +
+
+

Ansible Sandbox is Currently Offline

+

The Ansible Sandbox environment is currently in simulation mode. You can explore the interface, but actual deployments are not available at this time. We're working to bring the full functionality online soon.

+
+
+ +
+
+

Template Deployment

+
+ + +
+ + +
+

Select a Template to Deploy

+

Choose from our collection of interactive visualizations to deploy with Ansible automation.

+ +
+ +
+
+ +
+
+

Fireworks

+
Interactive fireworks animation with click-to-launch effects
+
+ Popular + Basic +
+
+
+ + +
+
+ +
+
+

Matrix Rain

+
Digital rain effect inspired by The Matrix movie
+
+ Intermediate +
+
+
+ + +
+
+ +
+
+

Starfield

+
3D space journey through a field of stars
+
+ Basic +
+
+
+ + +
+
+ +
+
+

Particles

+
Interactive particle system that responds to mouse movement
+
+ Intermediate +
+
+
+ + +
+
+ +
+
+

3D Globe

+
Interactive 3D Earth globe with custom markers
+
+ New + Advanced +
+
+
+
+ +
+ + +
+
+ + + + + + + + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/src/pages/ansible/docs.astro b/src/pages/ansible/docs.astro new file mode 100644 index 0000000..ecc70e3 --- /dev/null +++ b/src/pages/ansible/docs.astro @@ -0,0 +1,627 @@ +--- +// src/pages/ansible/docs.astro - Converted from static ansible-docs.html +import BaseLayout from '../../layouts/BaseLayout.astro'; +import Header from '../../components/Header.astro'; +import Footer from '../../components/Footer.astro'; + +const title = "Ansible Sandbox Documentation | Argobox"; +const description = "Comprehensive documentation for the Ansible Sandbox playbooks. Learn about infrastructure automation, deployment patterns, and best practices."; + +// Define sidebar structure (can be generated dynamically if needed) +const sidebarNav = [ + { + title: "Getting Started", + links: [ + { href: "#introduction", text: "Introduction" }, + { href: "#sandbox-overview", text: "Sandbox Overview" }, + { href: "#infrastructure", text: "Infrastructure Design" }, + ] + }, + { + title: "Playbooks", + links: [ + { href: "#web-server", text: "Web Server Deployment" }, + { href: "#docker-compose", text: "Docker Compose Stack" }, + { href: "#k3s-cluster", text: "K3s Kubernetes Cluster" }, + { href: "#lamp-stack", text: "LAMP Stack" }, + { href: "#security-hardening", text: "Security Hardening" }, + ] + }, + { + title: "Advanced Topics", + links: [ + { href: "#custom-roles", text: "Custom Roles" }, + { href: "#variables-inventory", text: "Variables & Inventory" }, + { href: "#best-practices", text: "Best Practices" }, + ] + }, + { + title: "Reference", + links: [ + { href: "#cli-commands", text: "CLI Commands" }, + { href: "#troubleshooting", text: "Troubleshooting" }, + ] + } +]; +--- + + + {/* Add Font Awesome if not loaded globally */} + {/* */} +
+ +
+ + +
+
+

Ansible Sandbox Documentation

+

Explore the playbooks, understand the infrastructure, and learn best practices for using the interactive Ansible Sandbox.

+
+ + +
+

Introduction

+

+ Welcome to the documentation for the ArgoBox Ansible Sandbox. This interactive environment allows you to safely experiment with Ansible playbooks designed to manage various aspects of a modern infrastructure setup, including web servers, containerized applications, and Kubernetes clusters. +

+

+ This documentation provides details on the available playbooks, the underlying infrastructure design of the sandbox environment, and best practices for writing and testing your own automation scripts. +

+
+

Purpose

+

The primary goal of the sandbox is to provide a hands-on learning experience for Ansible in a pre-configured, safe environment that mirrors real-world scenarios.

+
+
+ + +
+

Sandbox Overview

+

+ The Ansible Sandbox provides you with temporary access to a set of virtual machines (VMs) where you can execute pre-defined Ansible playbooks or even upload and run your own. The environment is reset periodically to ensure a clean state for each session. +

+

Key Features

+
    +
  • Isolated environment with multiple target VMs.
  • +
  • Pre-loaded collection of common Ansible roles and playbooks.
  • +
  • Ability to select and run specific playbooks via a web interface.
  • +
  • Real-time output streaming of playbook execution.
  • +
  • Network access between sandbox VMs for testing multi-tier applications.
  • +
  • Environment reset functionality.
  • +
+ {/* Updated Link */} + Launch Ansible Sandbox + +
+ + +
+

Infrastructure Design

+

+ The sandbox environment consists of several virtual machines managed by the main ArgoBox infrastructure, typically running on Proxmox VE. These VMs are provisioned specifically for sandbox use and are isolated from the core production services. +

+

Components

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ComponentDescriptionOSPurpose
Control NodeThe VM where Ansible commands are executed from.Debian 12Runs Ansible engine, hosts playbooks.
Web Server NodeTarget VM for web server playbooks (Nginx/Apache).Ubuntu 22.04Simulates a typical web server.
Database NodeTarget VM for database playbooks (PostgreSQL/MySQL).Debian 12Simulates a database server.
Docker NodeTarget VM with Docker installed for container playbooks.Ubuntu 22.04Runs Docker containers via Compose.
+
+

Networking

+

All sandbox VMs are placed on a dedicated, isolated VLAN with controlled access to simulate a realistic network environment.

+
+
+ + +
+

Available Playbooks

+

The following playbooks are available for execution within the sandbox environment. Each playbook demonstrates different Ansible concepts and common infrastructure tasks.

+ + {/* Web Server Playbook */} +
+

Web Server Deployment (Nginx)

+

Installs and configures the Nginx web server on the 'Web Server Node'. Includes setting up a basic virtual host and ensuring the service is running.

+
+
---
+- name: Deploy Nginx Web Server
+  hosts: web_server_node # Corresponds to inventory group
+  become: yes # Execute tasks with sudo
+  tasks:
+    - name: Update apt cache
+      ansible.builtin.apt:
+        update_cache: yes
+      tags: [install]
+
+    - name: Install Nginx
+      ansible.builtin.apt:
+        name: nginx
+        state: present
+      tags: [install]
+
+    - name: Ensure Nginx service is started and enabled
+      ansible.builtin.service:
+        name: nginx
+        state: started
+        enabled: yes
+      tags: [configure]
+
+    - name: Deploy basic index page (template example)
+      ansible.builtin.template:
+        src: templates/index.html.j2 # Example template path
+        dest: /var/www/html/index.nginx-debian.html # Default Nginx path
+        owner: root
+        group: root
+        mode: '0644'
+      tags: [configure]
+
+ + {/* Docker Compose Playbook */} +
+

Docker Compose Stack (Example: Portainer)

+

Deploys a simple Docker Compose application (e.g., Portainer) on the 'Docker Node'. Requires Docker and Docker Compose to be pre-installed on the target.

+
+
---
+- name: Deploy Docker Compose Application
+  hosts: docker_node
+  become: yes
+  vars:
+    app_name: portainer
+    app_dir: "/opt/{{ app_name }}"
+    compose_file_url: "https://downloads.portainer.io/ce2-19/portainer-agent-stack.yml" # Example URL
+  tasks:
+    - name: Ensure application directory exists
+      ansible.builtin.file:
+        path: "{{ app_dir }}"
+        state: directory
+        mode: '0755'
+
+    - name: Download Docker Compose file
+      ansible.builtin.get_url:
+        url: "{{ compose_file_url }}"
+        dest: "{{ app_dir }}/docker-compose.yml"
+        mode: '0644'
+      register: compose_download
+
+    - name: Deploy Docker Compose stack
+      community.docker.docker_compose:
+        project_src: "{{ app_dir }}"
+        state: present # Ensures stack is up
+      when: compose_download.changed # Only run if file was downloaded/updated
+
+
+
+ + {/* K3s Playbook */} +
+

K3s Kubernetes Cluster (Basic Setup)

+

Installs a single-node K3s cluster on the 'Control Node'. Note: This is a simplified setup for demonstration.

+
+
---
+- name: Install K3s Single Node Cluster
+  hosts: control_node # Install on the control node itself for demo
+  become: yes
+  tasks:
+    - name: Download K3s installation script
+      ansible.builtin.get_url:
+        url: https://get.k3s.io
+        dest: /tmp/k3s-install.sh
+        mode: '0755'
+
+    - name: Execute K3s installation script
+      ansible.builtin.command:
+        cmd: /tmp/k3s-install.sh
+        creates: /usr/local/bin/k3s # Avoid re-running if k3s exists
+      register: k3s_install_result
+      changed_when: k3s_install_result.rc == 0
+
+    - name: Ensure K3s service is started
+      ansible.builtin.service:
+        name: k3s
+        state: started
+        enabled: yes
+
+    - name: Wait for Kubeconfig to be available
+      ansible.builtin.wait_for:
+        path: /etc/rancher/k3s/k3s.yaml
+        timeout: 60
+
+    - name: Read Kubeconfig file
+      ansible.builtin.slurp:
+        src: /etc/rancher/k3s/k3s.yaml
+      register: k3s_kubeconfig
+
+    - name: Display Kubeconfig hint (for manual use)
+      ansible.builtin.debug:
+        msg: "K3s installed. Use 'sudo k3s kubectl get nodes' or copy Kubeconfig."
+
+
+
+

Simplified Setup

+

This playbook installs a basic single-node K3s cluster. Production setups require more complex configuration, multiple nodes, and security considerations.

+
+
+ + {/* LAMP Stack Playbook */} +
+

LAMP Stack Installation

+

Installs Apache, MySQL (MariaDB), and PHP on the 'Web Server Node'.

+ {/* Add LAMP playbook code example here */} +

Code example for LAMP stack coming soon...

+
+ + {/* Security Hardening Playbook */} +
+

Basic Security Hardening

+

Applies basic security measures like installing fail2ban and configuring UFW firewall rules on a target node.

+ {/* Add Security playbook code example here */} +

Code example for security hardening coming soon...

+
+
+ + {/* Advanced Topics Section */} +
+

Advanced Topics

+ +
+

Using Custom Roles

+

Learn how to structure your automation using Ansible Roles for better reusability and organization. Examples of common role structures will be provided.

+

Details on custom roles coming soon...

+
+ +
+

Variables and Inventory Management

+

Understand how to manage variables for different environments (e.g., development, production) and how to define your infrastructure using Ansible inventory files (static and dynamic).

+

Details on variables and inventory coming soon...

+
+ +
+

Ansible Best Practices

+

Explore recommended practices for writing effective, maintainable, and idempotent Ansible playbooks, including task naming, using handlers, and managing secrets.

+

Best practices details coming soon...

+
+
+ + +
+

Reference

+ +
+

Common CLI Commands

+

A quick reference for frequently used Ansible CLI commands.

+ + + + + + + + + + + + + + +
CommandDescription
ansible --versionCheck Ansible version.
ansible-inventory --list -i inventory.ymlList inventory hosts and groups.
ansible all -m ping -i inventory.ymlPing all hosts in inventory.
ansible-playbook playbook.yml -i inventory.ymlRun a playbook.
ansible-playbook playbook.yml --checkPerform a dry run of a playbook.
ansible-playbook playbook.yml --limit web_serversRun playbook only on specific hosts/groups.
ansible-vault create secrets.ymlCreate an encrypted vault file.
ansible-playbook playbook.yml --ask-vault-passRun playbook asking for vault password.
+
+ +
+

Troubleshooting Tips

+

Common issues and how to resolve them when working with the sandbox or Ansible in general.

+
    +
  • Connection Errors: Ensure SSH keys are correctly configured and target VMs are reachable. Check firewall rules.
  • +
  • Permission Denied: Use `become: yes` for tasks requiring root privileges. Verify sudo configuration on target nodes.
  • +
  • Module Not Found: Ensure required Ansible collections or Python libraries are installed on the control node.
  • +
  • Idempotency Issues: Review tasks to ensure they only make changes when necessary (e.g., use `creates` argument for command/shell modules).
  • +
  • Variable Undefined: Check variable definitions, scope (host_vars, group_vars), and precedence. Use `-v` or `-vvv` for verbose output.
  • +
+
+
+ + +
+
+ + + +