|
1 | 1 | // SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | +// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) |
2 | 3 | = K9 SVC User Guide |
3 | 4 | :toc: left |
4 | 5 | :toclevels: 3 |
@@ -551,6 +552,170 @@ See `pedigree.ncl` for the full schema with contracts. |
551 | 552 | │ └── bob.pub |
552 | 553 | ---- |
553 | 554 |
|
| 555 | +== Container Deployment with k9-svc |
| 556 | + |
| 557 | +This section covers how k9-svc wraps container deployments using the Leash |
| 558 | +security model, selur-compose, and Nickel typed configuration. |
| 559 | + |
| 560 | +=== When to Use k9-svc for Containers |
| 561 | + |
| 562 | +k9-svc is designed for **operational deployment components** — things that |
| 563 | +orchestrate, validate, and deploy container stacks. It is NOT a replacement |
| 564 | +for `Cargo.toml`, `mix.exs`, or other build-time manifests. |
| 565 | + |
| 566 | +Use k9-svc when you need: |
| 567 | + |
| 568 | +* **Typed deployment configs** — Nickel contracts catch invalid port numbers, |
| 569 | + missing environment variables, and impossible resource limits at eval time, |
| 570 | + before any container starts. |
| 571 | +* **Security-level enforcement** — The Leash system prevents accidental |
| 572 | + execution of destructive deployment recipes. |
| 573 | +* **Signed deployment artifacts** — Ed25519 signatures ensure only authorized |
| 574 | + operators can run deployment scripts. |
| 575 | +* **Self-validating components** — The dogfooding principle means each |
| 576 | + deployment component can validate its own configuration. |
| 577 | + |
| 578 | +=== Security Level Selection Guide |
| 579 | + |
| 580 | +Choosing the correct security level is the most important decision when |
| 581 | +creating a k9 container deployment component. |
| 582 | + |
| 583 | +[cols="1,2,3"] |
| 584 | +|=== |
| 585 | +| Level | Use When | Container Example |
| 586 | + |
| 587 | +| `'Kennel` |
| 588 | +| The component is pure data with no execution. |
| 589 | +| A static list of container image tags and their SHA256 digests. No commands, no evaluation. Just data. |
| 590 | + |
| 591 | +| `'Yard` |
| 592 | +| The component needs Nickel evaluation but performs no I/O. |
| 593 | +| A typed configuration that validates port ranges, memory limits, and environment variable shapes. It produces validated JSON output but does not start any containers. |
| 594 | + |
| 595 | +| `'Hunt` |
| 596 | +| The component executes commands, accesses the network, or writes files. |
| 597 | +| A deployment component that generates selur-compose files, pulls images, starts services, runs health checks, and performs rollback on failure. |
| 598 | +|=== |
| 599 | + |
| 600 | +[IMPORTANT] |
| 601 | +==== |
| 602 | +**Rule of thumb:** If your component runs `selur-compose`, `podman`, or any |
| 603 | +shell command, it MUST be `'Hunt` level. If it only evaluates Nickel |
| 604 | +expressions and produces output, use `'Yard`. If it is pure data (a list of |
| 605 | +images, a set of environment variables), use `'Kennel`. |
| 606 | +
|
| 607 | +**Never use `'Hunt` for read-only operations.** If your component only reads |
| 608 | +and displays data, `'Kennel` or `'Yard` is correct. Hunt requires |
| 609 | +cryptographic signatures and should be reserved for components with real |
| 610 | +side effects. |
| 611 | +==== |
| 612 | + |
| 613 | +=== Example: Container Deployment as a Hunt Component |
| 614 | + |
| 615 | +The `container-deploy.k9.ncl` example demonstrates a realistic multi-service |
| 616 | +deployment component. It deploys an app + database + cache stack across |
| 617 | +dev/staging/production environments. |
| 618 | + |
| 619 | +[source,nickel] |
| 620 | +---- |
| 621 | +# Security: Hunt level because this component: |
| 622 | +# - Runs selur-compose commands (subprocess) |
| 623 | +# - Pulls container images (network) |
| 624 | +# - Writes deployment state files (filesystem) |
| 625 | +security = { |
| 626 | + trust_level = 'Hunt, |
| 627 | + allow_network = true, |
| 628 | + allow_filesystem_write = true, |
| 629 | + allow_subprocess = true, |
| 630 | + signature = "REAL-ED25519-SIGNATURE-HERE", |
| 631 | +}, |
| 632 | +---- |
| 633 | + |
| 634 | +Key features of this component: |
| 635 | + |
| 636 | +* **Environment-specific overrides** — Dev (1 replica, debug logging), |
| 637 | + staging (2 replicas, info logging), production (3 replicas, warn logging). |
| 638 | + All validated by Nickel contracts. |
| 639 | +* **Rolling deployment** — Replaces one replica at a time, waits for health |
| 640 | + checks, and automatically rolls back on failure. |
| 641 | +* **Image signature verification** — Before deploying to staging or |
| 642 | + production, verifies that container images are signed with cerro-torre. |
| 643 | +* **Self-validation** — The component typechecks itself before deployment. |
| 644 | + |
| 645 | +See: `examples/container-deploy.k9.ncl` for the complete implementation. |
| 646 | + |
| 647 | +=== Example: Config Validator as a Yard Component |
| 648 | + |
| 649 | +Not every container-related component needs Hunt level. A configuration |
| 650 | +validator that checks deployment configs without executing anything is a |
| 651 | +perfect Yard-level component. |
| 652 | + |
| 653 | +[source,nickel] |
| 654 | +---- |
| 655 | +# Security: Yard level because this component: |
| 656 | +# - Evaluates Nickel contracts (typed validation) |
| 657 | +# - Produces validated JSON output |
| 658 | +# - Does NOT execute commands, access network, or write files |
| 659 | +security = { |
| 660 | + trust_level = 'Yard, |
| 661 | + allow_network = false, |
| 662 | + allow_filesystem_write = false, |
| 663 | + allow_subprocess = false, |
| 664 | +}, |
| 665 | +---- |
| 666 | + |
| 667 | +This component can: |
| 668 | + |
| 669 | +* Validate that container port mappings do not conflict |
| 670 | +* Check that resource limits are within acceptable ranges |
| 671 | +* Verify that environment variables match expected patterns |
| 672 | +* Export validated config as JSON for consumption by other tools |
| 673 | + |
| 674 | +See: `examples/config.k9.ncl` for a Yard-level configuration example. |
| 675 | + |
| 676 | +=== How k9-svc Wraps selur-compose |
| 677 | + |
| 678 | +The typical workflow for a k9-svc container deployment: |
| 679 | + |
| 680 | +[source] |
| 681 | +---- |
| 682 | +1. Author writes .k9.ncl with Nickel-typed service definitions |
| 683 | +2. nickel typecheck validates the configuration (Yard-level eval) |
| 684 | +3. nickel export generates selur-compose.toml from the typed config |
| 685 | +4. The Hunt-level deploy script: |
| 686 | + a. Verifies component signature (Ed25519) |
| 687 | + b. Verifies container image signatures (cerro-torre) |
| 688 | + c. Runs selur-compose up with the generated config |
| 689 | + d. Monitors health checks |
| 690 | + e. Rolls back on failure |
| 691 | +---- |
| 692 | + |
| 693 | +The key insight is that steps 1-3 are **Yard-level** operations — they only |
| 694 | +evaluate Nickel expressions and produce data. Step 4 is a **Hunt-level** |
| 695 | +operation that requires the cryptographic handshake. This separation means |
| 696 | +you can validate configs without any security ceremony, but execution always |
| 697 | +requires authorization. |
| 698 | + |
| 699 | +=== Anti-Pattern Warnings |
| 700 | + |
| 701 | +Before wrapping something in k9-svc, read link:examples/NOT-a-good-fit.adoc[NOT-a-good-fit.adoc]. |
| 702 | + |
| 703 | +Common mistakes: |
| 704 | + |
| 705 | +* **Do NOT** wrap plain config files in k9 pedigree. A `config.toml` is |
| 706 | + already Kennel-level by nature. Adding pedigree overhead provides zero |
| 707 | + security benefit. |
| 708 | +* **Do NOT** use k9-svc to manage library dependencies. Libraries are |
| 709 | + build-time artifacts, not deployment components. Use `Cargo.toml` or |
| 710 | + `mix.exs`. |
| 711 | +* **Do NOT** use Hunt level for read-only operations. If your component |
| 712 | + only reads data, use Kennel or Yard. |
| 713 | +* **Do NOT** wrap every directory in a2ml manifests. One at the repo root |
| 714 | + is sufficient for most projects. |
| 715 | + |
| 716 | +See: link:examples/NOT-a-good-fit.adoc[Comparison, Deprecation Analysis, and Anti-Patterns] |
| 717 | +for the full analysis. |
| 718 | + |
554 | 719 | == License |
555 | 720 |
|
556 | | -K9 SVC is licensed under AGPL-3.0-or-later. See LICENSE for details. |
| 721 | +K9 SVC is licensed under PMPL-1.0-or-later. See LICENSE for details. |
0 commit comments