provisioning/docs/book/guides/customize-infrastructure.html
Jesús Pérez 6a59d34bb1
chore: update provisioning configuration and documentation
Update configuration files, templates, and internal documentation
for the provisioning repository system.

Configuration Updates:
- KMS configuration modernization
- Plugin system settings
- Service port mappings
- Test cluster topologies
- Installation configuration examples
- VM configuration defaults
- Cedar authorization policies

Documentation Updates:
- Library module documentation
- Extension API guides
- AI system documentation
- Service management guides
- Test environment setup
- Plugin usage guides
- Validator configuration documentation

All changes are backward compatible.
2025-12-11 21:50:42 +00:00

537 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML>
<html lang="en" class="ayu sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Customize Infrastructure - Provisioning Platform Documentation</title>
<!-- Custom HTML head -->
<meta name="description" content="Complete documentation for the Provisioning Platform - Infrastructure automation with Nushell, KCL, and Rust">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "../";
const default_light_theme = "ayu";
const default_dark_theme = "navy";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('ayu')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Provisioning Platform Documentation</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/provisioning/provisioning-platform" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/provisioning/provisioning-platform/edit/main/provisioning/docs/src/guides/customize-infrastructure.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="customize-infrastructure-guide"><a class="header" href="#customize-infrastructure-guide">Customize Infrastructure Guide</a></h1>
<p>Complete guide to customizing infrastructure with layers, templates, and extensions.</p>
<h2 id="overview"><a class="header" href="#overview">Overview</a></h2>
<p>The provisioning platform uses a <strong>layered configuration system</strong> that allows progressive customization without modifying core code.</p>
<h2 id="configuration-layers"><a class="header" href="#configuration-layers">Configuration Layers</a></h2>
<p>Configuration is loaded in this priority order (low → high):</p>
<pre><code>1. Core Defaults (provisioning/config/config.defaults.toml)
2. Workspace Config (workspace/{name}/config/provisioning.yaml)
3. Infrastructure (workspace/{name}/infra/{infra}/config.toml)
4. Environment (PROVISIONING_* env variables)
5. Runtime Overrides (Command line flags)
</code></pre>
<h2 id="layer-system"><a class="header" href="#layer-system">Layer System</a></h2>
<h3 id="layer-1-core-defaults"><a class="header" href="#layer-1-core-defaults">Layer 1: Core Defaults</a></h3>
<p><strong>Location</strong>: <code>provisioning/config/config.defaults.toml</code>
<strong>Purpose</strong>: System-wide defaults
<strong>Modify</strong>: ❌ Never modify directly</p>
<pre><code class="language-toml">[paths]
base = "provisioning"
workspace = "workspace"
[settings]
log_level = "info"
parallel_limit = 5
</code></pre>
<h3 id="layer-2-workspace-configuration"><a class="header" href="#layer-2-workspace-configuration">Layer 2: Workspace Configuration</a></h3>
<p><strong>Location</strong>: <code>workspace/{name}/config/provisioning.yaml</code>
<strong>Purpose</strong>: Workspace-specific settings
<strong>Modify</strong>: ✅ Recommended</p>
<pre><code class="language-yaml">workspace:
name: "my-project"
description: "Production deployment"
providers:
- upcloud
- aws
defaults:
provider: "upcloud"
region: "de-fra1"
</code></pre>
<h3 id="layer-3-infrastructure-configuration"><a class="header" href="#layer-3-infrastructure-configuration">Layer 3: Infrastructure Configuration</a></h3>
<p><strong>Location</strong>: <code>workspace/{name}/infra/{infra}/config.toml</code>
<strong>Purpose</strong>: Per-infrastructure customization
<strong>Modify</strong>: ✅ Recommended</p>
<pre><code class="language-toml">[infrastructure]
name = "production"
type = "kubernetes"
[servers]
count = 5
plan = "4xCPU-8GB"
[taskservs]
enabled = ["kubernetes", "cilium", "postgres"]
</code></pre>
<h3 id="layer-4-environment-variables"><a class="header" href="#layer-4-environment-variables">Layer 4: Environment Variables</a></h3>
<p><strong>Purpose</strong>: Runtime configuration
<strong>Modify</strong>: ✅ For dev/CI environments</p>
<pre><code class="language-bash">export PROVISIONING_LOG_LEVEL=debug
export PROVISIONING_PROVIDER=aws
export PROVISIONING_WORKSPACE=dev
</code></pre>
<h3 id="layer-5-runtime-flags"><a class="header" href="#layer-5-runtime-flags">Layer 5: Runtime Flags</a></h3>
<p><strong>Purpose</strong>: One-time overrides
<strong>Modify</strong>: ✅ Per command</p>
<pre><code class="language-bash">provisioning server create --plan 8xCPU-16GB --zone us-west-2
</code></pre>
<h2 id="using-templates"><a class="header" href="#using-templates">Using Templates</a></h2>
<p>Templates allow reusing infrastructure patterns:</p>
<h3 id="1-create-template"><a class="header" href="#1-create-template">1. Create Template</a></h3>
<pre><code class="language-bash"># Save current infrastructure as template
provisioning template create kubernetes-ha \
--from my-cluster \
--description "3-node HA Kubernetes cluster"
</code></pre>
<h3 id="2-list-templates"><a class="header" href="#2-list-templates">2. List Templates</a></h3>
<pre><code class="language-bash">provisioning template list
# Output:
# NAME TYPE NODES DESCRIPTION
# kubernetes-ha cluster 3 3-node HA Kubernetes
# small-web server 1 Single web server
# postgres-ha database 2 HA PostgreSQL setup
</code></pre>
<h3 id="3-apply-template"><a class="header" href="#3-apply-template">3. Apply Template</a></h3>
<pre><code class="language-bash"># Create new infrastructure from template
provisioning template apply kubernetes-ha \
--name new-cluster \
--customize
</code></pre>
<h3 id="4-customize-template"><a class="header" href="#4-customize-template">4. Customize Template</a></h3>
<pre><code class="language-bash"># Edit template configuration
provisioning template edit kubernetes-ha
# Validate template
provisioning template validate kubernetes-ha
</code></pre>
<h2 id="creating-custom-extensions"><a class="header" href="#creating-custom-extensions">Creating Custom Extensions</a></h2>
<h3 id="custom-task-service"><a class="header" href="#custom-task-service">Custom Task Service</a></h3>
<p>Create a custom taskserv for your application:</p>
<pre><code class="language-bash"># Create taskserv from template
provisioning generate taskserv my-app \
--category application \
--version 1.0.0
</code></pre>
<p><strong>Directory structure</strong>:</p>
<pre><code>workspace/extensions/taskservs/application/my-app/
├── nu/
│ └── my_app.nu # Installation logic
├── kcl/
│ ├── my_app.k # Configuration schema
│ └── version.k # Version info
├── templates/
│ ├── config.yaml.j2 # Config template
│ └── systemd.service.j2 # Service template
└── README.md # Documentation
</code></pre>
<h3 id="custom-provider"><a class="header" href="#custom-provider">Custom Provider</a></h3>
<p>Create custom provider for internal cloud:</p>
<pre><code class="language-bash"># Generate provider scaffold
provisioning generate provider internal-cloud \
--type cloud \
--api rest
</code></pre>
<h3 id="custom-cluster"><a class="header" href="#custom-cluster">Custom Cluster</a></h3>
<p>Define complete deployment configuration:</p>
<pre><code class="language-bash"># Create cluster configuration
provisioning generate cluster my-stack \
--servers 5 \
--taskservs "kubernetes,postgres,redis" \
--customize
</code></pre>
<h2 id="configuration-inheritance"><a class="header" href="#configuration-inheritance">Configuration Inheritance</a></h2>
<p>Child configurations inherit and override parent settings:</p>
<pre><code class="language-yaml"># Base: workspace/config/provisioning.yaml
defaults:
server_plan: "2xCPU-4GB"
region: "de-fra1"
# Override: workspace/infra/prod/config.toml
[servers]
plan = "8xCPU-16GB" # Overrides default
# region inherited: de-fra1
</code></pre>
<h2 id="variable-interpolation"><a class="header" href="#variable-interpolation">Variable Interpolation</a></h2>
<p>Use variables for dynamic configuration:</p>
<pre><code class="language-yaml">workspace:
name: "{{env.PROJECT_NAME}}"
servers:
hostname_prefix: "{{workspace.name}}-server"
zone: "{{defaults.region}}"
paths:
base: "{{env.HOME}}/provisioning"
workspace: "{{paths.base}}/workspace"
</code></pre>
<p><strong>Supported variables</strong>:</p>
<ul>
<li><code>{{env.*}}</code> - Environment variables</li>
<li><code>{{workspace.*}}</code> - Workspace config</li>
<li><code>{{defaults.*}}</code> - Default values</li>
<li><code>{{paths.*}}</code> - Path configuration</li>
<li><code>{{now.date}}</code> - Current date</li>
<li><code>{{git.branch}}</code> - Git branch name</li>
</ul>
<h2 id="customization-examples"><a class="header" href="#customization-examples">Customization Examples</a></h2>
<h3 id="example-1-multi-environment-setup"><a class="header" href="#example-1-multi-environment-setup">Example 1: Multi-Environment Setup</a></h3>
<pre><code class="language-yaml"># workspace/envs/dev/config.yaml
environment: development
server_count: 1
server_plan: small
# workspace/envs/prod/config.yaml
environment: production
server_count: 5
server_plan: large
high_availability: true
</code></pre>
<pre><code class="language-bash"># Deploy to dev
provisioning cluster create app --env dev
# Deploy to prod
provisioning cluster create app --env prod
</code></pre>
<h3 id="example-2-custom-monitoring-stack"><a class="header" href="#example-2-custom-monitoring-stack">Example 2: Custom Monitoring Stack</a></h3>
<pre><code class="language-bash"># Create custom monitoring configuration
cat &gt; workspace/infra/monitoring/config.toml &lt;&lt;EOF
[taskservs]
enabled = [
"prometheus",
"grafana",
"alertmanager",
"loki"
]
[prometheus]
retention = "30d"
storage = "100GB"
[grafana]
admin_user = "admin"
plugins = ["cloudflare", "postgres"]
EOF
# Apply monitoring stack
provisioning cluster create monitoring --config monitoring/config.toml
</code></pre>
<h3 id="example-3-development-vs-production"><a class="header" href="#example-3-development-vs-production">Example 3: Development vs Production</a></h3>
<pre><code class="language-bash"># Development: lightweight, fast
provisioning cluster create app \
--profile dev \
--servers 1 \
--plan small
# Production: robust, HA
provisioning cluster create app \
--profile prod \
--servers 5 \
--plan large \
--ha \
--backup-enabled
</code></pre>
<h2 id="advanced-customization"><a class="header" href="#advanced-customization">Advanced Customization</a></h2>
<h3 id="custom-workflows"><a class="header" href="#custom-workflows">Custom Workflows</a></h3>
<p>Create custom deployment workflows:</p>
<pre><code class="language-kcl"># workspace/workflows/my-deploy.k
import provisioning.workflows as wf
my_deployment: wf.BatchWorkflow = {
name = "custom-deployment"
operations = [
# Your custom steps
]
}
</code></pre>
<h3 id="custom-validation-rules"><a class="header" href="#custom-validation-rules">Custom Validation Rules</a></h3>
<p>Add validation for your infrastructure:</p>
<pre><code class="language-nushell"># workspace/extensions/validation/my-rules.nu
export def validate-my-infra [config: record] {
# Custom validation logic
if $config.servers &lt; 3 {
error make {msg: "Production requires 3+ servers"}
}
}
</code></pre>
<h3 id="custom-hooks"><a class="header" href="#custom-hooks">Custom Hooks</a></h3>
<p>Execute custom actions at deployment stages:</p>
<pre><code class="language-yaml"># workspace/config/hooks.yaml
hooks:
pre_create_servers:
- script: "scripts/validate-quota.sh"
post_create_servers:
- script: "scripts/configure-monitoring.sh"
pre_install_taskserv:
- script: "scripts/check-dependencies.sh"
</code></pre>
<h2 id="best-practices"><a class="header" href="#best-practices">Best Practices</a></h2>
<h3 id="do-"><a class="header" href="#do-">DO ✅</a></h3>
<ul>
<li>Use workspace config for project-specific settings</li>
<li>Create templates for reusable patterns</li>
<li>Use variables for dynamic configuration</li>
<li>Document custom extensions</li>
<li>Test customizations in dev environment</li>
</ul>
<h3 id="dont-"><a class="header" href="#dont-">DONT ❌</a></h3>
<ul>
<li>Modify core defaults directly</li>
<li>Hardcode environment-specific values</li>
<li>Skip validation steps</li>
<li>Create circular dependencies</li>
<li>Bypass security policies</li>
</ul>
<h2 id="testing-customizations"><a class="header" href="#testing-customizations">Testing Customizations</a></h2>
<pre><code class="language-bash"># Validate configuration
provisioning validate config --strict
# Test in isolated environment
provisioning test env cluster my-custom-setup --check
# Dry run deployment
provisioning cluster create test --check --verbose
</code></pre>
<h2 id="related-documentation"><a class="header" href="#related-documentation">Related Documentation</a></h2>
<ul>
<li><strong><a href="../development/configuration.html">Configuration System</a></strong> - Configuration architecture</li>
<li><strong><a href="../development/extensions.html">Extension Development</a></strong> - Create extensions</li>
<li><strong><a href="../user/template-system.html">Template System</a></strong> - Template reference</li>
<li><strong><a href="../development/kcl/">KCL Patterns</a></strong> - KCL configuration language</li>
</ul>
<hr />
<p><strong>Need Help?</strong> Run <code>provisioning help customize</code> or see <a href="../user/WORKSPACE_SWITCHING_GUIDE.html">User Guide</a>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../guides/update-infrastructure.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../guides/quickstart-cheatsheet.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../guides/update-infrastructure.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../guides/quickstart-cheatsheet.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>