Restructured Documentation
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 8s

This commit is contained in:
2026-09-05 14:08:43 -06:00
parent c4bd235eba
commit 289769a601
281 changed files with 5403 additions and 3563 deletions
@@ -5,14 +5,14 @@ tags:
- Automation
---
**Purpose**:
## Purpose
Deploying a Rancher RKE2 Cluster-based Ansible AWX Operator server. This can scale to a larger more enterprise environment if needed.
!!! note Prerequisites
!!! note "Prerequisites"
This document assumes you are running **Ubuntu Server 22.04** or later with at least 16GB of memory, 8 CPU cores, and 64GB of storage.
## Deploy Rancher RKE2 Cluster
You will need to deploy a [Rancher RKE2 Cluster](../../../../platforms/containerization/kubernetes/deployment/rancher-rke2.md) on an Ubuntu Server-based virtual machine. After this phase, you can focus on the Ansible AWX-specific deployment. A single ControlPlane node is all you need to set up AWX, additional infrastructure can be added after-the-fact.
You will need to deploy a [Rancher RKE2 Cluster](<../../Containers/Kubernetes/Rancher RKE2.md>) on an Ubuntu Server-based virtual machine. After this phase, you can focus on the Ansible AWX-specific deployment. A single ControlPlane node is all you need to set up AWX, additional infrastructure can be added after-the-fact.
!!! tip "Checkpoint/Snapshot Reminder"
If this is a virtual machine, after deploying the RKE2 cluster and validating it functions, now would be the best time to take a checkpoint / snapshot of the VM before moving forward, in case you need to perform rollbacks of the server(s) if you accidentally misconfigure something during deployment.
@@ -20,7 +20,7 @@ You will need to deploy a [Rancher RKE2 Cluster](../../../../platforms/container
## Server Configuration
The AWX deployment will consist of 3 yaml files that configure the containers for AWX as well as the NGINX ingress networking-side of things. You will need all of them in the same folder for the deployment to be successful. For the purpose of this example, we will put all of them into a folder located at `/awx`.
``` sh
```sh
# Make the deployment folder
mkdir -p /awx
cd /awx
@@ -28,20 +28,23 @@ cd /awx
We need to increase filesystem access limits:
Temporarily Set the Limits Now:
``` sh
```sh
sudo sysctl fs.inotify.max_user_watches=524288
sudo sysctl fs.inotify.max_user_instances=512
```
Permanently Set the Limits for Later:
```jsx title="/etc/sysctl.conf"
```ini title="/etc/sysctl.conf"
# <End of File>
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512
```
Apply the Settings:
``` sh
```sh
sudo sysctl -p
```
@@ -96,32 +99,36 @@ You will need to create these files all in the same directory using the content
```
## Ensure the Kubernetes Cluster is Ready
Check that the status of the cluster is ready by running the following commands, it should appear similar to the [Rancher RKE2 Example](../../../../platforms/containerization/kubernetes/deployment/rancher-rke2.md#install-helm-rancher-certmanager-jetstack-rancher-and-longhorn):
```
Check that the status of the cluster is ready by running the following commands, it should appear similar to the [Rancher RKE2 Example](<../../Containers/Kubernetes/Rancher RKE2.md#install-helm-rancher-certmanager-jetstack-rancher-and-longhorn>):
```sh
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
kubectl get pods --all-namespaces
```
## Ensure the Timezone / Date is Accurate
You want to make sure that the Kubernetes environment and Node itself have accurate time for a number of reasons, least of which, is if you are using Ansible with Kubernetes authentication, if the date/time is inaccurate, things will not work correctly.
``` sh
```sh
sudo timedatectl set-timezone America/Denver
```
## Deploy AWX using Kustomize
Now it is time to tell Kubernetes to read the configuration files using Kustomize (*built-in to newer versions of Kubernetes*) to deploy AWX into the cluster.
Now it is time to tell Kubernetes to read the configuration files using Kustomize (*built-in to newer versions of Kubernetes*) to deploy AWX into the cluster.
!!! warning "Be Patient"
The AWX deployment process can take a while. Use the commands in the [Troubleshooting](./awx-operator.md#troubleshooting) section if you want to track the progress after running the commands below.
The AWX deployment process can take a while. Use the commands in the [Troubleshooting](<AWX Operator.md#troubleshooting>) section if you want to track the progress after running the commands below.
If you get an error that looks like the below, re-run the `kubectl apply -k .` command a second time after waiting about 10 seconds. The second time the error should be gone.
``` sh
```sh
error: resource mapping not found for name: "awx" namespace: "awx" from ".": no matches for kind "AWX" in version "awx.ansible.com/v1beta1"
ensure CRDs are installed first
```
To check on the progress of the deployment, you can run the following command: `kubectl get pods -n awx`
You will know that AWX is ready to be accessed in the next step if the output looks like below:
```
```text
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-7b9ccf9d4d-cnwhc 2/2 Running 2 (3m41s ago) 9m41s
awx-postgres-13-0 1/1 Running 0 6m12s
@@ -129,18 +136,18 @@ Now it is time to tell Kubernetes to read the configuration files using Kustomiz
awx-web-6dbd7df9f7-kn8k2 3/3 Running 0 93s
```
``` sh
```sh
cd /awx
kubectl apply -k .
```
!!! warning "Be Patient - Wait 20 Minutes"
The process may take a while to spin up AWX, postgresql, redis, and other workloads necessary for AWX to function. Depending on the speed of the server, it may take between 5 and 20 minutes for AWX to be ready to connect to. You can watch the progress via the CLI commands listed above, or directly on Rancher's WebUI at https://rancher.bunny-lab.io.
The process may take a while to spin up AWX, postgresql, redis, and other workloads necessary for AWX to function. Depending on the speed of the server, it may take between 5 and 20 minutes for AWX to be ready to connect to. You can watch the progress via the CLI commands listed above, or directly on Rancher's WebUI at https://rancher.bunny-lab.io.
## Access the AWX WebUI behind Ingress Controller
After you have deployed AWX into the cluster, it will not be immediately accessible to the host's network (such as your personal computer) unless you set up a DNS record pointing to it. In the example above, you would have an `A` or `CNAME` DNS record pointing to the internal IP address of the Rancher RKE2 Cluster host.
After you have deployed AWX into the cluster, it will not be immediately accessible to the host's network (such as your personal computer) unless you set up a DNS record pointing to it. In the example above, you would have an `A` or `CNAME` DNS record pointing to the internal IP address of the Rancher RKE2 Cluster host.
The RKE2 Cluster will translate `awx.bunny-lab.io` to the AWX web-service container(s) automatically due to having an internal Reverse Proxy within the Kubernetes Cluster. SSL certificates generated within Kubernetes/Rancher RKE2 are not covered in this documentation, but suffice to say, the AWX server can be configured on behind another reverse proxy such as Traefik or via Cert-Manager / JetStack. The process of setting this up goes outside the scope of this document.
The RKE2 Cluster will translate `awx.bunny-lab.io` to the AWX web-service container(s) automatically due to having an internal Reverse Proxy within the Kubernetes Cluster. SSL certificates generated within Kubernetes/Rancher RKE2 are not covered in this documentation, but suffice to say, the AWX server can be configured on behind another reverse proxy such as Traefik or via Cert-Manager / JetStack. The process of setting this up goes outside the scope of this document.
### Traefik Implementation
If you want to put this behind traefik, you will need a slightly unique traefik configuration file, seen below, to effectively transparently passthrough traffic into the RKE2 Cluster's reverse proxy.
@@ -168,16 +175,18 @@ tcp:
If you have gotten this far, you should now be able to access AWX via the WebUI and log in.
- AWX WebUI: https://awx.bunny-lab.io
![Ansible AWX WebUI](../awx.png)
![Ansible AWX WebUI](<AWX.png>)
You may see a prompt about "AWX is currently upgrading. This page will refresh when complete". Be patient, let it finish. When it's done, it will take you to a login page.
AWX will generate its own secure password the first time you set up AWX. Username is `admin`. You can run the following command to retrieve the password:
```
AWX will generate its own secure password the first time you set up AWX. Username is `admin`. You can run the following command to retrieve the password:
```text
kubectl get secret awx-admin-password -n awx -o jsonpath="{.data.password}" | base64 --decode ; echo
```
## Change Admin Password
You will want to change the admin password straight-away. Use the following navigation structure to find where to change the password:
``` mermaid
```mermaid
graph LR
A[AWX Dashboard] --> B[Access]
B --> C[Users]
@@ -190,9 +199,14 @@ You may wish to want to track the deployment process to verify that it is actual
### AWX-Manager Deployment Logs
You may want to track the internal logs of the `awx-manager` container which is responsible for the majority of the automated deployment of AWX. You can do so by running the command below.
```
```text
kubectl logs -n awx awx-operator-controller-manager-6c58d59d97-qj2n2 -c awx-manager
```
!!! note
The `-6c58d59d97-qj2n2` noted at the end of the Kubernetes "Pod" mentioned in the command above is randomized. You will need to change it based on the name shown when running the `kubectl get pods -n awx` command.
## Related Documentation
- [Related AWX Documentation](<../../../reference/Automation/AWX/index.md>) — Find the connected deployments, procedures, and references for this subject.
- [Traefik Deployment](<../../Networking and Access/Reverse Proxies/Traefik.md>) — Prepare the reverse proxy before applying this page's routing configuration.
@@ -5,14 +5,14 @@ tags:
- Automation
---
# Deploy AWX on Minikube Cluster
## Purpose
Minikube Cluster based deployment of Ansible AWX. (Ansible Tower)
!!! note Prerequisites
!!! note "Prerequisites"
This document assumes you are running **Ubuntu Server 20.04** or later.
## Install Minikube Cluster
### Update the Ubuntu Server
```
```sh
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
@@ -20,7 +20,8 @@ sudo apt autoremove -y
### Download and Install Minikube (Ubuntu Server)
Additional Documentation: https://minikube.sigs.k8s.io/docs/start/
```
```sh
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb
sudo dpkg -i minikube_latest_amd64.deb
@@ -30,28 +31,31 @@ sudo apt install docker.io nfs-common iptables nano htop -y
# Configure Docker User
sudo usermod -aG docker nicole
```
:::caution
Be sure to change the `nicole` username in the `sudo usermod -aG docker nicole` command to whatever your local username is.
:::
!!! warning "Warning"
Be sure to change the `nicole` username in the `sudo usermod -aG docker nicole` command to whatever your local username is.
### Fully Logout then sign back in to the server
```
```text
exit
```
### Validate that permissions allow you to run docker commands while non-root
```
```text
docker ps
```
### Initialize Minikube Cluster
Additional Documentation: https://github.com/ansible/awx-operator
```
```text
minikube start --driver=docker
minikube kubectl -- get nodes
minikube kubectl -- get pods -A
```
### Make sure Minikube Cluster Automatically Starts on Boot
```jsx title="/etc/systemd/system/minikube.service"
```ini title="/etc/systemd/system/minikube.service"
[Unit]
Description=Minikube service
After=network.target
@@ -66,14 +70,15 @@ ExecStop=/usr/bin/minikube stop
[Install]
WantedBy=multi-user.target
```
:::caution
Be sure to change the `nicole` username in the `User=nicole` line of the config to whatever your local username is.
:::
:::info
You can remove the `--addons=ingress` if you plan on running AWX behind an existing reverse proxy using a "**NodePort**" connection.
:::
!!! warning "Warning"
Be sure to change the `nicole` username in the `User=nicole` line of the config to whatever your local username is.
!!! info "Info"
You can remove the `--addons=ingress` if you plan on running AWX behind an existing reverse proxy using a "**NodePort**" connection.
### Restart Service Daemon and Enable/Start Minikube Automatic Startup
```
```sh
sudo systemctl daemon-reload
sudo systemctl enable minikube
sudo systemctl start minikube
@@ -81,17 +86,19 @@ sudo systemctl start minikube
### Make command alias for `kubectl`
Be sure to add the following to the bottom of your existing profile file noted below.
```jsx title="~/.bashrc"
```sh title="~/.bashrc"
...
alias kubectl="minikube kubectl --"
```
:::tip
If this is a virtual machine, now would be the best time to take a checkpoint / snapshot of the VM before moving forward, in case you need to perform rollbacks of the server(s) if you accidentally misconfigure something.
:::
## Make AWX Operator Kustomization File:
!!! tip "Tip"
If this is a virtual machine, now would be the best time to take a checkpoint / snapshot of the VM before moving forward, in case you need to perform rollbacks of the server(s) if you accidentally misconfigure something.
## Make AWX Operator Kustomization File
Find the latest tag version here: https://github.com/ansible/awx-operator/releases
```jsx title="kustomization.yml"
```yaml title="kustomization.yml"
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
@@ -102,7 +109,8 @@ images:
newTag: 2.4.0
namespace: awx
```
```jsx title="awx.yml"
```yaml title="awx.yml"
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
@@ -123,24 +131,31 @@ spec:
selector:
app.kubernetes.io/name: awx-web
```
### Apply Configuration File
Run from the same directory as the `awx-operator.yaml` file.
```
```text
kubectl apply -k .
```
:::info
If you get any errors, especially ones relating to "CRD"s, wait 30 seconds, and try re-running the `kubectl apply -k .` command to fully apply the `awx.yml` configuration file to bootstrap the awx deployment.
:::
!!! info "Info"
If you get any errors, especially ones relating to "CRD"s, wait 30 seconds, and try re-running the `kubectl apply -k .` command to fully apply the `awx.yml` configuration file to bootstrap the awx deployment.
### View Logs / Track Deployment Progress
```
```text
kubectl logs -n awx awx-operator-controller-manager -c awx-manager
```
### Get AWX WebUI Address
```
```text
minikube service -n awx awx-service --url
```
### Get WebUI Password:
```
### Get WebUI Password
```text
kubectl get secret awx-demo-admin-password -o jsonpath="{.data.password}" | base64 --decode ; echo
```
```
## Related Documentation
- [Related AWX Documentation](<../../../reference/Automation/AWX/index.md>) — Find the connected deployments, procedures, and references for this subject.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 122 KiB

@@ -0,0 +1,46 @@
---
tags:
- Docusaurus
- Documentation
- Docker
---
## Purpose
An optimized site generator in React. Docusaurus helps you to move fast and write content. Build documentation websites, blogs, marketing pages, and more.
```yaml title="docker-compose.yml"
version: "3"
services:
docusaurus:
image: awesometic/docusaurus
container_name: docusaurus
environment:
- TARGET_UID=1000
- TARGET_GID=1000
- AUTO_UPDATE=true
- WEBSITE_NAME=docusaurus
- TEMPLATE=classic
- TZ=America/Denver
restart: always
volumes:
- /srv/containers/docusaurus:/docusaurus
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "80:80"
networks:
docker_network:
ipv4_address: 192.168.5.72
networks:
docker_network:
external: true
```
```yaml title=".env"
Not Applicable
```
## Related Documentation
- [Docker Network Prerequisite](<../../Containers/Docker/Create the Docker Network.md>) — The configuration references the external `docker_network`; prepare it on the intended Docker host.
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,194 @@
---
tags:
- MkDocs
- Material MkDocs
- Documentation
- Docker
---
## Purpose
Documentation that simply works. Write your documentation in Markdown and create a professional static site for your Open Source or commercial project in minutes – searchable, customizable, more than 60 languages, for all devices.
## Deploy Material MKDocs
```yaml title="docker-compose.yml"
version: '3'
services:
mkdocs:
container_name: mkdocs
image: squidfunk/mkdocs-material
restart: always
environment:
- TZ=America/Denver
ports:
- "8000:8000"
volumes:
- /srv/containers/material-mkdocs/docs:/docs
networks:
docker_network:
ipv4_address: 192.168.5.76
networks:
docker_network:
external: true
```
```yaml title=".env"
N/A
```
## Config Example
When you deploy MKDocs, you will need to give it a configuration to tell MKDocs how to structure itself. The configuration below is what I used in my deployment. This file is one folder level higher than the `/docs` folder that holds the documentation of the website.
```yaml title="/srv/containers/material-mkdocs/docs/mkdocs.yml"
# Project information
site_name: Bunny Lab
site_url: https://kb.bunny-lab.io
site_author: Nicole Rappe
site_description: >-
Server, Script, Workflow, and Networking Documentation
repo_url: https://git.bunny-lab.io/bunny-lab/docs
repo_name: bunny-lab/docs
edit_uri: _edit/main/
# Configuration
theme:
name: material
custom_dir: material/overrides
features:
- announce.dismiss
- content.action.edit
# - content.action.view
- content.code.annotate
- content.code.copy
- content.code.select
- content.tabs.link
- content.tooltips
# - header.autohide
# - navigation.expand
# - navigation.footer
- navigation.indexes
- navigation.instant
- navigation.instant.prefetch
- navigation.instant.progress
- navigation.prune
- navigation.path
# - navigation.sections
- navigation.tabs
- navigation.tabs.sticky
- navigation.top
- navigation.tracking
- search.highlight
- search.share
- search.suggest
- toc.follow
# - toc.integrate ## If this is enabled, the TOC will appear on the left navigation menu.
palette:
- media: "(prefers-color-scheme)"
toggle:
icon: material/link
name: Switch to light mode
- media: "(prefers-color-scheme: light)"
scheme: default
primary: deep purple
accent: deep purple
toggle:
icon: material/toggle-switch
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: black
accent: deep purple
toggle:
icon: material/toggle-switch-off
name: Switch to system preference
font:
text: Roboto
code: Roboto Mono
favicon: assets/favicon.png
icon:
logo: logo
# Plugins
plugins:
- search:
separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
- minify:
minify_html: true
- blog
- tags
# Hooks
hooks:
- material/overrides/hooks/shortcodes.py
- material/overrides/hooks/translations.py
# Additional configuration
extra:
status:
new: Recently added
deprecated: Deprecated
extra_css:
- stylesheets/extra.css
# Extensions
markdown_extensions:
- abbr
- admonition
- attr_list
- def_list
- footnotes
- md_in_html
- toc:
permalink: true
toc_depth: 3
- pymdownx.arithmatex:
generic: true
- pymdownx.betterem:
smart_enable: all
- pymdownx.caret
- pymdownx.details
- pymdownx.emoji:
emoji_generator: !!python/name:material.extensions.emoji.to_svg
emoji_index: !!python/name:material.extensions.emoji.twemoji
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.keys
- pymdownx.magiclink:
normalize_issue_symbols: true
repo_url_shorthand: true
user: squidfunk
repo: mkdocs-material
- pymdownx.mark
- pymdownx.smartsymbols
- pymdownx.snippets:
auto_append:
- includes/mkdocs.md
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
combine_header_slug: true
slugify: !!python/object/apply:pymdownx.slugs.slugify
kwds:
case: lower
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.tilde
```
## Cleaning up
When the server is deployed, it will come with a bunch of unnecessary documentation that tells you how to use it. You will want to go into the `/docs` folder, and delete everything except `assets/favicon.png`, `schema.json`, and `/schema`. These files are necessary to allow MKDocs to automatically detect and structure the documentation based on the file folder structure under `/docs`.
## Hotloading Bug Workaround
There is a [known bug](https://github.com/mkdocs/mkdocs/issues/4055) with the most recent version of Material MKDocs (as of writing) that causes it to not hotload changes immediately. This can be fixed by entering a shell in the docker container using `/bin/sh` then running the following command to downgrade the python "click" package: `pip install click==8.2.1`. After running the command, restart the container and hotloaded changes should start working again. You will have to run this command every time you re-deploy Material MKDocs until the issue is resolved officially.
## Related Documentation
- [Docker Network Prerequisite](<../../Containers/Docker/Create the Docker Network.md>) — The configuration references the external `docker_network`; prepare it on the intended Docker host.
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,232 @@
---
tags:
- Zensical
- Documentation
---
## Purpose
After many years of using Material for MKDocs and it being updated with new features and security updates, it finally reached EOL around the end of 2025. The project maintainers started pivoting to a new successor called [Zensical](https://zensical.org/docs/get-started/). This document outlines my particular process for setting up a standalone documentation server within a virtual machine.
!!! info "Assumptions"
It is assumed that you are deploying this server into `Ubuntu Server 24.04.2 LTS (Minimal)`. It is also assumed that you are running every command as a user with superuser privileges (e.g. `root`).
You are generally safe to have a GuestVM with 16GB for the virtual disk, and expand it over-time based on your needs. CPU count and RAM allocation can also be extremely low based on your preferences, since this is simply a static page website at the end of the day.
## Architectural Overview
It is useful to understand the flow of data and how everything inter-connects, so I have provided a sequence diagram that you can follow below:
```mermaid
sequenceDiagram
autonumber
actor Author as Doc Author
participant Gitea as Gitea (Repo + Actions)
participant Runner as Act Runner
participant Zensical as Zensical Server (watch + build)
participant NGINX as NGINX (serves static site)
Author->>Gitea: Push to main
Gitea-->>Runner: Trigger workflow job
Runner->>Zensical: rsync docs → /srv/zensical/docs
Zensical-->>Zensical: Watch detects change
Zensical->>Zensical: Rebuild site → /srv/zensical/site
NGINX-->>NGINX: Serve files from /srv/zensical/site
```
## Setup Python Environment
The first thing we need to do is install the necessary python packages and install the zensical software stack inside of it.
```sh
sudo apt update && sudo apt upgrade -y
sudo apt install -y nano python3 python3.12-venv
mkdir -p /srv/zensical
cd /srv/zensical
python3 -m venv .venv
source .venv/bin/activate
pip install zensical
zensical new .
deactivate
# Remove Placeholder Example Docs
rm -rf /srv/zensical/docs/{*,.*}
```
## Zensical
### Configure Settings
Now we want to set some sensible defaults for Zensical to style it to look as close to Material for MKDocs as possible.
```sh
sudo tee /srv/zensical/zensical.toml > /dev/null <<'EOF'
[project]
site_name = "Bunny Lab"
site_description = "Server, Script, Workflow, and Networking Documentation"
site_author = "Nicole Rappe"
site_url = "https://kb.bunny-lab.io/"
repo_url = "https://git.bunny-lab.io/bunny-lab/docs"
repo_name = "bunny-lab/docs"
edit_uri = "_edit/main/"
[project.theme]
variant = "classic"
language = "en"
features = [
"announce.dismiss",
"content.action.edit",
"content.code.annotate",
"content.code.copy",
"content.code.select",
"content.footnote.tooltips",
"content.tabs.link",
"content.tooltips",
"navigation.indexes",
"navigation.instant",
"navigation.instant.prefetch",
"navigation.instant.progress",
"navigation.path",
"navigation.tabs",
"navigation.tabs.sticky",
"navigation.top",
"navigation.tracking",
"search.highlight",
]
[[project.theme.palette]]
scheme = "default"
toggle.icon = "lucide/sun"
toggle.name = "Switch to dark mode"
[[project.theme.palette]]
scheme = "slate"
toggle.icon = "lucide/moon"
toggle.name = "Switch to light mode"
EOF
```
### Create Watchdog Service
Since NGINX has taken over hosting the webpages, this does not need to be accessible from other servers, only NGINX itself which runs on the same host as Zensical. We only want to use the `zensical serve` command to keep a watchdog on the documentation folder and automatically rebuild the static site content when changes are detected. These changes are then served by NGINX's webserver.
```sh
# Create Service User, Assign Access, and Lockdown Zensical Data
sudo useradd --system --home /srv/zensical --shell /usr/sbin/nologin zensical || true
sudo chown -R zensical:zensical /srv/zensical
sudo find /srv/zensical -type d -exec chmod 2775 {} \;
sudo find /srv/zensical -type f -exec chmod 664 {} \; # This step likes to take a while, sometimes up to a minute.
sudo chmod 755 /srv/zensical/.venv/bin/* # Ensure Python Environment Executables Function
```
```sh
# Make Zensical Binary Executable for Service
sudo chmod +x /srv/zensical/.venv/bin/zensical
# Add Additional User(s) to Folder for Extra Access (Such as Doc Runners)
sudo usermod -aG zensical nicole
# Create Service
sudo tee /etc/systemd/system/zensical-watchdog.service > /dev/null <<'EOF'
[Unit]
Description=Zensical Document Changes Watchdog (zensical serve)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=zensical
Group=zensical
WorkingDirectory=/srv/zensical
# Run the venv binary directly; no activation needed
ExecStart=/srv/zensical/.venv/bin/zensical serve
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
EOF
# Start & Enable Automatic Startup of Service
sudo systemctl daemon-reload
sudo systemctl enable --now zensical-watchdog
```
### Updating
You will obviously want to keep Zensical up-to-date. You can run the following commands to upgrade it. This is taken and simplified from the original [Upgrade Documentation](https://zensical.org/docs/upgrade/) on Zensical's website.
```sh
# Upgrade Zensical
systemctl stop zensical-watchdog
cd /srv/zensical
source .venv/bin/activate
pip install --upgrade --force-reinstall zensical
deactivate
systemctl start zensical-watchdog
```
## NGINX Webserver
We need to deploy NGINX as a webserver, because when using reverse proxies like Traefik, it seems to not get along with Zensical at all. Attempts to resolve this all failed, so putting the statically-built copies of site data that Zensical generates into NGINX's root directory is the second-best solution I came up with. Traefik can be reasonably expected to behave when interacting with NGINX versus Zensical's built-in webserver.
```sh
sudo apt install -y nginx
sudo rm -f /etc/nginx/sites-enabled/default
sudo tee /etc/nginx/sites-available/zensical.conf > /dev/null <<'EOF'
server {
listen 80;
listen [::]:80;
server_name _;
root /srv/zensical/site;
index index.html;
# Primary document handling
location / {
try_files $uri $uri/ /index.html;
}
# Static asset caching (safe for docs)
location ~* \.(css|js|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable";
try_files $uri =404;
}
# Prevent access to source or metadata
location ~* \.(toml|md)$ {
deny all;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/zensical.conf /etc/nginx/sites-enabled/zensical.conf
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl enable nginx
```
## Configure Documentation Delivery
Continue with [Publish Zensical Documentation with a Host Runner](<../../../workflows/Automation/Gitea/Publish Zensical Documentation with a Host Runner.md>) to register the runner and configure repository synchronization. Return here to configure the reverse proxy.
## Traefik Reverse Proxy
It is assumed that you use a [Traefik](<../../Networking and Access/Reverse Proxies/Traefik.md>) reverse proxy and are configured to use [dynamic configuration files](<../../Networking and Access/Reverse Proxies/Traefik.md#dynamic-configuration-files>). Add the file below to expose the Zensical service to the rest of the world.
```yaml title="kb.bunny-lab.io.yml"
http:
routers:
kb:
entryPoints:
- websecure
tls:
certResolver: letsencrypt
service: kb
rule: Host(`kb.bunny-lab.io`)
services:
kb:
loadBalancer:
servers:
- url: http://192.168.3.8:80
passHostHeader: true
```
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
- [Traefik Deployment](<../../Networking and Access/Reverse Proxies/Traefik.md>) — Prepare the reverse proxy before applying this page's routing configuration.
@@ -1,3 +1,9 @@
---
tags:
- Automation
- Configure Pi-Hole PXE Boot
---
## Purpose
This document was written to provide instructions for setting up a FOG Project server behind a Pi-Hole that has DHCP configured on it. Start by connecting to the Pi-Hole's CLI either via SSH or Portainer/Docker Interactive CLI and create the following file:
@@ -20,4 +26,7 @@ dhcp-boot=undionly.kpxe,,192.168.3.9
### Reload Pi-Hole DNS
```sh
pihole reloaddns
```
```
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,2 +1,15 @@
---
tags:
- Automation
- Configure Windows Server PXE Boot
---
## Purpose
This document was written to provide instructions for setting up a FOG Project server behind a Windows Server that has DHCP configured on it.
This document was written to provide instructions for setting up a FOG Project server behind a Windows Server that has DHCP configured on it.
!!! warning "Incomplete Procedure"
This page records the intended DHCP/PXE integration but does not yet contain the configuration steps. It cannot be used as a complete Windows DHCP procedure.
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,3 +1,9 @@
---
tags:
- Automation
- Deploy FOG Project
---
## Purpose
If you want to deploy the FOG Project software in your homelab environment to remotely image devices via PXE boot, follow the instructions below to get through the process.
@@ -42,9 +48,9 @@ If you want to deploy the FOG Project software in your homelab environment to re
set-name: ens18
```
Apply the configuration safely and temporarily with `sudo netplan try` and if connectivity still works, accept the changes permanently by running `sudo netplan apply`. Otherwise, Netplan will roll back the changes automatically.
Apply the configuration safely and temporarily with `sudo netplan try` and if connectivity still works, accept the changes permanently by running `sudo netplan apply`. Otherwise, Netplan will roll back the changes automatically.
### Update & Snapshot the GuestVM
### Update and Snapshot the GuestVM
Before we take a checkpoint/snapshot and install FOG Project, we want to ensure that the GuestVM is fully updated. After the updates are complete, shutdown the GuestVM, take a snapshot, and boot it back up.
```sh
@@ -79,27 +85,27 @@ The steps below will guide you on a high-level through the external DHCP-server
- Are you sure you wish to continue? > `Y`
!!! example "Summary Example"
* Here are the settings FOG will use:
* Base Linux: Debian
* Detected Linux Distribution: Ubuntu
* Interface: ens18
* Server IP Address: 192.168.3.9
* Server Subnet Mask: 255.255.255.0
* Hostname: lab-fog-01
* Installation Type: Normal Server
* Internationalization: No
* Image Storage Location: /images
* Using FOG DHCP: No
* DHCP will NOT be setup but you must setup your
- Here are the settings FOG will use:
- Base Linux: Debian
- Detected Linux Distribution: Ubuntu
- Interface: ens18
- Server IP Address: 192.168.3.9
- Server Subnet Mask: 255.255.255.0
- Hostname: lab-fog-01
- Installation Type: Normal Server
- Internationalization: No
- Image Storage Location: /images
- Using FOG DHCP: No
- DHCP will NOT be setup but you must setup your
| current DHCP server to use FOG for PXE services.
* On a Linux DHCP server you must set: next-server and filename
- On a Linux DHCP server you must set: next-server and filename
* On a Windows DHCP server you must set options 066 and 067
- On a Windows DHCP server you must set options 066 and 067
* Option 066/next-server is the IP of the FOG Server: (e.g. 192.168.3.9)
* Option 067/filename is the bootfile: (e.g. undionly.kkpxe or snponly.efi)
* Send OS Name, OS Version, and FOG Version: No
- Option 066/next-server is the IP of the FOG Server: (e.g. 192.168.3.9)
- Option 067/filename is the bootfile: (e.g. undionly.kkpxe or snponly.efi)
- Send OS Name, OS Version, and FOG Version: No
### Database Schema Update/Install
At this point, you will be prompted to login to the website hosted by FOG Project to setup the database, navigate to the URL provided. (e.g. http://192.168.3.9/fog/management)
@@ -115,186 +121,167 @@ At this point, you will be prompted to login to the website hosted by FOG Projec
http://192.168.3.9/fog/management
Default User Information
- **Username**: fog
- **Password**: password
**Changed configurations**:
The FOG installer changed configuration files and created the
following backup files from your original files:
- /etc/vsftpd.conf <=> /etc/vsftpd.conf.1777937213
- /etc/exports <=> /etc/exports.1777937213
## Disorganized Next Steps (Under Construction)
After DHCP is correctly pointing clients to the FOG server (Options 66/67 or `next-server`/`filename`), the next phase is **PXE boot workflow + host registration and image management**—not user authentication at boot.
Short answer: **No, you do not need to create a PXE login user.** FOG does not use traditional authentication during PXE boot. Instead, it uses a **menu-driven iPXE environment** and **host registration + task assignment** from the web UI.
Short answer: **No, you do not need to create a PXE login user.** FOG does not use traditional authentication during PXE boot. Instead, it uses a **menu-driven iPXE environment** and **host registration + task assignment** from the web UI.
---
## What Actually Happens After DHCP is Set
Once DHCP is configured:
1. Client boots → gets IP + bootfile
2. Loads **iPXE from FOG**
3. Connects to FOG server
4. Displays **FOG PXE menu**
5. From there:
1. Client boots → gets IP + bootfile
2. Loads **iPXE from FOG**
3. Connects to FOG server
4. Displays **FOG PXE menu**
5. From there:
* Register host
* Deploy image
* Run tasks
- Register host
- Deploy image
- Run tasks
---
## Recommended Next Sections for Your Document
You should continue with something like this:
---
### Validate PXE Boot
Before doing anything else, confirm PXE is working end-to-end.
* Boot a test machine on the same network
* Ensure:
- Boot a test machine on the same network
- Ensure:
* It gets an IP from DHCP
* It downloads `undionly.kpxe` (BIOS) or `snponly.efi` (UEFI)
* It reaches the **FOG iPXE menu**
- It gets an IP from DHCP
- It downloads `undionly.kpxe` (BIOS) or `snponly.efi` (UEFI)
- It reaches the **FOG iPXE menu**
Expected result: You see a FOG menu (not a login prompt)
---
### Register a Host in FOG
FOG needs to know about devices before imaging.
#### Option 1: Register via PXE Menu (most common)
From the PXE menu:
* Select: **Perform Full Host Registration and Inventory**
* Enter:
- Select: **Perform Full Host Registration and Inventory**
- Enter:
* Hostname
* Optional description/location
- Hostname
- Optional description/location
This creates a host object in FOG.
#### Option 2: Pre-create in Web UI
- Go to: `FOG Management → Hosts → Create New Host`
- Add:
* Go to: `FOG Management → Hosts → Create New Host`
* Add:
* MAC address
* Hostname
- MAC address
- Hostname
---
### Create and Capture an Image
Before deploying, you need an image stored in FOG.
#### Create Image Definition
- Navigate: `Images → Create New Image`
- Set:
* Navigate: `Images → Create New Image`
* Set:
- Name
- Image Type:
* Name
* Image Type:
* `Single Disk - Resizable` (most common)
* Storage group (default is fine)
- `Single Disk - Resizable` (most common)
- Storage group (default is fine)
---
#### Assign Image to Host
* Go to the host you registered
* Set the **Image** field to your new image
- Go to the host you registered
- Set the **Image** field to your new image
---
#### Capture Image (Upload from a reference machine)
On your “golden image” machine:
1. Boot via PXE
2. Register it (if not already)
3. In Web UI:
1. Boot via PXE
2. Register it (if not already)
3. In Web UI:
* Select host
* Click **Capture**
4. Reboot machine → it uploads disk to FOG
- Select host
- Click **Capture**
4. Reboot machine → it uploads disk to FOG
---
### Deploy Image to a Host
Once an image exists:
1. Assign image to target host
2. Schedule a **Deploy Task**
3. Boot target machine via PXE
1. Assign image to target host
2. Schedule a **Deploy Task**
3. Boot target machine via PXE
No login required — it will automatically start imaging if a task is assigned.
---
## Important Clarification (This Answers Your Question Directly)
> “Do we need to set up a user to login via PXE?”
**No.** FOG uses:
* MAC address identification
* Task-based automation
* Optional menu interaction
- MAC address identification
- Task-based automation
- Optional menu interaction
There is:
* ❌ No PXE login system by default
* ❌ No per-user authentication during boot
* ✅ Central control via the web UI
- ❌ No PXE login system by default
- ❌ No per-user authentication during boot
- ✅ Central control via the web UI
---
## Optional (Advanced Sections You Might Add Later)
If you want to make your doc more complete:
### Secure the Environment
* Change default credentials (`fog/password`)
* Enable HTTPS (you skipped this earlier)
* Restrict PXE boot via VLANs or DHCP policies
- Change default credentials (`fog/password`)
- Enable HTTPS (you skipped this earlier)
- Restrict PXE boot via VLANs or DHCP policies
### UEFI vs BIOS Handling
* BIOS → `undionly.kpxe`
* UEFI → `snponly.efi`
- BIOS → `undionly.kpxe`
- UEFI → `snponly.efi`
### Automating Deployments
* Auto-assign hosts
* Use host groups
* Schedule multicast deployments
- Auto-assign hosts
- Use host groups
- Schedule multicast deployments
### Storage Optimization
* Separate `/images` to a larger disk
* NFS tuning
- Separate `/images` to a larger disk
- NFS tuning
---
## Suggested Next Heading for Your Doc
```md
### Validate PXE Boot and Access FOG Menu
```
@@ -303,4 +290,9 @@ followed by:
```md
### Register Hosts and Prepare Images
```
```
## Related Documentation
- [Pi-hole PXE Configuration](<Configure Pi-Hole PXE Boot.md>) — Use the documented DHCP integration when Pi-hole serves the network.
- [Windows DHCP PXE Scaffold](<Configure Windows Server PXE Boot.md>) — Check the explicitly incomplete alternative before choosing it.
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
+108
View File
@@ -0,0 +1,108 @@
---
tags:
- Gitea
- DevOps
- Docker
---
## Purpose
Gitea is a painless self-hosted all-in-one software development service, it includes Git hosting, code review, team collaboration, package registry and CI/CD. It is similar to GitHub, Bitbucket and GitLab. Gitea was forked from Gogs originally and almost all the code has been changed.
[Detailed SMTP Configuration Reference](https://docs.gitea.com/administration/config-cheat-sheet)
## Docker Configuration
```yaml title="docker-compose.yml"
version: "3"
services:
server:
image: gitea/gitea:latest
container_name: gitea
privileged: true
environment:
- USER_UID=1000
- USER_GID=1000
- TZ=America/Denver
- GITEA__mailer__ENABLED=true
- GITEA__mailer__FROM=${GITEA__mailer__FROM:?GITEA__mailer__FROM not set}
- GITEA__mailer__PROTOCOL=smtp+starttls
- GITEA__mailer__HOST=${GITEA__mailer__HOST:?GITEA__mailer__HOST not set}
- GITEA__mailer__IS_TLS_ENABLED=true
- GITEA__mailer__USER=${GITEA__mailer__USER:-apikey}
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
restart: always
volumes:
- /srv/containers/gitea:/data
# - /etc/timezone:/etc/timezone:ro
# - /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
networks:
docker_network:
ipv4_address: 192.168.5.70
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.gitea.rule=Host(`git.bunny-lab.io`)"
# - "traefik.http.routers.gitea.entrypoints=websecure"
# - "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
# - "traefik.http.services.gitea.loadbalancer.server.port=3000"
depends_on:
- postgres
postgres:
image: postgres:12-alpine
ports:
- 5432:5432
volumes:
- /srv/containers/gitea/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=gitea
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- TZ=America/Denver
restart: always
networks:
docker_network:
ipv4_address: 192.168.5.71
networks:
docker_network:
external: true
```
```yaml title=".env"
GITEA__mailer__FROM=noreply@bunny-lab.io
GITEA__mailer__HOST=mail.bunny-lab.io
GITEA__mailer__PASSWD=SecureSMTPPassword
GITEA__mailer__USER=noreply@bunny-lab.io
POSTGRES_PASSWORD=SomethingSuperSecure
```
## Traefik Reverse Proxy Configuration
If the container does not run on the same host as Traefik, you will need to manually add configuration to Traefik's dynamic config file, outlined below.
```yaml
http:
routers:
git:
entryPoints:
- websecure
tls:
certResolver: letsencrypt
http2:
service: git
rule: Host(`git.bunny-lab.io`)
services:
git:
loadBalancer:
servers:
- url: http://192.168.5.70:3000
passHostHeader: true
```
## Related Documentation
- [Docker Network Prerequisite](<../../Containers/Docker/Create the Docker Network.md>) — The configuration references the external `docker_network`; prepare it on the intended Docker host.
- [Related Gitea Workflows](<../../../reference/Automation/Gitea Configuration Delivery.md>) — Find the connected deployments, procedures, and references for this subject.
- [Traefik Deployment](<../../Networking and Access/Reverse Proxies/Traefik.md>) — Prepare the reverse proxy before applying this page's routing configuration.
@@ -4,13 +4,14 @@ tags:
- Automation
---
**Purpose**: Puppet Bolt can be leveraged in an Ansible-esque manner to connect to and enroll devices such as Windows Servers, Linux Servers, and various workstations. To this end, it could be used to run ad-hoc tasks or enroll devices into a centralized Puppet server. (e.g. `LAB-PUPPET-01.bunny-lab.io`)
## Purpose
Puppet Bolt can be leveraged in an Ansible-esque manner to connect to and enroll devices such as Windows Servers, Linux Servers, and various workstations. To this end, it could be used to run ad-hoc tasks or enroll devices into a centralized Puppet server. (e.g. `LAB-PUPPET-01.bunny-lab.io`)
!!! note "Assumptions"
This deployment assumes you are deploying Puppet bolt onto the same server as Puppet. If you have not already, follow the [Puppet Deployment](./puppet.md) documentation to do so before continuing with the Puppet Bolt deployment.
This deployment assumes you are deploying Puppet bolt onto the same server as Puppet. If you have not already, follow the [Puppet Deployment](<Puppet.md>) documentation to do so before continuing with the Puppet Bolt deployment.
## Initial Preparation
``` sh
```sh
# Install Bolt Repository
sudo rpm -Uvh https://yum.puppet.com/puppet-tools-release-el-9.noarch.rpm
sudo yum install -y puppet-bolt
@@ -32,7 +33,8 @@ bolt project init bunny_lab
## Configuring Inventory
At this point, you will want to create an inventory file that you can use for tracking devices. For now, this will have hard-coded credentials until a cleaner method is figured out.
``` yaml title="/etc/puppetlabs/bolt/inventory.yaml"
```yaml title="/etc/puppetlabs/bolt/inventory.yaml"
# Inventory file for Puppet Bolt
groups:
- name: linux_servers
@@ -78,14 +80,16 @@ groups:
### Validate Bolt Inventory Works
If the inventory file is created correctly, you will see the hosts listed when you run the command below:
``` sh
```sh
cd /etc/puppetlabs/bolt
bolt inventory show
```
??? example "Example Output of `bolt inventory show`"
You should expect to see output similar to the following:
``` sh
```sh
[root@lab-puppet-01 bolt-lab]# bolt inventory show
Targets
lab-auth-01.bunny-lab.io
@@ -118,25 +122,26 @@ If you work with Windows-based devices in a domain environment, you will need to
We need to install the necessary software on the puppet server to allow Kerberos authentication to occur.
=== "Rocky, CentOS, RHEL, Fedora"
``` sh
```sh
sudo yum install krb5-workstation
```
=== "Debian, Ubuntu"
``` sh
```sh
sudo apt-get install krb5-user
```
=== "SUSE"
``` sh
```sh
sudo zypper install krb5-client
```
### Prepare `/etc/krb5.conf` Configuration
We need to configure Kerberos to know how to reach the domain, this is achieved by editing `/etc/krb5.conf` to look similar to the following, with your own domain substituting the example values.
``` ini
```ini
[libdefaults]
default_realm = BUNNY-LAB.IO
dns_lookup_realm = false
@@ -162,14 +167,16 @@ We need to configure Kerberos to know how to reach the domain, this is achieved
### Initialize Kerberos Connection
Now we need to log into the domain using (preferrably) domain administrator credentials, such as the example below. You will be prompted to enter your domain password.
``` sh
```sh
kinit nicole.rappe@BUNNY-LAB.IO
klist
```
??? example "Example Output of `klist`"
You should expect to see output similar to the following. Finding a way to ensure the Kerberos tickets live longer is still under research, as 7 days is not exactly practical for long-term deployments.
``` sh
```sh
[root@lab-puppet-01 bolt-lab]# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: nicole.rappe@BUNNY-LAB.IO
@@ -182,20 +189,21 @@ klist
### Prepare Windows Devices
Windows devices need to be prepared ahead-of-time in order for WinRM functionality to work as-expected. I have prepared a powershell script that you can run on each device that needs remote management functionality. You can port this script based on your needs, and deploy it via whatever methods you have available to you. (e.g. Ansible, Group Policies, existing RMM software, manually via remote desktop, etc).
You can find the [WinRM Enablement Script](../../../../workflows/operations/automation/ansible/enable-winrm-on-windows-devices.md) in the Bunny Lab documentation.
You can find the [WinRM Enablement Script](<../../../workflows/Identity and Certificates/Windows/Enable WinRM over HTTPS.md>) in the Bunny Lab documentation.
## Ad-Hoc Command Examples
At this point, you should finally be ready to connect to Windows and Linux devices and run commands on them ad-hoc. Puppet Bolt Modules and Plans will be discussed further down the road.
??? example "Example Output of `bolt command run whoami -t domain_controllers --no-ssl-verify`"
You should expect to see output similar to the following. This is what you will see when leveraging WinRM via Kerberos on Windows devices.
``` sh
```sh
[root@lab-puppet-01 bolt-lab]# bolt command run whoami -t domain_controllers --no-ssl-verify
CLI arguments ["ssl-verify"] might be overridden by Inventory: /tmp/bolt-lab/inventory.yaml [ID: cli_overrides]
Started on lab-dc-01.bunny-lab.io...
Started on lab-dc-02.bunny-lab.io...
Finished on lab-dc-02.bunny-lab.io:
bunny-lab\nicole.rappe
bunny-lab\nicole.rappe
Finished on lab-dc-01.bunny-lab.io:
bunny-lab\nicole.rappe
Successful on 2 targets: lab-dc-01.bunny-lab.io,lab-dc-02.bunny-lab.io
@@ -204,16 +212,19 @@ At this point, you should finally be ready to connect to Windows and Linux devic
??? example "Example Output of `bolt command run whoami -t linux_servers`"
You should expect to see output similar to the following. This is what you will see when leveraging native SSH on Linux devices.
``` sh
```sh
[root@lab-puppet-01 bolt-lab]# bolt command run whoami -t linux_servers
CLI arguments ["ssl-verify"] might be overridden by Inventory: /tmp/bolt-lab/inventory.yaml [ID: cli_overrides]
Started on lab-auth-01.bunny-lab.io...
Started on lab-auth-02.bunny-lab.io...
Finished on lab-auth-02.bunny-lab.io:
nicole
nicole
Finished on lab-auth-01.bunny-lab.io:
nicole
Successful on 2 targets: lab-auth-01.bunny-lab.io,lab-auth-02.bunny-lab.io
Ran on 2 targets in 0.68 sec
```
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,15 +4,15 @@ tags:
- Automation
---
**Purpose**:
Puppet is another declarative configuration management tool that excels in system configuration and enforcement. Like Ansible, it's designed to maintain the desired state of a system's configuration but uses a client-server (master-agent) architecture by default.
## Purpose
Puppet is another declarative configuration management tool that excels in system configuration and enforcement. Like Ansible, it's designed to maintain the desired state of a system's configuration but uses a client-server (master-agent) architecture by default.
!!! note "Assumptions"
This document assumes you are deploying Puppet server onto Rocky Linux 9.4. Any version of RHEL/CentOS/Alma/Rocky should behave similarily.
## Architectural Overview
### Detailed
``` mermaid
```mermaid
sequenceDiagram
participant Gitea as Gitea Repo (Puppet Environment)
participant r10k as r10k (Environment Deployer)
@@ -33,24 +33,24 @@ sequenceDiagram
Agent->>PuppetMaster: Request to enroll (Agent Check-in)
PuppetMaster->>Agent: Verify SSL Certificate & Authenticate
Agent-->>PuppetMaster: Send facts about system (Facter)
%% PuppetMaster compiles catalog for the agent
PuppetMaster->>PuppetMaster: Compile Catalog
PuppetMaster->>PuppetMaster: Check if 'neofetch' is required in manifest
PuppetMaster-->>Agent: Send compiled catalog with 'neofetch' installation instructions
%% Agent installs neofetch
Agent->>Agent: Check if 'neofetch' is installed
Agent--xNeofetch: 'neofetch' not installed
Agent->>Neofetch: Install 'neofetch'
Neofetch-->>Agent: Installation complete
%% Agent reports back to PuppetMaster
Agent->>PuppetMaster: Report status (catalog applied and neofetch installed)
```
### Simplified
``` mermaid
```mermaid
sequenceDiagram
participant Gitea as Gitea (Puppet Repository)
participant PuppetMaster as Puppet Server
@@ -60,7 +60,7 @@ sequenceDiagram
%% PuppetMaster pulling environment updates
PuppetMaster->>Gitea: Pull environment updates
Gitea-->>PuppetMaster: Send updated code
%% Agent enrollment and catalog request
Agent->>PuppetMaster: Request catalog (Check-in)
PuppetMaster->>Agent: Send compiled catalog (neofetch required)
@@ -68,43 +68,45 @@ sequenceDiagram
%% Agent installs neofetch
Agent->>Neofetch: Install neofetch
Neofetch-->>Agent: Installation complete
%% Agent reports back
Agent->>PuppetMaster: Report catalog applied (neofetch installed)
```
### Breakdown
#### 1. **PuppetMaster Pulls Updates from Gitea**
- PuppetMaster uses `r10k` to fetch the latest environment updates from Gitea. These updates include manifests, hiera data, and modules for the specified Puppet environments.
- PuppetMaster uses `r10k` to fetch the latest environment updates from Gitea. These updates include manifests, hiera data, and modules for the specified Puppet environments.
#### 2. **PuppetMaster Compiles Catalogs and Modules**
- After pulling updates, the PuppetMaster compiles the latest node-specific catalogs based on the manifests and modules. It ensures the configuration is ready for agents to retrieve.
- After pulling updates, the PuppetMaster compiles the latest node-specific catalogs based on the manifests and modules. It ensures the configuration is ready for agents to retrieve.
#### 3. **Agent (fedora.bunny-lab.io) Checks In**
- The Puppet agent on `fedora.bunny-lab.io` checks in with the PuppetMaster for its catalog. This request tells the PuppetMaster to compile the node's desired configuration.
- The Puppet agent on `fedora.bunny-lab.io` checks in with the PuppetMaster for its catalog. This request tells the PuppetMaster to compile the node's desired configuration.
#### 4. **Agent Downloads and Applies the Catalog**
- The agent retrieves its compiled catalog from the PuppetMaster. It compares the current system state with the desired state outlined in the catalog.
- The agent retrieves its compiled catalog from the PuppetMaster. It compares the current system state with the desired state outlined in the catalog.
#### 5. **Agent Installs `neofetch`**
- The agent identifies that `neofetch` is missing and installs it using the system's package manager. The installation follows the directives in the catalog.
- The agent identifies that `neofetch` is missing and installs it using the system's package manager. The installation follows the directives in the catalog.
#### 6. **Agent Reports Success**
- Once changes are applied, the agent sends a report back to the PuppetMaster. The report includes details of the changes made, confirming `neofetch` was installed.
- Once changes are applied, the agent sends a report back to the PuppetMaster. The report includes details of the changes made, confirming `neofetch` was installed.
## Deployment Steps:
## Deployment Steps
You will need to perform a few steps outlined in the [official Puppet documentation](https://www.puppet.com/docs/puppet/7/install_puppet.html) to get a Puppet server operational. A summarized workflow is seen below:
### Install Puppet Repository
**Installation Scope**: Puppet Server / Managed Devices
``` sh
```sh
# Add Puppet Repository / Enable Puppet on YUM
sudo rpm -Uvh https://yum.puppet.com/puppet7-release-el-9.noarch.rpm
```
### Install Puppet Server
**Installation Scope**: Puppet Server
``` sh
```sh
# Install the Puppet Server
sudo yum install -y puppetserver
systemctl enable --now puppetserver
@@ -116,7 +118,8 @@ puppetserver -v
### Install Puppet Agent
**Installation Scope**: Puppet Server / Managed Devices
``` sh
```sh
# Install Puppet Agent (This will already be installed on the Puppet Server)
sudo yum install -y puppet-agent
@@ -138,13 +141,15 @@ puppetserver ca sign --certname fedora.bunny-lab.io
#### Validate Agent Functionality
At this point, you want to ensure that the device being managed by the agent is able to pull down configurations from the Puppet Server. You will know if it worked by getting a message similar to `Notice: Applied catalog in X.XX seconds` after running the following command:
``` sh
```sh
puppet agent --test
```
## Install r10k
At this point, we need to configure Gitea as the storage repository for the Puppet "Environments" (e.g. `Production` and `Development`). We can do this by leveraging a tool called "r10k" which pulls a Git repository and configures it as the environment in Puppet.
``` sh
At this point, we need to configure Gitea as the storage repository for the Puppet "Environments" (e.g. `Production` and `Development`). We can do this by leveraging a tool called "r10k" which pulls a Git repository and configures it as the environment in Puppet.
```sh
# Install r10k Pre-Requisites
sudo dnf install -y ruby ruby-devel gcc make
@@ -157,7 +162,7 @@ r10k version
```
### Configure r10k
``` sh
```sh
# Create the r10k Configuration Directory
sudo mkdir -p /etc/puppetlabs/r10k
@@ -177,7 +182,7 @@ sources:
basedir: '/etc/puppetlabs/code/environments'
```
``` sh
```sh
# Lockdown the Permissions of the Configuration File
sudo chmod 600 /etc/puppetlabs/r10k/r10k.yaml
@@ -194,7 +199,7 @@ You will make a repository on Gitea with the following files and structure as no
!!! example "Example Agent & Neofetch"
You will notice there is a section for `fedora.bunny-lab.io` as well as mentions of `neofetch`. These are purely examples in my homelab of a computer I was testing against during the development of the Puppet Server and associated documentation. You can feel free to not include the entire `modules/neofetch/manifests/init.pp` file in the Gitea repository, as well as remove this entire section from the `manifests/site.pp` file:
``` yaml
```yaml
# Node definition for the Fedora agent
node 'fedora.bunny-lab.io' {
# Include the neofetch class to ensure Neofetch is installed
@@ -215,7 +220,7 @@ You will make a repository on Gitea with the following files and structure as no
mod 'puppetlabs-concat', '9.0.2'
mod 'puppet-systemd', '7.1.0'
```
=== "environment.conf"
This file is mostly redundant, as it states the values below, which are the default values Puppet works with. I only included it in case I had a unique use-case that required a more custom approach to the folder structure. (This is very unlikely).
@@ -238,7 +243,8 @@ You will make a repository on Gitea with the following files and structure as no
!!! example "Neofetch Example"
In the example configuration below, you will notice this section. This tells Puppet to deploy the neofetch package to any device that has `include neofetch` written. Grouping devices etc is currently undocumented as of writing this.
``` sh
```sh
# Node definition for the Fedora agent
node 'fedora.bunny-lab.io' {
# Include the neofetch class to ensure Neofetch is installed
@@ -312,7 +318,8 @@ Navigate to "**Gitea > User (Top-Right) > Settings > Applications
It is critical that you store the token somewhere safe like a password manager as you will need to reference it later and might need it in the future if you re-build the r10k environment.
Now we want to configure Gitea to store the credentials for later use by r10k:
``` sh
```sh
# Enable Stored Credentials (We will address security concerns further down...)
sudo yum install -y git
sudo git config --global credential.helper store
@@ -333,7 +340,8 @@ sudo rm -rf /tmp/PuppetTest
```
Finally we validate that everything is working by pulling down the Puppet environments using r10k on the Puppet Server:
``` sh
```sh
# Deploy Puppy Environments from Gitea
sudo /usr/local/bin/r10k deploy environment -p
@@ -342,11 +350,11 @@ sudo ls /etc/puppetlabs/code/environments/production/modules
sudo ls /etc/puppetlabs/code/environments/development/modules
```
!!! success "Successful Puppet Environment Deployment
!!! success "Successful Puppet Environment Deployment"
If you got no errors about Puppetfile formatting or Gitea permissions errors, then you are good to move onto the next step.
## External Node Classifier (ENC)
An ENC allows you to define node-specific data, including the environment, on the Puppet Server. The agent requests its configuration, and the Puppet Server provides the environment and classes to apply.
An ENC allows you to define node-specific data, including the environment, on the Puppet Server. The agent requests its configuration, and the Puppet Server provides the environment and classes to apply.
**Advantages**:
@@ -355,7 +363,7 @@ An ENC allows you to define node-specific data, including the environment, on th
- **Scalability**: Suitable for managing environments for hundreds or thousands of nodes.
### Create an ENC Script
``` sh
```sh
sudo mkdir -p /opt/puppetlabs/server/data/puppetserver/scripts/
```
@@ -392,13 +400,14 @@ output = {
puts output.to_yaml
```
``` sh
```sh
# Ensure the File is Executable
sudo chmod +x /opt/puppetlabs/server/data/puppetserver/scripts/enc.rb
```
### Configure Puppet Server to Use the ENC
Edit the Puppet Server's `puppet.conf` and set the `node_terminus` and `external_nodes` parameters:
```ini title="/etc/puppetlabs/puppet/puppet.conf"
[master]
node_terminus = exec
@@ -406,13 +415,15 @@ external_nodes = /opt/puppetlabs/server/data/puppetserver/scripts/enc.rb
```
Restart the Puppet Service
``` sh
```sh
sudo systemctl restart puppetserver
```
## Pull Puppet Environments from Gitea
At this point, we can tell r10k to pull down the Puppet environments (e.g. `Production` and `Development`) that we made in the Gitea repository in previous steps. Run the following command on the Puppet Server to pull down the environments. This will download / configure any Puppet Forge modules as well as any hand-made modules such as Neofetch.
``` sh
```sh
sudo /usr/local/bin/r10k deploy environment -p
# OPTIONAL: You can pull down a specific environment instead of all environments if you specify the branch name, seen here:
#sudo /usr/local/bin/r10k deploy environment development -p
@@ -420,9 +431,13 @@ sudo /usr/local/bin/r10k deploy environment -p
### Apply Configuration to Puppet Server
At this point, we are going to deploy the configuration from Gitea to the Puppet Server itself so it installs PuppetDB automatically as well as configures firewall ports and other small things to functional properly. Once this is completed, you can add additional agents / managed devices and they will be able to communicate with the Puppet Server over the network.
``` sh
```sh
sudo /opt/puppetlabs/bin/puppet agent -t
```
!!! success "Puppet Server Deployed and Validated"
Congradulations! You have successfully deployed an entire Puppet Server, as well as integrated Gitea and r10k to deploy environment changes in a versioned environment, as well as validated functionality against a managed device using the agent (such as a spare laptop/desktop). If you got this far, be proud, because it took me over 12 hours write this documentation allowing you to deploy a server in less than 30 minutes.
Congradulations! You have successfully deployed an entire Puppet Server, as well as integrated Gitea and r10k to deploy environment changes in a versioned environment, as well as validated functionality against a managed device using the agent (such as a spare laptop/desktop). If you got this far, be proud, because it took me over 12 hours write this documentation allowing you to deploy a server in less than 30 minutes.
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,42 @@
---
tags:
- Tactical RMM
- RMM
---
## Purpose
Tactical RMM is a remote monitoring & management tool built with Django, Vue and Golang. [Official Documentation](https://docs.tacticalrmm.com/install_server/).
!!! info "Requirements"
Ubuntu Server 22.04 LTS, 8GB RAM, 64GB Storage.
## Deployment Script
```sh
# Check for Updates
sudo apt update
sudo apt install -y wget curl sudo ufw
sudo apt -y upgrade
# Create TacticalRMM User
sudo useradd -m -G sudo -s /bin/bash tactical
sudo passwd tactical
# Configure Firewall Rules
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow https
sudo ufw allow ssh
echo "y" | sudo ufw enable
sudo ufw reload
# Switch to TacticalRMM User
sudo su - tactical
# Deploy TacticalRMM via Deployment Script
wget https://raw.githubusercontent.com/amidaware/tacticalrmm/master/install.sh
chmod +x install.sh
./install.sh
```
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,82 @@
---
tags:
- Activepieces
- Automation
- Docker
---
## Purpose
Self-hosted open-source no-code business automation tool.
```yaml title="docker-compose.yml"
version: '3.0'
services:
activepieces:
image: activepieces/activepieces:0.3.11
container_name: activepieces
restart: unless-stopped
privileged: true
ports:
- '8080:80'
environment:
- 'POSTGRES_DB=${AP_POSTGRES_DATABASE}'
- 'POSTGRES_PASSWORD=${AP_POSTGRES_PASSWORD}'
- 'POSTGRES_USER=${AP_POSTGRES_USERNAME}'
env_file: stack.env
depends_on:
- postgres
- redis
networks:
docker_network:
ipv4_address: 192.168.5.62
postgres:
image: 'postgres:14.4'
container_name: postgres
restart: unless-stopped
environment:
- 'POSTGRES_DB=${AP_POSTGRES_DATABASE}'
- 'POSTGRES_PASSWORD=${AP_POSTGRES_PASSWORD}'
- 'POSTGRES_USER=${AP_POSTGRES_USERNAME}'
volumes:
- /srv/containers/activepieces/postgresql:/var/lib/postgresql/data'
networks:
docker_network:
ipv4_address: 192.168.5.61
redis:
image: 'redis:7.0.7'
container_name: redis
restart: unless-stopped
volumes:
- /srv/containers/activepieces/redis:/data'
networks:
docker_network:
ipv4_address: 192.168.5.60
networks:
default:
external:
name: docker_network
docker_network:
external: true
```
```ini title=".env"
AP_ENGINE_EXECUTABLE_PATH=dist/packages/engine/main.js
AP_ENCRYPTION_KEY=e81f8754faa04acaa7b13caa5d2c6a5a
AP_JWT_SECRET=REDACTED #BE SURE TO SET THIS WITH A VALID JWT SECRET > REFER TO OFFICIAL DOCUMENTATION
AP_ENVIRONMENT=prod
AP_FRONTEND_URL=https://ap.cyberstrawberry.net
AP_NODE_EXECUTABLE_PATH=/usr/local/bin/node
AP_POSTGRES_DATABASE=activepieces
AP_POSTGRES_HOST=192.168.5.61
AP_POSTGRES_PORT=5432
AP_POSTGRES_USERNAME=postgres
AP_POSTGRES_PASSWORD=REDACTED #USE A SECURE SHORT PASSWORD > ENSURE ITS NOT TOO LONG FOR POSTGRESQL
AP_REDIS_HOST=redis
AP_REDIS_PORT=6379
AP_SANDBOX_RUN_TIME_SECONDS=600
AP_TELEMETRY_ENABLED=true
```
## Related Documentation
- [Docker Network Prerequisite](<../../Containers/Docker/Create the Docker Network.md>) — The configuration references the external `docker_network`; prepare it on the intended Docker host.
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
+41
View File
@@ -0,0 +1,41 @@
---
tags:
- Node-RED
- Automation
- Docker
---
## Purpose
Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways.
```yaml title="docker-compose.yml"
version: "3.7"
services:
node-red:
image: nodered/node-red:latest
environment:
- TZ=America/Denver
ports:
- "1880:1880"
networks:
docker_network:
ipv4_address: 192.168.5.92
volumes:
- /srv/containers/node-red:/data
networks:
default:
external:
name: docker_network
docker_network:
external: true
```
```yaml title=".env"
Not Applicable
```
## Related Documentation
- [Docker Network Prerequisite](<../../Containers/Docker/Create the Docker Network.md>) — The configuration references the external `docker_network`; prepare it on the intended Docker host.
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,90 @@
---
tags:
- Semaphore
- Automation
- Docker
---
## Purpose
User friendly web interface for executing Ansible playbooks, Terraform, OpenTofu code and Bash scripts. It is designed to make your automation tasks easier and more enjoyable.
[Website Details](https://semaphoreui.com/)
!!! info "Standalone VM Assumption"
It is assumed that you are deploying Semaphore UI in its own standalone virtual machine. These instructions dont accomodate MACVLAN docker networking, and assume that Semaphore UI and its PostgreSQL database backend share their IP address with the VM they are running on.
## Docker Configuration
```yaml title="docker-compose.yml"
services:
semaphore-ui:
ports:
- 3000:3000
image: public.ecr.aws/semaphore/pro/server:v2.13.12
privileged: true
environment:
SEMAPHORE_DB_DIALECT: postgres
SEMAPHORE_DB_HOST: postgres
SEMAPHORE_DB_NAME: semaphore
SEMAPHORE_DB_USER: root
SEMAPHORE_DB_PASS: SuperSecretDBPassword
SEMAPHORE_ADMIN: nicole
SEMAPHORE_ADMIN_PASSWORD: SuperSecretPassword
SEMAPHORE_ADMIN_NAME: Nicole Rappe
SEMAPHORE_ADMIN_EMAIL: infrastructure@bunny-lab.io
SEMAPHORE_EMAIL_SENDER: "noreply@bunny-lab.io"
SEMAPHORE_EMAIL_HOST: "mail.bunny-lab.io"
SEMAPHORE_EMAIL_PORT: "587"
SEMAPHORE_EMAIL_USERNAME: "noreply@bunny-lab.io"
SEMAPHORE_EMAIL_PASSWORD: "SuperSecretSMTPPassword"
ANSIBLE_HOST_KEY_CHECKING: "False"
volumes:
- /srv/containers/semaphore-ui/data:/var/lib/semaphore
- /srv/containers/semaphore-ui/config:/etc/semaphore
- /srv/containers/semaphore-ui/tmp:/tmp/semaphore
depends_on:
- postgres
postgres:
image: postgres:12-alpine
ports:
- 5432:5432
volumes:
- /srv/containers/semaphore-ui/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=semaphore
- POSTGRES_USER=root
- POSTGRES_PASSWORD=SuperSecretDBPassword
- TZ=America/Denver
restart: always
```
```yaml title=".env"
N/A - Will be cleaned up later.
```
## Traefik Reverse Proxy Configuration
If the container does not run on the same host as Traefik, you will need to manually add configuration to Traefik's dynamic config file, outlined below.
```yaml
http:
routers:
semaphore:
entryPoints:
- websecure
tls:
certResolver: letsencrypt
http2:
service: semaphore
rule: Host(`semaphore.bunny-lab.io`)
services:
semaphore:
loadBalancer:
servers:
- url: http://192.168.3.51:3000
passHostHeader: true
```
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
- [Traefik Deployment](<../../Networking and Access/Reverse Proxies/Traefik.md>) — Prepare the reverse proxy before applying this page's routing configuration.
@@ -1,69 +0,0 @@
---
tags:
- Ansible
- AWX
- Automation
---
## Upgrading from 2.10.0 to 2.19.1+
There is a known issue with upgrading / install AWX Operator beyond version 2.10.0, because of how the PostgreSQL database upgrades from 13.0 to 15.0, and has changed permissions. The following workflow will help get past that and adjust the permissions in such a way that allows the upgrade to proceed successfully. If this is a clean installation, you can also perform this step if the fresh install of 2.19.1 is not working yet. (It wont work out of the box because of this bug). `The developers of AWX seem to just not care about this issue, and have not implemented an official fix themselves at this time).
### Create a Temporary Pod to Adjust Permissions
We need to create a pod that will mount the PostgreSQL PVC, make changes to permissions, then destroy the v15.0 pod to have the AWX Operator automatically regenerate it.
```yaml title="/awx/temp-pod.yml"
apiVersion: v1
kind: Pod
metadata:
name: temp-pod
namespace: awx
spec:
containers:
- name: temp-container
image: busybox
command: ['sh', '-c', 'sleep 3600']
volumeMounts:
- mountPath: /var/lib/pgsql/data
name: postgres-data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-15-awx-postgres-15-0
restartPolicy: Never
```
``` sh
# Deploy Temporary Pod
kubectl apply -f /awx/temp-pod.yaml
# Open a Shell in the Temporary Pod
kubectl exec -it temp-pod -n awx -- sh
# Adjust Permissions of the PostgreSQL 15.0 Database Folder
chown -R 26:root /var/lib/pgsql/data
exit
# Delete the Temporary Pod
kubectl delete pod temp-pod -n awx
# Delete the Crashlooped PostgreSQL 15.0 Pod to Regenerate It
kubectl delete pod awx-postgres-15-0 -n awx
# Track the Migration
kubectl get pods -n awx
kubectl logs -n awx awx-postgres-15-0
```
!!! warning "Be Patient"
This upgrade may take a few minutes depending on the speed of the node it is running on. Be patient and wait until the output looks something similar to this:
```
root@awx:/awx# kubectl get pods -n awx
NAME READY STATUS RESTARTS AGE
awx-migration-24.6.1-bh5vb 0/1 Completed 0 9m55s
awx-operator-controller-manager-745b55d94b-2dhvx 2/2 Running 0 25m
awx-postgres-15-0 1/1 Running 0 12m
awx-task-7946b46dd6-7z9jm 4/4 Running 0 10m
awx-web-9497647b4-s4gmj 3/3 Running 0 10m
```
If you see a migration pod, like seen in the above example, you can feel free to delete it with the following command: `kubectl delete pod awx-migration-24.6.1-bh5vb -n awx`.
+11 -27
View File
@@ -1,38 +1,22 @@
---
tags:
- Operations
- Automation
- Index
- Deployments
- Documentation
---
# Automation
## Purpose
Infrastructure automation, orchestration, and workflow tooling.
Find deployments for automation. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Ansible and Puppet patterns
- Inventory and credential conventions
- CI/CD and automation notes
- AWX
- Documentation
- FOG Project
- Gitea
- Puppet
- Remote Management
- Tools
## New Document Template
````markdown
# <Document Title>
## Purpose
<what this automation doc exists to describe>
!!! info "Assumptions"
- <platform or tooling assumptions>
- <privilege assumptions>
## Inputs
- <variables, inventories, secrets>
## Procedure
```sh
# Commands or job steps
```
## Validation
- <command + expected result>
````
## Follow the Subject
[Automation](<../../reference/Automation/index.md>) explains the relationships and offers starting points for the documented tasks.