-
Notifications
You must be signed in to change notification settings - Fork 0
feat(galaxy): package public roles as the decdn.node collection #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| MIT License | ||
|
|
||
| Copyright 2026 deCDN Contributors | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,3 +16,4 @@ rules: | |
| max-spaces-inside: 1 # allow "{{ var }}" Jinja spacing | ||
| ignore: | | ||
| collections/ | ||
| build/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Changelog — `decdn.node` | ||
|
|
||
| All notable changes to the `decdn.node` Ansible collection are documented here. | ||
| The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the | ||
| collection adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [Unreleased] | ||
|
|
||
| ## [0.1.0] — unreleased | ||
|
|
||
| Initial packaging of the public deCDN node roles as a distributable collection. | ||
| Not yet published to Galaxy (pre-1.0; the published shape may still change). | ||
|
|
||
| ### Added | ||
|
|
||
| - `decdn.node.baseline` — Debian/Ubuntu host baseline: nftables default-deny | ||
| inbound, fail2ban, unattended-upgrades, chrony, an admin sudo account, and DevSec | ||
| OS + SSH hardening applied last. | ||
| - `decdn.node.decdn_node` — the `decdn-node` daemon, installed from a pinned GitHub | ||
| Release tarball under a hardened systemd unit; public QUIC udp/4433, loopback | ||
| metrics + admin RPC. | ||
|
|
||
| <!-- No release tags exist yet; these resolve today. Switch to compare/tag links | ||
| (compare/v0.1.0...HEAD and releases/tag/v0.1.0) once v0.1.0 is cut. --> | ||
| [Unreleased]: https://github.com/decdn/devops/commits/main | ||
| [0.1.0]: https://github.com/decdn/devops/releases |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| # Ansible Collection — `decdn.node` | ||
|
|
||
| Deploy and harden a **public [deCDN](https://decdn.org) node**. This collection is | ||
| the public, reusable slice of the [`decdn/devops`](https://github.com/decdn/devops) | ||
| repository — two roles and nothing else: | ||
|
|
||
| | Role | Purpose | | ||
| |------|---------| | ||
| | `decdn.node.baseline` | Debian host baseline — nftables default-deny inbound, fail2ban, unattended-upgrades, chrony, an admin sudo user, then DevSec OS + SSH hardening (applied last). | | ||
| | `decdn.node.decdn_node` | The `decdn-node` daemon — installed from a pinned GitHub Release tarball under a hardened systemd unit; public QUIC udp/4433, loopback metrics + admin RPC. | | ||
|
|
||
| > The repo's internal team tooling (the anvil devnet — `anvil`, `caddy`, `contracts` | ||
| > roles) is **not** part of this collection. | ||
|
|
||
| ## Requirements | ||
|
|
||
| - **ansible-core ≥ 2.15** on the control machine. | ||
| - Target: **Debian (bookworm)** or **Ubuntu (jammy/noble)** over SSH with a sudo user. | ||
| - Collection dependencies (installed automatically with this collection): | ||
| `devsec.hardening (>=10.0.0)`, `ansible.posix (>=1.5.0)`. | ||
|
|
||
| ## Install | ||
|
|
||
| ```bash | ||
| ansible-galaxy collection install decdn.node | ||
| ``` | ||
|
|
||
| Or pin it in a `requirements.yml`: | ||
|
|
||
| ```yaml | ||
| collections: | ||
| - name: decdn.node | ||
| version: ">=0.1.0" | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| A minimal node playbook — baseline first (so the admin key lands before SSH | ||
| hardening), then the node: | ||
|
|
||
| ```yaml | ||
| - name: Provision a hardened deCDN node | ||
| hosts: decdn_nodes | ||
| become: true | ||
| roles: | ||
| - role: decdn.node.baseline | ||
| vars: | ||
| ssh_admin_user: deploy | ||
| ssh_admin_pubkey: "ssh-ed25519 AAAA... you@host" # REQUIRED — lockout guard | ||
| baseline_extra_inbound: | ||
| - { proto: udp, port: 4433, comment: "deCDN QUIC" } | ||
| - role: decdn.node.decdn_node | ||
| # decdn_node_version + rpc_url + the three contract addresses + region are | ||
| # REQUIRED — set them per host (host_vars). Contract addresses/chain-id are | ||
| # protocol facts: source them from the deployment / an ADR, never guess. | ||
| ``` | ||
|
|
||
| The node serves paid traffic only **after** on-chain stake + registration — an | ||
| operator step, not automated by this collection. See each role's README for the | ||
| full variable list, the eth-keystore prerequisite, and day-2 ops: | ||
|
|
||
| - [`roles/baseline`](https://github.com/decdn/devops/tree/main/ansible/roles/baseline) | ||
| - [`roles/decdn_node`](https://github.com/decdn/devops/tree/main/ansible/roles/decdn_node) | ||
|
|
||
| ## Security model | ||
|
|
||
| Backends bind `127.0.0.1`; the node opens exactly one public hole (QUIC udp/4433). | ||
| No secrets ship in the collection or are committed — the eth keystore is | ||
| operator-provisioned on the host, and `rpc_url` (which may embed an API key) renders | ||
| to a `0600` file. SSH hardening is applied last, after the admin key is in place, so | ||
| you cannot lock yourself out. | ||
|
|
||
| ## License | ||
|
|
||
| MIT © deCDN Contributors. Protocol facts trace to the deCDN ADRs, never invented here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| #!/usr/bin/env bash | ||
| # Stage and build the public `decdn.node` Galaxy collection. | ||
| # | ||
| # Only the roles/baseline + roles/decdn_node sources ship. The internal anvil | ||
| # devnet (anvil/caddy/contracts roles) and all deploy machinery (inventory, | ||
| # molecule, Makefile, ansible.cfg) are excluded BY CONSTRUCTION — they are simply | ||
| # never copied into the staging tree. This keeps the artifact clean and leaves the | ||
| # internal project untouched (no galaxy.yml at the project root, so ansible-lint / | ||
| # ansible / molecule still see a plain project). | ||
| # | ||
| # Output: ansible/build/decdn-node-<version>.tar.gz | ||
| set -euo pipefail | ||
|
|
||
| here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # ansible/galaxy | ||
| ansible_dir="$(cd "$here/.." && pwd)" # ansible/ | ||
| repo_root="$(cd "$ansible_dir/.." && pwd)" # repo root | ||
|
|
||
| build_dir="$ansible_dir/build" | ||
| stage="$build_dir/ansible_collections/decdn/node" | ||
| roles=(baseline decdn_node) | ||
|
|
||
| echo "staging decdn.node -> $stage" | ||
| rm -rf "$stage" | ||
| # Drop stale artifacts from earlier builds so the output dir holds exactly the | ||
| # tarball we are about to produce (galaxy-check globs build/decdn-node-*.tar.gz). | ||
| rm -f "$build_dir"/decdn-node-*.tar.gz | ||
| mkdir -p "$stage/roles" "$stage/meta" | ||
|
|
||
| # Canonical role sources (shared with the internal project). | ||
| for role in "${roles[@]}"; do | ||
| cp -R "$ansible_dir/roles/$role" "$stage/roles/$role" | ||
| done | ||
|
|
||
| # Collection overlay + license (the artifact must be self-contained). | ||
| cp "$here/galaxy.yml" "$stage/galaxy.yml" | ||
| cp "$here/README.md" "$stage/README.md" | ||
| cp "$here/CHANGELOG.md" "$stage/CHANGELOG.md" | ||
| cp "$here/meta/runtime.yml" "$stage/meta/runtime.yml" | ||
| cp "$repo_root/LICENSE" "$stage/LICENSE" | ||
|
|
||
| # ansible-galaxy validates galaxy.yml (required keys, semver, tag charset) here. | ||
| ansible-galaxy collection build "$stage" --output-path "$build_dir" --force | ||
|
|
||
| shopt -s nullglob | ||
| for tarball in "$build_dir"/decdn-node-*.tar.gz; do | ||
| echo "built: $tarball" | ||
| done | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| --- | ||
| # Manifest for the `decdn.node` Ansible collection — the public, distributable | ||
| # slice of this DevOps repo: deploy + harden a deCDN node. | ||
| # | ||
| # This file is an OVERLAY, not the project root manifest. It is assembled into a | ||
| # clean collection tree (with only the baseline + decdn_node roles) by | ||
| # galaxy/build.sh; it is deliberately NOT placed at ansible/ root, so the | ||
| # internal deploy project stays a plain Ansible project (bare role names, | ||
| # roles_path, production-profile ansible-lint) rather than being reinterpreted as | ||
| # a collection. See galaxy/README.md. | ||
| namespace: decdn | ||
| name: node | ||
| version: 0.1.0 # pre-1.0: published shape not yet stable | ||
| readme: README.md | ||
| authors: | ||
| - deCDN Contributors | ||
| description: Deploy and harden a public deCDN node — DevSec host baseline + decdn_node. | ||
| license: | ||
| - MIT | ||
| # Galaxy tags must match ^[a-z0-9]+$ (no hyphens/underscores). | ||
| tags: | ||
| - decdn | ||
| - cdn | ||
| - node | ||
| - systemd | ||
| - hardening | ||
| - debian | ||
| - devsec | ||
| - web3 | ||
| # Collection-level dependencies — only what the SHIPPED roles use: | ||
| # baseline -> devsec.hardening (os_hardening + ssh_hardening), ansible.posix | ||
| # (authorized_key) | ||
| # decdn_node -> ansible.builtin only | ||
| # community.general is NOT used by either shipped role (it backs the internal | ||
| # anvil/caddy roles, which do not ship), so it is intentionally absent here. | ||
| dependencies: | ||
| devsec.hardening: ">=10.0.0" | ||
| ansible.posix: ">=1.5.0" | ||
| repository: https://github.com/decdn/devops | ||
| documentation: https://github.com/decdn/devops/tree/main/ansible | ||
| homepage: https://decdn.org | ||
| issues: https://github.com/decdn/devops/issues | ||
| build_ignore: | ||
| - "*.example" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.