docs: Update docs for the correctness (#13)
This commit is contained in:
1 parent
8dba55272c
commit
51a783f93a
60 files changed
+2456
-380
No files matched your search
@@ -1,13 +1,13 @@
|
||||
---
|
||||
title: Root Infrastructure
|
||||
description: Documentation for the root.ermnvldmr.com infrastructure.
|
||||
title: Documentation of ermnvldmr.com root deployment commons
|
||||
description: Documentation for the ermnvldmr.com root deployment commons framework.
|
||||
weight: 1
|
||||
type: docs
|
||||
cascade:
|
||||
type: docs
|
||||
---
|
||||
|
||||
The engine powering the shared infrastructure of `root.ermnvldmr.com`. This framework provides a minimal-dependency deployment environment for independent, self-hosted projects.
|
||||
The `ermnvldmr.com-root-commons` framework provides a minimal-dependency deployment environment for independent, self-hosted projects.
|
||||
|
||||
The generic logic, scripts, and deployment patterns used across multiple unrelated self-hosted applications are stored in the [GitHub: ermnvldmr.com-root-commons](https://github.com/deytenit/ermnvldmr.com-root-commons) repository.
|
||||
|
||||
@@ -23,7 +23,6 @@ The generic logic, scripts, and deployment patterns used across multiple unrelat
|
||||
{{% cards %}}
|
||||
{{< card link="concepts" title="Concepts" icon="book-open" subtitle="Theoretical foundations, architecture, and security models." >}}
|
||||
{{< card link="guides" title="Guides" icon="map" subtitle="Step-by-step guides for installation and action development." >}}
|
||||
{{< card link="recipes" title="Recipes" icon="beaker" subtitle="Collection of step-by-step procedures for infrastructure maintenance and deployment." >}}
|
||||
{{< card link="reference" title="Reference" icon="code" subtitle="API and technical references for developers." >}}
|
||||
{{% /cards %}}
|
||||
|
||||
@@ -32,4 +31,3 @@ The generic logic, scripts, and deployment patterns used across multiple unrelat
|
||||
**See also:**
|
||||
|
||||
- [GitHub: ermnvldmr.com-root-commons](https://github.com/deytenit/ermnvldmr.com-root-commons)
|
||||
- [GitHub: root.ermnvldmr.com](https://github.com/deytenit/root.ermnvldmr.com)
|
||||
@@ -4,7 +4,7 @@ description: Theoretical foundations, architecture, and security models.
|
||||
weight: 10
|
||||
---
|
||||
|
||||
Theoretical foundations, architecture, and security models for the Root infrastructure framework.
|
||||
Theoretical foundations, architecture, and security models for the ermnvldmr.com root deployment commons framework.
|
||||
|
||||
{{% cards %}}
|
||||
{{< card link="principles" title="Infrastructure principles" icon="book-open" subtitle="Predictability, minimal dependencies, and decentralization." >}}
|
||||
|
||||
@@ -33,16 +33,31 @@ The framework is typically deployed as a shared [Commons](/root/glossary#commons
|
||||
{{< filetree/container >}}
|
||||
{{< filetree/folder name="configs-repo" state="open" >}}
|
||||
{{< filetree/folder name=".operator" state="open" >}}
|
||||
{{< filetree/folder name="shared" >}}
|
||||
{{< filetree/file name="root (dispatcher)" >}}
|
||||
{{< filetree/folder name="shared (submodule)" state="open" >}}
|
||||
{{< filetree/folder name="scripts" >}}
|
||||
{{< filetree/folder name="run" >}}
|
||||
{{< filetree/file name="root (dispatcher)" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< filetree/folder name="lib" >}}
|
||||
{{< filetree/file name="shared libraries" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< filetree/folder name="actions" >}}
|
||||
{{< filetree/file name="shared actions" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< filetree/folder name="local" >}}
|
||||
{{< filetree/file name="node-specific actions" >}}
|
||||
{{< filetree/folder name="local" state="open" >}}
|
||||
{{< filetree/folder name="scripts" >}}
|
||||
{{< filetree/folder name="actions" >}}
|
||||
{{< filetree/file name="node-specific overrides" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< filetree/folder name="node-1" >}}
|
||||
{{< filetree/folder name="daedalus (node)" >}}
|
||||
{{< filetree/file name="docker-compose.yml" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< filetree/file name="init.sh (bootstrap)" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/container >}}
|
||||
|
||||
|
||||
@@ -6,29 +6,62 @@ weight: 20
|
||||
|
||||
Security in Root is achieved through strict privilege isolation and project-level "sandboxing" to mitigate the impact of service compromises.
|
||||
|
||||
## The "No-Root" principle {#noroot}
|
||||
## The "No-Root" Principle {#noroot}
|
||||
|
||||
Running applications as `root` inside containers is a significant security risk. The framework enforces isolation via the `tiers/useradd` and `tiers/chown` actions.
|
||||
|
||||
### Project-specific users
|
||||
|
||||
Every project (e.g., `traefik`, `synapse`) is assigned a dedicated system user on the host.
|
||||
Every project located at `{repository root}/{node}/{project}` is assigned a dedicated system user on the host.
|
||||
|
||||
- **Isolation**: If a container is compromised, the attacker only gains the privileges of that specific low-privileged user.
|
||||
- **Filesystem safety**: Projects can only read/write to their own directories within the [Tiers](/root/glossary#tier).
|
||||
|
||||
## Docker socket protection {#socket-protection}
|
||||
|
||||
Direct access to `/var/run/docker.sock` is equivalent to root access on the host. To prevent services from abusing this access, the framework utilizes a **Socket Proxy**.
|
||||
Direct access to `/var/run/docker.sock` is equivalent to root access on the host. As a best practice, it is highly recommended to protect the Docker socket. One way to achieve this is by utilizing a **Socket Proxy** (e.g., based on `tecnativa/docker-socket-proxy`) to filter and restrict access to the Docker API.
|
||||
|
||||
- **Restricted API**: The proxy filters Docker API calls, allowing only necessary operations (e.g., `GET containers`) and blocking dangerous ones (e.g., `POST containers/create`).
|
||||
```yaml filename="docker-socket-proxy-example.yml"
|
||||
services:
|
||||
socket-proxy:
|
||||
image: tecnativa/docker-socket-proxy:0
|
||||
container_name: root-socket-proxy
|
||||
user: "0:0"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
CONTAINERS: 1
|
||||
SERVICES: 1
|
||||
TASKS: 1
|
||||
networks:
|
||||
socket: {}
|
||||
restart: unless-stopped
|
||||
|
||||
traefik:
|
||||
# ...
|
||||
depends_on:
|
||||
- socket-proxy
|
||||
command:
|
||||
# Use the proxy instead of the local socket
|
||||
- "--providers.docker.endpoint=tcp://root-socket-proxy:2375"
|
||||
networks:
|
||||
socket: {}
|
||||
```
|
||||
|
||||
## Security Monitoring (CrowdSec) {#crowdsec}
|
||||
|
||||
The framework integrates **CrowdSec** for behavioral detection and automated response.
|
||||
|
||||
- **Intrusion detection**: CrowdSec monitors logs from [Traefik](https://traefik.io/) and SSH for suspicious patterns (e.g., brute-force attacks, port scanning).
|
||||
- **Automated blocking**: When a threat is detected, the **CrowdSec Firewall Bouncer** automatically updates [UFW](https://help.ubuntu.com/community/UFW) rules to block the malicious IP at the host level.
|
||||
- **Shared threat intelligence**: CrowdSec shares anonymized threat data with its community, providing preemptive protection against known bad actors.
|
||||
|
||||
## Network hardening {#networking}
|
||||
|
||||
Root uses `configure/ufw` to implement a "Default Deny" policy.
|
||||
|
||||
- **Internal routing**: Services communicate over a dedicated `root-direct` bridge network.
|
||||
- **TProxy integration**: Outgoing traffic is routed through Xray for enclave-like isolation and granular routing rules.
|
||||
- **Internal routing**: Services communicate over a dedicated `root-proxy` bridge network, which is often configured as `internal: true`.
|
||||
- **Enclave isolation**: Outgoing traffic can be routed through a dedicated egress node for granular control.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,37 +8,67 @@ The framework enforces a standardized storage taxonomy. This ensures that every
|
||||
|
||||
## The storage taxonomy {#taxonomy}
|
||||
|
||||
Data is divided into three logical [Tiers](/root/glossary#tier) based on its lifecycle, volume, and importance.
|
||||
Data is divided into three logical [Tiers](/root/glossary#tier) based on its performance requirements, lifecycle, and importance.
|
||||
|
||||
### Tier 1: Configuration & critical state
|
||||
### Tier 1: Configuration & Cache
|
||||
|
||||
**Path:** `${ROOT_NODE_DIR}/@tier1`
|
||||
|
||||
- **Contents**: Config files, small SQLite databases, SSL certificates.
|
||||
- **Characteristics**: Extremely high value, low volume.
|
||||
- **Backup strategy**: Frequent (hourly/daily), long retention.
|
||||
- **Contents**: Config files, small SQLite databases, SSL certificates, application cache.
|
||||
- **Characteristics**: Extremely high value, low to medium volume, requires low latency.
|
||||
- **Hardware**: High-speed SSD storage, typically shared with the Operating System.
|
||||
|
||||
### Tier 2: Application data
|
||||
### Tier 2: Application Data
|
||||
|
||||
**Path:** `${ROOT_NODE_DIR}/@tier2`
|
||||
|
||||
- **Contents**: User uploads, large databases, persistent application state.
|
||||
- **Characteristics**: High value, medium to high volume.
|
||||
- **Backup strategy**: Daily, prioritized for integrity.
|
||||
- **Characteristics**: High value, medium to high volume, requires high reliability.
|
||||
- **Hardware**: Reliable HDD clusters, RAID arrays, or dedicated storage compute.
|
||||
|
||||
### Tier 3: Transients & bulk media
|
||||
### Tier 3: Transients & Bulk Media
|
||||
|
||||
**Path:** `${ROOT_NODE_DIR}/@tier3`
|
||||
|
||||
- **Contents**: Logs, caches, temporary files, bulk media downloads.
|
||||
- **Characteristics**: Low value, high volume.
|
||||
- **Backup strategy**: Minimal or none. These directories are typically excluded from sync operations.
|
||||
- **Contents**: Logs, temporary files, bulk media (movies, music), and other non-critical large data.
|
||||
- **Characteristics**: Low value, very high volume.
|
||||
- **Hardware**: High-capacity HDDs optimized for continuous sequential write/read (e.g., WD Purple). Note that Tier 3 is **too slow for cache**.
|
||||
|
||||
## Backup strategy {#backup}
|
||||
|
||||
The framework does not enforce a specific backup strategy or provide a default implementation, allowing for complete node-specific flexibility. Operators are expected to implement their own backup logic.
|
||||
|
||||
### Example: Restic backup
|
||||
|
||||
A common best practice is to use **Restic** for backups. For example, you might create an operator compose file to run Restic:
|
||||
|
||||
```yaml filename="operator-compose.yml"
|
||||
services:
|
||||
restic:
|
||||
image: restic/restic:0.18.1
|
||||
container_name: operator-restic
|
||||
volumes:
|
||||
- ./@tier2/{project}/{service}/{data}:/data/@tier2/{project}/{service}/{data}:ro
|
||||
- ./@tier1/{project}/{service}/{data}:/data/@tier1/{project}/{service}/{data}:ro
|
||||
- ./@tier1/.operator/restic/cache:/var/restic-cache
|
||||
environment:
|
||||
RESTIC_REPOSITORY: "s3:example.com/bucket"
|
||||
RESTIC_PASSWORD: ${RESTIC_PASSWORD}
|
||||
# ... AWS/S3 credentials
|
||||
network_mode: "host"
|
||||
entrypoint: [ "restic" ]
|
||||
user: "0:0"
|
||||
```
|
||||
|
||||
### Implementing the strategy
|
||||
|
||||
Operators can implement this strategy by defining a local action in `.operator/local/scripts/actions/sync/tiers`. The `root` dispatcher can then execute this script to trigger the backup, allowing for granular control over how data is persisted.
|
||||
|
||||
## Justification {#justification}
|
||||
|
||||
1. **Backup efficiency**: By separating logs (Tier 3) from configs (Tier 1), we avoid wasting storage space on redundant backups of transient data.
|
||||
2. **Hardware optimization**: Tier 1 and 2 can be placed on fast SSD storage, while Tier 3 can be mounted on slower, high-capacity HDDs.
|
||||
3. **Instant understanding**: Any operator can enter a [Node](/root/glossary#node) directory and immediately know where the critical data resides.
|
||||
1. **Hardware optimization**: By mapping tiers to specific hardware (SSDs for Tier 1, RAID for Tier 2, Purples for Tier 3), we optimize for both performance and cost.
|
||||
2. **Selective backup**: Separating transient logs and bulk media (Tier 3) from critical configs (Tier 1) prevents wasting expensive backup storage.
|
||||
3. **Architectural clarity**: Any operator can inspect a [Node](/root/glossary#node) directory and immediately understand the storage requirements and priority of its contents.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@ description: Step-by-step guides for installation and action development.
|
||||
weight: 20
|
||||
---
|
||||
|
||||
Step-by-step guides for installing and developing within the Root infrastructure framework.
|
||||
Step-by-step guides for installing and developing within the ermnvldmr.com root deployment commons framework.
|
||||
|
||||
{{% cards %}}
|
||||
{{< card link="installation" title="Installation" icon="arrow-down" subtitle="Initial setup of the Root framework on a new host." >}}
|
||||
{{< card link="first-node" title="Setting Up Your First Node" icon="map" subtitle="Practical guide to creating your own config repository." >}}
|
||||
{{< card link="installation" title="Installation" icon="arrow-down" subtitle="Initial setup of the framework on a new host." >}}
|
||||
{{< card link="action-development" title="Action development" icon="code" subtitle="Creating and managing atomic automation tasks." >}}
|
||||
{{% /cards %}}
|
||||
@@ -0,0 +1,190 @@
|
||||
---
|
||||
title: "Setting Up Your First Node"
|
||||
description: A practical guide on creating your first node and hooking up the deployment commons.
|
||||
weight: 25
|
||||
---
|
||||
|
||||
**Goal:** Create a configuration repository for your infrastructure, add the root deployment commons as a submodule, and define your first basic node.
|
||||
|
||||
## 1. Creating the Configuration Repository
|
||||
|
||||
Your infrastructure should be managed from a single Git repository. This repository will hold the configuration for all your servers (nodes).
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Step 1: Initialize the repository
|
||||
|
||||
Create a new directory and initialize Git.
|
||||
|
||||
```bash
|
||||
mkdir my-infrastructure
|
||||
cd my-infrastructure
|
||||
git init
|
||||
```
|
||||
|
||||
### Step 2: Add the commons submodule
|
||||
|
||||
The `ermnvldmr.com-root-commons` must be placed at `.operator/shared`.
|
||||
|
||||
```bash
|
||||
mkdir -p .operator
|
||||
git submodule add https://github.com/deytenit/ermnvldmr.com-root-commons.git .operator/shared
|
||||
```
|
||||
|
||||
### Step 3: Create the Bootstrap Script
|
||||
|
||||
Create an `init.sh` file at the root of your repository. This script links the commons framework into your local environment.
|
||||
|
||||
```bash filename="init.sh"
|
||||
#!/usr/bin/env bash
|
||||
# init.sh
|
||||
|
||||
# Source common utilities from the submodule
|
||||
source "$(git -C "$(dirname "$0")" rev-parse --show-toplevel)/.operator/shared/scripts/lib/common.sh"
|
||||
|
||||
SCRIPT_NAME="init"
|
||||
|
||||
navigate_to_repo_root
|
||||
|
||||
log_info "Setting up Git hooks..."
|
||||
git config core.hooksPath .operator/shared/githooks
|
||||
git config --global --add safe.directory "${REPO_ROOT}"
|
||||
|
||||
log_info "Setting up PATH for the root dispatcher..."
|
||||
ABSOLUTE_RUN_DIR="$(realpath "${REPO_ROOT}/.operator/shared/scripts/run")"
|
||||
BASHRC_ENTRY="export PATH=\"${ABSOLUTE_RUN_DIR}:\$PATH\""
|
||||
|
||||
sed -i '/\.operator\/shared\/scripts\/run/d' ~/.bashrc
|
||||
echo "$BASHRC_ENTRY" >> ~/.bashrc
|
||||
log_info "Done. Please run 'source ~/.bashrc' or re-login to your shell."
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
```bash
|
||||
chmod +x init.sh
|
||||
```
|
||||
|
||||
{{% /steps %}}
|
||||
|
||||
## 2. Defining Your First Node
|
||||
|
||||
A Node is a folder at the repository root that represents one physical or virtual server.
|
||||
|
||||
### Node Structure
|
||||
|
||||
Let's create a node named `daedalus`. Inside, we'll define an operator configuration (e.g., for backups) and a core service.
|
||||
|
||||
```bash
|
||||
mkdir -p daedalus/.operator/configs/{cron,crowdsec,systemd,ufw/docker,ufw/host}
|
||||
mkdir -p daedalus/root
|
||||
```
|
||||
|
||||
### Base Configurations (Optional)
|
||||
|
||||
You can place configuration files (like UFW rules or a crontab) inside the `daedalus/.operator/configs/` directory. For example, a basic crontab:
|
||||
|
||||
```bash filename="daedalus/.operator/configs/cron/crontab.template"
|
||||
# Run backups every night at 3:00 AM
|
||||
0 3 * * * root sync tiers daedalus
|
||||
```
|
||||
|
||||
## 3. Configuring Services (Docker Compose)
|
||||
|
||||
The framework relies on `docker-compose.yml` to orchestrate services.
|
||||
|
||||
### Node-Level Infrastructure (Operator)
|
||||
|
||||
The `daedalus/docker-compose.yml` file runs infrastructure utilities, such as `restic` for backups or VPN agents. This compose file has direct access to the filesystem via `@tierX` mounts.
|
||||
|
||||
```yaml filename="daedalus/docker-compose.yml"
|
||||
name: 'operator'
|
||||
|
||||
services:
|
||||
restic:
|
||||
image: restic/restic:0.18.1
|
||||
container_name: operator-restic
|
||||
volumes:
|
||||
# Example: mounting project data for backups (Read-Only)
|
||||
- ./@tier2/my-app/data:/data/@tier2/my-app/data:ro
|
||||
- ./@tier3/.operator/restic/cache:/var/restic-cache
|
||||
environment:
|
||||
RESTIC_REPOSITORY: "s3:example.com/my-bucket/daedalus"
|
||||
RESTIC_PASSWORD: "${RESTIC_PASSWORD?error}"
|
||||
# AWS credentials...
|
||||
network_mode: "host"
|
||||
entrypoint: [ "restic" ]
|
||||
```
|
||||
|
||||
### The Root Project
|
||||
|
||||
The `root` project typically contains your reverse proxies (Traefik) and core services that other projects will route through.
|
||||
|
||||
```yaml filename="daedalus/root/docker-compose.yml"
|
||||
name: root
|
||||
|
||||
services:
|
||||
socket-proxy:
|
||||
image: tecnativa/docker-socket-proxy:0
|
||||
container_name: root-socket-proxy
|
||||
user: "0:0"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
CONTAINERS: 1
|
||||
SERVICES: 1
|
||||
TASKS: 1
|
||||
networks:
|
||||
socket: {}
|
||||
restart: unless-stopped
|
||||
|
||||
traefik:
|
||||
image: traefik:3.6
|
||||
container_name: root-traefik
|
||||
# UID and GID are automatically populated by the framework after running 'root tiers useradd'
|
||||
user: "${UID?error}:${GID?error}"
|
||||
group_add:
|
||||
- "${SHARED_GID?error}"
|
||||
depends_on:
|
||||
- socket-proxy
|
||||
volumes:
|
||||
- ./@tier1/shared/root/traefik/letsencrypt:/letsencrypt
|
||||
- ./@tier3/traefik/logs:/logs
|
||||
- ./@tier1/traefik/dynamic:/etc/traefik/dynamic:ro
|
||||
ports:
|
||||
- '0.0.0.0:80:80'
|
||||
- '0.0.0.0:443:443'
|
||||
networks:
|
||||
proxy: {}
|
||||
socket: {}
|
||||
command:
|
||||
- "--api.dashboard=true"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.network=root-proxy"
|
||||
- "--providers.docker.endpoint=tcp://root-socket-proxy:2375"
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
name: root-proxy
|
||||
internal: true
|
||||
driver: bridge
|
||||
socket:
|
||||
name: root-socket
|
||||
internal: true
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## 4. Deployment
|
||||
|
||||
Now that your structure is ready:
|
||||
|
||||
1. Commit and push this repository to your Git server (e.g., GitHub).
|
||||
2. SSH into your VPS.
|
||||
3. Follow the [Installation](/root/guides/installation) guide, using your new repository URL instead of the example ones.
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Guide: Installation on a new host](/root/guides/installation)
|
||||
- [Concept: Infrastructure Architecture](/root/concepts/architecture)
|
||||
@@ -1,60 +1,199 @@
|
||||
---
|
||||
title: Installation
|
||||
description: Initial setup of the Root framework on a new host.
|
||||
weight: 25
|
||||
title: Initial Host Setup
|
||||
description: Setting up a fresh Debian host from scratch.
|
||||
weight: 1
|
||||
---
|
||||
|
||||
This guide covers the initial setup of the Root framework on a new host.
|
||||
Hardened setup for a fresh Debian host from zero to deployment.
|
||||
|
||||
## Prerequisites {#prerequisites}
|
||||
|
||||
- A Debian-based Linux distribution (Debian or Ubuntu).
|
||||
- Git installed.
|
||||
- Sudo privileges.
|
||||
|
||||
## Initializing the repository {#init}
|
||||
## Setup Procedure
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Step 1: Clone the configuration repository
|
||||
### Essential Packages
|
||||
|
||||
Clone the repository containing your [Node](/root/glossary#node) configurations.
|
||||
Install `sudo` and `docker-ce` first. This is necessary because the subsequent user setup relies on the `docker` group and `sudo` configuration.
|
||||
|
||||
**Install Sudo**
|
||||
|
||||
```bash
|
||||
git clone <your-configs-repo-url> ~/repo
|
||||
cd ~/repo
|
||||
# As root:
|
||||
apt update && apt install sudo -y
|
||||
```
|
||||
|
||||
### Step 2: Run the initialization script
|
||||
**Install Docker**
|
||||
|
||||
The `init.sh` script sets up the [Commons](/root/glossary#commons) submodule, configures Git hooks, and adds the `root` wrapper to your `PATH`.
|
||||
Follow the [Official Docker Installation Guide for Debian](https://docs.docker.com/engine/install/debian/) to install the latest Docker Engine.
|
||||
|
||||
### System User & Privileges
|
||||
|
||||
The `adam` user handles all administrative tasks. SSH-key authentication and passwordless `sudo` via the `wheel` group minimize friction while maintaining security.
|
||||
|
||||
**Create the Admin User**
|
||||
|
||||
```bash
|
||||
./init.sh
|
||||
# As root:
|
||||
# Create the user with a bash shell
|
||||
useradd -m -s /bin/bash adam
|
||||
|
||||
# Create the wheel group (common for cross-distro consistency)
|
||||
groupadd wheel
|
||||
|
||||
# Create a modular sudoers file
|
||||
# This allows members of 'wheel' to run sudo without a password
|
||||
echo "%wheel ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/99-custom-sudoers
|
||||
|
||||
# Validate syntax
|
||||
visudo -c -f /etc/sudoers.d/99-custom-sudoers
|
||||
|
||||
# Add adam to the necessary groups
|
||||
usermod -aG wheel,docker adam
|
||||
```
|
||||
|
||||
### Step 3: Refresh your shell
|
||||
### Swap Setup
|
||||
|
||||
Source your `.bashrc` to activate the `root` command.
|
||||
Configure a swap file to ensure system stability during memory-intensive operations.
|
||||
|
||||
```bash
|
||||
source ~/.bashrc
|
||||
# As root:
|
||||
# Create a 2GB swap file (adjust size as needed)
|
||||
fallocate -l 2G /swap
|
||||
chmod 600 /swap
|
||||
mkswap /swap
|
||||
swapon /swap
|
||||
|
||||
# Make it permanent
|
||||
echo '/swap none swap sw 0 0' >> /etc/fstab
|
||||
```
|
||||
|
||||
### SSH Access & Hardening
|
||||
|
||||
Passwords are disabled. Access is strictly via SSH keys.
|
||||
|
||||
**Authorize Operator Key**
|
||||
|
||||
Import your local public key to the `adam` user.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Setup directories
|
||||
mkdir -p /home/adam/.ssh
|
||||
chmod 700 /home/adam/.ssh
|
||||
|
||||
# Add your public key (Replace [PASTE_PUB_KEY_HERE])
|
||||
echo "[PASTE_PUB_KEY_HERE]" > /home/adam/.ssh/authorized_keys
|
||||
chmod 600 /home/adam/.ssh/authorized_keys
|
||||
chown -R adam:adam /home/adam/.ssh
|
||||
```
|
||||
|
||||
**Operator Side Access**
|
||||
|
||||
Configure your local machine for easy access to the host.
|
||||
|
||||
```bash
|
||||
# ~/.ssh/config on operator side
|
||||
Host daedalus.example.com
|
||||
Port 2222
|
||||
User adam
|
||||
IdentityFile ~/.ssh/adam_example_com_ed25519
|
||||
```
|
||||
|
||||
**Harden SSH Daemon**
|
||||
|
||||
Modify the SSH configuration to change the default port and disable password entry.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Create a dedicated override config
|
||||
cat <<EOF > /etc/ssh/sshd_config.d/99-custom-ssh.conf
|
||||
Port 2222
|
||||
PasswordAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
AllowUsers adam
|
||||
EOF
|
||||
|
||||
# Validate syntax before restarting to avoid lockout
|
||||
sshd -t && systemctl restart ssh
|
||||
```
|
||||
|
||||
### GitHub Access (Deploy Key)
|
||||
|
||||
The host requires its own identity to pull updates from the GitHub repository.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Generate a host-specific SSH key (no passphrase for automation)
|
||||
sudo -u adam ssh-keygen -t ed25519 -f /home/adam/.ssh/github_ed25519 -N ""
|
||||
|
||||
# Configure SSH to use this key for GitHub
|
||||
cat <<EOF | sudo -u adam tee /home/adam/.ssh/config
|
||||
Host github.com
|
||||
AddKeysToAgent yes
|
||||
IdentityFile ~/.ssh/github_ed25519
|
||||
EOF
|
||||
|
||||
# Display the public key to be added to GitHub (Settings > Deploy Keys)
|
||||
cat /home/adam/.ssh/github_ed25519.pub
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Add the output above to the Deploy Keys settings of your infrastructure repository (e.g., `https://github.com/your-username/your-repo/settings/keys`) with **read access**.
|
||||
|
||||
### Repository Deployment
|
||||
|
||||
Clone your infrastructure repository and initialize the node.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Setup the service directory
|
||||
export REPO_DIR="/srv/your-infrastructure-repo"
|
||||
mkdir -p $REPO_DIR
|
||||
chown adam:adam $REPO_DIR
|
||||
|
||||
# Clone as the adam user
|
||||
sudo -u adam git clone git@github.com:your-username/your-repo.git $REPO_DIR
|
||||
|
||||
# Initialize node (Set your node name, e.g., daedalus)
|
||||
export NODE="daedalus"
|
||||
cd $REPO_DIR
|
||||
sudo -u adam ./init.sh
|
||||
```
|
||||
|
||||
**Node-Specific Configuration**
|
||||
|
||||
Run the staged initialization scripts using the `root` dispatcher:
|
||||
|
||||
```bash
|
||||
# Run the sequence for your specific node (as the 'adam' user)
|
||||
# Ensure you have sourced ~/.bashrc or re-logged in if 'root' is not found
|
||||
root configure base $NODE
|
||||
root configure ufw $NODE
|
||||
root configure crowdsec $NODE
|
||||
root configure cron $NODE
|
||||
```
|
||||
|
||||
### Storage & Hardening
|
||||
|
||||
Define the data tiers and secure the environment by creating non-root users for containerized services.
|
||||
|
||||
```bash
|
||||
# Create (or mount) storage directories
|
||||
sudo mkdir -p /srv/my-infrastructure-root-$NODE-{tier1,tier2,tier3}
|
||||
|
||||
# Setup tiers and non-root users
|
||||
root tiers link $NODE \
|
||||
/srv/my-infrastructure-root-$NODE-tier1 \
|
||||
/srv/my-infrastructure-root-$NODE-tier2 \
|
||||
/srv/my-infrastructure-root-$NODE-tier3
|
||||
|
||||
root tiers useradd $NODE
|
||||
root tiers chown $NODE
|
||||
```
|
||||
|
||||
{{% /steps %}}
|
||||
|
||||
## Provisioning a node {#provision}
|
||||
|
||||
Once the framework is installed, you can provision a specific [Node](/root/glossary#node).
|
||||
|
||||
```bash
|
||||
root configure/base <node_name>
|
||||
root configure/ufw <node_name>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Infrastructure architecture](/root/concepts/architecture)
|
||||
- [Reference: ROOT_ API reference](/root/reference/root-api)
|
||||
- [Doc: Docker - Install on Debian](https://docs.docker.com/engine/install/debian/)
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: 'Recipes'
|
||||
description: 'Collection of step-by-step procedures for infrastructure maintenance and deployment.'
|
||||
weight: 50
|
||||
---
|
||||
|
||||
Step-by-step instructions for reproducible tasks and infrastructure maintenance.
|
||||
|
||||
## Available Recipes
|
||||
|
||||
{{% cards %}}
|
||||
{{< card link="initial-setup" title="Initial Host Setup" icon="server" subtitle="Hardened setup for a fresh Debian host from zero to deployment." >}}
|
||||
{{% /cards %}}
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [GitHub: root.ermnvldmr.com](https://github.com/deytenit/root.ermnvldmr.com)
|
||||
@@ -1,202 +0,0 @@
|
||||
---
|
||||
title: 'Initial Host Setup'
|
||||
description: 'Setting up a fresh Debian host from scratch.'
|
||||
weight: 1
|
||||
---
|
||||
|
||||
Hardened setup for a fresh Debian host from zero to deployment.
|
||||
|
||||
## Setup Procedure
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Essential Packages
|
||||
|
||||
Install `sudo` and `docker-ce` first. This is necessary because the subsequent user setup relies on the `docker` group and `sudo` configuration.
|
||||
|
||||
**Install Sudo**
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
apt update && apt install sudo -y
|
||||
```
|
||||
|
||||
**Install Docker**
|
||||
|
||||
Follow the [Official Docker Installation Guide for Debian](https://docs.docker.com/engine/install/debian/) to install the latest Docker Engine.
|
||||
|
||||
### System User & Privileges
|
||||
|
||||
The `adam` user handles all administrative tasks. SSH-key authentication and passwordless `sudo` via the `wheel` group minimize friction while maintaining security.
|
||||
|
||||
**Create the Admin User**
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Create the user with a bash shell
|
||||
useradd -m -s /bin/bash adam
|
||||
|
||||
# Create the wheel group (common for cross-distro consistency)
|
||||
groupadd wheel
|
||||
|
||||
# Create a modular sudoers file
|
||||
# This allows members of 'wheel' to run sudo without a password
|
||||
echo "%wheel ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/99-root-ermnvldmr
|
||||
|
||||
# Validate syntax
|
||||
visudo -c -f /etc/sudoers.d/99-root-ermnvldmr
|
||||
|
||||
# Add adam to the necessary groups
|
||||
usermod -aG wheel,docker adam
|
||||
```
|
||||
|
||||
### Swap Setup
|
||||
|
||||
Configure a swap file to ensure system stability during memory-intensive operations.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Create a 2GB swap file (adjust size as needed)
|
||||
fallocate -l 2G /swap
|
||||
chmod 600 /swap
|
||||
mkswap /swap
|
||||
swapon /swap
|
||||
|
||||
# Make it permanent
|
||||
echo '/swap none swap sw 0 0' >> /etc/fstab
|
||||
```
|
||||
|
||||
### SSH Access & Hardening
|
||||
|
||||
Passwords are disabled. Access is strictly via SSH keys.
|
||||
|
||||
**Authorize Operator Key**
|
||||
|
||||
Import your local public key to the `adam` user.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Setup directories
|
||||
mkdir -p /home/adam/.ssh
|
||||
chmod 700 /home/adam/.ssh
|
||||
|
||||
# Add your public key (Replace [PASTE_PUB_KEY_HERE])
|
||||
echo "[PASTE_PUB_KEY_HERE]" > /home/adam/.ssh/authorized_keys
|
||||
chmod 600 /home/adam/.ssh/authorized_keys
|
||||
chown -R adam:adam /home/adam/.ssh
|
||||
```
|
||||
|
||||
**Operator Side Access**
|
||||
|
||||
Configure your local machine for easy access to the host.
|
||||
|
||||
```bash
|
||||
# ~/.ssh/config on operator side
|
||||
Host daedalus.root.ermnvldmr.com
|
||||
Port 2222
|
||||
User adam
|
||||
IdentityFile ~/.ssh/adam_root_ermnvldmr_com_ed25519
|
||||
```
|
||||
|
||||
**Harden SSH Daemon**
|
||||
|
||||
Modify the SSH configuration to change the default port and disable password entry.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Create a dedicated override config
|
||||
cat <<EOF > /etc/ssh/sshd_config.d/99-root-ermnvldmr.conf
|
||||
Port 2222
|
||||
PasswordAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
AllowUsers adam
|
||||
EOF
|
||||
|
||||
# Validate syntax before restarting to avoid lockout
|
||||
sshd -t && systemctl restart ssh
|
||||
```
|
||||
|
||||
### GitHub Access (Deploy Key)
|
||||
|
||||
The host requires its own identity to pull updates from the GitHub repository.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Generate a host-specific SSH key (no passphrase for automation)
|
||||
sudo -u adam ssh-keygen -t ed25519 -f /home/adam/.ssh/github_ed25519 -N ""
|
||||
|
||||
# Configure SSH to use this key for GitHub
|
||||
cat <<EOF | sudo -u adam tee /home/adam/.ssh/config
|
||||
Host github.com
|
||||
AddKeysToAgent yes
|
||||
IdentityFile ~/.ssh/github_ed25519
|
||||
EOF
|
||||
|
||||
# Display the public key to be added to GitHub (Settings > Deploy Keys)
|
||||
cat /home/adam/.ssh/github_ed25519.pub
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Add the output above to the [GitHub: Repository Deploy Keys](https://github.com/deytenit/root.ermnvldmr.com/settings/keys) with **read access**.
|
||||
|
||||
### Repository Deployment
|
||||
|
||||
Clone the infrastructure repository and initialize the node.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Setup the service directory
|
||||
export REPO_DIR="/srv/root.ermnvldmr.com"
|
||||
mkdir -p $REPO_DIR
|
||||
chown adam:adam $REPO_DIR
|
||||
|
||||
# Clone as the adam user
|
||||
sudo -u adam git clone git@github.com:deytenit/root.ermnvldmr.com.git $REPO_DIR
|
||||
|
||||
# Initialize node (Set your node name, e.g., daedalus)
|
||||
export NODE="daedalus"
|
||||
cd $REPO_DIR
|
||||
sudo -u adam ./init.sh
|
||||
```
|
||||
|
||||
**Node-Specific Configuration**
|
||||
|
||||
Run the staged initialization scripts in order:
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Run the sequence for your specific node
|
||||
cd $REPO_DIR
|
||||
./$NODE/.host/.scripts/00-base
|
||||
./$NODE/.host/.scripts/10-ufw
|
||||
./$NODE/.host/.scripts/20-crowd
|
||||
./$NODE/.host/.scripts/30-cron
|
||||
```
|
||||
|
||||
### Storage & Hardening
|
||||
|
||||
Define the data tiers and secure the environment by creating non-root users for containerized services.
|
||||
|
||||
```bash
|
||||
# As root:
|
||||
# Create (or mount) storage directories
|
||||
mkdir -p /srv/com-ermnvldmr-root-$NODE-{tier1,tier2,tier3}
|
||||
|
||||
# Setup tiers and non-root users
|
||||
cd $REPO_DIR
|
||||
sudo -u adam .scripts/ops/setup-tiers $NODE \
|
||||
/srv/com-ermnvldmr-root-$NODE-tier1 \
|
||||
/srv/com-ermnvldmr-root-$NODE-tier2 \
|
||||
/srv/com-ermnvldmr-root-$NODE-tier3
|
||||
|
||||
sudo -u adam .scripts/ops/setup-noroot-users $NODE
|
||||
```
|
||||
|
||||
{{% /steps %}}
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Doc: Docker - Install on Debian](https://docs.docker.com/engine/install/debian/)
|
||||
- [GitHub: root.ermnvldmr.com](https://github.com/deytenit/root.ermnvldmr.com)
|
||||
@@ -4,8 +4,15 @@ description: API and technical references for developers.
|
||||
weight: 30
|
||||
---
|
||||
|
||||
Technical reference materials and APIs for the Root framework.
|
||||
Technical reference materials and APIs for the ermnvldmr.com root deployment commons framework.
|
||||
|
||||
{{% cards %}}
|
||||
{{< card link="compose" title="Compose actions reference" icon="play" subtitle="High-level entrypoint for orchestrating docker-compose." >}}
|
||||
{{< card link="configure" title="Configure actions reference" icon="arrow-down" subtitle="Host provisioning and system-level configuration." >}}
|
||||
{{< card link="initialization" title="Initialization actions reference" icon="play" subtitle="Actions for initial node setup." >}}
|
||||
{{< card link="root-api" title="ROOT_ API reference" icon="code" subtitle="Standardized environment variables and logging helpers." >}}
|
||||
{{< card link="source" title="Source services reference" icon="book-open" subtitle="Shared services built from source." >}}
|
||||
{{< card link="sync" title="Sync actions reference" icon="check" subtitle="Actions for keeping nodes up-to-date." >}}
|
||||
{{< card link="tiers" title="Tiers actions reference" icon="archive" subtitle="Storage tiers management." >}}
|
||||
{{< card link="utils" title="Utility actions reference" icon="check" subtitle="Helper scripts and utilities." >}}
|
||||
{{% /cards %}}
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Compose Actions
|
||||
description: Standardized high-level entrypoint for orchestrating docker-compose across a node.
|
||||
weight: 54
|
||||
---
|
||||
|
||||
The `compose` action provides a standardized, high-level entrypoint for orchestrating Docker Compose files across all projects within a specific node.
|
||||
|
||||
## Core Compose Action {#actions}
|
||||
|
||||
| Action | Description |
|
||||
| :--- | :--- |
|
||||
| `compose <node> <action>` | Executes a given Docker Compose command (e.g., `up`, `down`, `restart`) across the node's infrastructure. |
|
||||
|
||||
## Orchestration Order {#order}
|
||||
|
||||
To maintain correct dependencies (especially when shutting down or starting up infrastructure-level proxies and networks), the `compose` action intelligently orders the execution:
|
||||
|
||||
### Starting Up (`up`, `restart`)
|
||||
When starting or restarting services, the action follows a **Forward Order**:
|
||||
1. **Node Infrastructure**: First, it processes the node-level `docker-compose.yml` (located at the root of the node directory).
|
||||
2. **Root Infrastructure**: Next, it processes the `root/docker-compose.yml` project, if it exists (usually contains Traefik, Socket Proxy, etc.).
|
||||
3. **Projects**: Finally, it processes all other project directories in alphabetical order.
|
||||
|
||||
### Shutting Down (`down`)
|
||||
When stopping services, the action uses a **Reverse Order** to ensure projects disconnect gracefully before the network or proxy goes down:
|
||||
1. **Projects**: All standard projects are stopped in reverse alphabetical order.
|
||||
2. **Root Infrastructure**: The `root/docker-compose.yml` project is stopped.
|
||||
3. **Node Infrastructure**: Finally, the node-level `docker-compose.yml` is brought down.
|
||||
|
||||
## Options {#options}
|
||||
|
||||
You can pass standard Docker Compose arguments to the end of the command.
|
||||
Additionally, the action supports a dry-run mode:
|
||||
|
||||
- `--dry-run`: Prints the commands that would be executed without actually running them.
|
||||
|
||||
**Example usage:**
|
||||
```bash
|
||||
root compose daedalus up -d --remove-orphans
|
||||
root compose daedalus restart --dry-run
|
||||
root compose daedalus down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Infrastructure Architecture](/root/concepts/architecture)
|
||||
- [Reference: ROOT_ API Reference](/root/reference/root-api)
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: Configuration Actions
|
||||
description: Host provisioning, template engine, and system-level configuration.
|
||||
weight: 53
|
||||
---
|
||||
|
||||
Configuration actions are used to provision the host and maintain system-level services. They rely heavily on the built-in template engine to generate declarative configuration files.
|
||||
|
||||
## The Template Engine {#template-engine}
|
||||
|
||||
The Root framework uses `envsubst` (from `gettext-base`) to render templates. This allows you to use standard Bash environment variables directly within your configuration files.
|
||||
|
||||
### Template Conventions
|
||||
|
||||
- **File Extension**: Templates typically use the `.template` extension (e.g., `crontab.template`).
|
||||
- **Variable Syntax**: Use `${VARIABLE_NAME}` or `$VARIABLE_NAME` to inject values.
|
||||
- **Auto-Discovery**: Many actions automatically look for templates in specific directories within the [Configs](/root/glossary#configs) repository.
|
||||
|
||||
### Rendering Helpers
|
||||
|
||||
The `root_template.sh` library provides several helpers:
|
||||
|
||||
- `root_template_render <input> <output>`: Renders a single file.
|
||||
- `root_template_render_directory <src> <dest>`: Recursively renders an entire directory structure.
|
||||
- `root_template_crontab <template>`: Renders and installs a crontab for the current user.
|
||||
|
||||
## Core Configuration Actions {#actions}
|
||||
|
||||
| Action | Description |
|
||||
| :--- | :--- |
|
||||
| `configure/base` | Installs essential packages (`sudo`, `ufw`, `docker`) and sets up basic system users. |
|
||||
| `configure/cron` | Renders and installs node-specific crontabs. |
|
||||
| `configure/crowdsec` | Sets up the CrowdSec agent and bouncers. |
|
||||
| `configure/routing` | Configures system-level routing and bridge networks. |
|
||||
| `configure/systemd` | Installs and enables systemd service units. |
|
||||
| `configure/ufw` | Renders and applies firewall rules using UFW and `ufw-docker`. |
|
||||
|
||||
## Example: Nginx Template {#example}
|
||||
|
||||
```nginx filename="nginx.conf.template"
|
||||
# This template uses ROOT_NODE environment variable
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Injected from environment
|
||||
server_name ${ROOT_NODE}.example.com;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Infrastructure Architecture](/root/concepts/architecture)
|
||||
- [Reference: ROOT_ API Reference](/root/reference/root-api)
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: System Initialization
|
||||
description: Repository setup, Git hooks, and PATH configuration.
|
||||
weight: 51
|
||||
---
|
||||
|
||||
The Root framework requires a one-time initialization on each host to establish path linkages and repository-level configurations.
|
||||
|
||||
## The `init.sh` Script {#init-script}
|
||||
|
||||
The `init.sh` script located at the repository root is the primary bootstrap mechanism. It performs the following critical tasks:
|
||||
|
||||
1. **Submodule Initialization**: Ensures the [Commons](/root/glossary#commons) repository is present and up to date.
|
||||
2. **Git Hook Configuration**: Points `core.hooksPath` to `.operator/shared/githooks` to enable standardized pre-commit checks.
|
||||
3. **Safe Directory Registration**: Adds the repository to Git's `safe.directory` list, which is required for operations performed by different users (e.g., `root`, `adam`).
|
||||
4. **Vim Configuration**: Links a standardized `.vimrc` to both the current user and the `root` user for a consistent editing experience.
|
||||
5. **PATH Persistence**: Adds the `.operator/shared/scripts/run` directory to the user's `~/.bashrc`, making the `root` command available globally.
|
||||
|
||||
## Git Hooks {#githooks}
|
||||
|
||||
Root enforces standards through Git hooks stored in `.operator/shared/githooks/`.
|
||||
|
||||
- **Pre-commit**: Validates that all scripts follow the namespacing and structure conventions.
|
||||
- **Commit-msg**: (Optional) Enforces conventional commit messages if configured.
|
||||
|
||||
## PATH Configuration {#path}
|
||||
|
||||
The `root` command is a wrapper located in `.operator/shared/scripts/run/root`. By adding this directory to the `PATH`, the dispatcher can be invoked from any directory within the system, automatically resolving the repository root based on the current working directory or environment variables.
|
||||
|
||||
```bash
|
||||
# Example of manual PATH addition (performed automatically by init.sh)
|
||||
export PATH="$HOME/repo/.operator/shared/scripts/run:$PATH"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Guide: Initial Host Setup](/root/guides/installation)
|
||||
- [Reference: ROOT_ API Reference](/root/reference/root-api)
|
||||
@@ -4,11 +4,19 @@ description: Standardized environment variables for path resolution and node con
|
||||
weight: 50
|
||||
---
|
||||
|
||||
Every [Action](/root/glossary#action) script executed via the `root` dispatcher has access to a standardized set of environment variables. These variables are the single source of truth for path resolution and node context.
|
||||
Every [Action](/root/glossary#action) script executed via the `root` dispatcher has access to a standardized set of environment variables and Bash libraries. This provides a consistent "API" for interacting with the infrastructure.
|
||||
|
||||
## The `root` Dispatcher {#dispatcher}
|
||||
|
||||
The `root` command (located in `.operator/shared/scripts/run/root`) is the main entrypoint for all orchestration. Its primary responsibilities include:
|
||||
|
||||
1. **Context Resolution**: Locating the target [Node](/root/glossary#node) and its associated storage [Tiers](/root/glossary#tier).
|
||||
2. **Library Loading**: Sourcing the core namespaced libraries (e.g., `root_core`, `root_sys`).
|
||||
3. **Action Execution**: Discovering and running the requested action, prioritizing local overrides.
|
||||
|
||||
## Path resolution variables {#paths}
|
||||
|
||||
These variables define the physical location of the infrastructure components.
|
||||
These variables are established by the dispatcher and are available to all actions.
|
||||
|
||||
| Variable | Description |
|
||||
| :--- | :--- |
|
||||
@@ -20,40 +28,35 @@ These variables define the physical location of the infrastructure components.
|
||||
|
||||
## Node context variables {#node-context}
|
||||
|
||||
When an action targets a specific [Node](/root/glossary#node), the following variables are established by the `root_require_node` helper.
|
||||
When an action targets a specific node, the following variables are established by the `root_require_node` helper.
|
||||
|
||||
| Variable | Description |
|
||||
| :--- | :--- |
|
||||
| `ROOT_NODE` | The identifier of the target node (e.g., `icarus`). |
|
||||
| `ROOT_NODE` | The identifier of the target node (e.g., `daedalus`). |
|
||||
| `ROOT_NODE_DIR` | Absolute path to the node configuration directory. |
|
||||
| `ROOT_TIER1` | Absolute path to the [Tier 1](/root/glossary#tier) storage directory. |
|
||||
| `ROOT_TIER2` | Absolute path to the Tier 2 storage directory. |
|
||||
| `ROOT_TIER3` | Absolute path to the Tier 3 storage directory. |
|
||||
|
||||
## Logging helpers {#logging}
|
||||
## Core Logging Helpers {#logging}
|
||||
|
||||
Standardized logging uses the `[$ROOT_NODE] [$ROOT_ACTION_PATH]` prefix for consistency across the orchestration logs.
|
||||
Standardized logging ensure consistent output across all actions.
|
||||
|
||||
- `root_log_info`: Standard informational output.
|
||||
- `root_log_warn`: Warnings requiring attention but not stopping execution.
|
||||
- `root_log_warn`: Warnings requiring attention.
|
||||
- `root_log_error`: Critical errors sent to `stderr`.
|
||||
- `root_log_success`: Confirmation of successful task completion.
|
||||
|
||||
## Help system metadata {#help}
|
||||
## The Help System {#help}
|
||||
|
||||
The `root` [Dispatcher](/root/glossary#dispatcher) provides a built-in `--help` system. To keep action scripts "stupid", they do not implement their own help flags. Instead, the dispatcher parses a specific `action_metadata` block defined at the top of every action script.
|
||||
|
||||
When a user runs `root <action> --help`, the dispatcher extracts and displays this YAML-formatted block without executing the script.
|
||||
|
||||
### Example metadata
|
||||
The dispatcher provides a built-in help system by parsing an `action_metadata` block at the top of each script. This allows scripts to remain "stupid" and declarative without implementing their own CLI argument parsing.
|
||||
|
||||
```bash filename="example-action-metadata"
|
||||
action_metadata() {
|
||||
cat <<EOF
|
||||
description: "Brief summary of the task."
|
||||
description: "Brief summary of the action."
|
||||
args:
|
||||
- NODE: "The node name"
|
||||
- PARAM: "A custom parameter"
|
||||
- NODE: "The name of the target node."
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: The `source/` Directory
|
||||
description: Conceptual overview of the self-contained source directory structure.
|
||||
weight: 52
|
||||
---
|
||||
|
||||
The `source/` directory at the repository root contains the core components and projects that the Root framework orchestrates. It is designed for maximum isolation and self-containment.
|
||||
|
||||
## Core Philosophy {#philosophy}
|
||||
|
||||
The `source/` directory is not just a place to store code; it is a collection of independent [Projects](/root/glossary#project). Each project within this directory should follow these principles:
|
||||
|
||||
1. **Isolation**: Each project lives in its own subdirectory (e.g., `source/my-app/`).
|
||||
2. **Self-Documentation**: Each project directory **MUST** contain its own `README.md` file describing its purpose, dependencies, and configuration.
|
||||
3. **Internal Logic**: Projects handle their own build processes, Dockerfiles, and internal configurations. The Root framework's [Actions](/root/glossary#action) simply orchestrate these existing components.
|
||||
|
||||
## Directory Structure {#structure}
|
||||
|
||||
A typical project within the `source/` directory might look like this:
|
||||
|
||||
{{< filetree/container >}}
|
||||
{{< filetree/folder name="source" state="open" >}}
|
||||
{{< filetree/folder name="happ-subscription-generator" state="open" >}}
|
||||
{{< filetree/file name="Dockerfile" >}}
|
||||
{{< filetree/file name="generator.py" >}}
|
||||
{{< filetree/file name="README.md" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/container >}}
|
||||
|
||||
## Relationship with Actions {#actions}
|
||||
|
||||
Root actions (like `compose` or `sync`) interact with the `source/` directory by referencing paths within it. For example, the `compose` action might use a `docker-compose.yml` file that points to a `Dockerfile` located in `source/app/`.
|
||||
|
||||
This separation of concerns ensures that the orchestration logic (Actions) remains decoupled from the implementation details (Source).
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Infrastructure Architecture](/root/concepts/architecture)
|
||||
- [Reference: ROOT_ API Reference](/root/reference/root-api)
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Synchronization Actions
|
||||
description: Repository updates, package synchronization, and data backups.
|
||||
weight: 54
|
||||
---
|
||||
|
||||
Synchronization actions ensure that the host's state remains consistent with the defined configurations in the remote repositories.
|
||||
|
||||
## Core Synchronization Actions {#actions}
|
||||
|
||||
| Action | Description |
|
||||
| :--- | :--- |
|
||||
| `sync/packages` | Synchronizes node packages and their configurations across the system. |
|
||||
| `sync/repository` | Updates the main configuration repository to its latest state from GitHub. |
|
||||
| `sync/tiers` | Triggers the node-specific backup strategy for the configured [Tiers](/root/glossary#tier). |
|
||||
|
||||
## Repository Synchronization (`sync/repository`) {#repository}
|
||||
|
||||
The `sync/repository` action is responsible for keeping the host's configuration repository up-to-date with its remote source. It typically performs a `git pull` on the main configuration repository and may optionally trigger sub-module updates for the [Commons](/root/glossary#commons) repository.
|
||||
|
||||
This ensures that any changes to the node configurations, actions, or source files are correctly pulled down to the target host.
|
||||
|
||||
## Backup Synchronization (`sync/tiers`) {#tiers}
|
||||
|
||||
The `sync/tiers` action is the primary entry point for a node's backup strategy.
|
||||
|
||||
- **No Default Implementation**: The framework itself does not provide a default backup mechanism, allowing operators to design a custom strategy suitable for their needs.
|
||||
- **Custom Overrides**: As a "Smart Dispatcher" action, you can define your backup logic by placing a custom script in `.operator/local/scripts/actions/sync/tiers`.
|
||||
- **Example Implementation**: A common practice is to use a tool like [Restic](https://restic.net/) within this custom script to perform off-site backups of critical data (Tiers 1 and 2) to an S3-compatible storage backend.
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Tiered Storage Model](/root/concepts/tiered-storage)
|
||||
- [Reference: ROOT_ API Reference](/root/reference/root-api)
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Tier Management Actions
|
||||
description: Storage classification, symbolic linking, and privilege isolation.
|
||||
weight: 55
|
||||
---
|
||||
|
||||
Tier management actions are responsible for enforcing the framework's [Tiered Storage Model](/root/concepts/tiered-storage) and ensuring correct filesystem ownership and isolation.
|
||||
|
||||
## Core Tier Actions {#actions}
|
||||
|
||||
| Action | Description |
|
||||
| :--- | :--- |
|
||||
| `tiers/chown` | Sets correct filesystem ownership for project-specific [Non-Root Users](#useradd). |
|
||||
| `tiers/link` | Manages symbolic links between the project directories and their corresponding [Tiers](/root/glossary#tier). |
|
||||
| `tiers/useradd` | Provisions a unique system user for each project to achieve [Privilege Isolation](/root/concepts/security-model). |
|
||||
|
||||
## User Management (`tiers/useradd`) {#useradd}
|
||||
|
||||
The `tiers/useradd` action creates a dedicated, low-privileged system user for each project within a node. This user is then used to run the project's containers, ensuring that a compromise of one project does not grant the attacker access to the entire host.
|
||||
|
||||
- **Naming Convention**: Users are typically named after the project.
|
||||
- **Group Membership**: Users can optionally be added to the `docker` group or interact with Docker via other securely configured methods, depending on the operator's preference.
|
||||
|
||||
## Storage Linking (`tiers/link`) {#link}
|
||||
|
||||
The `tiers/link` action creates the symbolic link structure required for the tiered storage model. It ensures that directories like `config`, `data`, and `logs` within a project folder point to their physical locations in `@tier1`, `@tier2`, and `@tier3` respectively.
|
||||
|
||||
```bash
|
||||
# Example link structure created by tiers/link
|
||||
/srv/root/icarus/synapse/config -> /srv/storage/@tier1/synapse
|
||||
/srv/root/icarus/synapse/data -> /srv/storage/@tier2/synapse
|
||||
/srv/root/icarus/synapse/logs -> /srv/storage/@tier3/synapse
|
||||
```
|
||||
|
||||
## Ownership Management (`tiers/chown`) {#chown}
|
||||
|
||||
Once tiers and links are established, the `tiers/chown` action ensures that the physical directories in each tier are owned by the correct project user. This is critical for preventing permission-denied errors and ensuring that projects can only access their own data.
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Tiered Storage Model](/root/concepts/tiered-storage)
|
||||
- [Concept: Security & Privilege Isolation](/root/concepts/security-model)
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: Utility Actions
|
||||
description: Common helper scripts for maintenance, validation, and certificate management.
|
||||
weight: 56
|
||||
---
|
||||
|
||||
Utility actions provide common helper functions for node maintenance, validation, and project-specific tasks.
|
||||
|
||||
## Core Utility Actions {#actions}
|
||||
|
||||
| Action | Description |
|
||||
| :--- | :--- |
|
||||
| `utils/extract-traefik-certs` | Extracts SSL/TLS certificates and private keys from Traefik's `acme.json` storage. |
|
||||
| `utils/generate-happ-subscriptions` | Automatically generates HApp subscription files based on current project metadata. |
|
||||
| `utils/lint-docker-compose` | Performs a static analysis of all `docker-compose.yml` files to ensure they meet the framework's standards. |
|
||||
|
||||
## Certificate Management (`utils/extract-traefik-certs`) {#certificates}
|
||||
|
||||
Traefik stores its ACME-issued certificates (like those from Let's Encrypt) in a single `acme.json` file. The `utils/extract-traefik-certs` action parses this file and extracts individual `fullchain.pem` and `privkey.pem` files.
|
||||
|
||||
This is particularly useful when other services (e.g., mail servers, non-Dockerized applications) require the same SSL certificates.
|
||||
|
||||
## Quality Assurance (`utils/lint-docker-compose`) {#linting}
|
||||
|
||||
To maintain consistency and security, the `utils/lint-docker-compose` action validates all compose files across the infrastructure. It checks for:
|
||||
|
||||
- **Naming Standards**: Ensures project names and container names follow the `{node}-{project}` convention.
|
||||
- **Security Context**: Flags containers running as `root` without a justified override.
|
||||
- **Resource Constraints**: Identifies services lacking CPU or memory limits.
|
||||
- **Label Standards**: Validates required labels for routing (e.g., [Traefik](https://traefik.io/)) and [CrowdSec](/root/concepts/security-model#crowdsec).
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
|
||||
- [Concept: Infrastructure Principles](/root/concepts/principles)
|
||||
- [Concept: Security & Privilege Isolation](/root/concepts/security-model)
|
||||
Reference in new issue
Block a user