Compare commits

..

2 Commits

Author SHA1 Message Date
nicole 289769a601 Restructured Documentation
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 8s
2026-09-05 14:08:43 -06:00
nicole c4bd235eba Removed Platforms Top-Level Folder 2026-09-05 13:19:07 -06:00
287 changed files with 5403 additions and 3971 deletions
+6 -16
View File
@@ -1,26 +1,16 @@
---
tags:
- Blog
- Index
- Documentation
---
# Blog
## Purpose
Narrative posts for lessons learned, experiments, and updates.
Read the dated experiments and lessons behind changes in the lab. Follow the linked operational pages when you need the reusable configuration or procedure.
## New Post Template
````markdown
# <Post Title>
## Context
<why this mattered>
## Includes
- Posts
## What Changed
- <key actions or decisions>
## Results
- <what worked / what failed>
## Lessons Learned
- <what you would do differently next time>
````
## Follow the Experiments
- [Gitea Runners](<posts/05-16-2025 Learning to Leverage Gitea Runners.md>) — Read the configuration-delivery experiment and continue to the extracted runner procedures.
- [OpenStack](<posts/12-15-2024 OpenStack Frustrations.md>) — Read the context behind the separate OpenStack deployment attempts.
@@ -20,12 +20,15 @@ So I've been noticing a trend recently regarding something I never really took m
## Overview of the Problem
The general idea is that Windows devices (Workstations & Servers) have what are called power "**profiles**". These profiles, by default, are set to "**Balanced**". Which in basic terms means that the operating system will artificially limit the CPU speed to below 2.0GHz at all times. This means if the CPU is capable of 4GHz, it will be limited to 2GHz no-matter-what. This is a huge problem since it leaves performance just sitting on the table.
## Observations & Actions Taken
When I learned of the above, I began to audit every Windows-based server and workstation (Physical and Virtual) in my homelab. The virtual machines seemed unaffected by this issue, but I still configured them to "**High Performance**" power profiles regardless. However, every single physical host (`VIRT-NODE-01`, `VIRT-NODE-02`, and `LAB-DRAAS-01`), all saw notable performance improvements ranging from 32% to 41%, on average going from 1.75GHz to 2.6GHz on the virtualization hosts, and 1.9GHz to 3.2GHz on the backup server.
## Observations and Actions Taken
When I learned of the above, I began to audit every Windows-based server and workstation (Physical and Virtual) in my homelab. The virtual machines seemed unaffected by this issue, but I still configured them to "**High Performance**" power profiles regardless. However, every single physical host (`VIRT-NODE-01`, `VIRT-NODE-02`, and `LAB-DRAAS-01`), all saw notable performance improvements ranging from 32% to 41%, on average going from 1.75GHz to 2.6GHz on the virtualization hosts, and 1.9GHz to 3.2GHz on the backup server.
## Final Thoughts
I am so upset that for so many years, it never occured to me that the power profiles applied to server operating systems. I always just *assumed* they ran in "**High Performance**" power profiles all the time. I discovered I had non-trivial amounts of performance loss because of this simple checkbox setting in the OS.
!!! success "Performance Improvements"
The two Hyper-V Failover Cluster hosts saw a **32%** performance improvement (**1.75GHz to 2.6GHz**), while the Veeam Backup & Replication Server host observed a whopping **42%** performance improvement (**1.9GHz to 3.2GHz**).
## Related Documentation
- [Windows and Linux Administration](<../../reference/Windows and Linux/index.md>) — Find the operating-system procedures related to this performance observation.
- [Virtualization and Storage](<../../reference/Virtualization and Storage/index.md>) — Find the host and guest documentation for the environment being tuned.
@@ -1,7 +1,7 @@
---
draft: false
date: 2025-05-16
updated: 2025-05-16
updated: 2026-09-05
authors:
- nicole
categories:
@@ -15,7 +15,7 @@ tags:
---
# Learning to Leverage Gitea Runners
When I first started my journey with a GitOps mentality to transition a portion of my homelab's infrastructure to an "**Intrastructure-as-Code**" structure, I had made my own self-made Docker container that I called the [Git-Repo-Updater](../../deployments/platforms/containerization/docker/custom-containers/git-repo-updater.md). This self-made tool was useful to me because it copied the contents of Gitea repositories into bind-mounted container folders on my Portainer servers. This allowed me to set up configurations for Homepage-Docker, Material MkDocs, Traefik Reverse Proxy, and others to pull configuration changes from Gitea directly into the production servers, causing them to hot-load the changes instantly. (within 10 seconds, give or take).
When I first started my journey with a GitOps mentality to transition a portion of my homelab's infrastructure to an "**Intrastructure-as-Code**" structure, I had made my own self-made Docker container that I called the [Git-Repo-Updater](<../../deployments/Containers/Docker/Git Repo Updater.md>). This self-made tool was useful to me because it copied the contents of Gitea repositories into bind-mounted container folders on my Portainer servers. This allowed me to set up configurations for Homepage-Docker, Material MkDocs, Traefik Reverse Proxy, and others to pull configuration changes from Gitea directly into the production servers, causing them to hot-load the changes instantly. (within 10 seconds, give or take).
## Criticisms of Git-Repo-Updater
When I made the [Git-Repo-Updater docker container stack](https://git.bunny-lab.io/container-registry/git-repo-updater), I ran into the issue of having made something I knew existing solutions existed for but simply did not understand well-enough to use yet. This caused me to basically delegate the GitOps workflow to a bash script with a few environment variables, running inside of an Alpine Linux container. While the container did it's job, it would occassionally have hiccups, caching issues, or repository branch errors that made no sense. This lack of transparency and the need to build an entire VSCode development environment to push new docker package updates to Gitea's [package repository for Git-Repo-Updater](https://git.bunny-lab.io/container-registry/-/packages/container/git-repo-updater/latest) caused a lot of development headaches.
@@ -31,80 +31,10 @@ When I finally got around to figuring out the general architecture of how [Gitea
- The Gitea repository has a Gitea-specific workflows folder that holds `.yaml` files that the runner uses to define tasks that occur when the repository has changes made to it / commits pushed to it.
- The runner checks out the repository (*clones it to the runner environment*), and leverages rsync to copy the data into the production server's configuration folder(s) based on the unique needs of the task.
- The runner cleans up after itself and returns back to an "Idle" state.
- The production server hot-loads the changed configuration files (e.g. Material MkDocs, Traefik, Nginx, etc) and the changes go to into effect immediately
- The production server hot-loads the changed configuration files (e.g. Material MkDocs, Traefik, Nginx, etc) and the changes go to into effect immediately
### Docker-Compose Runner Deployment
When it comes to deploying a runner, (*assuming you want to use a docker-based runner*) it has a few simple things that need to be configured, the `docker-compose.yml` and the `.env` files. These tell the runner to reach out to Gitea server to register the runner with the given repository that you generated a registration token on.
```yaml title="docker-compose.yml"
version: "3.8"
services:
app:
image: docker.io/gitea/act_runner:latest
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: "${INSTANCE_URL}"
GITEA_RUNNER_REGISTRATION_TOKEN: "${REGISTRATION_TOKEN}"
GITEA_RUNNER_NAME: "${RUNNER_NAME}"
GITEA_RUNNER_LABELS: "${RUNNER_NAME}" # This can be anything, and is referenced by the workflow task(s) later.
volumes:
- /srv/containers/gitea-runner-mkdocs/config.yaml:/config.yaml # You have to manually make this file before you start the container
- /srv/containers/material-mkdocs/docs/docs:/Gitops_Destination # This is where the repository data will be copied to
```
```sh title=".env"
INSTANCE_URL=https://git.bunny-lab.io
RUNNER_NAME=gitea-runner-mkdocs
REGISTRATION_TOKEN=<Generated Here: https://git.bunny-lab.io/bunny-lab/docs/settings/actions/runners>
```
### Creating the `config.yaml`
The oddball thing about the way that I configured the Gitea Act Runner was telling it to run the container in "host mode" which tells it to run the tasks / workflows directly on the container itself instead of spinning up an instanced container (referred to as "*Docker-in-Docker*"). This keeps things simpler, but requires us to add a line to the `config.yaml` located at `/srv/containers/gitea-runner-mkdocs/config.yaml`. You can use your preferred text editor to add the following to the file's contents. This tells the runner to use itself for the tasks instead of an instanced docker container.
```yaml title="/srv/containers/gitea-runner-mkdocs/config.yaml"
container_engine: ""
```
!!! info "Quick Config Command"
```sh
mkdir -p /srv/containers/gitea-runner-mkdocs
echo 'container_engine: ""' > "/srv/containers/gitea-runner-mkdocs/config.yaml"
```
### Runner Workflow Task Files
When it comes to telling the runner what to do and how to do it, you create what are called runner "**Workflows**". These files reside within `<RepoRoot>/.gitea/workflows` and are `.yaml` format. If you have any familiarity with Ansible, the similarities are staggaring. You can have multiple workflows for one repository, with different flows that fire-off on different runners. An example of the flow used to replace Git-Repo-Updater's functionality can be seen below.
In the workflow below, it spins up a runner within the Alpine Linux environment that the `docker.io/gitea/act_runner:latest` uses, then installs NodeJS, Git, and Rsync for the core functionality that mirrors Git-Repo-Updater:
```yaml title=".gitea/workflows/gitops-automatic-deployment.yml"
name: GitOps Automatic Deployment
on:
push:
branches: [ main ]
jobs:
GitOps Automatic Deployment:
runs-on: gitea-runner-mkdocs
steps:
- name: Install Node.js, git, rsync, and curl
run: |
apk add --no-cache nodejs npm git rsync curl
- name: Checkout Repository
uses: actions/checkout@v3
- name: Copy Repository Data to Production Server
run: |
rsync -a --delete --exclude='.git/' --exclude='.gitea/' . /Gitops_Destination/
- name: Notify via NTFY
run: |
curl -d "https://docs.bunny-lab.io - Workflow Completed" https://ntfy.bunny-lab.io/gitea-runners
```
!!! note "`runs-on` Variable"
In this example workflow file, we are targeting the previously-mentioned `gitea-runner-mkdocs` runner, which we gave that "label" in the docker-compose.yaml file's `GITEA_RUNNER_LABELS` variable. You can name these labels whatever you want, as a way of organizing which runners run which workflows associated with a repository when changes are made to the repository.
### Runner Configuration
I have separated the Docker runner configuration and repository workflow into [Deliver Configuration with a Docker Runner](<../../workflows/Automation/Gitea/Deliver Configuration with a Docker Runner.md>). This preserves the operational example alongside the reasons I chose it. The [Zensical host runner workflow](<../../workflows/Automation/Gitea/Publish Zensical Documentation with a Host Runner.md>) documents the separate host-based implementation.
### It All Comes Together
When all of this is set up, it works exactly like Git-Repo-Updater did, but more securely, faster, and more robustly, as the tasks can be changed from the repository-level instead of having to make changes inside of a `Dockerfile` or having to learn how to publish your own Docker containers to a registry. When you learn how to do it, it becomes faster and easier to set up than Git-Repo-Updater as well.
@@ -113,6 +43,4 @@ Then, when you push changes to a repository, the workflow's task triggers automa
Gitea Act Runners are a beautiful thing, and it's a damn shame it took me this long to get around to learning how they work and using them.
![Gitea_Runner_Screenshot](./Images/Gitea_Runner_Screenshot.png)
![Gitea_Runner_Screenshot](<Images/Gitea_Runner_Screenshot.png>)
@@ -40,3 +40,7 @@ tags:
# Example Post Title
Placeholder Text / Body of the Blog Post.
```
## Related Documentation
- [Zensical Deployment](<../../deployments/automation/Documentation/Zensical.md>) — Find the separately documented Zensical service and its content-delivery workflow.
- [Blog Styling Contract](<../../reference/foundations/Documentation Styling.md>) — Use the canonical blog front matter and narrative structure.
@@ -5,8 +5,8 @@ updated: 2024-12-15
authors:
- nicole
links:
- platforms/virtualization/openstack/ansible-openstack.md
- platforms/virtualization/openstack/canonical-openstack.md
- ../../deployments/Virtualization and Storage/OpenStack/Ansible OpenStack.md
- ../../deployments/Virtualization and Storage/OpenStack/Canonical OpenStack.md
categories:
- Virtualization
- Containers
@@ -22,12 +22,10 @@ tags:
So, I want to start with a little context. As part of a long-standing project I have been working on, I have tried to deploy OpenStack. OpenStack is sort of envisioned as "Infrastructure as a Service (IAAS)". Basically you deploy an OpenStack cluster, which can run its own KVM for virtual machine and containers, or it can interface with an existing Hypervisor infrastructure, such as Hyper-V. In most cases, people branch out the "Control", "Compute", and "Storage" roles into different physical servers, but in my homelab, I have been attempting to deploy it via a "Converged" model, of having Control, Compute, and Storage on each node, spanning a high-availability cluster of 3 nodes.
## The Problem
The problems come into the overall documentation provided for deploying either [Canonical Openstack](https://ubuntu.com/openstack/install) which I have detailed my frustrations of the system in my own attempted re-write of the documentation [here](../../deployments/platforms/virtualization/openstack/canonical-openstack.md). I have also attempted to deploy it via [Ansible OpenStack](https://docs.openstack.org/project-deploy-guide/openstack-ansible/2024.1/), whereas my documentation thus far in my homelab is visible [here](../../deployments/platforms/virtualization/openstack/ansible-openstack.md).
The problems come into the overall documentation provided for deploying either [Canonical Openstack](https://ubuntu.com/openstack/install) which I have detailed my frustrations of the system in my own attempted re-write of the documentation [here](<../../deployments/Virtualization and Storage/OpenStack/Canonical OpenStack.md>). I have also attempted to deploy it via [Ansible OpenStack](https://docs.openstack.org/project-deploy-guide/openstack-ansible/2024.1/), whereas my documentation thus far in my homelab is visible [here](<../../deployments/Virtualization and Storage/OpenStack/Ansible OpenStack.md>).
You see, OpenStack is like icecream, it has many different ways to deploy it, and it can be as simple, or as overtly-complex as you need it to be, and it scales *really well* across a fleet of servers in a datacenter. My problems come in where the Canonical deployment has never worked fully / properly, and their own development team is hesitant to recommend the current documentation, and the Ansible OpenStack deployment process, while relatively simple, requires a base of existing knowledge that makes translating the instructions into more user-friendly instructions in my homelab documentation a difficult task. Eventually I want to automate much of the process as much as I can, but that will take time.
The common issue I've seen while trying to deploy OpenStack is understanding the networking, how networking is configured, network bridges, etc. The process is different based on the deployment method (Currently trying to deploy it via OpenStack Ansible). Hopefully in the near future I will make some kind of breakthrough in the deployment process and get everything working.
I will post an update later if I figure things out!
@@ -5,14 +5,15 @@ tags:
- Docker
---
**Purpose**: Homebox is the inventory and organization system built for the Home User! With a focus on simplicity and ease of use, Homebox is the perfect solution for your home inventory, organization, and management needs.
## Purpose
Homebox is the inventory and organization system built for the Home User! With a focus on simplicity and ease of use, Homebox is the perfect solution for your home inventory, organization, and management needs.
[Reference Documentation](https://hay-kot.github.io/homebox/quick-start/)
!!! warning "Protect with Keycloak"
The GitHub project for this software appears to have been archived in a read-only state in June 2024. There is no default admin credential, so setting the environment variable `HBOX_OPTIONS_ALLOW_REGISTRATION` to `false` will literally make you unable to log into the system. You also cannot change it after-the-fact, so you cannot just register an account then disable it and restart the container, it doesn't work that way.
Due to this behavior, it is imperative that you deploy this either only internally, or if its external, put it behind something like [Authentik](../authentication/authentik.md) or [Keycloak](../authentication/keycloak/deployment.md).
Due to this behavior, it is imperative that you deploy this either only internally, or if its external, put it behind something like [Authentik](<../../Identity and Certificates/Authentik.md>) or [Keycloak](<../../Identity and Certificates/Keycloak/Deploy Keycloak.md>).
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -60,6 +61,7 @@ HBOX_MAILER_FROM=noreply@bunny-lab.io
## 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:
@@ -81,3 +83,7 @@ http:
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 Applications Documentation](<../../../reference/Applications/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: A free open source IT asset/license management system.
## Purpose
A free open source IT asset/license management system.
!!! warning
The Snipe-IT container will attempt to launch after the MariaDB container starts, but MariaDB takes a while set itself up before it can accept connections; as a result, Snipe-IT will fail to initialize the database. Just wait about 30 seconds after deploying the stack, then restart the Snipe-IT container to initialize the database. You will know it worked if you see notes about data being `Migrated`.
@@ -111,6 +112,7 @@ APP_TRUSTED_PROXIES=192.168.5.29
## 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:
@@ -141,3 +143,8 @@ http:
- url: "http://192.168.5.50:8080"
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 Applications Documentation](<../../../reference/Applications/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Niltalk is a web based disposable chat server. It allows users to create password protected disposable, ephemeral chatrooms and invite peers to chat rooms.
## Purpose
Niltalk is a web based disposable chat server. It allows users to create password protected disposable, ephemeral chatrooms and invite peers to chat rooms.
```yaml title="docker-compose.yml"
version: "3.7"
@@ -50,3 +51,7 @@ volumes:
```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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,11 +5,13 @@ tags:
- Docker
---
**Purpose**: Deploy a RocketChat and MongoDB database together.
## Purpose
Deploy a RocketChat and MongoDB database together.
!!! caution Folder Pre-Creation
You need to make the folders for the Mongo database before launching the container stack for the first time. If you do not make this folder ahead of time, Mongo will give Permission Denied errors to the data directorry. You can create the folder as well as adjust permissions with the following commands:
``` sh
!!! caution "Folder Pre-Creation"
You need to make the folders for the Mongo database before launching the container stack for the first time. If you do not make this folder ahead of time, Mongo will give Permission Denied errors to the data directorry. You can create the folder as well as adjust permissions with the following commands:
```sh
mkdir -p /srv/containers/rocketchat/mongodb/data
chmod -R 777 /srv/containers/rocketchat
```
@@ -83,6 +85,7 @@ MONGODB_VERSION=6.0
MONGODB_INITIAL_PRIMARY_HOST=rc_mongodb #Redundant - Can be Removed
MONGODB_ADVERTISED_HOSTNAME=rc_mongodb #Redundant - Can be Removed
```
## Reverse Proxy Configuration
```yaml title="nginx.conf"
# Rocket.Chat Server
@@ -105,3 +108,8 @@ server {
}
}
```
## 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 Applications Documentation](<../../../../reference/Applications/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: A self-hostable personal dashboard built for you. Includes status-checking, widgets, themes, icon packs, a UI editor and tons more!
## Purpose
A self-hostable personal dashboard built for you. Includes status-checking, widgets, themes, icon packs, a UI editor and tons more!
```yaml title="docker-compose.yml"
version: "3.8"
@@ -61,6 +62,6 @@ networks:
external: true
```
```jsx 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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Dashboards
---
**Purpose**: A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.
## Purpose
A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.
```yaml title="docker-compose.yml"
version: '3.8'
@@ -63,3 +64,7 @@ networks:
```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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,79 @@
---
tags:
- Microsoft Exchange
- Lets Encrypt
- Email
---
## Purpose
If you want to set up automatic Let's Encrypt SSL certificates on a Microsoft Exchange server, you have to go through a few steps to install the WinACME bot, and configure it to automatically renew certificates.
!!! note "ACME Bot Provisioning Considerations"
This document assumes you want a fully-automated one-liner command for configuring the ACME Bot, it is also completely valid to go step-by-step through the bot to configure the SSL certificate, the IIS server, etc, and it will automatically create a Scheduled Task to renew on its own. The whole process is very straight-forward with most answers being the default option.
### Download the Win-ACME Bot
- Log into the on-premise Exchange Server via Datto RMM
- Navigate to: [https://www.win-acme.com/](https://www.win-acme.com/)
- On the top-right of the website, you will see a "**Download**" button with the most recent version of the Win-ACME bot
- Extract the contents of the ZIP file to "**C:\\Program Files (x86)\\Lets Encrypt**"
- Make the "**Lets Encrypt**" folder if it does not already exist
### Configure `settings_default.json`
- The next step involves us making a modification to the configuration of the Win-ACME bot that allows us to export the necessary private key data for Exchange
- Using a text editor, open the "**settings\_default.json**" file
- Look for the setting called "**PrivateKeyExportable**" and change the value from "**false**" to "**true**"
- Save and close the file
### Download and Install the SSL Certificate
- Open an administrative Command Line (DO NOT USE POWERSHELL)
- Navigate to the Let's Encrypt bot directory: `CD "C:\Program Files (x86)\Lets Encrypt"`
- Invoke the bot to automatically download and install the certificate into the IIS Server that Exchange uses to host the Exchange Server
- Be sure to change the placeholder subdomains to match the domain of the actual Exchange Server
- (e.g. "**mail.example.org**" | "**autodiscover.example.org**")
```text
wacs.exe --target manual --host mail.example.org,autodiscover.example.org --certificatestore My --acl-fullcontrol "network service,administrators" --installation iis,script --installationsiteid 1 --script "./Scripts/ImportExchange.ps1" --scriptparameters "'{CertThumbprint}' 'IIS,SMTP,IMAP' 1 '{CacheFile}' '{CachePassword}' '{CertFriendlyName}'" --verbose
```
- When the command is running, it will ask for an email address for alerts and abuse notifications, just put "**infrastructure@bunny-lab.io**"
- If you run into any unexpected errors that result in anything other than exiting with a status "0", consult with Nicole Rappe to proceed
- Check that the domain of the Exchange Server is reachable on port 80 as Let's Encrypt uses this to build the cert.
- Searching the external IP of the server on [Shodan](https://www.shodan.io/) will reveal all open ports.
### Troubleshooting
If you find that any of the services such as [https://mail.example.org/ecp](https://mail.example.org/ecp), [https://autodiscover.example.org](https://autodiscover.example.org), or [https://mail.example.org/owa](https://mail.example.org/owa) do not let you log in, proceed with the steps below to correct the "Certificate Binding" in IIS Manager:
- Open "**Server Manager**" > Tools > "**Internet Information Services (IIS) Manager**"
- Expand the "**Connections**" server tree on the left-hand side of the IIS Manager
- Expand the "**Sites**" folder
- Click on "**Default Web Site**"
- On the right-hand Actions menu, click on "**Bindings...**"
- A table will appear with different endpoints on the Exchange server > What you are looking for is an entry that looks like the following:
- **Type**: https
- **Host Name**: autodiscover.example.org
- **Port**: 443
- Double-click on the row, or click one then click the "**Edit**" button to open the settings for that endpoint
- Under "**SSL Certificate**" > Make sure the certificate name matches the following format: "**\[Manual\] autodiscover.example.org @ YYYY/MM/DD**"
- If it does not match the above, use the dropdown menu to correct it and click the "**OK**" button
- **Type**: https
- **Host Name**: mail.example.org
- **Port**: 443
- Repeat the steps seen above, except this time for "**mail.example.org**"
- Click on "**Exchange Back End**"
- On the right-hand Actions menu, click on "**Bindings...**"
- A table will appear with different endpoints on the Exchange server > What you are looking for is an entry that looks like the following:
- **Type**: https
- **Host Name**: <blank>
- **Port**: 444
- Repeat the steps seen above, ensuring that the "**\[Manual\] autodiscover.example.org @ YYYY/MM/DD**" certificate is selected and applied
- Click the "**OK**" button
- On the left-hand menu under "**Connections**" in IIS Manager, click on the server name itself
- (e.g. "**EXAMPLE-EXCHANGE (DOMAIN\\dptadmin**")
- On the right-hand "**Actions**" menu > Under "Manage Server" > Select "Restart"
- Wait for the IIS server to restart itself, then try accessing the webpages for Exchange that were exhibiting issues logging in
### Additional Documentation
- [https://www.alitajran.com/install-free-lets-encrypt-certificate-in-exchange-server/](https://www.alitajran.com/install-free-lets-encrypt-certificate-in-exchange-server/)
## Related Documentation
- [Related Email Documentation](<../../../../reference/Applications/Email/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,18 +1,13 @@
---
tags:
- Proxmox Mail Gateway
- PMG
- Mailcow
- Email
- SMTP
- Gateway
- Spam Filtering
- Proxmox Mail Gateway
- PMG
- Mailcow
- Email
- SMTP
---
# Proxmox Mail Gateway Inbound Filtering for Mailcow
## Purpose
This document defines the procedure for placing `Proxmox Mail Gateway` in front of an existing `Mailcow` server for inbound SMTP filtering.
PMG will handle inbound SMTP inspection before delivering accepted mail to Mailcow.
@@ -21,32 +16,31 @@ This document covers **inbound SMTP filtering only**.
It does not move:
* Outbound SMTP delivery
* DKIM signing
* SMTP submission
* IMAP
* POP3
* ManageSieve
* Mailcow certificates
* Mailcow web access
* Roundcube access
- Outbound SMTP delivery
- DKIM signing
- SMTP submission
- IMAP
- POP3
- ManageSieve
- Mailcow certificates
- Mailcow web access
- Roundcube access
## Assumptions
Mailcow is already deployed and functional.
Mailcow already handles:
* Mailbox hosting
* User authentication
* Webmail
* Mailcow admin interface
* IMAP
* POP3
* SMTP submission
* Outbound delivery
* DKIM signing
* TLS certificates for `mail.bunny-lab.io`
- Mailbox hosting
- User authentication
- Webmail
- Mailcow admin interface
- IMAP
- POP3
- SMTP submission
- Outbound delivery
- DKIM signing
- TLS certificates for `mail.bunny-lab.io`
Example environment:
@@ -62,14 +56,12 @@ Reverse Proxy: Traefik
!!! warning "Inbound SMTP Only"
Only move public inbound SMTP port `25` to PMG during this stage.
```
```text
Do not move mail client ports, outbound relay behavior, DKIM signing, or Mailcow web access.
```
## Architecture
### Existing Mail Flow
```text
Internet
|
@@ -81,7 +73,6 @@ Mailcow 192.168.3.61:25
```
### Target Mail Flow
```text
Internet
|
@@ -96,7 +87,6 @@ Mailcow 192.168.3.61:25
```
### Final Service Ownership
```text
PMG
- Inbound SMTP on port 25
@@ -125,7 +115,6 @@ Traefik
```
## DNS
Public DNS remains unchanged.
```text
@@ -144,12 +133,11 @@ pfSense WAN :25 -> PMG 192.168.3.15:25
!!! note "DNS Does Not Point to PMG Directly"
The public MX and A records do not point to the internal PMG IP.
```
```text
NAT controls the internal SMTP destination.
```
## Firewall and NAT Design
Only public inbound SMTP changes.
Change this:
@@ -186,12 +174,11 @@ WAN :443 -> Traefik :443
!!! warning "Do Not Move Mail Client Ports to PMG"
PMG is an SMTP gateway.
```
```text
Do not forward IMAP, POP3, SMTPS, Submission, or ManageSieve ports to PMG.
```
## Initial PMG Access
Access the PMG management interface.
```text
@@ -204,7 +191,6 @@ Use the `root` credentials configured during PMG installation.
Browser certificate warnings are expected when accessing PMG by IP address unless a trusted certificate has already been configured for the management interface.
## Pre-Cutover Connectivity Checks
Confirm PMG can reach Mailcow on SMTP port `25`.
Run from the PMG shell:
@@ -251,12 +237,11 @@ quit
!!! note "Mailcow SMTP Banner"
Mailcow commonly identifies its SMTP service as `Postcow`.
```
```text
That is expected.
```
## PMG Mail Proxy Ports
In PMG, navigate to:
```text
@@ -274,12 +259,11 @@ No outbound filtering is configured during this stage.
!!! note "Internal SMTP Port"
PMG also has an internal SMTP port used for outbound filtering from an internal mail server.
```
```text
This deployment does not use outbound PMG filtering yet.
```
## PMG Relay Domains
In PMG, navigate to:
```text
@@ -298,7 +282,6 @@ This authorizes PMG to accept mail for the domain.
If the domain is missing from Relay Domains, PMG may reject inbound mail because it is not configured as responsible for that domain.
## PMG Default Relay
In PMG, navigate to:
```text
@@ -327,19 +310,18 @@ Mailcow 192.168.3.61:25
!!! note "Disable MX Lookup"
PMG should deliver accepted inbound mail directly to the internal Mailcow server.
```
```text
It should not perform public MX lookup for the local mail domain.
```
!!! note "No Smarthost"
Leave `Smarthost` unset or set to `none` for inbound-only filtering.
```
```text
Smarthost configuration is used for outbound relay behavior.
```
## Mailcow Forwarding Host
Configure Mailcow to trust PMG as a forwarding host.
In Mailcow, navigate to:
@@ -363,19 +345,18 @@ Inactive
!!! note "Forwarding Host Behavior"
After cutover, Mailcow sees PMG as the immediate SMTP source for inbound mail.
```
```text
Trusting PMG allows Mailcow to interpret forwarded mail correctly.
```
!!! note "Spam Filtering Placement"
PMG is the primary inbound spam and virus filtering system.
```
```text
Leave Mailcow forwarding-host spam filtering inactive to avoid double-filtering messages already inspected by PMG.
```
## Outbound Mail
Leave outbound mail unchanged.
```text
@@ -400,12 +381,11 @@ DMARC record
!!! warning "Do Not Move DKIM"
DKIM signing applies to outbound mail.
```
```text
This document only moves inbound SMTP filtering.
```
## Filtering Policy
Initial filtering ownership:
```text
@@ -418,12 +398,11 @@ Avoid configuring both PMG and Mailcow to aggressively quarantine the same inbou
!!! note "Keep Filtering Boring"
PMG should own edge filtering first.
```
```text
Mailcow should continue owning mailbox and client access behavior.
```
## SMTP NAT Cutover
After PMG relay domains, PMG default relay, and Mailcow forwarding host settings are configured, update the pfSense NAT rule.
Change:
@@ -460,14 +439,12 @@ Do not change the Traefik web path.
!!! warning "Cutover Point"
Changing `WAN :25` is the actual inbound mail cutover.
```
```text
External SMTP servers will begin connecting to PMG instead of Mailcow directly.
```
## Validation
### External SMTP Reachability
From an external system:
```sh
@@ -492,7 +469,7 @@ SMTP banner returned by gateway
!!! note "Internal Testing Limitations"
Internal tests may not represent public mail flow if NAT reflection or split-horizon DNS is involved.
```
```text
Prefer external testing.
```
@@ -509,7 +486,6 @@ Work mailbox hosted outside Mailcow
```
### Inbound Delivery
Send an external message to a Mailcow-hosted mailbox.
Expected path:
@@ -555,7 +531,6 @@ System > Logs
or review the relevant Mailcow Postfix and Dovecot logs.
### Mail Client Access
Confirm normal mail client behavior remains unchanged.
Test:
@@ -581,7 +556,6 @@ Web: 443 -> Traefik -> Mailcow
Confirm outbound mail still works by replying from a Mailcow-hosted mailbox to the external sender.
### PMG Queues
Check PMG queues after test delivery.
```text
@@ -597,42 +571,39 @@ Queue empty or near-empty after delivery
Queue status confirms PMG is not silently holding or deferring mail because of relay, DNS, or delivery errors.
## Validation Checklist
* [ ] Public MX record points to `mail.bunny-lab.io`
* [ ] `mail.bunny-lab.io` resolves to the correct public WAN IP
* [ ] DNS records are unchanged
* [ ] PMG can reach Mailcow on `192.168.3.61:25`
* [ ] Mailcow SMTP banner is visible from PMG
* [ ] PMG external SMTP port is `25`
* [ ] PMG has `bunny-lab.io` configured as a relay domain
* [ ] PMG default relay points to `192.168.3.61`
* [ ] PMG relay port is `25`
* [ ] PMG relay protocol is `smtp`
* [ ] PMG internal delivery has MX lookup disabled
* [ ] PMG smarthost is unset or `none`
* [ ] Mailcow trusts `192.168.3.15` as a forwarding host
* [ ] Mailcow forwarding-host spam filter is `Inactive`
* [ ] Firewall forwards `WAN :25` to `192.168.3.15:25`
* [ ] Firewall still forwards mail client ports directly to Mailcow
* [ ] Traefik still handles Mailcow / Roundcube web traffic
* [ ] Inbound test mail appears in PMG Tracking Center
* [ ] PMG Tracking Center shows `accepted/delivered`
* [ ] PMG log shows delivery to `192.168.3.61:25`
* [ ] Inbound test mail is delivered to the Mailcow mailbox
* [ ] PMG queue is empty after delivery
* [ ] Mobile email client still works
* [ ] Desktop email client still works
* [ ] Webmail still works
* [ ] Replying outbound from Mailcow still works
* [ ] DKIM behavior is unchanged
* [ ] SPF record is unchanged
* [ ] DMARC record is unchanged
* [ ] Outbound mail routing is unchanged
- [ ] Public MX record points to `mail.bunny-lab.io`
- [ ] `mail.bunny-lab.io` resolves to the correct public WAN IP
- [ ] DNS records are unchanged
- [ ] PMG can reach Mailcow on `192.168.3.61:25`
- [ ] Mailcow SMTP banner is visible from PMG
- [ ] PMG external SMTP port is `25`
- [ ] PMG has `bunny-lab.io` configured as a relay domain
- [ ] PMG default relay points to `192.168.3.61`
- [ ] PMG relay port is `25`
- [ ] PMG relay protocol is `smtp`
- [ ] PMG internal delivery has MX lookup disabled
- [ ] PMG smarthost is unset or `none`
- [ ] Mailcow trusts `192.168.3.15` as a forwarding host
- [ ] Mailcow forwarding-host spam filter is `Inactive`
- [ ] Firewall forwards `WAN :25` to `192.168.3.15:25`
- [ ] Firewall still forwards mail client ports directly to Mailcow
- [ ] Traefik still handles Mailcow / Roundcube web traffic
- [ ] Inbound test mail appears in PMG Tracking Center
- [ ] PMG Tracking Center shows `accepted/delivered`
- [ ] PMG log shows delivery to `192.168.3.61:25`
- [ ] Inbound test mail is delivered to the Mailcow mailbox
- [ ] PMG queue is empty after delivery
- [ ] Mobile email client still works
- [ ] Desktop email client still works
- [ ] Webmail still works
- [ ] Replying outbound from Mailcow still works
- [ ] DKIM behavior is unchanged
- [ ] SPF record is unchanged
- [ ] DMARC record is unchanged
- [ ] Outbound mail routing is unchanged
## Troubleshooting
### Inbound Mail Never Reaches PMG
Verify NAT.
```text
@@ -655,7 +626,6 @@ PMG > Tracking Center
```
### PMG Receives Mail but Does Not Deliver to Mailcow
Verify PMG relay settings.
```text
@@ -687,7 +657,6 @@ Expected banner:
```
### PMG Shows Reverse DNS Warning for Mailcow
A warning like this is not automatically a failure:
```text
@@ -697,7 +666,6 @@ inverse host lookup failed: Unknown host
If the connection still reports port `25` as open, SMTP connectivity is working.
### Mailcow Rejects Mail from PMG
Verify Mailcow trusts PMG as a forwarding host.
```text
@@ -713,7 +681,6 @@ bunny-lab.io
Verify the recipient mailbox or alias exists in Mailcow.
### Mail Clients Stop Working
Verify only inbound SMTP port `25` was moved to PMG.
These ports should still forward directly to Mailcow:
@@ -736,7 +703,6 @@ Mailcow -> client access and mailbox services
```
### Roundcube or Mailcow Web UI Stops Working
Verify web traffic was not moved to PMG.
Expected path:
@@ -749,7 +715,6 @@ WAN :443 -> Traefik :443
PMG should not replace Traefik for Mailcow or Roundcube web access.
### Outbound Mail Stops Working
Outbound mail should not change during this deployment.
Verify no changes were made to:
@@ -764,7 +729,6 @@ Public DNS records
```
### Spam Filtering Behavior Is Confusing
Use one primary inbound filtering authority.
Recommended initial state:
@@ -777,7 +741,6 @@ Mailcow = mailbox hosting and client access
Avoid dual aggressive quarantine policies until basic mail flow is stable.
## Confirmed Final State
After Stage 1, the environment should operate as follows:
```text
@@ -818,7 +781,6 @@ Mailcow / Roundcube web access
```
## Deployment Status
This document completes Stage 1 of the PMG deployment.
```text
@@ -833,320 +795,8 @@ PMG = inbound SMTP filtering only
Mailcow = mailboxes, webmail, authenticated submission, certificates, DKIM, outbound delivery, user-facing mail services
```
## Enabling Direct Unfiltered Communication Between Mailcow and PMG
This workflow describes how to configure Mailcow to trust Proxmox Mail Gateway (PMG) as an upstream SMTP relay after PMG has been placed in front of Mailcow for inbound filtering. It prevents Mailcow from applying sender-domain validation and duplicate spam filtering to messages that PMG has already accepted, including messages released from the PMG quarantine.
In the current Bunny Lab design, this trust applies to the inbound delivery path from `192.168.3.15` to `192.168.3.61`. Mailcow continues to send outbound mail directly to the Internet and does not relay outbound mail through PMG.
!!! info "Assumptions"
- Mailcow is already deployed at `192.168.3.61`.
- PMG is already deployed at `192.168.3.15`.
- Public inbound SMTP port `25` is forwarded to PMG.
- PMG relays accepted inbound mail to Mailcow on `192.168.3.61:25`.
- Mailcow remains responsible for mailbox hosting, authenticated submission, DKIM signing, and outbound delivery.
- You have `root` access to the Mailcow host.
!!! warning "Trust Only the PMG Host"
Add only `192.168.3.15/32` to Mailcow's trusted networks. Do not trust the entire `192.168.3.0/24` subnet unless every system on that subnet is authorized to relay mail through Mailcow without authentication.
## Architecture
```text
Internet
|
v
pfSense WAN :25
|
v
PMG 192.168.3.15:25
|
v
Mailcow 192.168.3.61:25
|
v
User Mailbox
```
PMG is the primary inbound spam and virus filtering authority. Mailcow should accept the SMTP session from PMG as a trusted relay and avoid repeating edge filtering or rejecting PMG-generated envelope senders.
## Symptoms
Use this workflow when PMG receives and processes mail correctly, but Mailcow rejects or defers the final delivery.
Common symptoms include:
- A released PMG quarantine message remains in the PMG deferred queue
- Clicking **Flush** in PMG does not deliver the message
- PMG repeatedly attempts delivery to `192.168.3.61:25`
- Mailcow rejects a PMG-generated envelope sender such as `postmaster@lab-mail-gw-01.bunny-lab.io`
- PMG reports an SMTP response similar to:
```text
450 4.1.8 Sender address rejected: Domain not found
```
The visible message sender may be valid even when Mailcow rejects the PMG-generated envelope sender used during quarantine release.
## Confirm the PMG Source Address
Mailcow must trust the source address it actually sees on the SMTP connection. Confirm that address before changing the configuration.
On the Mailcow host, run:
```sh
cd /opt/mailcow-dockerized
docker compose logs --since 5m postfix-mailcow
```
Flush or resend a test message from PMG, then locate the connection line.
Expected connection source:
```text
connect from lab-mail-gw-01[192.168.3.15]
```
If Mailcow sees a different address because of NAT, a load balancer, or another SMTP proxy, use that observed address instead of `192.168.3.15`.
## Configure Mailcow Forwarding Hosts
Configure PMG as a trusted forwarding host in the Mailcow WebUI.
- Navigate to "**System > Configuration > Options > Forwarding Hosts**"
- Add `192.168.3.15`
- Set the forwarding-host spam filter option to **Inactive**
- Save the configuration
!!! note "Forwarding Host Behavior"
The forwarding-host entry tells Mailcow that PMG is the immediate upstream SMTP relay. Keeping the forwarding-host spam filter inactive avoids applying a second aggressive spam-filtering layer to mail that PMG has already inspected.
## Configure Postfix Trusted Networks
The forwarding-host entry does not replace Postfix `mynetworks`. Add PMG to `mynetworks` so Postfix treats SMTP sessions from PMG as trusted and evaluates `permit_mynetworks` before sender-domain restrictions.
### Inspect the Existing Trusted Networks
Before modifying `mynetworks`, determine the currently active value. Mailcow automatically populates `mynetworks` with its loopback and Docker networks. Defining your own value replaces that automatically generated configuration, so you must preserve the existing entries.
On the Mailcow host, run:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
Example output:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128
```
At this point, append the PMG address as a single-host CIDR. Do not remove any existing networks.
Expected result:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
### Update the Persistent Postfix Override
Edit the Postfix override file:
```sh
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
```
If `mynetworks` config line already exists, append the PMG address while preserving the existing values. If the key does not exist, create it using the value discovered in the previous step.
```ini title="/opt/mailcow-dockerized/data/conf/postfix/extra.cf"
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
!!! warning "Do Not Replace Existing Networks"
The `mynetworks` directive replaces Mailcow's automatically generated value. Removing the existing loopback or Docker networks may prevent Postfix from functioning correctly. Always preserve the existing entries and append the PMG address.
### Restart Mailcow Postfix
Apply the persistent override:
```sh
cd /opt/mailcow-dockerized
docker compose restart postfix-mailcow
```
## Validate the Trusted Relay Configuration
Confirm the active Postfix configuration after the restart:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
Expected result:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
Confirm the active SMTP restriction order includes `permit_mynetworks`:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf \
smtpd_sender_restrictions \
smtpd_recipient_restrictions \
smtpd_relay_restrictions
```
The exact restriction lists may change between Mailcow releases. Confirm that `permit_mynetworks` remains present and that the effective configuration recognizes `192.168.3.15/32` as trusted.
## Retry Deferred PMG Mail
After Mailcow trusts PMG, retry the deferred message from the PMG WebUI.
- Navigate to "**Administration > Queue Administration > Deferred Mail**"
- Select the deferred message
- Click **Flush**
Alternatively, run the following on PMG:
```sh
postqueue -f
```
To retry one specific queue item:
```sh
postsuper -r <QUEUE_ID>
postqueue -f
```
## Validate Mail Delivery
Monitor Mailcow while PMG retries the message:
```sh
cd /opt/mailcow-dockerized
docker compose logs -f postfix-mailcow
```
Mailcow should accept the SMTP transaction and return a successful queue response similar to:
```text
250 2.0.0 Ok: queued as <MAILCOW_QUEUE_ID>
```
On PMG, confirm the deferred queue no longer contains the message:
```sh
postqueue -p
```
Confirm the message is present in the destination Mailcow mailbox.
!!! success "Trusted PMG Delivery Confirmed"
The workflow is complete when Mailcow accepts mail from `192.168.3.15`, the PMG deferred queue clears, and the destination mailbox receives the message.
## Security Boundaries
Adding `192.168.3.15/32` to `mynetworks` permits PMG to relay mail through Mailcow without SMTP authentication. This is appropriate only while PMG remains a controlled gateway host.
Maintain the following boundaries:
- Restrict the trusted entry to `192.168.3.15/32`
- Prevent other hosts from impersonating the PMG source address
- Keep Mailcow port `25` restricted to expected SMTP sources where practical
- Confirm PMG is not configured as an unrestricted open relay
- Continue routing authenticated client submission directly to Mailcow on ports `465` and `587`
- Continue routing public inbound SMTP port `25` to PMG rather than directly to Mailcow
## Troubleshooting
### Mailcow Still Returns `450 4.1.8`
Confirm Mailcow is using the updated configuration:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
If `192.168.3.15/32` is missing, verify `/opt/mailcow-dockerized/data/conf/postfix/extra.cf` and restart `postfix-mailcow`.
### Mailcow Sees a Different Source Address
Inspect the Mailcow Postfix logs:
```sh
cd /opt/mailcow-dockerized
docker compose logs --since 5m postfix-mailcow
```
Use the IP address shown in the `connect from ...[IP_ADDRESS]` line. Do not assume Mailcow sees the PMG management address when NAT or an SMTP proxy exists between the systems.
### PMG Flushes the Message but the Mailbox Does Not Receive It
Determine whether Mailcow accepted the message.
If Mailcow returned `250 2.0.0`, the PMG-to-Mailcow relay succeeded. Continue troubleshooting inside Mailcow by reviewing Postfix, Rspamd, and Dovecot logs.
```sh
cd /opt/mailcow-dockerized
docker compose logs --since 10m postfix-mailcow rspamd-mailcow dovecot-mailcow
```
If Mailcow returned a `4xx` or `5xx` response, use the complete SMTP response as the controlling error and resolve that policy or recipient failure before retrying again.
### Mailcow Applies Spam Filtering Again
Confirm the PMG entry under "**System > Configuration > Options > Forwarding Hosts**" has its spam filter set to **Inactive**.
PMG should remain the primary inbound filtering authority in this deployment.
### Mail Clients or Outbound Delivery Stop Working
This workflow does not change client access or outbound delivery.
Confirm the existing service ownership remains:
```text
Inbound SMTP: Internet -> PMG -> Mailcow
Outbound SMTP: Mailcow -> Internet
SMTP Submission: Clients -> Mailcow
IMAP and POP3: Clients -> Mailcow
Webmail and Admin: Internet -> Traefik -> Mailcow
```
Do not redirect ports `465`, `587`, `993`, `995`, `110`, `143`, or `4190` to PMG.
## Rollback
Remove the PMG forwarding-host entry from the Mailcow WebUI only when PMG is no longer the upstream SMTP gateway.
Then edit:
```sh
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
```
Restore the previous `mynetworks` value:
```ini title="/opt/mailcow-dockerized/data/conf/postfix/extra.cf"
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128
```
Restart Postfix:
```sh
cd /opt/mailcow-dockerized
docker compose restart postfix-mailcow
```
!!! warning "Coordinate the SMTP Path Before Rollback"
Do not remove PMG trust while public inbound SMTP still routes through PMG. Mailcow may begin rejecting legitimate messages relayed from PMG.
## Confirmed Final State
The validated Bunny Lab configuration is:
```text
PMG Address: 192.168.3.15
Mailcow Address: 192.168.3.61
Mailcow Forwarder: 192.168.3.15
Forwarder Spam Check: Inactive
Postfix mynetworks: 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
The resulting mail flow is:
```text
Inbound SMTP:
Internet -> pfSense WAN :25 -> PMG 192.168.3.15:25 -> Mailcow 192.168.3.61:25
Outbound SMTP:
Mailcow -> Internet
```
## Maintain Mail Delivery
For sender-validation and trusted-relay failures after integration, follow [Repair Trusted Mail Delivery Between PMG and Mailcow](<../../../../workflows/Applications/Email/Proxmox Mail Gateway/Repair Trusted Mail Delivery Between PMG and Mailcow.md>).
## Related Documentation
- [Related Email Documentation](<../../../../reference/Applications/Email/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,17 @@
---
tags:
- cPanel
- Email
---
## Purpose
This documentation helps you deploy an email server within a cPanel hosted environment.
!!! warning "Incomplete Procedure"
The deployment steps remain a scaffold. No completed cPanel mail-server procedure is recorded here.
!!! note "Assumptions"
It is assumed that the cPanel environment is set up (prior) to following this documentation, as deploying cPanel itself is not covered in this document.
## Related Documentation
- [Related Email Documentation](<../../../../reference/Applications/Email/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,7 +4,7 @@ tags:
- Email
---
**Purpose**:
## Purpose
Self-Hosted Open-Source email server that can be setup in minutes, and is enterprise-grade if upgraded with an iRedAdmin-Pro license.
!!! note "Assumptions"
@@ -20,8 +20,9 @@ The instructions below are specific to my homelab environment, but can be easily
Ensure the FQDN of the server is correctly set in `/etc/hostname`. The `/etc/hosts` file will be automatically injected using the FQDN from `/etc/hostname` in a script further down, don't worry about editing it.
## Disable SELinux
iRedMail doesn't work with SELinux, so please disable it by setting below value in its config file /etc/selinux/config. After server reboot, SELinux will be completely disabled.
``` sh
iRedMail doesn't work with SELinux, so please disable it by setting below value in its config file /etc/selinux/config. After server reboot, SELinux will be completely disabled.
```sh
# Elevate to Root User
sudo su
@@ -33,10 +34,10 @@ setenforce 0
1. If you prefer to let SELinux prints warnings instead of enforcing, you can set this value instead: `SELINUX=permissive`
## iRedMail Installation
### Set Domain and iRedMail Version
Start by connecting to the server / VM via SSH, then set silent deployment variables below.
``` sh
```sh
# Define some deployment variables.
VERSION="1.6.8" # (1)
MAIL_DOMAIN="bunny-lab.io" # (2)
@@ -51,7 +52,7 @@ You will then proceed to bootstrap a silent unattended installation of iRedMail.
You absolutely need to ensure that `/var/vmail` has a lot of space. At least 16GB. This is where all of your emails / mailboxes / a lot of settings will be. If possible, create a second physical/virtual disk specifically for the `/var` partition, or specifically for `/var/vmail` at minimum, so you can expand it over time if necessary. LVM-based provisioning is recommended but not required.
### Install iRedMail
``` sh
```sh
# Automatically configure the /etc/hosts file to point to the server listed in "/etc/hostname".
sudo sed -i "1i 127.0.0.1 $(cat /etc/hostname) $(cut -d '.' -f 1 /etc/hostname) localhost localhost.localdomain localhost4 localhost4.localdomain4" /etc/hosts
@@ -86,7 +87,8 @@ AUTO_USE_EXISTING_CONFIG_FILE=y \
```
When the installation is completed, take note of any output it gives you for future reference. Then reboot the server to finalize the server installation.
```
```text
reboot
```
@@ -94,11 +96,10 @@ reboot
When you deploy iRedMail, it will give you a username and password for the postmaster account. If you accidentally forget to document this, you can log back into the server via SSH and see the credentials at `/root/iRedMail-$VERSION/iRedMail.tips`. This file is critical and contains passwords and DNS information such as DKIM record information as well.
## Networking Configuration
### Nested Reverse Proxy Configuration
In my homelab environment, I run Traefik reverse proxy in front of everything, which includes the NGINX reverse proxy that iRedMail creates. In my scenario, I have to make some custom adjustments to the reverse proxy dynamic configuration data to ensure it will step aside and let the NGINX reverse proxy inside of iRedMail handle everything, including handling its own SSL termination with Let's Encrypt.
``` sh
```sh
tcp:
routers:
mail-tcp-router:
@@ -121,7 +122,7 @@ At this point, we want to set up automatic Let's Encrypt SSL termination inside
#### Generate SSL Certificate
=== "Debian/Ubuntu"
``` sh
```sh
# Download the Certbot
sudo apt update
sudo apt install -y certbot
@@ -139,7 +140,7 @@ At this point, we want to set up automatic Let's Encrypt SSL termination inside
=== "CentOS/Rocky/AlmaLinux"
``` sh
```sh
# Download the Certbot
sudo yum install -y epel-release
sudo yum install -y certbot
@@ -156,15 +157,17 @@ At this point, we want to set up automatic Let's Encrypt SSL termination inside
```
#### Configure Automatic Renewal
To automate the renewal process, set up a cron job that runs the certbot renew command regularly. This command will renew certificates that are due to expire within 30 days.
To automate the renewal process, set up a cron job that runs the certbot renew command regularly. This command will renew certificates that are due to expire within 30 days.
Open the crontab editor with the following command:
```
```sh
sudo crontab -e
```
Add the following line to run the renewal process daily at 3:01 AM:
```
```text
1 3 * * * certbot renew --post-hook 'systemctl restart postfix dovecot nginx'
```
@@ -191,7 +194,7 @@ Lastly, we need to set up port forwarding to open the ports necessary for the se
## Install iRedAdmin-Pro
When it comes to adding extra features, start by copying the data from this [Bunny Lab repository](https://git.bunny-lab.io/bunny-lab/iRedAdmin-Pro-SQL) to the following folder by running these commands first:
``` sh
```sh
# Stop the iRedMail Services
sudo systemctl stop postfix dovecot nginx
@@ -212,14 +215,14 @@ At this point, if you want to use iRedAdmin-Pro, you either have a valid license
There is someone else who outlined all of these changes, and additional (aesthetic) ones, like removing the renew license button from the license page, but the core functionality is seen below. If you want to see the original repository this was inspired from, it can be found [Here](https://github.com/marcus-alicia/iRedAdmin-Pro-SQL)
``` sh
```sh
# Take permission of the python script
sudo chown nicole:nicole /opt/www/iRedAdmin-2.5/libs/sysinfo.py
```
=== "Original Activation Function"
```jsx title="/opt/www/iRedAdmin-2.5/libs/sysinfo.py"
```python title="/opt/www/iRedAdmin-2.5/libs/sysinfo.py"
def get_license_info():
if len(__id__) != 32:
web.conn_iredadmin.delete("updatelog")
@@ -251,7 +254,7 @@ sudo chown nicole:nicole /opt/www/iRedAdmin-2.5/libs/sysinfo.py
=== "Bypassed Activation Function"
```jsx title="/opt/www/iRedAdmin-2.5/libs/sysinfo.py"
```python title="/opt/www/iRedAdmin-2.5/libs/sysinfo.py"
def get_license_info():
return True, {
"status": "active",
@@ -267,7 +270,7 @@ sudo chown nicole:nicole /opt/www/iRedAdmin-2.5/libs/sysinfo.py
}
```
``` sh
```sh
# Revert permission of the python script
sudo chown iredadmin:iredadmin /opt/www/iRedAdmin-2.5/libs/sysinfo.py
@@ -277,3 +280,6 @@ sudo reboot
!!! success "Successful Activation"
At this point, if you navigate to the [iRedAdmin-Pro License Page](https://mail.bunny-lab.io/iredadmin/system/license) you should see the server is activated successfully.
## Related Documentation
- [Related Email Documentation](<../../../../reference/Applications/Email/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,10 +1,8 @@
---
tags:
- Mailcow
- Email
- Docker
- Mailcow
- Email
- Docker
---
## Purpose
@@ -23,10 +21,10 @@ apt install docker-compose-plugin # (3)
systemctl enable --now docker # (4)
```
1. Make yourself root.
2. Install `Docker`
3. Install `Docker-Compose`
4. Make docker run automatically when the server is booted.
1. Make yourself root.
2. Install `Docker`
3. Install `Docker-Compose`
4. Make docker run automatically when the server is booted.
### Download and Deploy Mailcow
Run the following commands to pull down the mailcow deployment files and install them with docker. Go get a cup of coffee as the `docker compose pull` command may take a while to run.
@@ -43,8 +41,8 @@ docker-compose pull # (2)
docker-compose up -d
```
1. Generate a configuration file. Use a FQDN (`host.domain.tld`) as hostname when asked.
2. If you get an error about the ports of the `nginx-mailcow` service in the `docker-compose.yml` stack, change the ports for that service as follows:
1. Generate a configuration file. Use a FQDN (`host.domain.tld`) as hostname when asked.
2. If you get an error about the ports of the `nginx-mailcow` service in the `docker-compose.yml` stack, change the ports for that service as follows:
```yaml
ports:
@@ -69,10 +67,10 @@ WAN :143 -> Mailcow :143
WAN :4190 -> Mailcow :4190
```
Mail protocol ports should be sent directly to the Mailcow server. Traefik should not terminate or proxy the SMTP, SMTPS, Submission, IMAP, IMAPS, POP3, POP3S, or ManageSieve ports.
Mail protocol ports should be sent directly to the Mailcow server. Traefik should not terminate or proxy the SMTP, SMTPS, Submission, IMAP, IMAPS, POP3, POP3S, or ManageSieve ports.
### Reverse-Proxy Configuration
For the purposes of this document, it will be assumed that you are deploying Mailcow behind Traefik for web traffic only. Traefik should pass HTTPS through transparently, allowing Mailcow to manage and serve its own certificates.
For the purposes of this document, it will be assumed that you are deploying Mailcow behind Traefik for web traffic only. Traefik should pass HTTPS through transparently, allowing Mailcow to manage and serve its own certificates.
You can use the following dynamic configuration file to achieve this:
@@ -120,7 +118,7 @@ tcp:
```
### Traefik-Specific Configuration
Traefik only needs the standard HTTP and HTTPS entrypoints for Mailcow web traffic. Mail protocol ports should not be exposed through Traefik if the firewall is forwarding those ports directly to Mailcow.
Traefik only needs the standard HTTP and HTTPS entrypoints for Mailcow web traffic. Mail protocol ports should not be exposed through Traefik if the firewall is forwarding those ports directly to Mailcow.
```yaml
#Entrypoints
@@ -156,11 +154,15 @@ docker compose restart postfix-mailcow dovecot-mailcow nginx-mailcow
### Login to Mailcow
At this point, the Mailcow server has been deployed so you can log into it.
* **Administrators**: `https://${MAILCOW_HOSTNAME}/admin` (Username: `admin` | Password: `moohoo`)
* **Regular Mailbox Users**: `https://${MAILCOW_HOSTNAME}` (*FQDN only*)
- **Administrators**: `https://${MAILCOW_HOSTNAME}/admin` (Username: `admin` | Password: `moohoo`)
- **Regular Mailbox Users**: `https://${MAILCOW_HOSTNAME}` (*FQDN only*)
### Mail-Client Considerations
You need to ensure that you generate an app password if you have MFA enabled within Mailcow. (MFA is non-functional in Roundcube/SoGo, you set it up via Mailcow itself). You can access it via the Mailcow configuration page: https://mail.bunny-lab.io/user, then look for the "**App Passwords**" tab.
### Running Updates
If you want to run updates, just SSH into the server, and navigate to `/opt/mailcow-dockerized` and run `./update.sh`. I recommend avoiding the IPv6 implementation section. Be patient, and the upgrade will be fully-automated.
## Related Documentation
- [Related Email Documentation](<../../../reference/Applications/Email/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,8 +5,8 @@ tags:
- Docker
---
## Purpose:
The Collabora CODE Server is used by Nextcloud Office to open and edit documents and spreadsheets collaboratively. When Nextcloud is not deployed in a [Nextcloud AIO](./nextcloud-aio.md) way, and is instead installed not as a container, you (may) run into stability issues with Collabora CODE Server just randomly breaking and not allowing users to edit documents. If this happens, you can follow this document to stand-up a dedicated Collabora CODE Server on the same host as your Nextcloud server.
## Purpose
The Collabora CODE Server is used by Nextcloud Office to open and edit documents and spreadsheets collaboratively. When Nextcloud is not deployed in a [Nextcloud AIO](<Nextcloud AIO.md>) way, and is instead installed not as a container, you (may) run into stability issues with Collabora CODE Server just randomly breaking and not allowing users to edit documents. If this happens, you can follow this document to stand-up a dedicated Collabora CODE Server on the same host as your Nextcloud server.
!!! info "Assumptions"
@@ -15,7 +15,7 @@ The Collabora CODE Server is used by Nextcloud Office to open and edit documents
- It is lastly assumed that (until changes are made to allow such) this will only work for internal access. Unless you port-forward port `9980` Collabora will not function for public internet-facing access.
### Install Docker and Configure Portainer
The first thing you need to do is install Docker then Portainer. You can do this by following the [Portainer Deployment](../../platforms/containerization/docker/deploy-portainer.md) documentation.
The first thing you need to do is install Docker then Portainer. You can do this by following the [Portainer Deployment](<../../Containers/Docker/Deploy Portainer.md>) documentation.
### Portainer Stack
```yaml title="docker-compose.yml"
@@ -67,6 +67,7 @@ CODESERVER_ADMIN_PASSWORD=ChangeThisPassword
## NGINX 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 title="/opt/collabora/nginx.conf"
map $http_upgrade $connection_upgrade {
default upgrade;
@@ -124,3 +125,5 @@ Now that the Collabora CODE Server was deployed and instructed to use the existi
### Administrating Collabora CODE Server
As aforementioned, we can manage Collabora CODE Server sessions and useful metrics about who is editing documents and being able to terminate their sessions if they get stuck or something can be useful. You can login to the management web interface at https://cloud.bunny-lab.io:9980/browser/dist/admin/admin.html using the `CODESERVER_ADMIN_USER` and `CODESERVER_ADMIN_PASSWORD` credentials.
## Related Documentation
- [Related Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -6,7 +6,7 @@ tags:
- Docker
---
**Purpose**:
## Purpose
Deploy a Nextcloud AIO Server. [Official Nextcloud All-in-One Documentation](https://github.com/nextcloud/all-in-one).
This version of Nextcloud consists of 12 containers that are centrally managed by a single "master" container. It is more orchestrated and automates the implementation of Nextcloud Office, Nextcloud Talk, and other integrations / apps.
@@ -167,3 +167,8 @@ It will ask you to provide a domain name. In this example, we will use `cloud.b
### Configuring Additional Packages
At this point, the rest of the setup is fairly straightforward. You just check every checkbox for the apps you want to install automatically, and be patient while Nextcloud deploys about 11 containers. You can track the progress more accurately if you log into Portainer and watch the container listing and logs to follow-along until every container reports "**Healthy**" indicating everything is ready, then press the "**Refresh**" button on the Nextcloud AIO WebUI to confirm it's ready to be used.
## Related Documentation
- [Collabora Office Integration](<Collabora Code Server.md>) — Review the standalone office-server option and its Nextcloud requirements.
- [Related Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Deploy a Nextcloud and PostgreSQL database together.
## Purpose
Deploy a Nextcloud and PostgreSQL database together.
```yaml title="docker-compose.yml"
version: "2.1"
@@ -69,3 +70,7 @@ NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=SomeSuperSecurePassword
NEXTCLOUD_TRUSTED_DOMAINS=cloud.bunny-lab.io
```
## 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 Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,76 @@
---
tags:
- OnlyOffice
- Productivity
- Docker
---
## Purpose
ONLYOFFICE offers a secure online office suite highly compatible with MS Office formats. Generally used with Nextcloud to edit documents directly within the web browser.
```yaml title="docker-compose.yml"
version: '3'
services:
app:
image: onlyoffice/documentserver-ee
ports:
- 80:80
- 443:443
volumes:
- /srv/containers/onlyoffice/DocumentServer/logs:/var/log/onlyoffice
- /srv/containers/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data
- /srv/containers/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice
- /srv/containers/onlyoffice/DocumentServer/db:/var/lib/postgresql
- /srv/containers/onlyoffice/DocumentServer/fonts:/usr/share/fonts/truetype/custom
- /srv/containers/onlyoffice/DocumentServer/forgotten:/var/lib/onlyoffice/documentserver/App_Data/cache/files/forgotten
- /srv/containers/onlyoffice/DocumentServer/rabbitmq:/var/lib/rabbitmq
- /srv/containers/onlyoffice/DocumentServer/redis:/var/lib/redis
labels:
- "traefik.enable=true"
- "traefik.http.routers.cyberstrawberry-onlyoffice.rule=Host(`office.cyberstrawberry.net`)"
- "traefik.http.routers.cyberstrawberry-onlyoffice.entrypoints=websecure"
- "traefik.http.routers.cyberstrawberry-onlyoffice.tls.certresolver=myresolver"
- "traefik.http.services.cyberstrawberry-onlyoffice.loadbalancer.server.port=80"
- "traefik.http.routers.cyberstrawberry-onlyoffice.middlewares=onlyoffice-headers"
- "traefik.http.middlewares.onlyoffice-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
#- "traefik.http.middlewares.onlyoffice-headers.headers.accessControlAllowOrigin=*"
environment:
- JWT_ENABLED=true
- JWT_SECRET=REDACTED #SET THIS TO SOMETHING SECURE
restart: always
networks:
docker_network:
ipv4_address: 192.168.5.143
networks:
default:
external:
name: docker_network
docker_network:
external: true
```
```yaml title=".env"
Not Applicable
```
!!! tip "Tip"
If you wish to use this in a non-commercial homelab environment without limits, [this script](https://wiki.muwahhid.ru/ru/Unraid/Docker/Onlyoffice-Document-Server) does an endless trial without functionality limits.
```text
docker stop office-document-server-ee
docker rm office-document-server-ee
rm -r /mnt/user/appdata/onlyoffice/DocumentServer
sleep 5
<USE A PORTAINER WEBHOOK TO RECREATE THE CONTAINER OR REFERENCE THE DOCKER RUN METHOD BELOW>
```
Docker Run Method:
```text
docker run -d --name='office-document-server-ee' --net='bridge' -e TZ="Europe/Moscow" -e HOST_OS="Unraid" -e 'JWT_ENABLED'='true' -e 'JWT_SECRET'='mySecret' -p '8082:80/tcp' -p '4432:443/tcp' -v '/mnt/user/appdata/onlyoffice/DocumentServer/logs':'/var/log/onlyoffice':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/data':'/var/www/onlyoffice/Data':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/lib':'/var/lib/onlyoffice':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/db':'/var/lib/postgresql':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/fonts':'/usr/share/fonts/truetype/custom':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/forgotten':'/var/lib/onlyoffice/documentserver/App_Data/cache/files/forgotten':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/rabbitmq':'/var/lib/rabbitmq':'rw' -v '/mnt/user/appdata/onlyoffice/DocumentServer/redis':'/var/lib/redis':'rw' 'onlyoffice/documentserver-ee'
```
## 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 Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -6,11 +6,11 @@ tags:
- Docker
---
**Purpose**: pyLoad-ng is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.
## Purpose
pyLoad-ng is a Free and Open Source download manager written in Python and designed to be extremely lightweight, easily extensible and fully manageable via web.
[Detailed LinuxServer.io Deployment Info](https://docs.linuxserver.io/images/docker-pyload-ng/)
## Docker Configuration
```yaml title="docker-compose.yml"
version: '3.9'
@@ -61,6 +61,7 @@ N/A
## 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:
@@ -84,3 +85,8 @@ http:
!!! warning "Change Default Admin Credentials"
Pyload ships with the username `pyload` and password `pyload`. Make sure you change the credentials immediately after initial login.
Navigate to "**Settings > Users > Pyload:"Change Password"**"
## 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 Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
## Purpose
This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -45,6 +46,7 @@ N/A
## 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:
@@ -64,3 +66,8 @@ http:
- url: http://192.168.5.54:8080
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 Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Build your personal knowledge base with [Trilium Notes](https://github.com/zadam/trilium/tree/master).
## Purpose
Build your personal knowledge base with [Trilium Notes](https://github.com/zadam/trilium/tree/master).
```yaml title="docker-compose.yml"
version: '2.1'
@@ -34,7 +35,7 @@ networks:
N/A
```
# Traefik Configuration
## Traefik Configuration
```yaml title="notes.bunny-lab.io.yml"
http:
routers:
@@ -54,3 +55,8 @@ http:
- url: http://192.168.5.11:8080
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 Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/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.
@@ -0,0 +1,134 @@
---
tags:
- DFS
- Windows Server
- Windows
- File Services
---
## Purpose
If you want data available from a single, consistent UNC path while hosting it on multiple file servers, use **DFS Namespaces (DFSN)**. A namespace presents a *virtual* folder tree (for example, `\\bunny-lab.io\Projects`) whose folders point to one or more **folder targets** (actual SMB shares on your servers).
**DFS Replication (DFSR)** is a *separate* feature you configure to keep the contents of those targets in sync.
This document walks through creating a domain-based DFS namespace and enabling DFS Replication for two servers.
!!! info "Assumptions"
You have two Windows Server machines (e.g., `LAB-FPS-01` and `LAB-FPS-02`) running an edition that supports DFS (Standard or Datacenter), both activated, domain-joined, and using static IPs.
### Installing Server Roles
Install the roles on **both servers**:
- **Server Manager → Manage → Add Roles and Features**
- Click **Next** to **Server Roles**
- Expand **File and Storage Services**
- Expand **File and iSCSI Services**
- Check **File Server**
- Check **DFS Namespaces**
- Check **DFS Replication**
- **Next → Next → Install**, then finish.
### Create and Configure Network Shares
Create (or identify) the folders you want to publish in the namespace, and share them on **each** server. Be sure to enable **Access-based Enumeration** on all of the folder shares for additional security. You only need to ensure that the files exist on one of the file servers,then you need to create empty top-level folders with the same names on the replica servers, data will be replicated automatically from the file server to the empty folders.
Additionally, it is recommended (if possible) to set the share names to be hidden. For example `\\LAB-FPS-01\Projects$`, that way it ensures that users access the share via DFS at `\\bunny-lab.io\Projects` and users don't accidentally access the network shares directly, bypassing DFS. For example, the local path would be `Z:\Projects` but the network share would be `\\LAB-FPS-01\Projects$`. *This wouldn't break things like replication, but it would muck things up a little bit organizationally. The data would still be replicated between both servers, we just dont want users using direct server shares like that, which bypasses the high-availability and load-balancing features of DFS*
!!! warning "What must match vs. what can differ"
- **Must exist on each server:** a shared folder to act as the *folder target* (path can differ per server).
- **Share permissions:** are **not replicated**; set them on each server.
- **NTFS permissions inside the replicated folder:** **are replicated** by DFSR and should be consistent.
- Targets do **not** have to use identical share names/paths, but keeping them consistent simplifies things.
| **Permission Type** | **User / Group** | **Access** | Level** |
| :---- | :---- | :---- | :---- |
| Share | `Everyone` (or `Authenticated Users`) | Full Control | Best practice is to grant broad Full Control on the **share** and enforce access with NTFS. |
| NTFS | `SYSTEM` | Full Control | Required for DFSR service. |
| NTFS | `Share_Admins` | Full Control | Optional admin group for data management. |
| NTFS | *Business groups needing access* | Modify | Grant least privilege to required users/groups. |
!!! info "Note On Inheritance"
Disabling inheritance is **not required** for DFS/DFSR. Keep it enabled unless you have a clear reason to flatten ACLs; inheritance often reduces long-term admin overhead.
### DFS Breakdown
A **namespace** is a logical view like `\\bunny-lab.io\Projects`. Inside it, you create DFS **folders** (e.g., `Scripting`) that point to one or more **folder targets**, such as:
- `\\LAB-FPS-01\Projects$\Scripting`
- `\\LAB-FPS-02\Projects$\Scripting`
The namespace root itself isn't where you store data; it's a directory of links. Place data in the folder targets the DFS folder points to.
### DFS Configuration
You can run these steps from either server (or any admin workstation with the RSAT tools). DFSN configuration is stored in AD and on namespace servers and applies across members automatically.
#### Create Namespace
- **Server Manager → Tools → DFS Management**
- Right-click **Namespaces** → **New Namespace...**
- Choose a server to host the namespace (e.g., `LAB-FPS-01`) → **Next**
- Name the namespace (e.g., `Projects`) → **Next**
- You can leave **Edit Settings** at defaults; those control the local folder that backs the namespace root, not your data.
- Choose **Domain-based namespace** and check **Enable Windows Server 2008 mode** (required for larger scale and Access-based enumeration).
- Resulting path: `\\bunny-lab.io\Projects`
- **Next → Create**
#### Make Namespace Highly-Available
We have to perform an extra step to ensure that every file server can act as within a multi-master context, allowing for high availability. To do this in this example, we will add `LAB-FPS-02` as a secondary namespace server for every namespace that we create.
- Right-Click **DFS Management** > **Namespaces** > `\\bunny-lab.io\Projects`
- Click **Add Namespace Server...**
- Under "Namespace Server" enter `LAB-FPS-02` then click **OK**.
#### Enable Access-Based Enumeration on Namespace
- Right-Click **DFS Management** > **Namespaces** > `\\bunny-lab.io\Projects`
- Click **Properties**
- Click **Advanced**
- Check **Enable access-based enumeration for this namespace**
- Click **OK**
#### Link Folders to Namespace
Create the DFS folders and add folder targets:
- Right-click the new namespace (e.g., `\\bunny-lab.io\Projects`) → **New Folder...**
- **Name:** `Scripting`
- **Add** folder targets (one per server), e.g.:
- `\\LAB-FPS-01\Projects$\Scripting`
- `\\LAB-FPS-02\Projects$\Scripting`
- You can simply copy-paste the previous server location and substitute the hostname (e.g. switching `01` to `02`) instead of browsing for the folder.
- You *may* be prompted to create the folder because it does not exist on `LAB-FPS-02`, in this circumstance, you can tell it to create the folder automatically with read-only permissions. *Don't worry, when replication from `LAB-FPS-01` occurs, NTFS permissions will be overwritten to the correct users and groups.*
- When prompted *"Create a replication group to synchronize the folder targets?"*, click **Yes** to launch the DFS Replication wizard.
!!! info "**Be patient**"
The Replication wizard can take ~1 minute to appear.
#### Configure Replication Group
In the Replication wizard that appears after about a minute, you can configure the replication group for the folder:
!!! bug "If Wizard did Not Appear (or Crashed)"
In my homelab testing, I had two times when the wizard crashed or simply never opened. If this happens to you, you can manually re-trigger the wizard for the target folder by right-clicking the folder (e.g. `\\bunny-lab.io\Projects\Scripting`) and selecting **Replicate Folder**.
- **Replication Group Name**: *(leave as suggested)*
- **Replicated Folder Name**: *(leave as suggested)*
- **Next → Next**
- **Primary member**: pick the server with the **most up-to-date** copy of the data (e.g., `LAB-FPS-01`).
!!! abstract "Replication Behavior and Expectations"
When you first create a replication group, DFSR needs a baseline copy of the data to start from. You designate one server as the Primary Member to serve as that baseline. (e.g. `LAB-FPS-01`) During the first sync, DFSR assumes that whatever exists on the primary member's folder is the "truth." So if the same file exists on another server (e.g. `LAB-FPS-02`) but with different timestamps, sizes, or hashes, the primary member's copy wins - but only during this first synchronization. After that initial sync is complete, the "primary" flag loses all authority. Replication becomes multi-master, meaning every member can make changes, and DFSR uses its conflict resolution algorithm (based on version vectors, update sequence numbers, and timestamps) to decide which change wins going forward. In other words, no server remains “the boss” after initialization. Files unique to other member servers that only exist on them will not be wiped and will be replicated across all member servers including the primary member.
- **Topology**: `Full mesh` (good for two servers; for many sites, consider hub-and-spoke).
- **Replication schedule**: leave **Full** (24x7) unless you need bandwidth windows.
- **Create**
!!! success "Replication group created"
You should see green ticks for the following. Give everything some time to replicate as it depends on active directory replication speeds to push out the configuration across the DFS member servers and begin the replication.
- ✅Create replication group
- ✅Create members
- ✅Update folder security
- ✅Create replicated folder
- ✅Create membership objects
- ✅Update folder properties
- ✅Create connections
## Validate and Maintain DFS
Use [the namespace and replication report](<../../../../scripts/Applications/Files and Collaboration/DFS/Report DFS Namespaces and Replication.md>) to inspect the deployed structure, then [check the directional replication backlog](<../../../../scripts/Applications/Files and Collaboration/DFS/Report DFS Replication Backlog.md>). If the management console shows inconsistent objects, follow [the console repair workflow](<../../../../workflows/Applications/Files and Collaboration/DFS/Repair an Inconsistent DFS Management Console.md>).
## Related Documentation
- [Related Files and Collaboration Documentation](<../../../../reference/Applications/Files and Collaboration/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: At its core, WordPress is the simplest, most popular way to create your own website or blog. In fact, WordPress powers over 43.3% of all the websites on the Internet. Yes – more than one in four websites that you visit are likely powered by WordPress.
## Purpose
At its core, WordPress is the simplest, most popular way to create your own website or blog. In fact, WordPress powers over 43.3% of all the websites on the Internet. Yes – more than one in four websites that you visit are likely powered by WordPress.
```yaml title="docker-compose.yml"
version: '3.7'
@@ -54,3 +55,7 @@ networks:
WORDPRESS_DB_PASSWORD=SecurePassword101
MYSQL_ROOT_PASSWORD=SecurePassword202
```
## 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 Files and Collaboration Documentation](<../../../reference/Applications/Files and Collaboration/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,7 +4,7 @@ tags:
- Gaming
---
**Purpose**:
## Purpose
This document outlines some of the prerequisites as well as deployment process for an ARK: Survival Ascended Server
## Prerequisites
@@ -13,20 +13,20 @@ We need to install the Visual C++ Redistributable for both x86 and x64
- [Download Visual C++ Redistributable (x64)](https://aka.ms/vs/17/release/vc_redist.x64.exe)
- [Download Visual C++ Redistributable (x86)](https://aka.ms/vs/17/release/vc_redist.x86.exe)
## Run Unreal Engine Certificate Trust Script
There is an issue where if you run a dedicated server, part of that requires API access to Epic Games and that will not work without installing a few certificates. The original Github page can be found [here](https://github.com/Ch4r0ne/UnrealEngine_Dedicated_Server_Install_CA/tree/main), which details the reason for it in more detail.
!!! note "Run as Administrator"
You need to run the command as an administrator. This command will download the script automatically and temporarily bypass the script execution policy to run the script:
```
```text
PowerShell -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/Ch4r0ne/UnrealEngine_Dedicated_Server_Install_CA/main/Install_Certificate.ps1' | iex"
```
## SteamCMD Deployment Script
You will need to make a folder somewhere on the computer, such as the desktop, and name it something like "ARK Updater", then put the following script into it. You will need to run this script before you can proceed to the next step.
```jsx title="C:\Users\nicole.rappe\Desktop\ARK_Updater\Update_Server.bat"
```text title="C:\Users\nicole.rappe\Desktop\ARK_Updater\Update_Server.bat"
@echo off
set STEAMCMDDIR="C:\SteamCMD\"
set SERVERDIR="C:\ASAServer\"
@@ -43,7 +43,7 @@ exit
## Launch Script
Now you need to configure a launch script to actually start the dedicated server. This can be placed anywhere, but I suggest putting it into `C:\asaserver\ShooterGame\Saved` along with the world save data.
```jsx title="C:\asaserver\ShooterGame\Saved\Launch_Server.bat"
```text title="C:\asaserver\ShooterGame\Saved\Launch_Server.bat"
@echo off
start C:\asaserver\ShooterGame\Binaries\Win64\ArkAscendedServer.exe ScorchedEarth_WP?listen?SessionName=BunnyLab?Port=7777?QueryPort=27015?ServerPassword=SomethingSecure?ServerAdminPassword=SomethingVerySecure -WinLiveMaxPlayers=50 -log -crossplay-enable-pc -crossplay-enable-wingdk -mods=928548,928621,928597,928818,929543,937546,930684,930404,940022,941697,930851,948051,932365,929420,967786,930494
exit
@@ -55,7 +55,7 @@ exit
## Dump Configuration .ini Files
At this point, you will want to launch the server and have someone join it so it can generate the necessary world files / configuration data. Then you will run the following commands in the console (from the server hosting the ARK server) in order to dump the configuration (ini) files to disk.
```
```text
enablecheats <AdminPassword>
cheat SaveWorld
cheat DoExit
@@ -70,3 +70,6 @@ You will find the dumped configuration files at `C:\asaserver\ShooterGame\Saved\
You may want to start a singleplayer world and set all of the configuration variables to your desired values, then load into the world. Once you have made landfall, quit out of the game to shut down the singleplayer world.
From this point, you can find your `Game.ini` and `GameUserSettings.ini` files in `steamapps\common\ARK Survival Ascended\ShooterGame\Saved\Config\Windows`. Simply copy these two files into your server's configuration folder located at `C:\asaserver\ShooterGame\Saved\Config\WindowsServer` and launch the server.
## Related Documentation
- [Related Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -6,7 +6,8 @@ tags:
- Docker
---
**Purpose**: Emulatorjs is a browser web based emulation portable to nearly any device for many retro consoles. A mix of emulators is used between Libretro and EmulatorJS.
## Purpose
Emulatorjs is a browser web based emulation portable to nearly any device for many retro consoles. A mix of emulators is used between Libretro and EmulatorJS.
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -43,6 +44,7 @@ N/A
## 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:
@@ -66,3 +68,8 @@ http:
!!! note
Port 80 = Frontend
Port 3000 = Management Backend
## 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 Applications Documentation](<../../../reference/Applications/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.
@@ -4,18 +4,21 @@ tags:
- Gaming
---
**Purpose**: Pterodactyl is the open-source game server management panel built with PHP, React, and Go. Designed with security in mind, Pterodactyl runs all game servers in isolated Docker containers while exposing a beautiful and intuitive UI to administrators and users.
## Purpose
Pterodactyl is the open-source game server management panel built with PHP, React, and Go. Designed with security in mind, Pterodactyl runs all game servers in isolated Docker containers while exposing a beautiful and intuitive UI to administrators and users.
[Official Website](https://pterodactyl.io/panel/1.0/getting_started.html)
!!! note
This documentation assumes you are running Rocky Linux 9.3 or higher.
**Install EPEL Repository and other tools**:
```bash
sudo yum -y install epel-release curl ca-certificates gnupg
```
**Add Redis Repository**:
```bash
sudo rpm --import https://packages.redis.io/gpg
echo "[redis6]
@@ -27,26 +30,33 @@ gpgkey=https://packages.redis.io/gpg" | sudo tee /etc/yum.repos.d/redis.repo
```
**Add MariaDB Repository**:
```bash
sudo curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
```
**Update Repositories List**:
```bash
sudo yum update
```
**Install Dependencies**:
Before installing PHP, check the available PHP versions in your enabled repositories. Install PHP and other dependencies as follows:
Before installing PHP, check the available PHP versions in your enabled repositories. Install PHP and other dependencies as follows:
```bash
sudo yum -y install php php-{common,cli,gd,mysql,mbstring,bcmath,xml,fpm,curl,zip} mariadb-server nginx tar unzip git redis
```
7. **Installing Composer**:
```bash
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
chmod +x /usr/local/bin/composer
```
This script should work well with Rocky Linux and similar RHEL-based distributions, using `yum` for package management. However, keep in mind that package names and versions may vary between repositories, so you might need to adjust them based on what's available in your system's repositories.
This script should work well with Rocky Linux and similar RHEL-based distributions, using `yum` for package management. However, keep in mind that package names and versions may vary between repositories, so you might need to adjust them based on what's available in your system's repositories.
## Related Documentation
- [Related Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,7 +4,7 @@ tags:
- Gaming
---
**Purpose**:
## Purpose
This document outlines some of the prerequisites as well as deployment process for an dedicated Valheim server.
## Prerequisites
@@ -16,7 +16,7 @@ We need to install the Visual C++ Redistributable for both x86 and x64
## SteamCMD Deployment Script
You will need to make a folder somewhere on the computer, such as the desktop, and name it something like "ARK Updater", then put the following script into it. You will need to run this script before you can proceed to the next step.
```jsx title="C:\Users\nicole.rappe\Downloads\SteamCMD\Update_Server.bat"
```text title="C:\Users\nicole.rappe\Downloads\SteamCMD\Update_Server.bat"
@echo off
steamcmd.exe +force_install_dir "C:\Valheim_Dedicated_Server" +login anonymous +app_update 896660 -beta public validate +quit
```
@@ -24,7 +24,7 @@ steamcmd.exe +force_install_dir "C:\Valheim_Dedicated_Server" +login anonymous +
## Launch Script
Now you need to configure a launch script to actually start the dedicated server. This can be placed anywhere, but I suggest putting it into `C:\asaserver\ShooterGame\Saved` along with the world save data.
```jsx title="C:\valheim_dedicated_server\Launch_Server.bat"
```text title="C:\valheim_dedicated_server\Launch_Server.bat"
@echo off
set SteamAppId=892970
@@ -37,3 +37,6 @@ valheim_server -nographics -batchmode -name "Bunny Lab" -port 2456 -world "Dedic
- Make a local copy of this script to avoid it being overwritten by steam.
- Minimum password length is 5 characters & Password cant be in the server name.
- You need to make sure the ports TCP/UDP 2456-2457 is being forwarded to your server through your server VM & firewall.
## Related Documentation
- [Related Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: A complete and local NVR designed for Home Assistant with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras.
## Purpose
A complete and local NVR designed for Home Assistant with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras.
```yaml title="docker-compose.yml"
version: "3.9"
@@ -54,3 +55,7 @@ networks:
```yaml title=".env"
FRIGATE_RTSP_PASSWORD=SomethingSecure101
```
## 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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts.
## Purpose
Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts.
```yaml title="docker-compose.yml"
version: '3'
@@ -42,3 +43,10 @@ networks:
```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.
- [Docker Macvlan Subinterface](<../../../workflows/Containers/Docker/Create a Macvlan Subinterface.md>) — Review the network setup documented for the home-automation environment.
- [Tuya Device Integration](<../../../workflows/Applications/Home Automation/Connect Tuya Smart Lights.md>) — Find the device reservations and local integration notes.
- [Frigate](<Frigate.md>) — Find the separately documented camera service.
- [Related Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Gatus Service Status Server.
## Purpose
Gatus Service Status Server.
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -59,6 +60,7 @@ N/A
## 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:
@@ -79,3 +81,8 @@ http:
- url: http://192.168.5.8:8080
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 Applications Documentation](<../../../reference/Applications/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: ntfy (pronounced notify) is a simple HTTP-based pub-sub notification service. It allows you to send notifications to your phone or desktop via scripts from any computer, and/or using a REST API. It's infinitely flexible, and 100% free software.
## Purpose
ntfy (pronounced notify) is a simple HTTP-based pub-sub notification service. It allows you to send notifications to your phone or desktop via scripts from any computer, and/or using a REST API. It's infinitely flexible, and 100% free software.
```yaml title="docker-compose.yml"
version: "2.1"
@@ -41,3 +42,7 @@ networks:
```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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,7 @@ tags:
- Docker
---
## Purpose:
## Purpose
Speedtest Tracker is a self-hosted application that monitors the performance and uptime of your internet connection over time.
[Detailed Configuration Reference](https://docs.speedtest-tracker.dev/getting-started/installation)
@@ -87,6 +87,7 @@ BASE64_APPKEY=SECUREAPPKEY
## 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:
@@ -106,3 +107,8 @@ http:
- url: http://192.168.5.38:80
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 Applications Documentation](<../../../reference/Applications/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Deploy Uptime Kuma uptime monitor to monitor services in the homelab and send notifications to various services.
## Purpose
Deploy Uptime Kuma uptime monitor to monitor services in the homelab and send notifications to various services.
```yaml title="docker-compose.yml"
version: '3'
@@ -38,3 +39,7 @@ networks:
```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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Detect website content changes and perform meaningful actions - trigger notifications via Discord, Email, Slack, Telegram, API calls and many more.
## Purpose
Detect website content changes and perform meaningful actions - trigger notifications via Discord, Email, Slack, Telegram, API calls and many more.
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -39,13 +40,14 @@ networks:
external: true
```
```jsx title=".env"
```ini title=".env"
N/A
```
## 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
```yaml
http:
routers:
changedetection:
@@ -64,3 +66,8 @@ http:
- url: http://192.168.5.49:5000
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 Applications Documentation](<../../../reference/Applications/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.
@@ -0,0 +1,40 @@
---
tags:
- CyberChef
- Security
- Docker
---
## Purpose
The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis.
```yaml title="docker-compose.yml"
version: "3.8"
services:
app:
image: mpepping/cyberchef:latest
container_name: cyberchef
environment:
- TZ=America/Denver
ports:
- 8000:8000
restart: always
networks:
docker_network:
ipv4_address: 192.168.5.55
networks:
default:
external:
name: docker_network
docker_network:
external: true
```
```ini title=".env"
N/A
```
## 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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,38 @@
---
tags:
- IT-Tools
- Security
- Docker
---
## Purpose
Collection of handy online tools for developers, with great UX.
```yaml title="docker-compose.yml"
version: "3"
services:
server:
image: corentinth/it-tools:latest
container_name: it-tools
environment:
- TZ=America/Denver
restart: always
ports:
- "80:80"
networks:
docker_network:
ipv4_address: 192.168.5.16
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 Applications Documentation](<../../../reference/Applications/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Deploys a SearX Meta Search Engine Server
## Purpose
Deploys a SearX Meta Search Engine Server
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -38,6 +39,7 @@ Not Applicable
## 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:
@@ -56,3 +58,8 @@ http:
- url: http://192.168.5.124:8080
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 Applications Documentation](<../../../reference/Applications/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.
+24
View File
@@ -0,0 +1,24 @@
---
tags:
- Applications
- Deployments
- Documentation
---
# Applications
## Purpose
Find deployments for applications. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Asset Management
- Communication
- Dashboards
- Email
- Files and Collaboration
- Gaming and Media
- Home Automation
- Monitoring
- Utilities
## Follow the Subject
[Applications](<../../reference/Applications/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Cross-platform backup tool for Windows, macOS & Linux with fast, incremental backups, client-side end-to-end encryption, compression and data deduplication. CLI and GUI included.
## Purpose
Cross-platform backup tool for Windows, macOS & Linux with fast, incremental backups, client-side end-to-end encryption, compression and data deduplication. CLI and GUI included.
```yaml title="docker-compose.yml"
version: '3.7'
@@ -39,12 +40,16 @@ networks:
docker_network:
external: true
```
!!! note "Credentials"
Your username will be `kopia@kopia-backup` and the password will be the value you set for `--server-password` in the entrypoint section of the compose file. The `KOPIA_PASSWORD:` is used by the backup repository, such as Backblaze B2, to encrypt/decrypt the backed-up data, and must be updated in the compose file if the repository is changed / updated.
```yaml title=".env"
KOPIA_ENRYPTION_PASSWORD=PasswordUsedToEncryptDataOnBackblazeB2
KOPIA_SERVER_PASSWORD=ThisIsUsedToLogIntoKopiaWebUI
KOPIA_SERVER_USERNAME=kopia@kopia-backup
```
## 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 Backup and Recovery Documentation](<../../reference/Backup and Recovery/index.md>) — Find the connected deployments, procedures, and references for this subject.
+16
View File
@@ -0,0 +1,16 @@
---
tags:
- Backup and Recovery
- Deployments
- Documentation
---
# Backup and Recovery
## Purpose
Find deployments for backup and recovery. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Kopia
## Follow the Subject
[Backup and Recovery](<../../reference/Backup and Recovery/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -4,11 +4,18 @@ tags:
- Networking
---
## Purpose
This document records the procedure for create the docker network. Follow the environment assumptions and commands below.
### Configure Docker Network
We want to use a dedicated subnet / network specifically for containers, so they don't trample over the **SERVER** and **LAN** networks. If you are unsure of the name of the network adapter, in this case `eth0`, just type `ipaddr` in the terminal to list the network interfaces to locate it.
```
```text
docker network create -d macvlan --subnet=192.168.5.0/24 --gateway=192.168.5.1 -o parent=eth0 docker_network
```
!!! note
Be sure to replace `eth0` with the correct interface name using `ip addr` in the terminal. e.g. It may appear as something else like `ens18`, etc. If the interface doesn't exist, Docker will produce an error complaining about it.
Be sure to replace `eth0` with the correct interface name using `ip addr` in the terminal. e.g. It may appear as something else like `ens18`, etc. If the interface doesn't exist, Docker will produce an error complaining about it.
## Related Documentation
- [Related Containers Documentation](<../../../reference/Containers/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,19 +5,22 @@ tags:
- Containerization
---
## Purpose
This document records the procedure for deploy portainer. Follow the environment assumptions and commands below.
### Update The Package Manager
We need to update the server before installing Docker
=== "Ubuntu Server"
``` sh
```sh
sudo apt update
sudo apt upgrade -y
```
=== "Rocky Linux"
``` sh
```sh
sudo dnf check-update
```
@@ -25,7 +28,8 @@ We need to update the server before installing Docker
Install Docker then deploy Portainer
Convenience Script:
```
```text
curl -fsSL https://get.docker.com | sudo sh
dockerd-rootless-setuptool.sh install
```
@@ -34,7 +38,7 @@ Alternative Methods:
=== "Ubuntu Server"
``` sh
```sh
sudo apt install docker.io -y
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /srv/containers/portainer:/data portainer/portainer-ee:latest # (1)
```
@@ -43,7 +47,7 @@ Alternative Methods:
=== "Rocky Linux"
``` sh
```sh
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable docker --now
@@ -54,10 +58,12 @@ Alternative Methods:
2. Be sure to set the `-v /srv/containers/portainer:/data` value to a safe place that gets backed up regularily.
### Configure Docker Network
I highly recomment setting up a [Dedicated Docker MACVLAN Network](../../../../reference/infrastructure/networking/docker-networking/docker-networking.md). You can use it to keep your containers on their own subnet.
I highly recomment setting up a [Dedicated Docker MACVLAN Network](<Create the Docker Network.md>). You can use it to keep your containers on their own subnet.
### Access Portainer WebUI
You will be able to access the Portainer WebUI at the following address: `https://<IP Address>:9443`
!!! warning
You need to be quick, as there is a timeout period where you wont be able to onboard / provision Portainer and will be forced to restart it's container. If this happens, you can find the container using `sudo docker container ls` proceeded by `sudo docker restart <ID of Portainer Container>`.
## Related Documentation
- [Related Containers Documentation](<../../../reference/Containers/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,69 @@
---
tags:
- Containers
- Docker
- Containerization
---
## Purpose
Docker container running Alpine Linux that automates and improves upon much of the script mentioned in the [Git Repo Updater](<../../../scripts/Automation/Gitea/Git Repo Updater.md>) document. It offers the additional benefits of checking for updates every 5 seconds instead of every 60 seconds. It also accepts environment variables to provide credentials and notification settings, and can have an infinite number of monitored repositories.
!!! info "Earlier Configuration Delivery Approach"
The Gitea runners blog records replacing this polling approach for the documented configuration-delivery use case. The configuration-delivery reference links both runner implementations and this retained watcher deployment.
### Deployment
You can find the current up-to-date Gitea repository that includes the `docker-compose.yml` and `.env` files that you need to deploy everything [here](https://git.bunny-lab.io/container-registry/-/packages/container/git-repo-updater/latest)
```yaml title="docker-compose.yml"
version: '3.3'
services:
git-repo-updater:
privileged: true
container_name: git-repo-updater
env_file:
- stack.env
image: git.bunny-lab.io/container-registry/git-repo-updater:latest
volumes:
- /srv/containers:/srv/containers
- /srv/containers/git-repo-updater/Repo_Cache:/root/Repo_Cache
restart: always
```
```ini title=".env"
# Gitea Credentials
GIT_USERNAME=nicole.rappe
GIT_PASSWORD=USE-AN-APP-PASSWORD
# NTFY Push Notification Server URL
NTFY_URL=https://ntfy.cyberstrawberry.net/git-repo-updater
# Repository/Destination Pairs (Add as Many as Needed)
REPO_01="https://${GIT_USERNAME}:${GIT_PASSWORD}@git.bunny-lab.io/bunny-lab/docs.git,/srv/containers/material-mkdocs/docs/docs"
REPO_02="https://${GIT_USERNAME}:${GIT_PASSWORD}@git.bunny-lab.io/GitOps/servers.bunny-lab.io.git,/srv/containers/homepage-docker"
```
### Build / Development
If you want to learn how the container was assembled, the related build files are located [here](https://git.cyberstrawberry.net/container-registry/git-repo-updater)
```dockerfile title="Dockerfile"
# Use Alpine as the base image of the container
FROM alpine:latest
# Install necessary packages
RUN apk --no-cache add git curl rsync
# Add script
COPY repo_watcher.sh /repo_watcher.sh
RUN chmod +x /repo_watcher.sh
#Create Directory to store Repositories
RUN mkdir -p /root/Repo_Cache
# Start script (Alpine uses /bin/sh instead of /bin/bash)
CMD ["/bin/sh", "-c", "/repo_watcher.sh"]
```
Save the complete [Git Repo Updater script](<../../../scripts/Automation/Gitea/Git Repo Updater.md>) as `repo_watcher.sh` next to the Dockerfile before building the image.
## Related Documentation
- [Related Containers Documentation](<../../../reference/Containers/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,11 +4,11 @@ tags:
- Containerization
---
# Deploy Generic Kubernetes
## Purpose
The instructions outlined below assume you are deploying the environment using Ansible Playbooks either via Ansible's CLI or AWX.
### Deploy K8S User
```jsx title="01-deploy-k8s-user.yml"
```yaml title="01-deploy-k8s-user.yml"
- hosts: 'controller-nodes, worker-nodes'
become: yes
@@ -29,7 +29,7 @@ The instructions outlined below assume you are deploying the environment using A
```
### Install K8S
```jsx title="02-install-k8s.yml"
```yaml title="02-install-k8s.yml"
---
- hosts: "controller-nodes, worker-nodes"
remote_user: nicole
@@ -110,7 +110,7 @@ The instructions outlined below assume you are deploying the environment using A
```
### Configure ControlPlanes
```jsx title="03-configure-controllers.yml"
```yaml title="03-configure-controllers.yml"
- hosts: controller-nodes
become: yes
@@ -159,7 +159,7 @@ The instructions outlined below assume you are deploying the environment using A
```
### Join Worker Node(s)
```jsx title="04-join-worker-nodes.yml"
```yaml title="04-join-worker-nodes.yml"
- hosts: worker-nodes
become: yes
gather_facts: yes
@@ -179,7 +179,7 @@ The instructions outlined below assume you are deploying the environment using A
```
### Host Inventory File Template
```jsx title="hosts"
```text title="hosts"
[controller-nodes]
k8s-ctrlr-01 ansible_host=192.168.3.6 ansible_user=nicole
@@ -191,3 +191,6 @@ k8s-node-02 ansible_host=192.168.3.5 ansible_user=nicole
ansible_become_user=root
ansible_become_method=sudo
```
## Related Documentation
- [Related Containers Documentation](<../../../reference/Containers/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -6,7 +6,7 @@ tags:
- Containerization
---
# Deploy RKE2 Cluster
## Purpose
Deploying a Rancher RKE2 Cluster is fairly straightforward. Just run the commands in-order and pay attention to which steps apply to all machines in the cluster, the controlplanes, and the workers.
!!! note "Prerequisites"
@@ -17,7 +17,8 @@ Assume all commands are running as root moving forward. (e.g. `sudo su`)
### Run Updates
You will need to run these commands on every server that participates in the cluster then perform a reboot of the server **PRIOR** to moving onto the next section.
``` sh
```sh
apt update && apt upgrade -y
apt install nfs-common iptables nano htop -y
echo "Adding 15 Second Delay to Ensure Previous Commands finish running"
@@ -25,19 +26,22 @@ sleep 15
apt autoremove -y
reboot
```
!!! 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.
## Initial ControlPlane Node
When you are starting a brand new cluster, you need to create what is referred to as the "Initial ControlPlane". This node is responsible for bootstrapping the entire cluster together in the beginning, and will eventually assist in handling container workloads and orchestrating operations in the cluster.
!!! warning
You only want to follow the instructions for the **initial** controlplane once. Running it on another machine to create additional controlplanes will cause the cluster to try to set up two different clusters, wrecking havok. Instead, follow the instructions in the next section to add redundant controlplanes.
### Download the Run Server Deployment Script
```
```text
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=server sh -
```
### Enable & Configure Services
``` sh
### Enable and Configure Services
```sh
# Start and Enable the Kubernetes Service
systemctl enable --now rke2-server.service
@@ -59,14 +63,15 @@ kubectl get node
When the cluster is ready, you should see something like this when you run `kubectl get node`
This may be a good point to step away for 5 minutes, get a cup of coffee, and come back so it has a little extra time to be fully ready before moving on.
```
```text
root@awx:/home/nicole# kubectl get node
NAME STATUS ROLES AGE VERSION
awx Ready control-plane,etcd,master 3m21s v1.26.12+rke2r1
```
### Install Helm, Rancher, CertManager, Jetstack, Rancher, and Longhorn
``` sh
```sh
# Install Helm
curl -L https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4 | bash
@@ -94,7 +99,8 @@ helm upgrade -i longhorn longhorn/longhorn --namespace longhorn-system --create-
If you want to keep an eye on the deployment progress, you need to run the following command: `KUBECONFIG=/etc/rancher/rke2/rke2.yaml kubectl get pods --all-namespaces`
The output should look like how it does below:
```
```text
NAMESPACE NAME READY STATUS RESTARTS AGE
cattle-fleet-system fleet-controller-59cdb866d7-94r2q 1/1 Running 0 4m31s
cattle-fleet-system gitjob-f497866f8-t726l 1/1 Running 0 4m31s
@@ -159,7 +165,8 @@ At this point, you can log into the webUI at https://rke2-cluster.bunny-lab.io u
### Rebooting the ControlNode
If you ever find yourself needing to reboot the ControlNode, and need to run kubectl CLI commands, you will need to run the command below to import the cluster credentials upon every reboot. Reboots should take much less time to get the cluster ready again as compared to the original deployments.
```
```sh
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
```
@@ -167,11 +174,12 @@ export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
This is the part where you can add additional controlplane nodes to add additional redundancy to the RKE2 Cluster. This is important for high-availability environments.
### Download the Server Deployment Script
``` sh
```sh
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=server sh -
```
### Configure and Connect to Existing/Initial ControlPlane Node
``` sh
```sh
# Symlink the Kubectl Management Command
ln -s $(find /var/lib/rancher/rke2/data/ -name kubectl) /usr/local/bin/kubectl
@@ -183,11 +191,12 @@ echo "server: https://192.168.3.69:9345" > /etc/rancher/rke2/config.yaml
# Inject the Initial ControlPlane Node trust token into the config file
# You can get the token by running the following command on the first node in the cluster: `cat /var/lib/rancher/rke2/server/node-token`
echo "token: K10aa0632863da4ae4e2ccede0ca6a179f510a0eee0d6d6eb53dca96050048f055e::server:3b130ceebfbb7ed851cd990fe55e6f3a" >> /etc/rancher/rke2/config.yaml
echo "token: <RKE2_CLUSTER_TOKEN>" >> /etc/rancher/rke2/config.yaml
# Start and Enable the Kubernetes Service
systemctl enable --now rke2-server.service
```
!!! note
Be sure to change the IP address of the initial controlplane node provided in the example above to match your environment.
@@ -195,11 +204,12 @@ systemctl enable --now rke2-server.service
Worker nodes are the bread-and-butter of a Kubernetes cluster. They handle running container workloads, and acting as storage for the cluster (this can be configured to varying degrees based on your needs).
### Download the Server Worker Script
``` sh
```sh
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent sh -
```
### Configure and Connect to RKE2 Cluster
``` sh
```sh
# Manually Create a Rancher-Kubernetes-Specific Config File
mkdir -p /etc/rancher/rke2/
@@ -208,7 +218,7 @@ echo "server: https://192.168.3.21:9345" > /etc/rancher/rke2/config.yaml
# Inject the Initial ControlPlane Node trust token into the config file
# You can get the token by running the following command on the first node in the cluster: `cat /var/lib/rancher/rke2/server/node-token`
echo "token: K10aa0632863da4ae4e2ccede0ca6a179f510a0eee0d6d6eb53dca96050048f055e::server:3b130ceebfbb7ed851cd990fe55e6f3a" >> /etc/rancher/rke2/config.yaml
echo "token: <RKE2_CLUSTER_TOKEN>" >> /etc/rancher/rke2/config.yaml
# Start and Enable the Kubernetes Service**
systemctl enable --now rke2-agent.service
@@ -224,3 +234,6 @@ Once you have added the DNS record, you should be able to access the login page
| HOST FILE | rke2-cluster.bunny-lab.io | 192.168.3.69 |
| REVERSE PROXY | http://rke2-cluster.bunny-lab.io:80 | 192.168.5.29 |
| DNS RECORD | A Record: rke2-cluster.bunny-lab.io | 192.168.3.69 |
## Related Documentation
- [Related Containers Documentation](<../../../reference/Containers/index.md>) — Find the connected deployments, procedures, and references for this subject.
+17
View File
@@ -0,0 +1,17 @@
---
tags:
- Containers
- Deployments
- Documentation
---
# Containers
## Purpose
Find deployments for containers. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Docker
- Kubernetes
## Follow the Subject
[Containers](<../../reference/Containers/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -6,22 +6,22 @@ tags:
---
## Purpose
This document outlines the Microsoft-recommended best practices for deploying a secure, internal-use-only, two-tier Public Key Infrastructure (PKI) using Windows Server 2022 or newer. The PKI supports securing S/MIME email, 802.1X Wi-Fi with NPS, and LDAP over SSL (LDAPS).
This document outlines the Microsoft-recommended best practices for deploying a secure, internal-use-only, two-tier Public Key Infrastructure (PKI) using Windows Server 2022 or newer. The PKI supports securing S/MIME email, 802.1X Wi-Fi with NPS, and LDAP over SSL (LDAPS).
!!! abstract "CA Deployment Breakdown"
The environment will consist of at least 2 virtual machines. For the purposes of this document they will be named `LAB-CA-01` and `LAB-CA-02`. This stands for "*Lab Certificate Authority [01|02]*". In a two-tier hierarchy, an offline (*you intentionally keep this VM offline*) Root CA signs a single "*Subordinate*" Enterprise CA certificate. The Subordinate CA is domain-joined and handles all certificate requests. Clients trust the PKI via Group Policy and Active Directory integration.
The environment will consist of at least 2 virtual machines. For the purposes of this document they will be named `LAB-CA-01` and `LAB-CA-02`. This stands for "*Lab Certificate Authority [01|02]*". In a two-tier hierarchy, an offline (*you intentionally keep this VM offline*) Root CA signs a single "*Subordinate*" Enterprise CA certificate. The Subordinate CA is domain-joined and handles all certificate requests. Clients trust the PKI via Group Policy and Active Directory integration.
In this case, `LAB-CA-01` is the Root CA, while `LAB-CA-02` is the Intermediary/Subordinate CA. You can add more than one subordinate CA if you desire more redundancy in your environment. Making them operate together is generally automatic and does not require manual intervention.
!!! warning "Critical PKI Revocation Requirement"
CRL Distribution Points (CDP) and Authority Information Access (AIA) are required for this deployment, even if the immediate use case is only LDAPS. Certificate chain validation and revocation checking still occur for CA certificates and issued certificates. If CDP/AIA is missing, invalid, or unreachable, the Subordinate CA service may fail to start with revocation-related errors such as `0x80092013 (CRYPT_E_REVOCATION_OFFLINE)`.
CRL Distribution Points (CDP) and Authority Information Access (AIA) are required for this deployment, even if the immediate use case is only LDAPS. Certificate chain validation and revocation checking still occur for CA certificates and issued certificates. If CDP/AIA is missing, invalid, or unreachable, the Subordinate CA service may fail to start with revocation-related errors such as `0x80092013 (CRYPT_E_REVOCATION_OFFLINE)`.
!!! note "Certificate Authority Server Provisioning Assumptions"
- OS = Windows Server 2022/2025 bare-metal or as a VM
- You should give it at least 4GB of RAM.
- [Change the edition of Windows Server from "**Evaluation**" to "**Standard**" via DISM](../../../../workflows/operations/windows/change-windows-edition.md)
- [Change the edition of Windows Server from "**Evaluation**" to "**Standard**" via DISM](<../../../workflows/Windows and Linux/Windows/Change Windows Edition.md>)
- Ensure the server is fully updated
- [Ensure the server is activated](../../../../workflows/operations/windows/change-windows-edition.md#force-activation-edition-switcher)
- [Ensure the server is activated](<../../../workflows/Windows and Linux/Windows/Change Windows Edition.md#force-activation-edition-switcher>)
- Ensure the timezone is correctly configured
- Ensure the hostname is correctly configured
@@ -33,9 +33,9 @@ This document outlines the Microsoft-recommended best practices for deploying a
- `pki.bunny-lab.io`
This DNS name should resolve to the server hosting the PKI publication directory. In this deployment, the HTTP distribution point is hosted on `LAB-CA-02`.
This DNS name should resolve to the server hosting the PKI publication directory. In this deployment, the HTTP distribution point is hosted on `LAB-CA-02`.
This indirection is intentional. Certificate CDP/AIA URLs are embedded into issued certificates, so they should point to a stable DNS name rather than directly coupling clients to a CA hostname.
This indirection is intentional. Certificate CDP/AIA URLs are embedded into issued certificates, so they should point to a stable DNS name rather than directly coupling clients to a CA hostname.
## Offline (Non-Domain-Joined) Root CA `LAB-CA-01`
### Role Deployment
@@ -54,7 +54,7 @@ This is the initial deployment of the root certificate authority, the settings h
- `Certification Authority Web Enrollment`
- When prompted to confirm multiple times, click the "**Add Features**" button
- Ensure the "**Include management tools (if applicable)**" checkbox is checked.
- The Root CA still requires properly configured CDP and AIA publication settings. These are configured after the CA role is installed and before the Subordinate CA certificate is issued.
- The Root CA still requires properly configured CDP and AIA publication settings. These are configured after the CA role is installed and before the Subordinate CA certificate is issued.
- Click "**Next**" > "**Next**" > "**Next**" > "**Install**"
- Restart the Server
@@ -68,7 +68,7 @@ We have a few things we need to configure within the CA to make it ready to hand
- Check the "**Root CA** radio box then click "**Next**"
- Check the "**Create a new private key**" radio box then click "**Next**"
- Click the dropdown menu for "**Select a crypotographic provider**" and ensure that "**RSA#Microsoft Software Key Storage Provider**" is selected
- *Microsoft Software Key Storage Provider (KSP) is the latest, most flexible provider designed to work with the Cryptography Next Generation (CNG) APIs. It offers better support for modern algorithms and improved security management (such as support for key attestation, better hardware integration, and improved key protection mechanisms).*
- *Microsoft Software Key Storage Provider (KSP) is the latest, most flexible provider designed to work with the Cryptography Next Generation (CNG) APIs. It offers better support for modern algorithms and improved security management (such as support for key attestation, better hardware integration, and improved key protection mechanisms).*
- Set the key length to `4096`
- Set the hash algorithm to `SHA256`
- Click "**Next**"
@@ -96,12 +96,12 @@ You will see a finalization screen confirming everything we have configured, it
If everything went well, you will see that the "**Certificate Authority**" and "**Certification Authority Web Enrollment**" both have a status of "**Configuration succeeded**". At this point, you can click the "**Close**" button to conclude the Root CA configuration.
### Configure Root CA CDP and AIA Publication URLs
Before the Root CA issues the Subordinate CA certificate, configure CDP and AIA publication URLs. These settings control what revocation and CA certificate locations are embedded into certificates issued by the Root CA.
Before the Root CA issues the Subordinate CA certificate, configure CDP and AIA publication URLs. These settings control what revocation and CA certificate locations are embedded into certificates issued by the Root CA.
!!! warning "PowerShell Syntax"
The following commands are written for PowerShell. Use single percent signs such as `%3%8%9.crl`.
The following commands are written for PowerShell. Use single percent signs such as `%3%8%9.crl`.
If using `cmd.exe`, percent escaping may differ. Do not paste caret-based (`^`) line continuations into PowerShell.
If using `cmd.exe`, percent escaping may differ. Do not paste caret-based (`^`) line continuations into PowerShell.
On `LAB-CA-01`, run:
@@ -267,7 +267,7 @@ Now that we have set up the root certificate authority, we can focus on setting
- Check the "**Subordinate CA**" radio box then click "**Next**"
- Check the "**Create a new private key**" radio box then click "**Next**"
- Click the dropdown menu for "**Select a crypotographic provider**" and ensure that "**RSA#Microsoft Software Key Storage Provider**" is selected
- *Microsoft Software Key Storage Provider (KSP) is the latest, most flexible provider designed to work with the Cryptography Next Generation (CNG) APIs. It offers better support for modern algorithms and improved security management (such as support for key attestation, better hardware integration, and improved key protection mechanisms).*
- *Microsoft Software Key Storage Provider (KSP) is the latest, most flexible provider designed to work with the Cryptography Next Generation (CNG) APIs. It offers better support for modern algorithms and improved security management (such as support for key attestation, better hardware integration, and improved key protection mechanisms).*
- Set the key length to `4096`
- Set the hash algorithm to `SHA256`
- Click "**Next**"
@@ -340,15 +340,19 @@ At this point, we will need to focus on getting the certificate signing request
- Browse to the `RootCA.cer` file exported from `LAB-CA-01`
- Place all certificates in the following store: "Trusted Root Certification Authorities"
- Click "**Next**" and finish importing the Root CA certificate
- Do **not** rely on manually importing the Root CA CRL into a certificate store as the revocation strategy. Revocation should be validated through the HTTP CDP URL embedded in the issued certificates.
- Do **not** rely on manually importing the Root CA CRL into a certificate store as the revocation strategy. Revocation should be validated through the HTTP CDP URL embedded in the issued certificates.
- Verify Root CA CRL retrieval from `LAB-CA-02`:
```powershell
Invoke-WebRequest http://pki.bunny-lab.io/pki/BunnyLab-RootCA.crl
```
- Verify the Subordinate CA certificate chain and revocation status:
```powershell
certutil -verify -urlfetch LAB-CA-02-SubCA.cer
```
- Right-click the CA node in the treeview on the left-hand sidebar (e.g. `BunnyLab-SubordinateCA-01`)
- Click on "**All Tasks" > "Start Service**"
- Verify that the CA status is now green (running).
@@ -401,12 +405,12 @@ C:\inetpub\wwwroot\pki\
Validate HTTP access to the Subordinate CA CRL and certificate after copying them to IIS.
!!! note "Subordinate CA Publication"
The Root CA signs the Subordinate CA certificate. The Subordinate CA signs domain/server/client certificates. Therefore, clients need access to both Root CA revocation data and Subordinate CA revocation data.
The Root CA signs the Subordinate CA certificate. The Subordinate CA signs domain/server/client certificates. Therefore, clients need access to both Root CA revocation data and Subordinate CA revocation data.
## Reissuing the Subordinate CA Certificate After CDP/AIA Corrections
If the Root CA CDP/AIA settings were configured or corrected after the original Subordinate CA certificate was issued, the Subordinate CA certificate must be reissued.
This is required because CDP/AIA values are embedded into issued certificates at issuance time. Changing the Root CA registry values later does not retroactively fix already-issued Subordinate CA certificates.
This is required because CDP/AIA values are embedded into issued certificates at issuance time. Changing the Root CA registry values later does not retroactively fix already-issued Subordinate CA certificates.
### Generate a New Subordinate CA Renewal Request
On `LAB-CA-02`, run:
@@ -415,7 +419,7 @@ On `LAB-CA-02`, run:
certutil -renewCert ReuseKeys
```
If prompted to submit the request to an online parent CA, click **Cancel**. This is expected for an offline Root CA workflow. A new `.req` file will be generated locally.
If prompted to submit the request to an online parent CA, click **Cancel**. This is expected for an offline Root CA workflow. A new `.req` file will be generated locally.
### Submit the Renewal Request to the Root CA
Copy the generated `.req` file to `LAB-CA-01`.
@@ -479,7 +483,7 @@ The Certificate Auto-Enrollment Group Policy enables domain-joined devices (*com
- Run a `gpupdate /force` on your domain controller(s) and give it a few minutes to pull down their new domain controller certificates
!!! note "Reissuing Certificates After PKI Corrections"
If any machine certificates, domain controller certificates, terminal server certificates, NPS certificates, or other service certificates were issued before CDP/AIA was configured correctly, reissue them. Old certificates may continue to work in some paths, but revocation checking and chain validation may be inconsistent.
If any machine certificates, domain controller certificates, terminal server certificates, NPS certificates, or other service certificates were issued before CDP/AIA was configured correctly, reissue them. Old certificates may continue to work in some paths, but revocation checking and chain validation may be inconsistent.
For auto-enrolled certificates, use:
@@ -550,104 +554,11 @@ Run an equivalent check for the Subordinate CA CRL after confirming the exact ge
C:\Windows\System32\CertSrv\CertEnroll\
```
## CRL Publishing and Maintenance
CRLs must be generated and published on a recurring basis. If a CRL expires, certificate validation may fail even if the CA services themselves are running.
## Maintain Certificate Revocation Lists
After deployment, use [Publish and Maintain Certificate Revocation Lists](<../../../workflows/Identity and Certificates/Certificates/Publish and Maintain Certificate Revocation Lists.md>) for recurring publication and monitoring.
### Root CA CRL Publishing
Because the Root CA is offline, periodically bring it online only long enough to generate a new CRL and copy it to the HTTP distribution point.
## Connect LDAPS Clients
Use [Export Certificates for LDAPS Clients](<../../../workflows/Identity and Certificates/Certificates/Export Certificates for LDAPS Clients.md>) when an application needs the certificate chain.
On `LAB-CA-01`:
```powershell
certutil -crl
```
Copy the generated CRL from:
```text
C:\Windows\System32\CertSrv\CertEnroll\
```
to the IIS publication directory on `LAB-CA-02`:
```text
C:\inetpub\wwwroot\pki\
```
Validate:
```powershell
Invoke-WebRequest http://pki.bunny-lab.io/pki/BunnyLab-RootCA.crl
```
### Subordinate CA CRL Publishing
On `LAB-CA-02`:
```powershell
certutil -crl
```
Copy or confirm the Subordinate CA CRL exists in:
```text
C:\inetpub\wwwroot\pki\
```
Validate the URL from a domain-joined system.
### Operational Monitoring
Monitor CRL expiration and publication. Certificate validation failures can occur if CRLs expire, even if certificates themselves have not expired.
Recommended operational tasks:
- Track Root CA CRL expiration.
- Track Subordinate CA CRL expiration.
- Verify HTTP CRL URLs after each publication.
- Keep the Root CA offline except during controlled maintenance windows.
- Document the expected CRL filenames generated in `C:\Windows\System32\CertSrv\CertEnroll\`.
!!! abstract "Raw Unprocessed/Unimplemented Steps"
Publish CRLs regularly, configure overlap periods, and monitor expiration. Enable Delta CRLs on the Subordinate CA, but not on the Root.
Security Recommendations
- Harden CA servers; limit access to PKI admins.
- Use BitLocker or HSM for key protection.
- Monitor issuance and renewals with audit logs and scripts.
## Export the LDAPS Certificate for Third-Party Applications
Some applications do not automatically trust your internal PKI and require you to manually install the certificate used by your domain controllers for LDAPS. In most cases, you should export the issuing CA certificates rather than the individual domain controller certificate. Only export the domain controller certificate if the third-party application explicitly requires it.
### Export the Root and Subordinate CA Certificates
The Root CA and Subordinate CA certificates establish trust for every domain controller certificate issued by your PKI.
From any domain-joined system:
* Launch `certlm.msc`
* Navigate to "**Trusted Root Certification Authorities > Certificates**"
* Locate your Root CA certificate
* Right-click the certificate and select "**All Tasks > Export...**"
* Select "**No, do not export the private key**"
* Export the certificate as either:
* `DER encoded binary X.509 (.CER)`, or
* `Base-64 encoded X.509 (.CER)`
* Navigate to "**Intermediate Certification Authorities > Certificates**"
* Locate your Subordinate CA certificate
* Repeat the export process
Import both certificates into the trusted certificate store required by the third-party application.
### Export a Domain Controller Certificate
If the application requires the LDAPS server certificate itself:
* On the target domain controller, launch `certlm.msc`
* Navigate to "**Personal > Certificates**"
* Locate the certificate issued to the domain controller's FQDN that includes **Server Authentication** as an intended purpose
* If the certificate's intended purpose looks like `Client Authentication, Server Authentication, Smart Card Logon, KDC Authentication` this cert may be more versatile for you.
* Right-click the certificate and select "**All Tasks > Export...**"
* Select "**No, do not export the private key**"
* Export the certificate as either:
* `DER encoded binary X.509 (.CER)`, or
* `Base-64 encoded X.509 (.CER)`
!!! warning "Do Not Export the Private Key"
Third-party LDAPS clients require only the public certificate. Do **not** export the certificate as a `.pfx` file or include the private key unless the vendor explicitly documents that requirement.
## Related Documentation
- [Related Identity and Certificates Documentation](<../../../reference/Identity and Certificates/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies.
## Purpose
Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies.
```yaml title="docker-compose.yml"
services:
@@ -47,6 +48,6 @@ networks:
external: true
```
```jsx 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 Identity and Certificates Documentation](<../../reference/Identity and Certificates/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,11 +5,12 @@ tags:
- Docker
---
## Purpose
Authentik is an open-source Identity Provider, focused on flexibility and versatility. With authentik, site administrators, application developers, and security engineers have a dependable and secure solution for authentication in almost any type of environment. There are robust recovery actions available for the users and applications, including user profile and password management. You can quickly edit, deactivate, or even impersonate a user profile, and set a new password for new users or reset an existing password.
!!! bug
The docker-compose version of the deployment appears bugged and has known issues, deployment via Kubernetes is required to stability and support.
**Purpose**: Authentik is an open-source Identity Provider, focused on flexibility and versatility. With authentik, site administrators, application developers, and security engineers have a dependable and secure solution for authentication in almost any type of environment. There are robust recovery actions available for the users and applications, including user profile and password management. You can quickly edit, deactivate, or even impersonate a user profile, and set a new password for new users or reset an existing password.
This document is based on the [Official Docker-Compose Documentation](https://goauthentik.io/docs/installation/docker-compose). It is meant for testing / small-scale production deployments.
## Docker Configuration
@@ -155,7 +156,8 @@ To start the initial setup, navigate to https://192.168.5.4:9443/if/flow/initial
## 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
```yaml
http:
routers:
PLACEHOLDER:
@@ -173,3 +175,8 @@ http:
- url: http://PLACEHOLDER:80
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 Identity and Certificates Documentation](<../../reference/Identity and Certificates/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,15 @@ tags:
- Docker
---
**Purpose**: Keycloak is an open source identity and access management system for modern applications and services.
## Purpose
Keycloak is an open source identity and access management system for modern applications and services.
- [Original Reference Compose File](https://github.com/JamesTurland/JimsGarage/blob/main/Keycloak/docker-compose.yaml)
- [Original Reference Deployment Video](https://www.youtube.com/watch?v=6ye4lP9EA2Y)
- [Theme Customization Documentation](https://www.baeldung.com/spring-keycloak-custom-themes)
## Keycloak Authentication Sequence
``` mermaid
```mermaid
sequenceDiagram
participant User
participant Traefik as Traefik Reverse Proxy
@@ -30,8 +31,8 @@ sequenceDiagram
Services->>Traefik: Response back to Traefik
Traefik->>User: Return service response
```
## Docker Configuration
## Docker Configuration
=== "docker-compose.yml"
```yaml
@@ -140,6 +141,7 @@ sequenceDiagram
## 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:
@@ -173,12 +175,13 @@ http:
X-Forwarded-Port: "443"
```
# Traefik Keycloak Middleware
At this point, we need to add the official Keycloak plugin to Traefik's main configuration. In this example, it will be assumed you need to configure this in Portainer/Docker Compose, and not via a static yml/toml file. Assume you follow the [Docker Compose based Traefik Deployment](../../edge/traefik.md).
## Traefik Keycloak Middleware
At this point, we need to add the official Keycloak plugin to Traefik's main configuration. In this example, it will be assumed you need to configure this in Portainer/Docker Compose, and not via a static yml/toml file. Assume you follow the [Docker Compose based Traefik Deployment](<../../Networking and Access/Reverse Proxies/Traefik.md>).
## Install Keycloak Plugin
If you do not already have the following added to the end of your `command:` section of the docker-compose.yml file in Portainer, go ahead and add it:
``` yaml
```yaml
# Keycloak plugin configuration
- "--experimental.plugins.keycloakopenid.moduleName=github.com/Gwojda/keycloakopenid"
- "--experimental.plugins.keycloakopenid.version=v0.1.34"
@@ -187,7 +190,7 @@ If you do not already have the following added to the end of your `command:` sec
## Add Middleware to Traefik Dynamic Configuration
You will want to ensure the following exists in the dynamically-loaded config file folder, you can name the file whatever you want, but it will be a one-all middleware for any services you want to have communicating as a specific OAuth2 `Client ID`. For example, you might want to have some services exist in a particular realm of Keycloak, or to have different client rules apply to certain services. If this is the case, you can create multiple middlewares in this single yaml file, each handling a different service / realm. It can get pretty complicated if you want to handle a multi-tenant environment, such as one seen in an enterprise environment.
```jsx title="keycloak-middleware.yml"
```yaml title="keycloak-middleware.yml"
http:
middlewares:
auth-bunny-lab-io:
@@ -215,6 +218,7 @@ At this point, you are in the final stretch, you just need to add the middleware
```
A full example config file would look like the following:
```yaml
http:
routers:
@@ -236,3 +240,7 @@ http:
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 Identity and Certificates Documentation](<../../../reference/Identity and Certificates/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,7 +5,8 @@ tags:
- Docker
---
**Purpose**: An application to securely communicate passwords over the web. Passwords automatically expire after a certain number of views and/or time has passed. Track who, what and when.
## Purpose
An application to securely communicate passwords over the web. Passwords automatically expire after a certain number of views and/or time has passed. Track who, what and when.
## Docker Configuration
```yaml title="docker-compose.yml"
@@ -69,6 +70,7 @@ PWP__LOG_LEVEL=info
## 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:
@@ -87,3 +89,8 @@ http:
- url: http://192.168.5.170:5100
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 Identity and Certificates Documentation](<../../reference/Identity and Certificates/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.
@@ -4,7 +4,8 @@ tags:
- Authentication
---
**Purpose**: privacyIDEA is a modular authentication system. Using privacyIDEA you can enhance your existing applications like local login, VPN, remote access, SSH connections, access to web sites or web portals with a second factor during authentication.
## Purpose
privacyIDEA is a modular authentication system. Using privacyIDEA you can enhance your existing applications like local login, VPN, remote access, SSH connections, access to web sites or web portals with a second factor during authentication.
!!! info "Assumptions"
It is assumed you have a provisioned virtual machine / physical machine, running Ubuntu Server 22.04 to deploy a privacyIDEA server.
@@ -46,7 +47,8 @@ Now we need to launch the template. Assuming all of the above was completed, we
!!! success
You will know if everything was successful if you see something that looks like the following:
``` sh
```sh
ok: [auth]
TASK [Install wget and software-properties-common] *****************************
ok: [auth]
@@ -66,7 +68,8 @@ Now we need to launch the template. Assuming all of the above was completed, we
## Admin Access to WebUI
### Create a privacyIDEA Administrator Account
You will need to use the CLI in the server in order to create the first administrative account. Run the following command and provide a password for the administrator account.
``` sh
```sh
sudo pi-manage admin add nicole.rappe -e nicole.rappe@bunny-lab.io
```
@@ -111,7 +114,7 @@ You will need to create several policies, you can make them all individual, or m
## Enrolling the First Token
!!! bug "Push Notifications Broken"
Currently, the push notification system (e.g. Cisco DUO") is not behaving as-expected. For now, you can use other authentication methods for the tokens, such as HOTP (on-demand MFA codes) or TOTP (conventional time-based MFA codes).
Currently, the push notification system (e.g. Cisco DUO") is not behaving as-expected. For now, you can use other authentication methods for the tokens, such as HOTP (on-demand MFA codes) or TOTP (conventional time-based MFA codes).
### TOTP Token
Navigate to "**Tokens > Enroll Token**"
@@ -142,3 +145,6 @@ When you want to leverage MFA in an environment using the server, you need to ha
- Click "**Install**" then "**Finish**"
You can now log out and verify that the credential provider is displayed as an option, and can log in using your domain username, domain password, and TOTP that you configured in the privacyIDEA WebUI.
## Related Documentation
- [Related Identity and Certificates Documentation](<../../reference/Identity and Certificates/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Unofficial Bitwarden compatible server written in Rust, formerly known as bitwarden_rs.
## Purpose
Unofficial Bitwarden compatible server written in Rust, formerly known as bitwarden_rs.
```yaml title="docker-compose.yml"
---
@@ -41,14 +42,17 @@ networks:
docker_network:
external: true
```
!!! warning "ADMIN_TOKEN"
It is **CRITICAL** that you never share the `ADMIN_TOKEN` with anyone. It allows you to log into the instance at https://vault.example.com/admin to add users, delete users, make changes system wide, etc.
```yaml title=".env"
Not Applicable
```
## 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:
@@ -67,3 +71,8 @@ http:
- url: http://192.168.5.15:80
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 Identity and Certificates Documentation](<../../reference/Identity and Certificates/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.
@@ -0,0 +1,22 @@
---
tags:
- Identity and Certificates
- Deployments
- Documentation
---
# Identity and Certificates
## Purpose
Find deployments for identity and certificates. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Active Directory
- Authelia
- Authentik
- Keycloak
- Password Pusher
- Privacyidea
- Vaultwarden
## Follow the Subject
[Identity and Certificates](<../../reference/Identity and Certificates/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -0,0 +1,38 @@
---
tags:
- AdGuard Home
- DNS
- Docker
---
## Purpose
AdGuard Home is a network-wide software for blocking ads & tracking. After you set it up, it will cover ALL your home devices, and you don’t need any client-side software for that. With the rise of Internet-Of-Things and connected devices, it becomes more and more important to be able to control your whole network.
```yaml title="docker-compose.yml"
version: '3'
services:
app:
image: adguard/adguardhome
ports:
- 3000:3000
- 53:53
- 80:80
volumes:
- /srv/containers/adguard_home/workingdir:/opt/adguardhome/work
- /srv/containers/adguard_home/config:/opt/adguardhome/conf
restart: always
networks:
docker_network:
ipv4_address: 192.168.5.189
networks:
default:
external:
name: docker_network
docker_network:
external: 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 Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Pi-hole is a Linux network-level advertisement and Internet tracker blocking application which acts as a DNS sinkhole and optionally a DHCP server, intended for use on a private network.
## Purpose
Pi-hole is a Linux network-level advertisement and Internet tracker blocking application which acts as a DNS sinkhole and optionally a DHCP server, intended for use on a private network.
```yaml title="docker-compose.yml"
version: "3"
@@ -46,3 +47,7 @@ networks:
```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 Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -50,3 +50,6 @@ If everything is working correctly, you can go make some coffee and come back.
```sh
```
## Related Documentation
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,7 +4,8 @@ tags:
- Docker
---
**Purpose**: HTML5-based Remote Access Broker for SSH, RDP, and VNC. Useful for remote access into an environment.
## Purpose
HTML5-based Remote Access Broker for SSH, RDP, and VNC. Useful for remote access into an environment.
### Docker Compose Stack
=== "docker-compose.yml"
@@ -99,7 +100,7 @@ tags:
### Environment Variables
=== ".env"
``` sh
```sh
N/A
```
@@ -113,10 +114,9 @@ tags:
```
## Reverse Proxy Configuration
=== "Traefik"
``` yaml
```yaml
http:
routers:
apache-guacamole:
@@ -154,3 +154,7 @@ tags:
}
}
```
## 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 Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,10 +4,11 @@ tags:
- Docker
---
**Purpose**: Sometimes you just want an instance of Firefox running on an Alpine Linux container, that has persistence (Extensions, bookmarks, history, etc) outside of the container (with bind-mapped folders). This is useful for a number of reasons, but insecure by default, so you have to protect it behind something like a [Keycloak Server](../authentication/keycloak/deployment.md) so it is not misused.
## Purpose
Sometimes you just want an instance of Firefox running on an Alpine Linux container, that has persistence (Extensions, bookmarks, history, etc) outside of the container (with bind-mapped folders). This is useful for a number of reasons, but insecure by default, so you have to protect it behind something like a [Keycloak Server](<../../Identity and Certificates/Keycloak/Deploy Keycloak.md>) so it is not misused.
## Keycloak Authentication Sequence
``` mermaid
```mermaid
sequenceDiagram
participant User
participant Traefik as Traefik Reverse Proxy
@@ -56,7 +57,7 @@ It is important, due to how this browser just allows anyone to access it, to loc
These rules will drop all traffic by default, allow port 22, and restrict access to port 5800.
``` sh
```sh
# Set the default zone to drop
sudo firewall-cmd --set-default-zone=drop
@@ -76,6 +77,7 @@ sudo firewall-cmd --reload
## 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:
@@ -108,3 +110,6 @@ Due to the nature of how this is deployed, you need to make some additional conf
- **Install Merge All Windows Extension**: At times, you may misclick somewhere in the Firefox environment causing Firefox to open a new instance / window losing all of your tabs, and because there is no window manager, there is no way to alt+tab or switch between the instances of Firefox, effectively breaking your current session forcing you to re-open tabs. With this extension, you can merge all of the windows, collapsing them into one window, resolving the issue.
- **Configure New Tab behavior**: If a new tab opens in a new window, it will absolutely throw everything into disarray, that is why all hyperlinks will be forced to open in a new tab instead of a new window. You can do this by navigating to `about:config` and setting the variable `browser.link.open_newwindow.restriction` to a value of `0`. [Original Reference Documentation](https://support.mozilla.org/en-US/questions/1066799)
## Related Documentation
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
- [Traefik Deployment](<../Reverse Proxies/Traefik.md>) — Prepare the reverse proxy before applying this page's routing configuration.
@@ -9,16 +9,18 @@ tags:
## Purpose
You may find that you need to install an XFCE desktop environment or something into Fedora Server, if this is the case, for installing something like Rustdesk remote access, you can follow the steps below.
### Install & Configure XFCE
### Install and Configure XFCE
We need to install XFCE and configure it to be the default environment when the server turns on.
```sh
sudo dnf install @xfce-desktop-environment -y
sudo systemctl set-default graphical.target
sudo reboot
```
#### Install Rustdesk:
#### Install Rustdesk
We need to install Rustdesk into the server.
```sh
curl -L -o /tmp/rustdesk_installer.rpm https://github.com/rustdesk/rustdesk/releases/download/1.4.0/rustdesk-1.4.0-0.x86_64.rpm
cd /tmp
@@ -34,6 +36,7 @@ sudo yum install rustdesk_installer.rpm -y
For Rustdesk specifically, we have to configure XFCE to automatically login via SDDM then immediately lock the computer once it's logged in, so the XFCE session is running, allowing Rustdesk to connect to it.
**Create SDDM Config File**:
```sh
sudo mkdir -p /etc/sddm.conf.d/
sudo nano /etc/sddm.conf.d/autologin.conf
@@ -71,6 +74,10 @@ Comment=Lock the screen on login
```
Lastly, test that everything is working by rebooting the server.
```sh
sudo reboot
```
## Related Documentation
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -6,10 +6,10 @@ tags:
- Linux
---
**Purpose**:
## Purpose
If you need to set up RDP access to a Linux environment, you will want to install XRDP. Once it is installed, you can leverage other tools such as Apache Guacamole to remotely connect to it.
```
```sh
# Install and Start XRDP Service
sudo dnf install epel-release -y
sudo dnf install xrdp -y
@@ -24,3 +24,6 @@ sudo firewall-cmd --reload
echo "startxfce4" > ~/.Xclients
chmod +x ~/.Xclients
```
## Related Documentation
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more.
## Purpose
NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more.
```yaml title="docker-compose.yml"
---
@@ -39,3 +40,7 @@ networks:
```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 Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,10 +5,11 @@ tags:
- Docker
---
**Purpose**: A traefik reverse proxy is a server that sits between your network firewall and servers hosting various web services on your private network(s). Traefik automatically handles the creation of Let's Encrypt SSL certificates if you have a domain registrar that is supported by Traefik such as CloudFlare; by leveraging API keys, Traefik can automatically make the DNS records for Let's Encrypt's DNS "challenges" whenever you add a service behind the Traefik reverse proxy.
## Purpose
A traefik reverse proxy is a server that sits between your network firewall and servers hosting various web services on your private network(s). Traefik automatically handles the creation of Let's Encrypt SSL certificates if you have a domain registrar that is supported by Traefik such as CloudFlare; by leveraging API keys, Traefik can automatically make the DNS records for Let's Encrypt's DNS "challenges" whenever you add a service behind the Traefik reverse proxy.
!!! info "Assumptions"
This Traefik deployment document assumes you have deployed [Portainer](../../platforms/containerization/docker/deploy-portainer.md) to either a Rocky Linux or Ubuntu Server environment. Other docker-compose friendly operating systems have not been tested, so your mileage may vary regarding successful deployment ouside of these two operating systems.
This Traefik deployment document assumes you have deployed [Portainer](<../../Containers/Docker/Deploy Portainer.md>) to either a Rocky Linux or Ubuntu Server environment. Other docker-compose friendly operating systems have not been tested, so your mileage may vary regarding successful deployment ouside of these two operating systems.
Portainer makes deploying and updating Traefik so much easier than via a CLI. It's also much more intuitive.
@@ -21,7 +22,7 @@ tags:
!!! warning "Get DNS Registrar API Keys BEFORE DEPLOYMENT"
When you are deploying this container, you have to be mindful to set valid data for the environment variables related to the DNS registrar. In this example, it is CloudFlare.
```jsx title="Environment Variables"
```text title="Environment Variables"
CF_API_EMAIL=nicole.rappe@bunny-lab.io
CF_API_KEY=REDACTED-CLOUDFLARE-DOMAIN-API-KEY
```
@@ -145,7 +146,7 @@ The first is that it reads "labels" from the docker-compose file of any deployed
By adding these labels to any container on the same server as Traefik, traefik will automatically "adopt" this service and route traffic to it as well as assign an SSL certificate to it from Let's Encrypt. The only downside is as mentioned above, if you are dealing with something that is not just a container, or maybe a container on a different physical server, you need to rely on dynamic configuration files, such as the one seen below.
### Dynamic Configuration Files
Dynamic configuration files exist under the Traefik container located at `/etc/traefik/dynamic`. Any `*.yml` files located in this folder will be hot-loaded anytime they are modified. This makes it convenient to leverage something such as the [Git Repo Updater](../../platforms/containerization/docker/custom-containers/git-repo-updater.md) container to leverage [Gitea](../devops/gitea.md) to push configuration files from Git into the production environment, saving yourself headache and enabling version control over every service behind the reverse proxy.
Dynamic configuration files exist under the Traefik container located at `/etc/traefik/dynamic`. Any `*.yml` files located in this folder will be hot-loaded anytime they are modified. This makes it convenient to leverage something such as the [Git Repo Updater](<../../Containers/Docker/Git Repo Updater.md>) container to leverage [Gitea](<../../automation/Gitea/Gitea.md>) to push configuration files from Git into the production environment, saving yourself headache and enabling version control over every service behind the reverse proxy.
An example of a dynamic configuration file would look something like this:
@@ -196,3 +197,7 @@ You can see the similarities between the labeling method and how you designate t
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.
- [Gitea Configuration Delivery](<../../../reference/Automation/Gitea Configuration Delivery.md>) — Choose the delivery implementation for the dynamic configuration directory.
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -7,17 +7,17 @@ tags:
- Routing
---
**Purpose**: You may have two Sophos XGS appliances (or a mixed configuration) and need to set up a site-to-site VPN tunnel between two remote locations. You can achieve this with a simple passphrase-based IPSec VPN tunnel.
## Purpose
You may have two Sophos XGS appliances (or a mixed configuration) and need to set up a site-to-site VPN tunnel between two remote locations. You can achieve this with a simple passphrase-based IPSec VPN tunnel.
!!! info "Assumptions"
This documentation only provides instruction for Sophos XGS based devices. It does not account for third-party vendors or other manufactured hardware. If you need to set up a mixed VPN tunnel with a different brand of networking device, you need to do your best to match the settings on the tunnels manually. (e.g. Encryption Type, Phase Lifetimes, etc).
This documentation only provides instruction for Sophos XGS based devices. It does not account for third-party vendors or other manufactured hardware. If you need to set up a mixed VPN tunnel with a different brand of networking device, you need to do your best to match the settings on the tunnels manually. (e.g. Encryption Type, Phase Lifetimes, etc).
## Architecture
!!! tip "Best Practices - Initiators / Responders"
If you have a hub-and-spoke network, where one location acts as a central authority (e.g. domain controllers, auth servers, identity providers, headquarters, etc), you will set up the central "hub" as a VPN responder on its side of the VPN tunnel, and all the remote "spoke" locations would behave as VPN initiators.
``` mermaid
```mermaid
graph TB
Responder((Responder<br/>Headquarters))
Initiator1((Initiator<br/>Remote Site 1))
@@ -40,7 +40,6 @@ You will need to access the firewall either directly on the local network at `ht
Navigate to "**Configure > Site-to-Site VPN > Add**"
### General settings
| **Field** | **Value** |
| :--- | :--- |
| Name | `<ThisLocation> to <RemoteLocation>` |
@@ -49,14 +48,12 @@ Navigate to "**Configure > Site-to-Site VPN > Add**"
| Gateway Type | `Initiate the Connection` / `Respond Only` (*See "Best Practices" Section*) |
### Encryption
| **Field** | **Value** |
| :--- | :--- |
| Encryption Profile | `Custom_IKEv2_Initiator` / `Custom_IKEv2_Responder` (*Based on the "Gateway Type"*) |
| Authentication Type | `Preshared Key / Passphrase` |
### Gateway Settings
| **Field** | **Value** |
| :--- | :--- |
| Listening Interface | `<WAN Interface / Generally "Port2">` (*Internal IP Address*) |
@@ -103,3 +100,5 @@ You will need to repeat the steps on both firewalls, so one firewall is the init
## Connect the IPSec Tunnels
Now you need to start the tunnel on the Initiator side first, then start the tunnel on the responder side. If both sides show green status indicators, the tunnel should be active.
## Related Documentation
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: The UniFi® Controller is a wireless network management software solution from Ubiquiti Networks™. It allows you to manage multiple wireless networks using a web browser.
## Purpose
The UniFi® Controller is a wireless network management software solution from Ubiquiti Networks™. It allows you to manage multiple wireless networks using a web browser.
```yaml title="docker-compose.yml"
version: "2.1"
@@ -46,3 +47,8 @@ networks:
```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.
- [Ubuntu UniFi Installation Notes](<Deploy UniFi Network Server on Ubuntu.md>) — Review the separate installation approach and its incomplete status.
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,7 +4,7 @@ tags:
- Networking
---
**Purpose**:
## Purpose
If you need to deploy Unifi Controller bare-metal into a virtual machine, you can do so with a few simple commands. You can feel free to reference the [original documentation](https://help.ui.com/hc/en-us/articles/220066768-Updating-and-Installing-Self-Hosted-UniFi-Network-Servers-Linux) if additional clarity is needed.
!!! note "Assumptions"
@@ -18,12 +18,12 @@ If you need to deploy Unifi Controller bare-metal into a virtual machine, you ca
curl -sO https://get.glennr.nl/unifi/install/install_latest/unifi-latest.sh && bash unifi-latest.sh
```
## Install Components
The installation will consist of a MongoDB server and a Unifi Network (controller) server. You will install the database first, then install the Unifi Controller second, so it can provision the newly-installed local MongoDB database server.
### General Configuration
We need to configure APT with a few commands to ensure that we can download the MongoDB and Unifi packages.
```sh
sudo apt-get update && sudo apt-get install ca-certificates apt-transport-https
echo 'deb [ arch=amd64,arm64 ] https://www.ui.com/downloads/unifi/debian stable ubiquiti' | sudo tee /etc/apt/sources.list.d/100-ubnt-unifi.list
@@ -32,14 +32,19 @@ echo "deb [trusted=yes] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/3
sudo apt-get update
```
!!! node "Alternative GPG Key Installation"
!!! note "Alternative GPG Key Installation"
If you run into issues installing the GPG key for the Unifi packages, you can alternatively run the command seen below:
```sh
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 06E85760C0A52C50
```
### MongoDB Server
Run the following commands install and enable automatic startup for the MongoDB server. Original reference documentation can be found [here](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/).
```sh
```
## Related Documentation
- [Related Networking and Access Documentation](<../../../reference/Networking and Access/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,21 @@
---
tags:
- Networking and Access
- Deployments
- Documentation
---
# Networking and Access
## Purpose
Find deployments for networking and access. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- DNS
- NetBird
- Remote Access
- Reverse Proxies
- Sophos
- UniFi
## Follow the Subject
[Networking and Access](<../../reference/Networking and Access/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -6,7 +6,7 @@ tags:
- Linux
---
**Purpose**:
## Purpose
You may need to install the QEMU guest agent on linux VMs manually, while Windows-based devices work out-of-the-box after installing the VirtIO guest tools installer.
=== "Ubuntu Server"
@@ -25,3 +25,6 @@ You may need to install the QEMU guest agent on linux VMs manually, while Window
dnf install -y qemu-guest-agent
systemctl enable --now qemu-guest-agent
```
## Related Documentation
- [Related Virtualization and Storage Documentation](<../../../reference/Virtualization and Storage/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,9 +1,11 @@
---
tags:
- Documentation
- Virtualization and Storage
- Deploy Failover Cluster Node
---
**Purpose**: Deploying a Windows Server Node into the Hyper-V Failover Cluster is an essential part of rebuilding and expanding the backbone of my homelab. The documentation below goes over the process of setting up a bare-metal host from scratch and integrating it into the Hyper-V Failover Cluster.
## Purpose
Deploying a Windows Server Node into the Hyper-V Failover Cluster is an essential part of rebuilding and expanding the backbone of my homelab. The documentation below goes over the process of setting up a bare-metal host from scratch and integrating it into the Hyper-V Failover Cluster.
!!! note "Prerequisites & Assumptions"
This document assumes you are have installed and are running a bare-metal Hewlett-Packard Enterprise server with iLO (Integrated Lights Out) with the latest build of **Windows Server 2022 Datacenter (Desktop Experience)**.
@@ -19,14 +21,14 @@ Enable remote desktop however you can, but just be sure to disable NLA, see the
This step can be disregarded if the domain controller(s) exist outside of the Hyper-V Failover Cluster.
``` powershell
```powershell
# Enable Remote Desktop (NLA-Disabled)
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 0
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 0 Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
```
### Provision Server Roles, Activate, and Domain Join
``` powershell
```powershell
# Rename the server
Rename-Computer BUNNY-NODE-02
@@ -56,10 +58,10 @@ Restart-Computer
You will need to start off by configuring a Switch Embedded Teaming (SET) team. This is the backbone that the server will use for all Guest VM traffic as well as remote-desktop access to the server node itself. You will need to rename the network adapters to make management easier.
- Navigate to "Network Connections" then "Change Adapter Options"
* Rename the network adapters with simpler names. e.g. (`Ethernet 1` becomes `Port_1`)
* For the sake of demonstration, assume there are 2 10GbE NICs (`Port_1` and `Port_2`)
- Rename the network adapters with simpler names. e.g. (`Ethernet 1` becomes `Port_1`)
- For the sake of demonstration, assume there are 2 10GbE NICs (`Port_1` and `Port_2`)
``` powershell
```powershell
# Create Switch Embedded Teaming (SET) team
New-VMSwitch -Name Cluster_SET -NetAdapterName Port_1, Port_2 -EnableEmbeddedTeaming $true
@@ -70,55 +72,60 @@ Get-NetAdapter | Where-Object { $_.Name -ne "vEthernet (Cluster_SET)" } | ForEac
New-NetIPAddress -InterfaceAlias "vEthernet (Cluster_SET)" -IPAddress 192.168.3.5 -PrefixLength 24 -DefaultGateway 192.168.3.1
Set-DnsClientServerAddress -InterfaceAlias "vEthernet (Cluster_SET)" -ServerAddresses ("192.168.3.25","192.168.3.26")
```
### Configure iSCSI Initiator to Connect to TrueNAS Core Server
At this point, now that we have verified that the 10GbE NICs can ping their respective iSCSI target server IP addresses, we can add them to the iSCSI Initiator in Server Manager which will allow us to mount the cluster storage for the Hyper-V Failover Cluster.
- Open **Server Manager > MPIO**
* Navigate to the "Discover Multi-Paths" tab
* Check the "Add support for iSCSI devices" checkbox
* Click the "Add" button
- Navigate to the "Discover Multi-Paths" tab
- Check the "Add support for iSCSI devices" checkbox
- Click the "Add" button
- Open **TrueNAS Core Server**
* Navigate to the [TrueNAS Core server](http://192.168.3.3) and add the "Initiator Name" seen on the "Configuration" tab of the iSCSI Initiator on the Virtualization Host to the `Sharing > iSCSI > Initiator Groups` > "iSCSI-Connected Servers"
- Navigate to the [TrueNAS Core server](http://192.168.3.3) and add the "Initiator Name" seen on the "Configuration" tab of the iSCSI Initiator on the Virtualization Host to the `Sharing > iSCSI > Initiator Groups` > "iSCSI-Connected Servers"
- Open **iSCSI Initiator**
* Click on the "Discovery" tab
* Click the "Discover Portal" button
* Enter the IP addresses of "192.168.3.3". Leave the port as "3260".
* Example Initiator Name: `iqn.1991-05.com.microsoft:bunny-node-02.bunny-lab.io`
* Click the "Targets" tab to go back to the main page
* Click the "Refresh" button to display available iSCSI Targets
* Click on the first iSCSI Target `iqn.2005-10.org.moon-storage-01.ctl:iscsi-cluster-storage` then click the "Connect" button
* Check the "Enable Multi-Path" checkbox
* Click the "Advanced" button
* Click the "OK" button
* Navigate to "Disk Management" to bring the iSCSI drives "Online" (Dont do anything after this in Disk Management)
- Click on the "Discovery" tab
- Click the "Discover Portal" button
- Enter the IP addresses of "192.168.3.3". Leave the port as "3260".
- Example Initiator Name: `iqn.1991-05.com.microsoft:bunny-node-02.bunny-lab.io`
- Click the "Targets" tab to go back to the main page
- Click the "Refresh" button to display available iSCSI Targets
- Click on the first iSCSI Target `iqn.2005-10.org.moon-storage-01.ctl:iscsi-cluster-storage` then click the "Connect" button
- Check the "Enable Multi-Path" checkbox
- Click the "Advanced" button
- Click the "OK" button
- Navigate to "Disk Management" to bring the iSCSI drives "Online" (Dont do anything after this in Disk Management)
## Initialize and Join to Existing Failover-Cluster
### Validate Server is Ready to Join Cluster
Now it is time to set up the Failover Cluster itself so we can join the server to the existing cluster.
- Open **Server Manager**
* Click on the "Tools" dropdown menu
* Click on "Failover Cluster Manager"
* Click the "Validate Configuration" button in the middle of the window that appears
* Click "Next"
* Enter Server Name: `BUNNY-NODE-02.bunny-lab.io`
* Click the "Add" button, then "Next"
* Ensure "Run All Tests (Recommended)" is selected, then click "Next", then click "Next" to start.
### Join Server to Failover Cluster
* On the left-hand side, right-click on the "Failover Cluster Manager" in the tree
* Click on "Connect to Cluster"
* Enter `USAGI-CLUSTER.bunny-lab.io`
* Click "OK"
* Expand "USAGI-CLUSTER.bunny-lab.io" on the left-hand tree
* Right-click on "Nodes"
* Click "Add Node..."
* Click "Next"
* Enter Server Name: `BUNNY-NODE-02.bunny-lab.io`
* Click the "Add" button, then "Next"
* Ensure that "Run Configuration Validation Tests" radio box is checked, then click "Next"
* Validate that the node was successfully added to the Hyper-V Failover Cluster
- Click on the "Tools" dropdown menu
- Click on "Failover Cluster Manager"
- Click the "Validate Configuration" button in the middle of the window that appears
- Click "Next"
- Enter Server Name: `BUNNY-NODE-02.bunny-lab.io`
- Click the "Add" button, then "Next"
- Ensure "Run All Tests (Recommended)" is selected, then click "Next", then click "Next" to start.
## Cleanup & Final Touches
### Join Server to Failover Cluster
- On the left-hand side, right-click on the "Failover Cluster Manager" in the tree
- Click on "Connect to Cluster"
- Enter `USAGI-CLUSTER.bunny-lab.io`
- Click "OK"
- Expand "USAGI-CLUSTER.bunny-lab.io" on the left-hand tree
- Right-click on "Nodes"
- Click "Add Node..."
- Click "Next"
- Enter Server Name: `BUNNY-NODE-02.bunny-lab.io`
- Click the "Add" button, then "Next"
- Ensure that "Run Configuration Validation Tests" radio box is checked, then click "Next"
- Validate that the node was successfully added to the Hyper-V Failover Cluster
## Cleanup and Final Touches
Ensure that you run all available Windows Updates before delegating guest VM roles to the new server in the failover cluster. This ensures you are up-to-date before you become reliant on the server for production operations.
## Related Documentation
- [Related Virtualization and Storage Documentation](<../../../../reference/Virtualization and Storage/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,11 +4,12 @@ tags:
- Ansible
---
## Purpose
Deploying OpenStack via Ansible.
!!! warning "Document Under Construction"
This document is very unfinished and should **NOT** be followed by anyone for deployment at this time.
**Purpose**: Deploying OpenStack via Ansible.
## Required Hardware/Infrastructure Breakdown
Every node in the OpenStack environment (including the deployment node) will be running Rocky Linux 9.5, as OpenStack Ansible only supports CentOS/RHEL/Rocky for its deployment.
@@ -23,6 +24,7 @@ Every node in the OpenStack environment (including the deployment node) will be
We want to ensure everything works even if the nodes have no internet access. By hardcoding the FQDNs, this protects us against several possible stupid situations.
Run the following script to add the DNS entries.
```sh
# Make yourself root
sudo su
@@ -45,6 +47,7 @@ cat /etc/hosts
!!! example "/etc/hosts Example Contents"
When you run `cat /etc/hosts`, you should see output similar to the following:
```ini title="/etc/hosts"
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
@@ -70,7 +73,7 @@ Ansible uses SSH with public key authentication to connect the deployment host a
!!! warning "Do not run as root"
You want to make sure you run these commands as a normal user. (e.g. `nicole`).
``` sh
```sh
# Generate SSH Keys (Private / Public)
ssh-keygen
@@ -87,6 +90,7 @@ ssh nicole@openstack-node-03.bunny-lab.io
### Install the source and dependencies
Install the source and dependencies for the deployment host.
```sh
sudo su
git clone -b master https://opendev.org/openstack/openstack-ansible /opt/openstack-ansible
@@ -95,7 +99,8 @@ bash scripts/bootstrap-ansible.sh
```
### Disable Firewalld
The `firewalld` service is enabled on most CentOS systems by default and its default ruleset prevents OpenStack components from communicating properly. Stop the firewalld service and mask it to prevent it from starting.
The `firewalld` service is enabled on most CentOS systems by default and its default ruleset prevents OpenStack components from communicating properly. Stop the firewalld service and mask it to prevent it from starting.
```sh
systemctl stop firewalld
systemctl mask firewalld
@@ -106,12 +111,14 @@ Now we need to get the cluster/target nodes configured so that OpenStack can be
### Disable SELinux
SELinux enabled is not currently supported in OpenStack-Ansible for CentOS/RHEL due to a lack of maintainers for the feature.
```sh
sudo sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
```
### Disable Firewalld
The `firewalld` service is enabled on most CentOS systems by default and its default ruleset prevents OpenStack components from communicating properly. Stop the firewalld service and mask it to prevent it from starting.
The `firewalld` service is enabled on most CentOS systems by default and its default ruleset prevents OpenStack components from communicating properly. Stop the firewalld service and mask it to prevent it from starting.
```sh
systemctl stop firewalld
systemctl mask firewalld
@@ -125,12 +132,14 @@ dnf install -y iputils lsof openssh-server sudo tcpdump python3
### Reduce Kernel Logging
Reduce the kernel log level by changing the printk value in your sysctls.
```sh
sudo echo "kernel.printk='4 1 7 4'" >> /etc/sysctl.conf
```
### Configure Local Cinder/Ceph Storage (Optional if using iSCSI)
At this point, we need to configure `/dev/sdb` as the local storage for Cinder.
```sh
pvcreate --metadatasize 2048 /dev/sdb
vgcreate cinder-volumes /dev/sdb
@@ -138,7 +147,8 @@ vgcreate cinder-volumes /dev/sdb
!!! failure "`Cannot use /dev/sdb: device is partitioned`"
You may (in rare cases) see the following error when trying to run `pvcreate --metadatasize 2048 /dev/sdb`, if that happens, just use `lsblk` to get the drive of the expected disk. In my example, we want the 500GB disk located at `/dev/sda`, seen in the example below:
```
```text
[root@openstack-node-02 nicole]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 500G 0 disk
@@ -154,3 +164,6 @@ vgcreate cinder-volumes /dev/sdb
This is the end of where I have currently iterated in my lab and followed-along with the official documentation while generalizing it for my specific lab scenarios. The following link is where I am currently at/stuck and need to revisit at my earliest convenience.
https://docs.openstack.org/project-deploy-guide/openstack-ansible/latest/targethosts.html#configuring-the-network
## Related Documentation
- [Related Virtualization and Storage Documentation](<../../../reference/Virtualization and Storage/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,9 +1,10 @@
---
tags:
- OpenStack
- Virtualization and Storage
---
# OpenStack
## Purpose
OpenStack is basically a virtual machine hypervisor that is HA and cluster-friendly. This particular variant is deployed via Canonical's MiniStack environment using SNAP. It will deploy OpenStack onto a single node, which can later be expanded to additional nodes. You can also use something like OpenShift to deploy a Kubernetes Cluster onto OpenStack automatically via its various APIs.
**Reference Documentation**:
@@ -13,33 +14,39 @@ OpenStack is basically a virtual machine hypervisor that is HA and cluster-frien
!!! note
This document assumes your bare-metal host server is running Ubuntu 22.04 LTS, has at least 16GB of Memory (**32GB for Multi-Node Deployments**), two network interfaces (one for management, one for remote VM access), 200GB of Disk Space for the root filesystem, another 200GB disk for Ceph distributed storage, and 4 processor cores. See [Single-Node Mode System Requirements](https://ubuntu.com/openstack/install)
!!! note Assumed Networking on the First Cluster Node
!!! note "Assumed Networking on the First Cluster Node"
- **eth0** = 192.168.3.5
- **eth1** = 192.168.5.200
### Update APT then install upgrades
```
```sh
sudo apt update && sudo apt upgrade -y && sudo apt install htop ncdu iptables nano -y
```
!!! tip
At this time, it would be a good idea to take a checkpoint/snapshot of the server (if it is a virtual machine). This gives you a starting point to come back to as you troubleshoot inevitable deployment issues.
### Update SNAP then install OpenStack SNAP
```
```sh
sudo snap refresh
sudo snap install openstack --channel 2023.1
```
### Install & Configure Dependencies
### Install and Configure Dependencies
Sunbeam can generate a script to ensure that the machine has all of the required dependencies installed and is configured correctly for use in MicroStack.
```
```sh
sunbeam prepare-node-script | bash -x && newgrp snap_daemon
sudo reboot
```
### Bootstrapping
Deploy the OpenStack cloud using the cluster bootstrap command.
```
```text
sunbeam cluster bootstrap
```
!!! warning
If you get an "Unable to connect to websocket" error, run `sudo snap restart lxd`.
[Known Bug Report](https://bugs.launchpad.net/snap-openstack/+bug/2033400)
@@ -48,7 +55,7 @@ sunbeam cluster bootstrap
Management networks shared by hosts = `192.168.3.0/24`
MetalLB address allocation range (supports multiple ranges, comma separated) (10.20.21.10-10.20.21.20): `192.168.3.50-192.168.3.60`
### Cloud Initialization:
### Cloud Initialization
- nicole@moon-stack-01:~$ `sunbeam configure --openrc demo-openrc`
- Local or remote access to VMs [local/remote] (local): `remote`
- CIDR of network to use for external networking (10.20.20.0/24): `192.168.5.0/24`
@@ -63,19 +70,24 @@ sunbeam cluster bootstrap
- End of IP allocation range for external network (192.168.5.254): `192.168.5.251`
- Network type for access to external network [flat/vlan] (flat):
- Free network interface that will be configured for external traffic: `eth1`
- WARNING: Interface eth1 is configured. Any configuration will be lost, are you sure you want to continue? [y/n]: y
- WARNING: Interface eth1 is configured. Any configuration will be lost, are you sure you want to continue? [y/n]: y
### Pull Down / Generate the Dashboard URL
```
```text
sunbeam openrc > admin-openrc
sunbeam dashboard-url
```
### Launch a Test VM:
### Launch a Test VM
Verify the cloud by launching a VM called ‘test’ based on the ‘ubuntu’ image (Ubuntu 22.04 LTS).
```
```text
sunbeam launch ubuntu --name test
```
!!! note Sample output:
!!! note "Sample output:"
- Launching an OpenStack instance ...
- Access instance with `ssh -i /home/ubuntu/.config/openstack/sunbeam ubuntu@10.20.20.200`
## Related Documentation
- [Related Virtualization and Storage Documentation](<../../../reference/Virtualization and Storage/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -24,14 +24,13 @@ This approach is intended to:
- All VM workloads are drained from at least one Proxmox node for maintenance
!!! note "Proxmox VE Version Context"
This guide assumes **Proxmox VE 9.1.4 (or later)**. Snapshot-as-volume-chain support on shared LVM (e.g., iSCSI) is available and improved, including enhanced handling of vTPM state in offline snapshots.
This guide assumes **Proxmox VE 9.1.4 (or later)**. Snapshot-as-volume-chain support on shared LVM (e.g., iSCSI) is available and improved, including enhanced handling of vTPM state in offline snapshots.
!!! warning "Important"
`volblocksize` **cannot be changed after zvol creation**. Choose carefully.
`volblocksize` **cannot be changed after zvol creation**. Choose carefully.
## Target Architecture
```
```text
ZFS Pool
└─ Zvol (Thick / Reserved)
└─ iSCSI Extent
@@ -41,7 +40,6 @@ ZFS Pool
```
## Create a Dedicated Zvol for Proxmox
### Variables
Adjust as needed before execution.
@@ -65,14 +63,12 @@ zfs create -V ${ZVOL_SIZE} \
The `refreservation` enforces **true thick provisioning** and prevents overcommit.
## Configure iSCSI Target (TrueNAS CORE)
This section uses a **hybrid approach**:
- **CLI** is used for ZFS and LUN (extent backing) creation
- **TrueNAS GUI** is used for iSCSI portal, target, and association
- **CLI** is used again for validation
### Enable iSCSI Service
```sh
service ctld start
sysrc ctld_enable=YES
@@ -93,7 +89,6 @@ ctladm create -b block \
```
### Verify the LUN is real and correctly sized
```sh
ctladm devlist -v
```
@@ -102,7 +97,6 @@ ctladm devlist -v
`Size (Blocks)` must be **non-zero** and match the zvol size. If it is `0`, stop and correct before proceeding.
### Configure iSCSI Portal, Target, and Extent Association (CLI Only)
!!! warning "Do NOT Use the TrueNAS iSCSI GUI"
**Once you choose a CLI-managed iSCSI configuration, the TrueNAS Web UI must never be used for iSCSI.**
Opening or modifying **Sharing → Block Shares (iSCSI)** in the GUI will **overwrite CTL runtime state**, invalidate manual `ctladm` configuration, and result in targets that appear correct but expose **no LUNs** to initiators.
@@ -114,7 +108,6 @@ Opening or modifying **Sharing → Block Shares (iSCSI)** in the GUI will **over
- Do **not** mix GUI extents with CLI-created LUNs
#### Create iSCSI Portal (Listen on All Interfaces)
```sh
# Backup any existing ctl.conf
cp -av /etc/ctl.conf /etc/ctl.conf.$(date +%Y%m%d-%H%M%S).bak 2>/dev/null || true
@@ -185,9 +178,8 @@ lsblk
```
## Create Shared LVM (Execute on One Node Only)
!!! warning "Important"
**Only run LVM creation on ONE node**. All other nodes will only scan.
**Only run LVM creation on ONE node**. All other nodes will only scan.
```sh
# Initialize Physical Volume
@@ -214,7 +206,6 @@ vgscan
- Allow Snapshots as Volume-Chain: ✔️
## Validation
- Snapshot create / revert / delete
- Live migration between nodes
- PBS backup and restore test
@@ -250,3 +241,6 @@ pvresize /dev/sdX
pvscan
vgscan
```
## Related Documentation
- [Related Proxmox Documentation](<../../../reference/Virtualization and Storage/Proxmox/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -7,8 +7,12 @@ tags:
## Purpose
You may need to deploy many copies of a virtual machine rapidly, and don't want to go through the hassle of setting up everything ad-hoc as the needs arise for each VM workload. Creating a cloud-init template allows you to more rapidly deploy production-ready copies of a template VM (that you create below) into a ProxmoxVE environment.
!!! warning "Incomplete Template Procedure"
The package-configuration script and final hostname section are incomplete. Complete and validate those sections before relying on this page to produce a reusable template.
### Download Image and Import into ProxmoxVE
You will first need to pull down the OS image from Ubuntu's website via CLI, as there is currently no way to do this via the WebUI. Using SSH or the Shell within the WebUI of one of the ProxmoxVE servers, run the following commands to download and import the image into ProxmoxVE.
```sh
# Make a place to keep cloud images
mkdir -p /var/lib/vz/template/images/ubuntu && cd /var/lib/vz/template/images/ubuntu
@@ -36,8 +40,9 @@ qm set 9000 --scsi0 nfs-cluster-storage:9000/vm-9000-disk-0.qcow2
qm set 9000 --boot c --bootdisk scsi0
```
### Add Cloud-Init Drive & Configure Template Defaults
Now that the Ubuntu cloud image is attached as the VM’s primary disk, you need to attach a Cloud-Init drive. This special drive is where Proxmox writes your user data (username, SSH keys, network settings, etc.) at clone time.
### Add Cloud-Init Drive and Configure Template Defaults
Now that the Ubuntu cloud image is attached as the VM’s primary disk, you need to attach a Cloud-Init drive. This special drive is where Proxmox writes your user data (username, SSH keys, network settings, etc.) at clone time.
```sh
# Add a Cloud-Init drive to the VM
qm set 9000 --ide2 nfs-cluster-storage:cloudinit
@@ -69,7 +74,7 @@ qm set 9000 --sshkey /root/infrastructure_id_rsa.pub
qm set 9000 --ipconfig0 ip=dhcp
```
### Setup Packages in VM & Convert to Template
### Setup Packages in VM and Convert to Template
At this point, we have a few things we need to do first before we can turn the VM into a template and make clones of it. You will need to boot up the VM we made (id 9000) and run the following commands to prepare it for becoming a template:
```sh
@@ -103,7 +108,7 @@ You can now create new VMs instantly from the template we created above.
=== "Via CLI"
``` sh
```sh
# Create a new VM (example: VM 9100) cloned from the template
qm clone 9000 9100 --name ubuntu-2404-test --full
@@ -117,6 +122,10 @@ You can now create new VMs instantly from the template we created above.
### Configure VM Hostname
At this point, the hostname of the VM will be randomized and you will probably want to set it to something statically, you can do that with the following commands after the server has finished starting:
```sh
```
## Related Documentation
- [Related Proxmox Documentation](<../../../reference/Virtualization and Storage/Proxmox/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -1,10 +1,17 @@
---
tags:
- Proxmox
- Virtualization and Storage
---
## Purpose
This document records the procedure for deploy proxmox ve. Follow the environment assumptions and commands below.
!!! info "Recorded Host Environment"
This deployment records the earlier Proxmox VE 8.1 and `MOONGATE.local` environment. Its backplane addresses differ from the separate shared-storage guide. Confirm the target host version and network plan before combining these instructions.
## Initial Installation / Configuration
Proxmox Virtual Environment is an open source server virtualization management solution based on QEMU/KVM and LXC. You can manage virtual machines, containers, highly available clusters, storage and networks with an integrated, easy-to-use web interface or via CLI.
Proxmox Virtual Environment is an open source server virtualization management solution based on QEMU/KVM and LXC. You can manage virtual machines, containers, highly available clusters, storage and networks with an integrated, easy-to-use web interface or via CLI.
!!! note
This document assumes you have a storage server that hosts both ISO files via CIFS/SMB share, and has the ability to set up an iSCSI LUN (VM & Container storage). This document assumes that you are using a TrueNAS Core server to host both of these services.
@@ -14,13 +21,14 @@ You will need to download the [Proxmox VE 8.1 ISO Installer](https://www.proxmox
!!! warning
If you are virtualizing Proxmox under a Hyper-V environment, you will need to follow the [Official Documentation](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/enable-nested-virtualization) to ensure that nested virtualization is enabled. An example is listed below:
```
```powershell
Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true # (1)
Get-VMNetworkAdapter -VMName <VMName> | Set-VMNetworkAdapter -MacAddressSpoofing On # (2)
```
1. This tells Hyper-V to allow the GuestVM to behave as a hypervisor, nested under Hyper-V, allowing the virtualization functionality of the Hypervisor's CPU to be passed-through to the GuestVM.
2. This tells Hyper-V to allow your GuestVM to have multiple nested virtual machines with their own independant MAC addresses. This is useful when using nested Virtual Machines, but is also a requirement when you set up a [Docker Network](../../../../reference/infrastructure/networking/docker-networking/docker-networking.md) leveraging MACVLAN technology.
2. This tells Hyper-V to allow your GuestVM to have multiple nested virtual machines with their own independant MAC addresses. This is useful when using nested Virtual Machines, but is also a requirement when you set up a [Docker Network](<../../Containers/Docker/Create the Docker Network.md>) leveraging MACVLAN technology.
### Networking
You will need to set a static IP address, in this case, it will be an address within the 20GbE network. You will be prompted to enter these during the ProxmoxVE installation. Be sure to set the hostname to something that matches the following FQDN: `proxmox-node-01.MOONGATE.local`.
@@ -35,7 +43,7 @@ You will need to set a static IP address, in this case, it will be an address wi
### iSCSI Initator Configuration
You will need to add the iSCSI initiator from the proxmox node to the allowed initiator list in TrueNAS Core under "**Sharing > Block Shares (iSCSI) > Initiators Groups**"
In this instance, we will reference Group ID: `2`. We need to add the iniator to the "**Allowed Initiators (IQN)**" section. This also includes the following networks that are allowed to connect to the iSCSI portal:
In this instance, we will reference Group ID: `2`. We need to add the iniator to the "**Allowed Initiators (IQN)**" section. This also includes the following networks that are allowed to connect to the iSCSI portal:
- `192.168.101.0/24`
- `192.168.102.0/24`
@@ -47,7 +55,8 @@ To get the iSCSI Initiator IQN of the current Proxmox node, you need to navigate
- On the left-hand side, click on the name of the server node (e.g. `proxmox-node-01` or `proxmox-node-02`)
- Click on "**Shell**" to open a CLI to the server
- Run the following command to get the iSCSI Initiator (IQN) name to give to TrueNAS Core for the previously-mentioned steps:
``` sh
```sh
cat /etc/iscsi/initiatorname.iscsi | grep "InitiatorName=" | sed 's/InitiatorName=//'
```
@@ -58,7 +67,8 @@ cat /etc/iscsi/initiatorname.iscsi | grep "InitiatorName=" | sed 's/InitiatorNam
You will likely not be paying for / using the enterprise subscription, so we are going to disable that functionality and enable unstable builds. The unstable builds are surprisingly stable, and should not cause you any issues.
Add Unstable Update Repository:
```jsx title="/etc/apt/sources.list"
```text title="/etc/apt/sources.list"
# Add to the end of the file
# Non-Production / Unstable Updates
deb https://download.proxmox.com/debian bookworm pve-no-subscription
@@ -68,12 +78,14 @@ deb https://download.proxmox.com/debian bookworm pve-no-subscription
Please note the reference to `bookworm` in both the sections above and below this notice, this may be different depending on the version of ProxmoxVE you are deploying. Please reference the version indicated by the rest of the entries in the sources.list file to know which one to use in the added line section.
Comment-Out Enterprise Repository:
```jsx title="/etc/apt/sources.list.d/pve-enterprise.list"
```text title="/etc/apt/sources.list.d/pve-enterprise.list"
# deb https://enterprise.proxmox.com/debian/pve bookworm pve-enterprise
```
Pull / Install Available Updates:
``` sh
```sh
apt-get update
apt dist-upgrade
reboot
@@ -83,14 +95,16 @@ reboot
You will need to set up NIC teaming to configure a LACP LAGG. This will add redundancy and a way for devices outside of the 20GbE backplane to interact with the server.
- Ensure that all of the network interfaces appear as something similar to the following:
```jsx title="/etc/network/interfaces"
```text title="/etc/network/interfaces"
iface eno1 inet manual
iface eno2 inet manual
# etc
```
- Adjust the network interfaces to add a bond:
```jsx title="/etc/network/interfaces"
```text title="/etc/network/interfaces"
auto eno1
iface eno1 inet manual
@@ -120,33 +134,33 @@ iface vmbr0 inet static
- Reboot the server again to make the networking changes take effect fully. Use iLO / iDRAC / IPMI if you have that functionality on your server in case your configuration goes errant and needs manual intervention / troubleshooting to re-gain SSH control of the proxmox server.
## Generalizing VMs for Cloning / Templating:
## Generalizing VMs for Cloning / Templating
These are the commands I run after cloning a Linux machine so that it resets all information for the machine it was cloned from.
!!! note
If you use cloud-init-aware OS images as described under Cloud-Init Support on https://pve.proxmox.com/pve-docs/chapter-qm.html, these steps won’t be necessary!
```jsx title="Change Hostname"
```sh title="Change Hostname"
sudo nano /etc/hostname
```
```jsx title="Change Hosts File"
```sh title="Change Hosts File"
sudo nano /etc/hosts
```
```jsx title="Reset the Machine ID"
```text title="Reset the Machine ID"
rm -f /etc/machine-id /var/lib/dbus/machine-id
dbus-uuidgen --ensure=/etc/machine-id
dbus-uuidgen --ensure
```
```jsx title="Regenerate SSH Keys"
```text title="Regenerate SSH Keys"
rm -f /etc/machine-id /var/lib/dbus/machine-id
dbus-uuidgen --ensure=/etc/machine-id
dbus-uuidgen --ensure
```
```jsx title="Reboot the Server to Apply Changes"
```text title="Reboot the Server to Apply Changes"
reboot
```
@@ -155,3 +169,5 @@ Setting up alerts in Proxmox is important and critical to making sure you are no
https://technotim.live/posts/proxmox-alerts/
## Related Documentation
- [Related Proxmox Documentation](<../../../reference/Virtualization and Storage/Proxmox/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -5,7 +5,8 @@ tags:
- iSCSI
---
**Purpose**: There is a way to incorporate ProxmoxVE and TrueNAS more deeply using SSH, simplifying the deployment of virtual disks/volumes passed into GuestVMs in ProxmoxVE. Using ZFS over iSCSI will give you the following non-exhaustive list of benefits:
## Purpose
There is a way to incorporate ProxmoxVE and TrueNAS more deeply using SSH, simplifying the deployment of virtual disks/volumes passed into GuestVMs in ProxmoxVE. Using ZFS over iSCSI will give you the following non-exhaustive list of benefits:
- Automatically make Zvols in a ZFS Storage Pool
- Automatically bind device-based iSCSI Extents/LUNs to the Zvols
@@ -20,7 +21,7 @@ tags:
Secondly, this guide assumes the ProxmoxVE cluster nodes and TrueNAS server exist on the same network `192.168.101.0/24`.
## ZFS over iSCSI Operational Flow
``` mermaid
```mermaid
sequenceDiagram
participant ProxmoxVE as ProxmoxVE Cluster
participant TrueNAS as TrueNAS Core (inc. iSCSI & ZFS Storage)
@@ -39,14 +40,14 @@ You first need to make some changes to the SSHD configuration of the ZFS server(
=== "OpenSSH-based OS"
```jsx title="/etc/ssh/sshd_config"
```text title="/etc/ssh/sshd_config"
UseDNS no
GSSAPIAuthentication no
```
=== "Solaris-based OS"
```jsx title="/etc/ssh/sshd_config"
```text title="/etc/ssh/sshd_config"
LookupClientHostnames no
VerifyReverseMapping no
GSSAPIAuthentication no
@@ -58,7 +59,7 @@ The first step is creating SSH trust between the ProxmoxVE cluster nodes and the
**Note**: I will be writing the SSH configuration with the name `192.168.101.100` for simplicity so I know what server the identity belongs to. You could also name it something else like `storage.bunny-lab.io_id_rsa`.
``` sh
```sh
mkdir /etc/pve/priv/zfs
ssh-keygen -f /etc/pve/priv/zfs/192.168.101.100_id_rsa # (1)
ssh-copy-id -i /etc/pve/priv/zfs/192.168.101.100_id_rsa.pub root@192.168.101.100 # (2)
@@ -69,10 +70,10 @@ ssh -i /etc/pve/priv/zfs/192.168.101.100_id_rsa root@192.168.101.100 # (3)
2. Send the SSH key to the TrueNAS server.
3. Connect to the TrueNAS server at least once to finish establishing the connection.
### Install & Configure Storage Provider
### Install and Configure Storage Provider
Now you need to set up the storage provider in TrueNAS. You will run the commands below within a ProxmoxVE shell, then when finished, log out of the ProxmoxVE WebUI, clear the browser cache for ProxmoxVE, then log back in. This will have added a new storage provider called `FreeNAS-API` under the `ZFS over iSCSI` storage type.
``` sh
```sh
keyring_location=/usr/share/keyrings/ksatechnologies-truenas-proxmox-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/ksatechnologies/truenas-proxmox/gpg.284C106104A8CE6D.key' | gpg --dearmor >> ${keyring_location}
@@ -121,3 +122,6 @@ Navigate to **"Datacenter (BUNNY-CLUSTER) > Storage > Add > ZFS over iSCSI"**
!!! success "Storage is Provisioned"
At this point, the storage should propagate throughout the ProxmoxVE cluster, and appear as a location to deploy virtual machines and/or containers. You can now use this storage for snapshots and live-migrations between ProxmoxVE cluster nodes as well.
## Related Documentation
- [Related Proxmox Documentation](<../../../reference/Virtualization and Storage/Proxmox/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,64 @@
---
tags:
- Rancher
- Harvester
---
## Purpose
Rancher Harvester is an awesome tool that acts like a self-hosted cloud VDI provider, similar to AWS, Linode, and other online cloud compute platforms. In most scenarios, you will deploy "Rancher" in addition to Harvester to orchestrate the deployment, management, and rolling upgrades of a Kubernetes Cluster. You can also just run standalone Virtual Machines, similar to Hyper-V, RHEV, oVirt, Bhyve, XenServer, XCP-NG, and VMware ESXi.
!!! note "Prerequisites"
This document assumes your bare-metal host has at least 32GB of Memory, 200GB of Disk Space, and 8 processor cores. See [Recommended System Requirements](https://docs.harvesterhci.io/v1.1/install/requirements)
## First Harvester Node
### Download Installer ISO
You will need to navigate to the Rancher Harvester GitHub to download the [latest ISO release of Harvester](https://releases.rancher.com/harvester/v1.1.2/harvester-v1.1.2-amd64.iso), currently **v1.1.2**. Then image it onto a USB flashdrive using a tool like [Rufus](https://github.com/pbatard/rufus/releases/download/v4.2/rufus-4.2p.exe). Proceed to boot the bare-metal server from the USB drive to begin the Harvester installation process.
### Begin Setup Process
You will be waiting a few minutes while the server boots from the USB drive, but you will eventually land on a page where it asks you to set up various values to use for networking and the cluster itself.
The values seen below are examples and represent how my homelab is configured.
- **Management Interface(s)**: `eno1,eno2,eno3,eno4`
- **Network Bond Mode**: `Active-Backup`
- **IP Address**: `192.168.3.254/24` *<---- **Note:** Be sure to add CIDR Notation*.
- **Gateway**: `192.168.3.1`
- **DNS Server(s)**: `1.1.1.1,1.0.0.1,8.8.8.8,8.8.4.4`
- **Cluster VIP (Virtual IP)**: `192.168.3.251` *<---- **Note**: See "VIRTUAL IP CONFIGURATION" note below.*
- **Cluster Node Token**: `19-USED-when-JOINING-more-NODES-to-EXISTING-cluster-55`
- **NTP Server(s)**: `0.suse.pool.ntp.org`
!!! warning "Virtual IP Configuration"
The VIP assigned to the first node in the cluster will act as a proxy to the built-in load-balancing system. It is important that you do not create a second node with the same VIP (Could cause instability in existing cluster), or use an existing VIP as the Node IP address of a new Harvester Cluster Node.
!!! tip "Tip"
Based on your preference, it would be good to assign the device a static DHCP reservation, or use numbers counting down from **.254** (e.g. `192.168.3.254`, `192.168.3.253`, `192.168.3.252`, etc...)
### Wait for Installation to Complete
The installation process will take quite some time, but when it is finished, the Harvester Node will reboot and take you to a splash screen with the Harvester logo, with indicators as to what the VIP and Management Interface IPs are configured as, and whether or not the associated systems are operational and ready. **Be patient until both statuses say `READY`**. If after 15 minutes the status has still not changed to `READY` both for fields, see the note below.
!!! warning "Issues with `rancher-harvester-repo` Image"
During my initial deployment efforts with Harvester v.1.1.2, I noticed that the Harvester Node never came online. That was because something bugged-out during installation and the `rancher-harvester-repo` image was not properly installed prior to node initialization. This will effectively soft-lock the node unless you reinstall the node from scratch, as the Docker Hub Registry that Harvester is looking for to finish the deployment does not exist anymore and depends on the local image bundled with the installer ISO.
If this happens, you unfortunately need to start over and reinstall Harvester and hope that it works the second time around. No other workarounds are currently known at this time on version 1.1.2.
## Additional Harvester Nodes
If you work in a production environment, you will want more than one Harvester node to allow live-migrations, high-availability, and better load-balancing in the Harvester Cluster. The section below will outline the steps necessary to create additional Harvester nodes, join them to the existing Harvester cluster, and validate that they are functioning without issues.
### Installation Process
Not Documented Yet
### Joining Node to Existing Cluster
Not Documented Yet
## Installing Rancher
If you plan on using Harvester for more than just running Virtual Machines (e.g. Containers), you will want to deploy Rancher inside of the Harvester Cluster in order or orchestrate the deployment, management, and rolling upgrades of various forms of Kubernetes Clusters (RKE2 Suggested). The steps below will go over the process of deploying a High-Availability Rancher environment to "adopt" Harvester as a VDI/compute platform for deploying the Kubernetes Cluster.
### Provision ControlPlane Node(s) VMs on Harvester
Not Documented Yet
### Adopt Harvester as Cluster Target
Not Documented Yet
### Deploy Production Kubernetes Cluster to Harvester
Not Documented Yet
## Related Documentation
- [Related Virtualization and Storage Documentation](<../../../reference/Virtualization and Storage/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -0,0 +1,20 @@
---
tags:
- Virtualization and Storage
- Deployments
- Documentation
---
# Virtualization and Storage
## Purpose
Find deployments for virtualization and storage. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Guests
- Hyper-V
- OpenStack
- Proxmox
- Rancher Harvester
## Follow the Subject
[Virtualization and Storage](<../../reference/Virtualization and Storage/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -5,7 +5,7 @@ tags:
- Workstation
---
**Purpose**:
## Purpose
This document serves as a general guideline for my workstation deployment process when working with Fedora Workstation 41 and up. This document will constantly evolve over time based on my needs.
## Automate Initial Configurations
@@ -56,3 +56,6 @@ Backups are located here: https://cloud.bunny-lab.io/f/792649
By default, XFCE has a really small threshold for telling windows to "snap" to the sides of the screens, such as a half:half arrangement. This can be adjusted by navigating to "**Applications Menu > Settings > Settings Manager > Windows Manager Tweaks > Placement**"
Once you have reached this window, you will see a slider from "**Small**" to "**Large**". Slide the slider all the way to the right, facing "**Large**". Now windows will snap to the sides of the screen successfully.
## Related Documentation
- [Related Windows and Linux Documentation](<../../../reference/Windows and Linux/index.md>) — Find the connected deployments, procedures, and references for this subject.
+16
View File
@@ -0,0 +1,16 @@
---
tags:
- Windows and Linux
- Deployments
- Documentation
---
# Windows and Linux
## Purpose
Find deployments for windows and linux. Follow the subject guide to choose the relevant environment and connect this material to the other document types.
## Includes
- Fedora
## Follow the Subject
[Windows and Linux](<../../reference/Windows and Linux/index.md>) explains the relationships and offers starting points for the documented tasks.
@@ -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.
!!! 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,7 +136,7 @@ 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 .
```
@@ -140,7 +147,7 @@ kubectl apply -k .
## 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.
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

@@ -5,7 +5,8 @@ tags:
- 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.
## 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"
@@ -39,3 +40,7 @@ networks:
```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.
@@ -6,7 +6,8 @@ tags:
- 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.
## 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"
@@ -37,6 +38,7 @@ 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
@@ -186,3 +188,7 @@ When the server is deployed, it will come with a bunch of unnecessary documentat
## 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.
@@ -15,7 +15,7 @@ After many years of using Material for MKDocs and it being updated with new feat
## 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
```mermaid
sequenceDiagram
autonumber
actor Author as Doc Author
@@ -148,6 +148,7 @@ EOF
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.
@@ -201,142 +202,11 @@ sudo systemctl reload nginx
sudo systemctl enable nginx
```
## Gitea ACT Runner
Now is time for the arguably most-important stage of deployment, which is setting up a [Gitea Act Runner](https://docs.gitea.com/usage/actions/act-runner). This is how document changes in a Gitea repository will propagate automatically into Zensical's `/srv/zensical/docs` folder.
```sh
# Install Dependencies
sudo apt install -y nodejs npm git rsync curl
# Create dedicated Gitea runner service account
sudo useradd --system --create-home --home /var/lib/gitea_runner --shell /usr/sbin/nologin gitearunner || true
# Allow the runner to write documentation changes
sudo usermod -aG zensical gitearunner
# Allow the runner to start and stop Zensical Watchdog Service
sudo tee /etc/sudoers.d/gitearunner-systemctl > /dev/null <<'EOF'
gitearunner ALL=NOPASSWD: /usr/bin/systemctl start zensical-watchdog.service, /usr/bin/systemctl stop zensical-watchdog.service
EOF
sudo chmod 440 /etc/sudoers.d/gitearunner-systemctl
sudo chown root:root /etc/sudoers.d/gitearunner-systemctl
sudo visudo -c
# Download Newest Gitea Runner Binary (https://gitea.com/gitea/act_runner/releases)
cd /tmp
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-linux-amd64
sudo install -m 0755 act_runner-0.2.13-linux-amd64 /usr/local/bin/gitea_runner
gitea_runner --version
# Generate Gitea Runner Configuration
sudo mkdir -p /etc/gitea_runner
sudo chown gitearunner:gitearunner /etc/gitea_runner
sudo -u gitearunner gitea_runner generate-config > /etc/gitea_runner/config.yaml
```
### Configure Registration Token
- Navigate to: "**<Gitea Repo> > Settings > Actions > Runners**"
- If you don't see this, it needs to be enabled. Navigate to: "**<Gitea Repo> > Settings > "Enable Repository Actions: Enabled" > Update Settings**"
- Click the "**Create New Runner**" button on the top-right of the page and copy the registration token somewhere temporarily.
- Navigate back to the GuestVM running Zensical and run the following commands.
```sh
# Start Token Registration Process
sudo -u gitearunner env HOME=/var/lib/gitea_runner /usr/local/bin/gitea_runner register --config /etc/gitea_runner/config.yaml
# Gitea Instance URL: https://git.bunny-lab.io
# Gitea Runner Token: <Gitea-Runner-Token>
# Runner Name: zensical-docs-runner
# Move Runner Config to Correct Location & Configure Permissions
sudo mv /tmp/.runner /var/lib/gitea_runner/.runner
sudo chown gitearunner:gitearunner /var/lib/gitea_runner/.runner
sudo chmod 600 /var/lib/gitea_runner/.runner
```
### Create Service
Now we need to configure the Gitea runner to start automatically via a service just like the Zensical Watchdog service.
```sh
# Create Gitea Runner Service
sudo tee /etc/systemd/system/gitea-runner.service > /dev/null <<'EOF'
[Unit]
Description=Gitea Actions Runner (gitea_runner)
After=network-online.target
Wants=network-online.target
[Service]
Environment=HOME=/var/lib/gitea_runner
User=gitearunner
Group=gitearunner
WorkingDirectory=/var/lib/gitea_runner
ExecStart=/usr/local/bin/gitea_runner daemon --config /etc/gitea_runner/config.yaml
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
EOF
# Remove Container-Based Configurations to Force Runner to Run in Host Mode
sudo sed -i \
'/^[[:space:]]*labels:/,/^[[:space:]]*cache:/{
/^[[:space:]]*labels:/c\ labels:\n - "zensical-host:host"
/^[[:space:]]*cache:/!d
}' \
/etc/gitea_runner/config.yaml
# Enable and Start the Service
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-runner.service
```
### Repository Workflow
Place the following file into your documentation repository at the given location and this will enable the runner to execute when changes happen to the repository data.
```yaml title="gitea/workflows/automatic-deployment.yml"
name: Automatic Documentation Deployment
on:
push:
branches: [ main ]
jobs:
zensical_deploy:
name: Sync Docs to https://kb.bunny-lab.io
runs-on: zensical-host
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Stop Zensical Service
run: sudo /usr/bin/systemctl stop zensical-watchdog.service
- name: Sync repository into /srv/zensical/docs
run: |
rsync -rlD --delete \
--exclude='.git/' \
--exclude='.gitea/' \
--exclude='assets/' \
--exclude='schema/' \
--exclude='stylesheets/' \
--exclude='schema.json' \
--chmod=D2775,F664 \
. /srv/zensical/docs/
- name: Start Zensical Service
run: sudo /usr/bin/systemctl start zensical-watchdog.service
- name: Notify via NTFY
if: always()
run: |
curl -d "https://kb.bunny-lab.io - Zensical job status: ${{ job.status }}" https://ntfy.bunny-lab.io/gitea-runners
```
## 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](../edge/traefik.md) reverse proxy and are configured to use [dynamic configuration files](../edge/traefik.md#dynamic-configuration-files). Add the file below to expose the Zensical service to the rest of the world.
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:
@@ -356,3 +226,7 @@ http:
- 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:
@@ -21,3 +27,6 @@ dhcp-boot=undionly.kpxe,,192.168.3.9
```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.
!!! 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)
@@ -127,174 +133,155 @@ At this point, you will be prompted to login to the website hosted by FOG Projec
- /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
```
@@ -304,3 +291,8 @@ 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.
@@ -5,11 +5,11 @@ tags:
- 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.
## 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"
@@ -81,6 +81,7 @@ 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:
@@ -100,3 +101,8 @@ http:
- 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,14 +189,15 @@ 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...
@@ -204,7 +212,8 @@ 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...
@@ -217,3 +226,5 @@ At this point, you should finally be ready to connect to Windows and Linux devic
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)
@@ -50,7 +50,7 @@ sequenceDiagram
```
### Simplified
``` mermaid
```mermaid
sequenceDiagram
participant Gitea as Gitea (Puppet Repository)
participant PuppetMaster as Puppet Server
@@ -75,36 +75,38 @@ sequenceDiagram
### 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
```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
@@ -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.
## Related Documentation
- [Related Automation Documentation](<../../../reference/Automation/index.md>) — Find the connected deployments, procedures, and references for this subject.
@@ -4,14 +4,14 @@ tags:
- RMM
---
**Purpose**:
## Purpose
Tactical RMM is a remote monitoring & management tool built with Django, Vue and Golang. [Official Documentation](https://docs.tacticalrmm.com/install_server/).
!!! Requirements
!!! 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
@@ -37,3 +37,6 @@ 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.
@@ -5,7 +5,8 @@ tags:
- Docker
---
**Purpose**: Self-hosted open-source no-code business automation tool.
## Purpose
Self-hosted open-source no-code business automation tool.
```yaml title="docker-compose.yml"
version: '3.0'
@@ -58,7 +59,7 @@ networks:
external: true
```
```jsx title=".env"
```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
@@ -75,3 +76,7 @@ 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.
@@ -5,7 +5,8 @@ tags:
- 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.
## 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/)
@@ -63,6 +64,7 @@ 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:
@@ -82,3 +84,7 @@ http:
- 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.
+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.
+22 -5
View File
@@ -1,15 +1,32 @@
---
tags:
- Deployments
- Index
- Documentation
---
# Deployments
## Purpose
Build and deployment documentation for platforms, services, and automation stacks.
Build the system you need, then follow its linked maintenance and reference material. Use the subject guides to select prerequisites and distinguish documented implementation alternatives.
## Includes
- Platform deployments (virtualization and containerization)
- Service deployments and integration patterns
- Automation stack deployment guides
- Applications
- Automation
- Backup and Recovery
- Containers
- Identity and Certificates
- Networking and Access
- Virtualization and Storage
- Windows and Linux
## Start with a Subject
- [Applications](<../reference/Applications/index.md>) — Find applications by the service they provide, then continue to their deployment, authentication, data, and maintenance documentation.
- [Automation](<../reference/Automation/index.md>) — Connect source control, automation controllers, managed hosts, and configuration delivery. Use the documented execution environment and authentication method for each workflow.
- [Backup and Recovery](<../reference/Backup and Recovery/index.md>) — Find backup concepts, repository maintenance, and recovery dependencies. Select the procedure for the affected backup system and distinguish a backup restore from a replica or snapshot operation.
- [Containers](<../reference/Containers/index.md>) — Prepare the Docker or Kubernetes environment used by application deployments, then follow the operating procedures for building, moving, and exposing workloads.
- [Identity and Certificates](<../reference/Identity and Certificates/index.md>) — Connect directory services, certificate trust, single sign-on, and application authentication. Start with the identity system involved, then follow the integration or maintenance procedure.
- [Networking and Access](<../reference/Networking and Access/index.md>) — Find the DNS, proxy, VPN, and remote-access instructions that connect users and services. Use the address plans to identify the intended network before changing connectivity.
- [Virtualization and Storage](<../reference/Virtualization and Storage/index.md>) — Follow the relationship between hypervisors, shared storage, guest disks, and recovery procedures. Select the documented storage design before choosing a maintenance command.
- [Windows and Linux](<../reference/Windows and Linux/index.md>) — Find workstation and server operating-system setup, updates, and repairs. Storage, networking, and identity tasks are linked to their subject guides when they cross operating-system boundaries.
## Find Related Knowledge
[The subject guides](<../reference/index.md>) connect these deployments to the other document roles.
@@ -1,114 +0,0 @@
---
tags:
- Containers
- Docker
- Containerization
---
**Purpose**: Docker container running Alpine Linux that automates and improves upon much of the script mentioned in the [Git Repo Updater](../../../../../scripts/bash/git-repo-updater.md) document. It offers the additional benefits of checking for updates every 5 seconds instead of every 60 seconds. It also accepts environment variables to provide credentials and notification settings, and can have an infinite number of monitored repositories.
### Deployment
You can find the current up-to-date Gitea repository that includes the `docker-compose.yml` and `.env` files that you need to deploy everything [here](https://git.bunny-lab.io/container-registry/-/packages/container/git-repo-updater/latest)
```jsx title="docker-compose.yml"
version: '3.3'
services:
git-repo-updater:
privileged: true
container_name: git-repo-updater
env_file:
- stack.env
image: git.bunny-lab.io/container-registry/git-repo-updater:latest
volumes:
- /srv/containers:/srv/containers
- /srv/containers/git-repo-updater/Repo_Cache:/root/Repo_Cache
restart: always
```
```jsx title=".env"
# Gitea Credentials
GIT_USERNAME=nicole.rappe
GIT_PASSWORD=USE-AN-APP-PASSWORD
# NTFY Push Notification Server URL
NTFY_URL=https://ntfy.cyberstrawberry.net/git-repo-updater
# Repository/Destination Pairs (Add as Many as Needed)
REPO_01="https://${GIT_USERNAME}:${GIT_PASSWORD}@git.bunny-lab.io/bunny-lab/docs.git,/srv/containers/material-mkdocs/docs/docs"
REPO_02="https://${GIT_USERNAME}:${GIT_PASSWORD}@git.bunny-lab.io/GitOps/servers.bunny-lab.io.git,/srv/containers/homepage-docker"
```
### Build / Development
If you want to learn how the container was assembled, the related build files are located [here](https://git.cyberstrawberry.net/container-registry/git-repo-updater)
```jsx title="Dockerfile"
# Use Alpine as the base image of the container
FROM alpine:latest
# Install necessary packages
RUN apk --no-cache add git curl rsync
# Add script
COPY repo_watcher.sh /repo_watcher.sh
RUN chmod +x /repo_watcher.sh
#Create Directory to store Repositories
RUN mkdir -p /root/Repo_Cache
# Start script (Alpine uses /bin/sh instead of /bin/bash)
CMD ["/bin/sh", "-c", "/repo_watcher.sh"]
```
```jsx title="repo_watcher.sh"
#!/bin/sh
# Function to process each repo-destination pair
process_repo() {
FULL_REPO_URL=$1
DESTINATION=$2
# Extract the URL without credentials for logging and notifications
CLEAN_REPO_URL=$(echo "$FULL_REPO_URL" | sed 's/https:\/\/[^@]*@/https:\/\//')
# Directory to hold the repository locally
REPO_DIR="/root/Repo_Cache/$(basename $CLEAN_REPO_URL .git)"
# Clone the repo if it doesn't exist, or navigate to it if it does
if [ ! -d "$REPO_DIR" ]; then
curl -d "Cloning: $CLEAN_REPO_URL" $NTFY_URL
git clone "$FULL_REPO_URL" "$REPO_DIR" > /dev/null 2>&1
fi
cd "$REPO_DIR" || exit
# Fetch the latest changes
git fetch origin main > /dev/null 2>&1
# Check if the local repository is behind the remote
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse @{u})
if [ "$LOCAL" != "$REMOTE" ]; then
curl -d "Updating: $CLEAN_REPO_URL" $NTFY_URL
git pull origin main > /dev/null 2>&1
rsync -av --delete --exclude '.git/' ./ "$DESTINATION" > /dev/null 2>&1
fi
}
# Main loop
while true; do
# Iterate over each environment variable matching 'REPO_[0-9]+'
env | grep '^REPO_[0-9]\+=' | while IFS='=' read -r name value; do
# Split the value by comma and read into separate variables
OLD_IFS="$IFS" # Save the original IFS
IFS=',' # Set IFS to comma for splitting
set -- $value # Set positional parameters ($1, $2, ...)
REPO_URL="$1" # Assign first parameter to REPO_URL
DESTINATION="$2" # Assign second parameter to DESTINATION
IFS="$OLD_IFS" # Restore original IFS
process_repo "$REPO_URL" "$DESTINATION"
done
# Wait for 5 seconds before the next iteration
sleep 5
done
```

Some files were not shown because too many files have changed in this diff Show More