This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Projects

Project tree

This tree contains first-party products and reusable project code. All tracked content follows the repository’s public-source policy.

Each project owns its specifications and maintained changes in <project>/openspec/. Use the pinned OpenSpec workflow with that project selected. infra/src/ owns repository evolution.

  • Bazel targets MAY use public visibility when their owner intends external reuse.
  • Project artifacts MAY be published through an explicit release workflow.
  • Project targets MAY be used by production build targets.

Each project has a landing page in the main website at https://alwaldend.com/projects/<name>/. Sites are published with the main site rather than as separate Pages repositories, and repository reference documentation, including each project README, lives under /docs/.

Project Description Landing page
ActivityWatch ingester Android Android accessibility collector that sends browser tabs to ActivityWatch alwaldend.com/projects/activitywatch_ingester_android/
Agents Repository-wide reusable agent skills alwaldend.com/projects/agents/
Al Repository command runner and Bazel configuration rules alwaldend.com/projects/al/
Alwaldend.com Main website and project documentation alwaldend.com
Android launcher Text-only Android launcher built with Kotlin and Jetpack Compose alwaldend.com/projects/android_launcher/
Ansible collection Ansible collection alwaldend.main with Bazel source packaging alwaldend.com/projects/ansible_collection/
Autoscroll Mouse-driven autoscroll CLI with reloadable configuration alwaldend.com/projects/autoscroll/
Bazel agent Bazel runner for repository agents alwaldend.com/projects/bazel_agent/
Ci platform Abandoned CI platform with a Go backend and Vue frontend alwaldend.com/projects/ci_platform/
Dotfiles Personal configuration files with installation and comparison commands alwaldend.com/projects/dotfiles/
Infinitime InfiniTime firmware fork with a text watchface and Pomodoro app alwaldend.com/projects/infinitime/
Kustomization Kubernetes resources for Flux, Traefik, and cert-manager alwaldend.com/projects/kustomization/
Leetcode downloader LeetCode submission export and documentation tools alwaldend.com/projects/leetcode_downloader/
MCP Cordis Workspace-local runtime packages behind a stable MCP server alwaldend.com/projects/mcp_cordis/
Nexus security plugin Security plugin for Sonatype Nexus 3 alwaldend.com/projects/nexus_security_plugin/
Renders Repository-owned render assets and their acceptance evidence alwaldend.com/projects/renders/
Sri Command-line Subresource Integrity calculator using OpenSSL alwaldend.com/projects/sri/
Tf modules Reusable Terraform modules for Vault, virtual machines, and storage alwaldend.com/projects/tf_modules/
Useless QT GUI Desktop GUI application built with C++ and Qt alwaldend.com/projects/useless_qt_gui/

1 - ActivityWatch ingester Android

Accessibility-based Android collector that sends browser URLs to ActivityWatch

ActivityWatch ingester Android

An Android collector that reads supported browser address-bar text through Android accessibility and sends it to an ActivityWatch server. The app holds full accessibility permission only to obtain the URL; it never uses that permission for anything else.

  • Enabling accessibility for this app lets it read the focused address bar.
  • The accessibility service matches browser view IDs (url_bar and common Chrome-derived variants), extracts the current URL, and sends an ActivityWatch heartbeat for the web.tab.current bucket to a configurable server.
  • web.tab.current heartbeats use pulsetime=1.0; consecutive URLs are sent with the time spent on the previous tab as the duration field.
  • Data goes directly from this app to the ActivityWatch HTTP API; it is not uploaded to any other service.

Open the app to configure:

  • ActivityWatch server URL — the base URL of the ActivityWatch server. The default is http://127.0.0.1:5600 for the ActivityWatch Android app on the same device. Changes are saved immediately.
  • API key (optional) — bearer token sent as Authorization: Bearer ... when the ActivityWatch server has API authentication enabled.

The INTERNET permission is required to reach the ActivityWatch HTTP API. The default loopback URL is sent over cleartext HTTP only to 127.0.0.1 and localhost, so no host data leaves the device.

Chrome and Chromium-based browsers that expose the url_bar view ID (including ordinary Chrome and many Chrome-based forks). Firefox, Samsung Internet, Opera, and Edge do not use that view ID yet.

  1. Build the APK: bazel build //projects/activitywatch_ingester_android/main/java:ingester_binary
  2. Verify the APK starts on an already running device or emulator: bazel run //projects/activitywatch_ingester_android/test:ingester_smoke_test This manual smoke test installs the Bazel-built APK, launches the activity, waits for the process, and confirms it stays alive. It is not a CI test.
  3. Install the APK on the device from bazel-bin/projects/activitywatch_ingester_android/main/java/ingester_binary.apk.
  4. Start the app and set the ActivityWatch server URL.
  5. Enable accessibility for the app in Android settings; Android shows the full-access warning, which is the mechanism this collector is built on.
  6. Open a browser. The current URL is re-sent to ActivityWatch whenever the address bar changes.
  • Minimum Android SDK 25 (Android 7.0).
  • Tested against the ActivityWatch v0.13 HTTP API (POST /api/0/buckets and POST /api/0/buckets/web.tab.current/heartbeat).

The landing page is published at activitywatch-ingester-android.alwaldend.com, built from this README by the shared Hugo landing template. The DNS record lives in dnsconfig.json; the project Terraform stage describes its configuration and ownership activation workflow.

1.1 -

Releases

Release packaging for the ActivityWatch ingester Android app.

1.1.1 - head

Release head

2 - Agents

Repository-wide reusable agent skills

Repository agent skills

This project owns the reusable cross-repository agent skills. Maintained improvement work lives in this project’s OpenSpec workspace. It does not centralize component facts or runtime state: each fact remains canonical at its natural owner.

Document Purpose
OpenSpec changes Maintained work, acceptance, and preserved goal history
Root agent guide Current repository-wide operating policy

Dated audits remain in migrated history.

  • openspec/ owns agent-system requirements, changes, and evidence; the migration map locates historical records.
  • Other components own their specifications and changes under their own openspec/ directory. infra/src/openspec/ describes repository evolution.
  • skills/ owns reusable cross-product, repository-wide agent procedures and their development-time evaluations. A product-specific procedure belongs with its product; a procedure that no narrower project genuinely owns lives here rather than in a contrived local home.
  • Product-specific skills remain with their project at projects/<project>/skills/<name>. Do not split one skill across owners.

Every canonical skill is packaged as a skill_library in its owning directory.

The repository discovery directory .agents/skills/ contains one relative symlink per skill. Each link points directly to its canonical project-owned directory. .agents/BUILD.bazel declares the complete discovery set and generates those links with //.agents:write_skills; its generated exact-state test verifies them. Bazel ignores the discovery directory and builds only canonical targets, preventing duplicate packages while allowing skills from more than one owning project. Each skill grants //.agents:skill_discovery read access so the owning declaration can reach it.

Skill evaluation data is not part of the runtime skill_library unless a skill explicitly declares otherwise. Every new or updated skill includes an offline Promptfoo configuration-validation target. That target checks the eval harness, not answer correctness. Live behavioral evaluations are manual, networked tests and must not be included in ordinary wildcard test runs; they may be omitted when representative coverage requires tool calls or external state that cannot be provided safely and reproducibly, with the gap documented beside the eval configuration.

3 - Al

Repository command runner and Bazel configuration rules

AL is a command runner that prepares credentials and environment variables through plugins, runs your command, and cleans up afterward. Its Bazel rules package commands with their configuration and required plugins.

al tool runs tools declared in AL configuration from a source-keyed executable cache. With no --config, it uses the repository-root al.lua; explicit --config paths replace that default. Cache misses build the tool’s configured Bazel label and publish the selected executable under $XDG_CACHE_HOME/al/tools. AL_TOOL_CACHE or tool --cache-root PATH selects an alternate cache root.

Repository agent skills are written by bazel run //.agents:write_skills and checked by //.agents:write_skills_test.

3.1 - Command and plugin lifecycle

Startup, shutdown, and secret cleanup guarantees

al run starts selected plugins, passes their environment to a command, and keeps plugin resources available until that command exits. On cancellation it asks the command to terminate and waits up to ten seconds before killing it. Plugin shutdown then drains requests, releases resources in reverse registration order, and waits for plugin exit. Startup failure cancels sibling starts and rolls back partially initialized resources. Cleanup errors fail the invocation.

The injector creates secret files with owner-only permissions and removes them after consumers stop. Vault stores revoke AppRole tokens they issue; failed AppRole login attempts destroy their unused single-use SecretID. The role’s bootstrap policy must permit secret-id-accessor/destroy, as declared by projects/tf_modules/vault_approle. The user’s existing token-helper credential is never erased or revoked. Secret inputs and remote response bodies are omitted from diagnostic messages. OIDC authorization uses the configured Vault HTTPS origin and TLS transport, rejecting alternate origins and redirects. Explicit config dumps still contain the requested configuration; file outputs use owner-only permissions and truncate previous contents.

no_auth prevents AL’s Vault client from loading credentials. For environment injection it clears inherited VAULT_TOKEN; it does not sandbox the command or prevent a command from independently reading the user’s token helper. Plugins and invoked commands remain trusted programs with the user’s filesystem access.

Cleanup is observable best effort, not secure erasure. Memory copies are not zeroized. Forced termination, host failure, unresponsive cleanup code, or an unavailable service can prevent deletion or revocation. Subprocess signaling targets direct children, not arbitrary descendants. Credential expiry remains a fallback; service-specific logout requirements are documented with each plugin.

3.2 - Releases

Releases

3.2.1 - head

Release head

3.3 - Rules

Bazel rules

3.3.1 - Bzl

Bazel rules

3.3.1.1 - al_config

al_config

load("@com_alwaldend_src//projects/al/rules/al:al_config.bzl", "al_config")

al_config(name, deps, srcs, data)

Dump al config

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Al configs (targets) List of labels optional []
srcs Al configs (source files) List of labels optional []
data Data List of labels optional []

load("@com_alwaldend_src//projects/al/rules/al:al_config.bzl", "AlConfigInfo")

AlConfigInfo(config)

Config info

FIELDS

Name Description
config Merged config file

3.3.1.2 - al_toolchain

al_toolchain

load("@com_alwaldend_src//projects/al/rules/al:al_toolchain.bzl", "al_toolchain")

al_toolchain(name, al)

Al toolchain

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
al Al binary Label required

3.3.1.3 - al_toolchain_resolved

al_toolchain_resolved

load("@com_alwaldend_src//projects/al/rules/al:al_toolchain_resolved.bzl", "al_toolchain_resolved")

al_toolchain_resolved(name)

Resolved al toolchain (for genrules)

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required

4 - Alwaldend.com

Main website and project documentation

Alwaldend.com is the repository’s main website and documentation site. It uses Hugo with Docsy to publish project documentation on GitHub Pages.

Run from the repository root:

bazel_agent bazel build //projects/alwaldend.com:site
bazel_agent bazel test //projects/alwaldend.com:site_test
bazel_agent bazel run //projects/alwaldend.com:site_serve

The preview serves the local build at http://127.0.0.1:1313.

The site publishes dated articles from content/blog. Each post is its own Bazel package with an index.md and a BUILD.bazel declaring its docs_filegroup; the section package aggregates them. The section publishes HTML, an RSS feed, and a print edition, and appears in the main navigation. The section index and its posts carry a github_subdir cascade so the per-page GitHub links point at the content sources.

A post stays unpublished while its front matter declares draft: true. Local builds render drafts for review and the release build excludes them, so the draft state alone withholds a post from the deployed site.

Agent workflow: Add a blog post.

The site publishes each registered project’s visitor-facing landing page at /projects/<name>/, with the section index at /projects/. Each project owns its landing content in projects/<name>/site/content/; this site packages those directories into content/projects/<name>/ from the registry in projects/projects.bzl. Landing content carries no layouts, styles, or build rules, and participates in the shared statuses, languages, and tags taxonomies.

Repository reference documentation, including each project README, stays under /docs/projects/<name>/. Because every landing is part of this one build, a content error in any landing fails the whole site build and the blog deployment.

Markdown links and images resolve relative to their source directory. README.md and _index.md links resolve to generated pages; packaged resources use their published URLs, including when embedded in print pages. Link files that exist only in the repository with explicit GitHub URLs. Unknown internal destinations remain unchanged rather than being silently redirected to GitHub.

Print pages scope IDs and their fragment and control references to each source document, keeping anchors distinct when documents are combined.

  • DNS setup: infra/dns
  • This project’s DNS declaration owns the shared pages address. Project landing pages are published by this site under /projects/<name>/, so no project owns a CNAME or a dedicated hostname. The project directory links to every landing page. The apex and www records stay managed centrally.
  • Deploy to the Github Pages repo (the pages branch of alwaldend/alwaldend.github.io, which GitHub Pages serves):
    tools/versioning/cmd/versioning/versioning.sh bazel -- \
      run --config=release //projects/alwaldend.com:deploy
    
    The deploy script clones the pages branch, replaces its contents with the built site, writes .nojekyll, and pushes only when the output changed.
bazel run //projects/alwaldend.com/tf # Apply tf
bazel run //projects/alwaldend.com/tf:update_pve_disk # Update the disk
Taxonomy Meaning
Categories General category
Languages Programming language
Sites Sites
Statuses Project status
Tags Generic tags
{{< alwaldend/alert >}}
Alert body
{{< /alwaldend/alert >}}

Create a link using a bazel label

Usage:

{{% alwaldend/label_link "//tools/qt" %}}

Render common links

Usage:

{{% alwaldend/links %}}

Render a packaged SVG using its published URL. Set alt to describe the image; the page title is the fallback.

Usage:

{{< alwaldend/svg_file file="local_file.svg" alt="Project architecture" >}}

Include a local html file

Usage:

{{< alwaldend/include_html "file.html" >}}

Render books

Usage:

{{< alwaldend/docs_misc_books >}}

4.1 - Releases

Releases

4.1.1 - head

Release head

4.2 - Tf

Terraform

This service stage consumes the project DNS declaration through the shared global DNS module. The DNS workflow uses the project’s AppRole, HTTP state backend, and Cloudflare credentials. This public-only module does not require RouterOS. Ordinary service commands retain their tf=main authentication, including PVE login.

Operational commands require the project AppRole and Vault provider fields in the migration prerequisites. dns_enabled defaults to true after verified adoption. Keep it enabled to retain existing records; disabling it would propose deletion. The zone input remains optional.

The dns.plan, dns.show, and dns.apply targets select only the DNS workflow in this same root and backend. They use dns=1 to load DNS credentials without starting PVE login. Apply requires a reviewed saved plan file. Targeted DNS planning does not establish PVE or other service health.

Follow the DNS migration workflow for continued reconciliation and recovery. The adoption record contains the earlier blocked attempt and completed scoped DNS verification.

Offline formatting is available through //projects/alwaldend.com/tf:tf_tests.fmt_test.

5 - Android launcher

Text-only Android launcher built with Kotlin and Jetpack Compose

A text-only Android launcher built with Kotlin and Jetpack Compose. It lets you hide apps and runs without ads, tracking, or internet access.

  • Android app
  • Kotlin, Jetpack Compose
  • Only text
  • FOSS, no ads, no internet access, no tracking, minimal dependencies
  • Allows you to hide apps

5.1 - Releases

Releases

5.1.1 - head

Release head

6 - Ansible collection

Ansible collection alwaldend.main with Bazel source packaging

alwaldend.main is the repository’s Ansible collection. Bazel packages its Ansible source for reuse in repository automation.

  • Ansible collection
  • Bazel-managed Ansible source packaging.
namespace: alwaldend
name: main
version: 0.0.0
readme: README.md
authors:
-  <example@domain.com>
description: main alwaldend ansible collection
license:
  - AGPL-3.0-or-later
license_file: LICENSE.txt
tags: []
dependencies:
  ansible.posix: 1.5.4
  community.crypto: 2.17.0
  community.general: 11.3.0
  devsec.hardening: 9.0.1
  community.docker: 3.11.0
repository: https://git.alwaldend.com/src
documentation: https://collection-main.docs.alwaldend.com
homepage: https://collection-main.docs.alwaldend.com
issues: ""
build_ignore: []

6.1 - Playbooks

Ansible playbooks

6.2 - Roles

Ansible roles

6.2.1 - Adguard

Role to deploy adguard

6.2.1.1 - Defaults

Defaults for adguard
adguard_dir: /etc/adguard
adguard_work_dir: "{{ adguard_dir }}"
adguard_gpg_key_url: https://keys.openpgp.org/vks/v1/by-fingerprint/28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6
adguard_gpg_key_src: files/key.asc
adguard_gpg_key_path: "{{ adguard_dir }}/release-key.asc"
adguard_gpg_key_checksum: "22d78dbacb461667861ee7d2dd13d13240ee003d"
adguard_release_source_url: https://github.com/AdguardTeam/AdGuardHome/releases/download
adguard_release_version: v0.107.48
adguard_release_checksum: "sha512:c0a336212e3792ae6fc6b8de976befce0038c5d6ddde919a00994c43a929349958c7bd65f7fb7fdd471962afa20855ecbf5830cc7a1d26f3037a716db638c101"
adguard_release_distrib: AdGuardHome_linux_amd64.tar.gz
adguard_release_url: "{{ adguard_release_source_url }}/{{ adguard_release_version }}/{{ adguard_release_distrib }}"
adguard_release_archive_dest: "{{ adguard_dir }}/release-{{ adguard_release_version }}-{{ adguard_release_distrib }}" 
adguard_release_dest: "{{ adguard_dir }}/release-{{ adguard_release_version }}" 
adguard_release_dir: "{{ adguard_release_dest }}/AdGuardHome"
adguard_release_bin: "{{ adguard_release_dir }}/AdGuardHome"
adguard_release_sig: "{{ adguard_release_bin }}.sig"

6.2.2 - Caddy

Role to deploy caddy

6.2.2.1 - Defaults

Defaults for caddy
caddy_enabled: false
caddy_user: caddy
caddy_config_path: /etc/caddy/Caddyfile
caddy_config_dir: /etc/caddy/configs
caddy_config: |
  import {{ caddy_config_dir }}/*

6.2.3 - CIFS

Setup cifs

6.2.3.1 - Defaults

Defaults for cifs
cifs_enabled: false
cifs_systemd_dir: /etc/systemd/system
cifs_mounts: []

6.2.4 - Consul

Consul

6.2.4.1 - Defaults

Defaults for consul
consul_user: consul
consul_user_uid: 4266
consul_dir: "/opt/consul"
consul_data_dir: "{{ consul_dir }}/data"
consul_config_dir: "{{ consul_dir }}/configs"
consul_config_path: "{{ consul_config_dir }}/consul.hcl"
consul_config_local_path: "files/consul.hcl"
consul_log_dir: "{{ consul_dir }}/logs"
consul_tls_dir: "{{ consul_dir }}/tls"
consul_service_path: "/lib/systemd/system/consul.service"
consul_tls_ca_file_local_path: files/pki_ca_servers.crt
consul_tls_ca_file_path: "{{ consul_tls_dir }}/tls_ca_file.crt"
consul_tls_cert_file_path: "{{ consul_tls_dir }}/cert_file.crt"
consul_tls_key_file_path: "{{ consul_tls_dir }}/key_file.crt"
consul_tls_common_name: "{{ inventory_hostname }}"
consul_tls_ttl: "2629746" # month
consul_tls_alt_names: ""
consul_vault_local_path: "{{ role_path }}/files/vault"
consul_bin_local_path: "{{ role_path }}/files/consul"
consul_bin_path: /usr/bin/consul

6.2.5 - Consul

Setup consul

6.2.5.1 - Defaults

Defaults for consul_old
consul_is_server: false
consul_user_name: consul
consul_user_uid:
consul_dir: "/opt/consul"
consul_persistence_dir: "{{ consul_dir }}"
consul_releases_dir: "{{ consul_dir }}/releases"
consul_config_symlink_dir: "{{ consul_configs_dir }}/current"
consul_config_symlink_data_dir: "{{ consul_config_symlink_dir }}/configs"
consul_configs_dir: "{{ consul_persistence_dir }}/configs/{{ inventory_hostname }}"
consul_data_dir: "{{ consul_persistence_dir }}/data/{{ inventory_hostname }}"
consul_config_path: "{{ consul_config_config_dir }}/consul.json"
consul_config_dir: "{{ consul_configs_dir }}/{{ consul_config_dir_name }}" 
consul_config_data_dir: "{{ consul_config_dir }}/data"
consul_config_config_dir: "{{ consul_config_dir }}/configs"
consul_config_dir_name: "{{ consul_config_version }}"
consul_config_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
consul_env: {}
consul_configs: []
consul_env_path: "{{ consul_config_data_dir }}/consul.env"
consul_env_symlink_path: "{{ consul_config_symlink_dir }}/data/consul.env"
consul_release_dir: "{{ consul_releases_dir }}/{{ consul_release_dir_name }}"
consul_release_dir_name: "{{ consul_release_version }}"
consul_release_symlink_path: "{{ consul_releases_dir }}/current"
consul_release_symlink_bin_path: "{{ consul_release_symlink_path }}/consul"
consul_release_version: 1.20.2
consul_release_archive_name: "consul_{{ consul_release_version }}_linux_amd64"
consul_release_archive_fullname: "{{ consul_release_archive_name }}.zip"
consul_release_bin_path: "{{ consul_release_dir }}/consul"
consul_release_url: "https://releases.hashicorp.com/consul/{{ consul_release_version }}/{{ consul_release_archive_fullname }}"
consul_release_checksum: "sha256:1bf7ddf332f02e6e36082b0fdf6c3e8ce12a391e7ec7dafd3237bb12766a7fd5"
consul_agent_ca_cert_path: "{{ consul_config_data_dir }}/agent_ca_cert.pub"
consul_agent_ca_cert:
consul_server_cert_path: "{{ consul_config_data_dir }}/server_cert_{{ inventory_hostname }}.pub"
consul_server_cert:
consul_server_key_path: "{{ consul_config_data_dir }}/server_cert_{{ inventory_hostname }}.key"
consul_server_key:

6.2.6 - Consul envoy

Setup envoy for consul

6.2.6.1 - Defaults

Defaults for consul_envoy
consul_envoy_dir: "/opt/consul_envoy"
consul_envoy_deployments_dir: "{{ consul_envoy_dir }}/deployments"
consul_envoy_releases_dir: "{{ consul_envoy_dir }}/releases"
consul_envoy_deployment_dir: "{{ consul_envoy_deployments_dir }}/{{ consul_envoy_deployment_version }}"
consul_envoy_release_dir: "{{ consul_envoy_releases_dir }}/{{ consul_envoy_release_version }}"
consul_envoy_configs_dir: "{{ consul_envoy_deployment_dir }}/configs"
consul_envoy_bootstrap_config_path: "{{ consul_envoy_configs_dir }}/bootstrap.json"
consul_envoy_deployment_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
consul_envoy_user_name: consul_envoy
consul_envoy_release_version: 1.31.0
consul_envoy_release_archive_fullname: "envoy_{{ consul_envoy_release_version }}_linux_amd64.zip"
consul_envoy_release_url: "https://releases.hashicorp.com/envoy/{{ consul_envoy_release_version }}/{{ consul_envoy_release_archive_fullname }}"
consul_envoy_release_bin_path: "{{ consul_envoy_release_dir }}/envoy"
consul_envoy_release_symlink_path: "{{ consul_envoy_releases_dir }}/current"
consul_envoy_release_checksum: "sha256:350782275de0fe50699844b4f9096d77a0193a5bcf205e14b8ad964ec429d45e"

6.2.7 - Dev VM

Set up repositories and packages for a development VM

The default task entry point configures package repositories and development packages. It uses the same dev_vm_packages list with either the ordinary package manager or RPM-OSTree layering. dev_vm_package_backend accepts auto, package, or rpm_ostree; auto selects RPM-OSTree when /run/ostree-booted exists. Set dev_vm_install_packages to false to skip repository and package management entirely.

RPM-OSTree changes are staged for the next boot by default. The role reports a pending deployment but does not reboot the host. Set dev_vm_rpm_ostree_apply_live to true only when live application is known to be safe for the selected packages.

The packaged Fedora mirror and Bazelisk tool currently make this role specific to Linux x86-64 development hosts.

The packages task entry point exposes package management separately from other role tasks. The bazel task entry point installs a caller-provided Bazel rc, Bazelisk, and the repository’s bazel_agent runner for one developer account.

Import the Bazel entry point with tasks_from: bazel and set:

  • dev_vm_bazel_user: owner of the installed files.
  • dev_vm_bazel_group: group of the installed files; defaults to the user.
  • dev_vm_bazel_home: absolute home directory for the developer account.
  • dev_vm_bazelrc_src: controller-side Bazel rc source; defaults to bazelrc.
  • dev_vm_bazelisk_src: controller-side Bazelisk source; defaults to bazelisk.
  • dev_vm_bazel_agent_src: controller-side bazel_agent source; defaults to bazel_agent.

The role packages its default Linux x86-64 Bazelisk and bazel_agent sources. The calling playbook must package the Bazel rc, plus any overridden binary sources, in an Ansible file search path. Cache storage and machine-specific Bazel settings remain the caller’s responsibility.

6.2.7.1 - Defaults

Defaults for dev_vm
---
dev_vm_install_packages: true
dev_vm_package_backend: auto
dev_vm_rpm_ostree_apply_live: false
dev_vm_packages:
  - clang
  - clang-tools-extra
  - java-latest-openjdk-devel
  - rust
  - cargo
  - mesa-libGL-devel
  - go
  - Xvfb
  - python3
  - gmp-devel
  - patch
  - podman
  - git
  - git-lfs
  - fuse
  - fuse-libs
  - pcsc-lite
  - pcsc-lite-devel
  - openssl
  - gnutls-utils
  - opensc
  - openssl-pkcs11
  - libdnet
  - qemu-kvm
  - qemu-img
dev_vm_bazel_user: "{{ undefined() }}"
dev_vm_bazel_group: "{{ dev_vm_bazel_user }}"
dev_vm_bazel_home: "{{ undefined() }}"
dev_vm_bazelrc_src: bazelrc
dev_vm_bazelisk_src: bazelisk
dev_vm_bazel_agent_src: bazel_agent
dev_vm_selinux_android_emulation: true

6.2.8 - DNS

Setup dns records

6.2.8.1 - Defaults

Defaults for dns
dns_records: []
dns_domains: []
dns_njalla_api_url: https://njal.la/api/1/
dns_njalla_token:

6.2.9 - Docker

Setup docker

6.2.9.1 - Defaults

Defaults for docker
docker_enabled: false

6.2.10 - Facts

Setup ansible facts

6.2.10.1 - Defaults

Defaults for facts
facts_debug: false

6.2.11 - Filesystem

Setup filesystems

6.2.11.1 - Defaults

Defaults for filesystem
filesystem_setup: []

6.2.12 - Firewall

Setup firewall

6.2.12.1 - Defaults

Defaults for firewall
firewall_state: enabled
firewall_enabled: true
firewall_allow_port_from: []
firewall_allow_forward: []

6.2.13 - Forgejo

Forgejo

6.2.13.1 - Defaults

Defaults for forgejo
forgejo_user: forgejo
forgejo_user_uid: 5157
forgejo_dir: "/opt/forgejo"
forgejo_data_dir: "{{ forgejo_dir }}/data"
forgejo_config_dir: "{{ forgejo_dir }}/configs"
forgejo_work_dir: "{{ forgejo_dir }}/work"
forgejo_config_path: "{{ forgejo_config_dir }}/forgejo.ini"
forgejo_config_local_path: "files/forgejo.ini"
forgejo_disk:
forgejo_log_dir: "{{ forgejo_dir }}/logs"
forgejo_service_path: "/lib/systemd/system/forgejo.service"
forgejo_vault_local_path: "{{ role_path }}/files/vault"
forgejo_bin_local_path: "{{ role_path }}/files/forgejo"
forgejo_bin_path: /usr/bin/forgejo

6.2.14 - Forgejo

Forgejo

6.2.14.1 - Defaults

Defaults for threexui
threexui_user: threexui
threexui_user_uid: 6468
threexui_dir: "/opt/threexui"
threexui_data_dir: "{{ threexui_dir }}/data"
threexui_work_dir: "{{ threexui_dir }}/work"
threexui_disk:
threexui_log_dir: "{{ threexui_dir }}/logs"
threexui_service_path: "/lib/systemd/system/threexui.service"
threexui_vault_local_path: "{{ role_path }}/files/vault"
threexui_bin_dir: "{{ threexui_dir }}/bin"
threexui_bin_local_dir: "{{ role_path }}/files/threexui_bin"
threexui_config_dir: "{{ threexui_dir }}/configs"
threexui_env_path: "{{ threexui_config_dir }}/threexui.env"
threexui_env_override: {}
threexui_base_path: /
threexui_username: "{{ undefined() }}"
threexui_password: "{{ undefined() }}"
threexui_port: "2053"
threexui_debug: "false"
threexui_env:
  # https://docs.sanaei.dev/docs/reference/env-vars/
  XUI_DB_TYPE: sqlite
  XUI_DB_FOLDER: "{{ threexui_data_dir }}"
  XUI_PORT: "{{ threexui_port }}"
  XUI_INIT_WEB_BASE_PATH: "{{ threexui_base_path }}"
  XUI_ENABLE_FAIL2BAN: "true"
  XUI_SKIP_HSTS: "true"
  XUI_LOG_LEVEL: info
  XUI_DEBUG: "{{ threexui_debug }}"
  XUI_LOG_FOLDER: "{{ threexui_log_dir }}"
  XUI_BIN_FOLDER: "{{ threexui_bin_dir }}/bin"
  XRAY_VMESS_AEAD_FORCED: "false"
  XUI_ACCESS_URL: "https://{{ inventory_hostname }}{{ threexui_base_path }}"
  XUI_USERNAME: "{{ threexui_username }}"
  XUI_PASSWORD: "{{ threexui_password }}"

6.2.15 - Forgejo runner

Install and register a Forgejo Actions runner

6.2.15.1 - Defaults

Defaults for forgejo_runner
forgejo_runner_user: forgejo-runner
forgejo_runner_user_uid: 5721
forgejo_runner_dir: /opt/forgejo-runner
forgejo_runner_disk:
forgejo_runner_home_dir: /opt/forgejo-runner/home
forgejo_runner_work_dir: /opt/forgejo-runner/work
forgejo_runner_bin_local_path: "{{ role_path }}/files/forgejo-runner"
forgejo_runner_bin_path: /usr/bin/forgejo-runner
forgejo_runner_service_path: /lib/systemd/system/forgejo-runner.service
forgejo_runner_instance: "{{ undefined() }}"
forgejo_runner_token: "{{ undefined() }}"
forgejo_runner_name: "{{ inventory_hostname }}"
forgejo_runner_labels:
  - "self-hosted:host"

6.2.16 - Gpg

Setup GPG

6.2.16.1 - Defaults

Defaults for gpg
gpg_users: []

6.2.17 - Harboer

Harbor

6.2.17.1 - Defaults

Defaults for harbor
harbor_user: harbor
harbor_user_uid: 7049
harbor_dir: "/opt/harbor"
harbor_installer_dir: "{{ harbor_dir }}/installer"
harbor_logs_dir: "{{ harbor_dir }}/logs"
harbor_data_dir: "{{ harbor_dir }}/data"
harbor_installer_local_dir: "{{ role_path }}/files/harbor_installer"
harbor_config_path: "{{ harbor_installer_dir }}/harbor.yml"
harbor_config_local_path: "files/harbor.yaml"
harbor_domain: "{{ undefined() }}"
harbor_ca_local_path: "{{ role_path }}/files/pki_ca_servers.crt"
harbor_ca_path: /etc/docker/certs.d/{{ harbor_domain }}/ca.crt
harbor_root_ca_local_path: "{{ role_path }}/files/pki_ca_root.crt"

6.2.18 - Hermes

Install and run the Hermes Agent gateway

6.2.18.1 - Defaults

Defaults for hermes
hermes_user: hermes
hermes_user_uid: 8150
hermes_dir: /opt/hermes
hermes_home_dir: "{{ hermes_dir }}/home"
hermes_install_dir: "{{ hermes_dir }}/hermes-agent"
hermes_disk:
hermes_port: 8642
hermes_commit: "{{ undefined() }}"
hermes_installer_local_path: "{{ role_path }}/files/install.sh"
hermes_installer_path: "{{ hermes_dir }}/install.sh"
hermes_config_local_path: "files/hermes.yaml"
hermes_config_path: "{{ hermes_home_dir }}/.hermes/config.yaml"
hermes_env_path: "{{ hermes_home_dir }}/.hermes/.env"
hermes_env: {}
hermes_bin_path: "{{ hermes_home_dir }}/.local/bin/hermes"
hermes_dashboard_service_path: /lib/systemd/system/hermes-dashboard.service

6.2.19 - Hiddify manager

Setup hiddify manager

6.2.19.1 - Defaults

Defaults for hiddify_manager
hiddify_manager_env:
  HIDDIFY_MANAGER_IMAGE: ghcr.io/hiddify/hiddify-manager:main@sha256:d5edef06d2133ffa26f0fcbb67e711f4356dba44c44a41a96570c4e03845a84c
  HIDDIFY_MANAGER_REDIS_IMAGE: redis:7.4.1@sha256:bb142a9c18ac18a16713c1491d779697b4e107c22a97266616099d288237ef47
  HIDDIFY_MANAGER_MARIADB_IMAGE: mariadb:11.6.2@sha256:a9547599cd87d7242435aea6fda22a9d83e2c06d16c658ef70d2868b3d3f6a80
  HIDDIFY_MANAGER_REDIS_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_REDIS_PASSWORD', default=undef()) }}"
  HIDDIFY_MANAGER_MYSQL_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_MYSQL_PASSWORD', default=undef()) }}"
  HIDDIFY_MANAGER_MARIADB_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_MARIADB_PASSWORD', default=undef()) }}"
hiddify_manager_env_override: {}
hiddify_manager_dir: /opt/hiddify_manager

6.2.20 - Hiddify manager with host

Setup host and then hiddify manager

6.2.20.1 - Defaults

Defaults for hiddify_manager_host

6.2.21 - Host

Common host setup

6.2.21.1 - Defaults

Defaults for host

6.2.22 - Install CA

Install a certificate authority

6.2.22.1 - Defaults

Defaults for install_ca
install_ca:
  - path: "{{ role_path }}/files/pki_ca_root.crt"
  - path: "{{ role_path }}/files/pki_ca_servers.crt"

6.2.23 - K3s

Setup k3s

6.2.23.1 - Defaults

Defaults for k3s
k3s_data_dir: /srv/k3s_data
k3s_service_name: k3s
k3s_data_disk: /dev/sdb
k3s_storage_dir: /srv/k3s_storage
k3s_storage_disk: /dev/sdc
k3s_config_path: "/etc/rancher/k3s/config.yaml"
k3s_config_local_path: "files/k3s.yaml"
k3s_admission_config_path: "/etc/rancher/k3s/admission.yaml"
k3s_admission_config_local_path: "files/k3s_admission.yaml"
k3s_auth_config_path: "{{ [(k3s_config_path | dirname), 'k3s_auth.yaml'] | path_join }}"
k3s_auth_config_local_path: "files/k3s_auth.yaml"
k3s_manifests_local_path: "files/k3s_manifests.yaml"
k3s_manifests_path: "{{ k3s_data_dir }}/server/manifests/k3s-manifests.yaml"
k3s_bin_local_path: "{{ role_path }}/files/k3s"
k3s_bin_path: /usr/local/bin/k3s
k3s_install_script_local_path: "{{ role_path }}/files/k3s_install"
k3s_install_script_path: /usr/local/bin/k3s_install

6.2.24 - K3s bootstrap

Bootstrap k3s cluster

6.2.24.1 - Defaults

Defaults for k3s_bootstrap
k3s_bootstrap_apply_path:
k3s_bootstrap_token_name: "{{ lookup('ansible.builtin.env', 'USER', default=undef()) }}"
k3s_bootstrap_token_namespace: kube-system
k3s_bootstrap_venv_dir: "/opt/bootstrap-venv"
k3s_bootstrap_venv_bin: "{{ k3s_bootstrap_venv_dir | mandatory }}/bin/python"
k3s_bootstrap_kubeconfig: /etc/rancher/k3s/k3s.yaml
k3s_bootstrap_cluster_name: "{{ inventory_hostname }}"
k3s_bootstrap_cluster_ca_path: "{{ lookup('ansible.builtin.env', 'HOME', default=undef()) }}/.kube/ca-{{ k3s_bootstrap_cluster_name | mandatory }}.ca.crt"
k3s_bootstrap_user_ca_path: "{{ k3s_bootstrap_cluster_ca_path | mandatory | dirname }}/ca-{{ k3s_bootstrap_cluster_name | mandatory }}-{{ k3s_bootstrap_token_name | mandatory }}.ca.crt"
k3s_bootstrap_user_name: "{{ k3s_bootstrap_cluster_name | mandatory }}-{{ k3s_bootstrap_token_name | mandatory }}"
k3s_bootstrap_cluster_port:

6.2.25 - K3s cluster

Setup k3s cluster

6.2.25.1 - Defaults

Defaults for k3s_cluster

6.2.26 - K3s kubeconfig

Write k3s kubeconfig to a secret

6.2.26.1 - Defaults

Defaults for k3s_kubeconfig
k3s_kubeconfig_secret_path: "{{ undefined() }}"
k3s_kubeconfig_secret_mount: "{{ undefined() }}"
k3s_kubeconfig_path: /etc/rancher/k3s/k3s.yaml
k3s_kubeconfig_vault_bin_local_path: "{{ role_path }}/files/vault"

6.2.27 - lvg

Setup LVM volume groups

lvg_volume_groups describes the complete desired physical-volume list for each volume group. Extra physical volumes are not removed unless a caller sets remove_extra_pvs: true.

Creating a volume group initializes every listed device as an LVM physical volume. Callers must resolve stable device paths and verify that each device is the intended, unused disk before applying this role; pvcreate may overwrite an existing disk signature.

6.2.27.1 - Defaults

Defaults for lvg
lvg_volume_groups: []

6.2.28 - lvol

Setup LVM logical volumes

Each lvol_volumes entry can constrain allocation with pvs, pass creation arguments with opts, and disable shrinking with shrink: false.

6.2.28.1 - Defaults

Defaults for lvol
lvol_volumes: []

6.2.29 - Mount

Setup posix mounts

Mount entries can set opts, dump, and passno; state: mounted keeps the mount active and writes its persistent /etc/fstab entry.

6.2.29.1 - Defaults

Defaults for mount
mount_points: []

6.2.30 - Opencode

Opencode

6.2.30.1 - Defaults

Defaults for opencode
opencode_user: opencode
opencode_user_uid: 8149
opencode_dir: "/opt/opencode"
opencode_port: 4096
opencode_domain: "{{ undefined() }}"
opencode_log_dir: "{{ opencode_dir }}/logs"
opencode_work_dir: "{{ opencode_dir }}/work"
opencode_home_dir: "{{ opencode_dir }}/home"
opencode_config_dir: "{{ opencode_home_dir }}/.config/opencode"
opencode_config_path: "{{ opencode_config_dir }}/opencode.json"
opencode_config_local_path: "files/opencode.json"
opencode_disk:
opencode_service_path: "/lib/systemd/system/opencode.service"
opencode_bin_local_path: "{{ role_path }}/files/opencode"
opencode_bin_path: /usr/bin/opencode
opencode_env_path: "{{ opencode_config_dir }}/opencode.env"
opencode_env_override: {}
opencode_ssh_public_key: "{{ undefined() }}"
opencode_ssh_private_key: "{{ undefined() }}"
opencode_server_username: "{{ undefined() }}"
opencode_server_password: "{{ undefined() }}"
opencode_env:
  OPENCODE_SERVER_USERNAME: "{{ opencode_server_username }}"
  OPENCODE_SERVER_PASSWORD: "{{ opencode_server_password }}"

6.2.31 - OpenHands automation

OpenHands automation server

Runs the OpenHands automation server natively from a uv-managed virtual environment. It stores schedules and event triggers, tracks run lifecycle, and dispatches conversations to the agent server.

The automation server is not a sandbox. It records which agent server should run a dispatched conversation and hands that work to AUTOMATION_AGENT_SERVER_URL; setting that variable selects the agent server’s local mode, which uses a persistent local agent server instead of managed OpenHands Cloud sandboxes.

openhands_automation_agent_server_api_key must equal the agent server’s session API key because both services authenticate the same X-Session-API-Key value. openhands_automation_local_api_key is the key browsers present to this service.

The service stores state in SQLite via AUTOMATION_DB_URL by default, which local mode supports without a separate database role. Set openhands_automation_database_url to a PostgreSQL URL to use one instead. openhands_automation_kv_secret enables the automation key-value store and is required for automations that persist state between runs.

openhands_automation_base_url is the externally reachable origin the service appends /api/automation to when it builds callback URLs, so it must be the origin the browser and the dispatched agent server side both use.

6.2.31.1 - Defaults

Defaults for openhands_automation
openhands_automation_user: openhands
openhands_automation_user_uid: 8154
openhands_automation_dir: /opt/openhands-automation
openhands_automation_home_dir: "{{ openhands_automation_dir }}/home"
openhands_automation_work_dir: "{{ openhands_automation_dir }}/work"
openhands_automation_state_dir: "{{ openhands_automation_dir }}/state"
openhands_automation_disk:
openhands_automation_packages:
  - python3.12
  - uv
openhands_automation_host: 127.0.0.1
openhands_automation_port: 18001
openhands_automation_version: "{{ undefined() }}"
openhands_automation_agent_server_version: "{{ undefined() }}"
openhands_automation_agent_server_url: "{{ undefined() }}"
openhands_automation_sandbox_agent_server_url: ""
openhands_automation_agent_server_api_key: "{{ undefined() }}"
openhands_automation_base_url: "{{ undefined() }}"
openhands_automation_local_api_key: "{{ undefined() }}"
openhands_automation_kv_secret: "{{ undefined() }}"
openhands_automation_database_url: "sqlite+aiosqlite:///{{ openhands_automation_state_dir }}/automations.db"
openhands_automation_workspace_base: "{{ openhands_automation_work_dir }}/automations"
openhands_automation_venv_dir: "{{ openhands_automation_dir }}/venv"
openhands_automation_service_path: /lib/systemd/system/openhands-automation.service
openhands_automation_env_path: "{{ openhands_automation_dir }}/.env"
openhands_automation_env:
  PYTHONUTF8: "1"
  OPENHANDS_REMOTE_WS_READY_REQUIRED: "false"
  OPENHANDS_SUPPRESS_BANNER: "1"
openhands_automation_env_override: {}

6.2.32 - OpenHands canvas

OpenHands Agent Canvas frontend

Runs the OpenHands Agent Canvas browser client from the published npm package. The service listens on loopback port openhands_canvas_port; TLS, the public hostname, and routing to the agent server and automation API belong to the deployment’s Traefik role.

The service runs the package’s scripts/static-server.mjs directly with Node, an explicit loopback host, and the package’s build/ directory. It serves the browser client without starting an agent server, an automation server, or the npm launcher’s additional ingress process. Agent Canvas owns no conversation or automation state and executes no tools.

The browser starts with no configured backend. The operator adds one with the canvas origin as the host and the agent server’s session key as the credential. The static server receives no session key and injects none into served assets. This configuration does not advertise an embedded VSCode editor.

The npm prefix is installed inside openhands_canvas_dir. openhands_canvas_package_dir identifies the installed package containing the static server and browser assets.

6.2.32.1 - Defaults

Defaults for openhands_canvas
openhands_canvas_user: openhands
openhands_canvas_user_uid: 8153
openhands_canvas_dir: /opt/openhands-canvas
openhands_canvas_home_dir: "{{ openhands_canvas_dir }}/home"
openhands_canvas_work_dir: "{{ openhands_canvas_dir }}/work"
openhands_canvas_state_dir: "{{ openhands_canvas_dir }}/state"
openhands_canvas_package_dir: "{{ openhands_canvas_dir }}/lib/node_modules/@openhands/agent-canvas"
openhands_canvas_disk:
openhands_canvas_packages:
  - nodejs24
  - nodejs24-npm
openhands_canvas_host: 127.0.0.1
openhands_canvas_port: 8000
openhands_canvas_version: "{{ undefined() }}"
openhands_canvas_service_path: /lib/systemd/system/openhands-canvas.service
openhands_canvas_env_path: "{{ openhands_canvas_dir }}/.env"
openhands_canvas_env:
  NODE_ENV: production
openhands_canvas_env_override: {}

6.2.33 - Openhands server

OpenHands agent server

Runs the OpenHands agent server natively from a uv-managed virtual environment. It hosts conversations, executes tools, and streams events for Agent Canvas. The service binds loopback only; TLS and external reachability belong to the calling deployment.

Set openhands_server_secure to true to require a session API key. The unsecured mode omits the session key and is only appropriate where the loopback boundary is trusted.

The caller can set openhands_server_install_packages to false and install openhands_server_packages through its host-specific package workflow. OSTree hosts use the shared dev_vm package entry point and must boot into a deployment containing those dependencies before installing the service. They also set openhands_server_service_path under /etc/systemd/system.

6.2.33.1 - Defaults

Defaults for openhands_server
openhands_server_user: openhands
openhands_server_user_uid: 8152
openhands_server_dir: /opt/openhands-server
openhands_server_home_dir: "{{ openhands_server_dir }}/home"
openhands_server_work_dir: "{{ openhands_server_dir }}/work"
openhands_server_state_dir: "{{ openhands_server_dir }}/state"
openhands_server_conversations_dir: "{{ openhands_server_state_dir }}/conversations"
openhands_server_persistence_dir: "{{ openhands_server_state_dir }}/persistence"
openhands_server_workspace_dir: "{{ openhands_server_work_dir }}/project"
openhands_server_bash_events_dir: "{{ openhands_server_state_dir }}/bash_events"
openhands_server_tools_dir: "{{ openhands_server_dir }}/tools"
openhands_server_disk:
openhands_server_secure: true
openhands_server_install_packages: true
openhands_server_packages:
  - python3.12
  - uv
openhands_server_host: 127.0.0.1
openhands_server_port: 18000
openhands_server_version: "{{ undefined() }}"
openhands_server_session_api_key: "{{ undefined() }}"
openhands_server_secret_key: "{{ undefined() }}"
openhands_server_import_modules: canvas_ui_tool
openhands_server_vscode_port: 8001
openhands_server_vscode_base_path: /vscode
openhands_server_venv_dir: "{{ openhands_server_dir }}/venv"
openhands_server_venv_python: "{{ openhands_server_venv_dir }}/bin/python"
openhands_server_service_path: /lib/systemd/system/openhands-server.service
openhands_server_env_path: "{{ openhands_server_dir }}/.env"
openhands_server_env:
  LOG_JSON: "true"
  PYTHONUTF8: "1"
  OPENHANDS_REMOTE_WS_READY_REQUIRED: "false"
  OH_PERSISTENCE_DIR: "{{ openhands_server_persistence_dir }}"
  OH_CONVERSATIONS_PATH: "{{ openhands_server_conversations_dir }}"
  OH_WORKSPACE_PATH: "{{ openhands_server_workspace_dir }}"
  OH_BASH_EVENTS_DIR: "{{ openhands_server_bash_events_dir }}"
  OH_SECRET_KEY: "{{ openhands_server_secret_key }}"

6.2.34 - OS

Common os setup

6.2.34.1 - Defaults

Defaults for os
os_hardening_enabled: true

6.2.35 - Posgresql

Setup Postgresql

6.2.35.1 - Defaults

Defaults for postgresql
postgresql_packages:
  - postgresql-server
  - postgresql-contrib
postgresql_service: postgresql

6.2.36 - Pve

Proxmox Virtual Environment deploy

6.2.36.1 - Defaults

Defaults for pve
pve_repo_keyring_path: /usr/share/keyrings/proxmox-archive-keyring.gpg
pve_repo_path: /etc/apt/sources.list.d/pve-install-repo.sources
pve_repo_keyring_url: https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg
pve_repo_keyring_checksum: "sha256:136673be77aba35dcce385b28737689ad64fd785a797e57897589aed08db6e45"
pve_snippets_dir: /var/lib/vz/snippets
pve_snippets: []
pve_repo_content: |
  Types: deb
  URIs: http://download.proxmox.com/debian/pve
  Suites: trixie
  Components: pve-no-subscription
  Signed-By: {{ pve_repo_keyring_path }}

6.2.37 - PVE cluster

Setup PVE cluster

6.2.37.1 - Defaults

Defaults for pve_cluster
pve_cluster_remove_repos:
  - pve-enterprise.list 
  - ceph.list
pve_cluster_add_repos:
  - name: pve-no-subscription
    value: deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
  - name: ceph-squid
    value: deb http://download.proxmox.com/debian/ceph-squid bookworm no-subscription
pve_cluster_node_config: []
pve_cluster_admins: []
pve_cluster_cluster_name:
pve_cluster_acme_accounts: []
pve_cluster_acme_plugins: []
pve_cluster_venv_dir: /opt/ansible/pve_cluster_venv
pve_cluster_venv_packages: 
  - pexpect
pve_cluster_base_image_dir: /var/lib/vz/template
pve_cluster_node_name: "{{ inventory_hostname | mandatory | split('.') | first }}"
pve_cluster_ceph_enabled: false
pve_cluster_ceph_repository: no-subscription
pve_cluster_ceph_osd: []
pve_cluster_ceph_pools: []
pve_cluster_ceph_mon: []
pve_cluster_ceph_mgr: []
pve_cluster_ceph_mds: []
pve_cluster_storages: []
pve_cluster_storage_config_path: /etc/pve/storage.cfg

6.2.38 - PVE VM

Setup PVE VM

6.2.38.1 - Defaults

Defaults for pve_vm
pve_vm_agent: 
pve_vm_name: "{{ inventory_hostname }}"
pve_vm_delegate_update_known_hosts: localhost
pve_vm_delegate_pve: 
pve_vm_set: "{{ pve_vm_set_default + pve_vm_set_additional }}"
pve_vm_set_default: []
pve_vm_set_additional: []
pve_vm_set_creation: "{{ pve_vm_set_creation_default + pve_vm_set_creation_additional }}"
pve_vm_set_creation_default: []
pve_vm_set_creation_additional: []
pve_vm_resize: []
pve_vm_venv_dir: "/opt/ansible/pve_vm_venv"
pve_vm_init_user:
pve_vm_venv_packages:
  - proxmoxer
  - requests

6.2.39 - PVE VM remove

Remove PVE VM

6.2.39.1 - Defaults

Defaults for pve_vm_remove

6.2.40 - Raspberry pi

Setup raspberry pi

6.2.40.1 - Defaults

Defaults for raspberry_pi
raspberry_pi_argon_enabled: false
raspberry_pi_containers_enabled: false
raspberry_pi_argon_eeprom_script_path: /usr/local/bin/argon_argon_eeprom.sh
raspberry_pi_argon_argon1_script_path: /usr/local/bin/argon_argon1.sh
raspberry_pi_cmdline_path: /boot/firmware/cmdline.txt

6.2.41 - SSH

Setup ssh

6.2.41.1 - Defaults

Defaults for ssh
ssh_hardening_enabled: true
ssh_vault_mount: ssh/servers
ssh_vault_role: "{{ undefined }}"
ssh_sign_ignore_errors: false
ssh_valid_principals: []

6.2.42 - SSH port forwarding

Setup SSH port forwarding

6.2.42.1 - Defaults

Defaults for ssh_port_forward
ssh_port_forward_local_addr: 127.0.0.1
ssh_port_forward_script_path: /usr/local/bin/ssh-port-forward

6.2.43 - SSH update known hosts

Update known hosts

6.2.43.1 - Defaults

Defaults for ssh_update_known_hosts
ssh_update_known_hosts_hosts: []

6.2.44 - T3 Code

Run the T3 Code server as a systemd service

6.2.44.1 - Defaults

Defaults for t3code
t3code_user: t3code
t3code_user_uid: 8151
t3code_dir: /opt/t3code
t3code_home_dir: "{{ t3code_dir }}/home"
t3code_work_dir: "{{ t3code_dir }}/work"
t3code_disk:
t3code_port: 5120
t3code_version: "{{ undefined() }}"
t3code_state_dir: "{{ t3code_dir }}/state"
t3code_auth_token: "{{ undefined() }}"
t3code_service_path: /lib/systemd/system/t3code.service
t3code_env_path: "{{ t3code_dir }}/.env"
t3code_env: {}

6.2.45 - Traefik

Traefik

6.2.45.1 - Defaults

Defaults for traefik
traefik_user: traefik
traefik_no_user: false
traefik_owner: root
traefik_user_uid: 3578
traefik_dir: "/opt/traefik"
traefik_log_dir: "{{ traefik_dir }}/logs"
traefik_data_dir: "{{ traefik_dir }}/data"
traefik_tls_dir: "{{ traefik_dir }}/tls"
traefik_disk:
traefik_mtls_ca_local_path: "{{ role_path }}/files/traefik_mtls_ca.crt"
traefik_mtls_ca_path: "{{ traefik_tls_dir }}/mtls_ca.crt"
traefik_acme_path: "{{ undefined }}"
traefik_config_dir: "{{ traefik_dir }}/configs"
traefik_config_path: "{{ traefik_config_dir }}/traefik.toml"
traefik_disable_eab: false
traefik_config_local_path: "files/traefik.toml"
traefik_dynamic_config_path: "{{ traefik_config_dir }}/traefik_dynamic.toml"
traefik_dynamic_config_local_path: "files/traefik_dynamic.toml"
traefik_service_path: "/lib/systemd/system/traefik.service"
traefik_service_scope: system
traefik_bin_local_path: "{{ role_path }}/files/traefik"
traefik_bin_path: /usr/bin/traefik
traefik_vault_bin_local_path: "{{ role_path }}/files/vault"

6.2.46 - Traefik (old)

Old traefik role

6.2.46.1 - Defaults

Defaults for traefik_old
traefik_user: traefik
traefik_user_uid: 3653
traefik_env: {}
traefik_data_dir: /mnt/traefik
traefik_log_dir: "/var/log/traefik"
traefik_certificates_dir: "{{ traefik_data_dir }}/certificates"
traefik_configs_dir: "{{ traefik_data_dir }}/configs"
traefik_configs_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
traefik_configs_dynamic_dir: "{{ traefik_configs_cur_dir }}/dynamic"
traefik_configs_dynamic_dir_symlink: "{{ traefik_configs_symlink }}/dynamic"
traefik_configs_cur_dir_name: "{{ traefik_configs_version }}"
traefik_configs_cur_dir: "{{ traefik_configs_dir }}/{{ traefik_configs_cur_dir_name }}"
traefik_configs_symlink: "{{ traefik_configs_dir }}/current"
traefik_static_config_path: "{{ traefik_configs_symlink }}/traefik.yaml"
traefik_releases_dir: /opt/traefik/releases
traefik_static_config:
traefik_dynamic_configs: []
traefik_release_version: v3.3.1
traefik_release_dir_name: "{{ traefik_release_version }}"
traefik_release_dir: "{{ traefik_releases_dir }}/{{ traefik_release_dir_name }}"
traefik_release_symlink: "{{ traefik_releases_dir }}/current"
traefik_release_symlink_bin: "{{ traefik_release_symlink }}/traefik"
traefik_release_archive_name: "traefik_{{ traefik_release_version }}_linux_amd64"
traefik_release_archive_full: "traefik_{{ traefik_release_version }}_linux_amd64.tar.gz"
traefik_release_bin_path: "{{ traefik_release_dir }}/traefik"
traefik_release_download_url: "https://github.com/traefik/traefik/releases/download/{{ traefik_release_version }}/{{ traefik_release_archive_full }}"
traefik_release_download_checksum: sha256:27fd502a8d80fc81b97faf5cebd7a1cbc1a2c5369d18e0f4471a66d1a8c139ce

6.2.47 - Update all packages

Update all system packages

6.2.47.1 - Defaults

Defaults for update_all_packages

6.2.48 - Users

Setup system users

6.2.48.1 - Defaults

Defaults for users
users_regular: {}
users_remove: {}
users_admins:
  ansible:
    name: ansible
    disable_passwd: true
    sudo_no_passwd: true
users_ssh_keys: {}

6.2.49 - Vault

Setup Hashicorp Vault

6.2.49.1 - Defaults

Defaults for vault
vault_user: vault
vault_user_uid: 3123
vault_dir: "/opt/vault"
vault_data_dir: "{{ vault_dir }}/data"
vault_raft_dir: "{{ vault_dir }}/raft"
vault_config_dir: "{{ vault_dir }}/configs"
vault_config_path: "{{ vault_config_dir }}/vault.hcl"
vault_config_local_path: "files/vault.hcl"
vault_log_dir: "{{ vault_dir }}/logs"
vault_tls_dir: "{{ vault_dir }}/tls"
vault_service_path: "/lib/systemd/system/vault.service"
vault_tls_client_ca_file_local_path: files/tls_client_ca_file.pem
vault_tls_client_ca_file_path: "{{ vault_tls_dir }}/tls_client_ca_file.pem"
vault_tls_cert_file_path: "{{ vault_tls_dir }}/tls_cert_file.pem"
vault_tls_key_file_path: "{{ vault_tls_dir }}/tls_key_file.pem"
vault_tls_issue_path:
vault_tls_alt_names: ""
vault_bin_local_path: "{{ role_path }}/files/vault"
vault_bin_path: /usr/bin/vault
vault_peers_write: false
vault_peers_local_path:
vault_peers_remote_path: "{{ vault_raft_dir }}/raft/peers.json"

6.2.50 - Wireguard

Setup wireguard

6.2.50.1 - Defaults

Defaults for wireguard
wireguard_dir: "/etc/wireguard"
wireguard_local_config_paths: []

6.2.51 - Xray

Setup xray

Links:

6.2.51.1 - Defaults

Defaults for xray
xray_enabled: false
xray_config_dir: /usr/local/etc/xray
xray_log_dir: /var/log/xray
xray_config_path: "{{ xray_config_dir }}/0-main.json"
xray_client_id:
xray_wireguard_relays: []
xray_wireguard_ipv4_address:
xray_wireguard_ipv6_address:
xray_wireguard_private_key:
xray_config:
xray_configs: {}
xray_user: xray
xray_socket_dir: /var/shm/xray
xray_caddy_config_path: /etc/caddy/configs/xray.Caddyfile
xray_subscriptions_dir: /usr/local/etc/xray-subscriptions
xray_caddy_user: caddy

7 - Autoscroll

Mouse-driven autoscroll CLI with reloadable configuration

Autoscroll is a Python and PyQt6 command-line application that turns mouse movement into horizontal and vertical scrolling. It supports configurable buttons, scroll speed, and configuration changes without restarting.

  • Platfrom-independent autoscroll
  • Config file with hot-reload
  • Some argparse tinkering
  • Python3, PyQt6

By default, the icon is disabled, to enable it pass --icon-enable

You can pass file contents as command line arguments using @path/to/the/file syntax. Arguments in that case can be placed wherever - on one line, on several lines

If you want to dynamically pass runtime arguments (without restarting the process), you can use --config options for it

Once you press --buttons-start, you can scroll vertically or horizontally just by moving your mouse untill you press --buttons-end

If --buttons-hold is set, the srolling ends once you release --buttons-start

Once --buttons-start is pressed, the scroll thread starts looping Every loop consists of sleeping for an interval, then scrolling for either 0, 1, or -1 pixels on both axis towards the starting point Starting point is the point where --buttons-start was pressed Sleep interval is recalculated on every mouse move as such:

    100 / (--scrolling-acceleration * max(distance) + --scrolling-speed)

If --scrolling-acceleration is not 0, the speed of scrolling will be faster the farther away you are from the starting point If --scrolling-acceleration is 0, the speed of scrolling will be constant

python3 -m venv venv
. venv/bin/activate
pip install autoscroll
autoscroll
autoscroll --buttons-start 1 --debug-click --icon-disable
autoscroll --icon-enable @config.txt

If config.txt is defined like this, its contents will be used as command line arguments - they will be loaded only once Arguments can be placed wherever - on one line, on several lines For example,

--buttons-start 1
--buttons-hold --debug-click
autoscroll --config-enable --config-path config.txt

If config.txt is defined like this, the process will listen for changes in that file and update itself Arguments can be placed wherever - on one line, on several lines The file is checked for changess every --config-interval For example:

--buttons-start 1 --buttons-hold
--debug_click
usage: autoscroll [-h] [-ss SCROLLING_SPEED] [-sd SCROLLING_DEAD_AREA]
                  [-sa SCROLLING_ACCELERATION] [-bh] [-bs BUTTONS_START] [-be BUTTONS_END]
                  [-ce] [-cp CONFIG_PATH] [-ci CONFIG_INTERVAL] [-ie] [-ip ICON_PATH]
                  [-is ICON_SIZE] [-df] [-dc] [-ds] [-di]

...

options:
  -h, --help            show this help message and exit

scrolling:

  -ss, --scrolling-speed int
                        constant part of the scrolling speed
                        [default: 300]
  -sd, --scrolling-dead-area int
                        size of the square area aroung the starting point where scrolling will stop, in
                        pixels
                        [default: 50]
  -sa, --scrolling-acceleration int
                        dynamic part of the scrolling speed, depends on the distance from the point
                        where the scrolling started, can be set to 0
                        [default: 10]

buttons:

  -bh, --buttons-hold   if set, the scrolling will end once you release --buttons-start
  -bs, --buttons-start int
                        button that starts the scrolling
                        [default: 2]
  -be, --buttons-end int
                        button that ends the scrolling
                        [default: --buttons-start]

config:

  -ce, --config-enable  if set, arguments from the configuration file on --config-path will be loaded
                        every --config-interval
  -cp, --config-path str
                        path to the configuration file
                        [default: ~/.config/autoscroll/config.txt]
  -ci, --config-interval int
                        how often the config file should be checked for changes, in seconds
                        [default: 5]

icon:

  -ie, --icon-enable    if set, the icon will be enabled
  -ip, --icon-path str  path to the icon
                        [default: resources/img/icon.svg]
  -is, --icon-size int  size of the icon, in pixels
                        [default: 30]

debug:

  -df, --debug-file     if set, every time the config file is parsed, information will be printed to
                        stdout
  -dc, --debug-click    if set, click info will be printed to stdout
  -ds, --debug-scroll   if set, scroll info will be printed to stdout
  -di, --debug-initial  if set, startup configuration will be printed to stdout

7.1 - Releases

Releases

7.1.1 - head

Release head

8 - Bazel agent

Bazel runner for repository agents

bazel_agent is the repository Bazel entry point for agents. It keeps the Bazel invocation behind a validated subcommand while consistently applying the agent configuration:

bazel_agent bazel test //path/to/package:all
    ->
bazel test --config=agent //path/to/package:all

bazel is the only Bazel entry point, and it is a validated subcommand. The runner accepts a known Bazel command after the bazel keyword, rejects arbitrary leading arguments, and places --config=agent after the command. Targets, command options, and arguments after the -- separator of a bazel run invocation pass through unchanged. Later options therefore retain Bazel’s normal precedence and can override settings supplied by the agent configuration. The runner resolves bazel from PATH and replaces itself with that process, so signals and the final exit status are not mediated by another wrapper process. Uses of the persistent Bazel server follow the host Codex network policy; the host-bot profile allows loopback so the client-server connection is not blocked.

The runner does not create or inject a host temporary directory. Bazel actions use declared outputs and Bazel-managed temporary storage, and tests use their test temporary-directory contract. Repository-updating host tools that need scratch must accept or derive an explicit task/run path under out/<task>/ instead of relying on ambient TMPDIR, TMP, or TEMP values propagated to the whole build.

bazel_agent doctor --workspace-root PATH --task-scratch out/<task>/<run> is a read-only, bounded JSON diagnostic. It reports runner and built-source identity, Bazelisk pins, platform, rc/profile composition, task scratch classification, and stale host-install state without dumping the environment.

Bootstrap the host installation with the underlying Bazel command:

bazel run --config=agent //projects/bazel_agent:install

Once installed, update it with:

bazel_agent bazel run //projects/bazel_agent:install

The install target atomically replaces ~/.local/bin/bazel_agent. After every code update to this project, rerun the install target; the installed binary is not updated automatically.

9 - Ci platform

Abandoned CI platform with a Go backend and Vue frontend

An abandoned continuous integration platform with a Go backend and a Vue single-page frontend. The source retains its job, pipeline, and project management components.

  • Clean architecture
  • Backend: Golang, Gorm, Fiber, Hcl, Postgresql
  • Frontend: SPA, VueJS with PrimeVue

Arch

ci_platform
├── api [Interface Adapters]
│   ├── controller
│   ├── middleware
│   └── presenter
├── cmd (CLI interface)
├── docs (OpenAPI Specification and other documentation)
│   └── diagrams
├── entity [Enterprise Business Rules]
├── infrastructure [Frameworks and Drivers]
│   ├── access
│   ├── branch
│   ├── config
│   ├── job
│   ├── jwt
│   ├── lifecycle
│   ├── pipeline
│   ├── pool
│   ├── project
│   ├── schedule
│   ├── session
│   └── user
├── pkg (Support packages)
│   └── error
└── usecase [Application Business Rules]
│   ├── access
│   ├── branch
│   ├── job
│   ├── jwt
│   ├── lifecycle
│   ├── pipeline
│   ├── pool
│   ├── project
│   ├── schedule
│   ├── session
│   └── user
└── web (Web interface)

9.1 - Releases

Releases

9.1.1 - head

Release head

10 - Dotfiles

Personal configuration files with installation and comparison commands

This project packages personal configuration files into an installable archive. Make and Bazel entry points compare the packaged files with the local system and install selected configurations.

  • Archive with dotfiles that can be installed using make
bazel run //projects/dotfiles:help # Show help
bazel run //projects/dotfiles:diff # Show diff
bazel run //projects/dotfiles:install # Install files
oras pull --output "${PWD}" docker.io/alwaldend/src:projects_dotfiles_dotfiles_tar_head
cd releases/projects/dotfiles/head/files
tar -xf dotfiles.tar
cd dotfiles
make help # Show help
make diff # Check diff between system files and those from the archive
make diff/nvim # Check diff for all nvim files
make diff/nvim/.config/nvim/lazy-lock.json # Diff specific file
make install # Install all files from the archive
make install/nvim # Install nvim files
make install/nvim/.config/nvim/lazy-lock.json # Install a specific file
help: Show help
install: Install files from the archive
diff: Show diff between archive files and system files
install/bin: Install bin files
diff/bin: Diff bin files
install/home: Install home files
diff/home: Diff home files
install/nvim: Install nvim files
diff/nvim: Diff nvim files
make: Nothing to be done for 'help'.

10.1 - Releases

Releases

10.1.1 - head

Release head

11 - Infinitime

InfiniTime firmware fork with a text watchface and Pomodoro app

This InfiniTime firmware fork adds a text watchface and a Pomodoro app. The repository packages the pinned firmware source and its build dependencies.

  • Extra Watchface: Text
  • Extra app: Pomodoro
  • C++, embedded

The root workspace declares the pinned firmware with use_repo_rule in include.MODULE.bazel, preserving recursive Git submodules and the CMake toolchain patch. Firmware source is fetched when referenced, rather than during module resolution. Its Python/npm lockfiles and SDK archives retain the upstream pins; Python and Node runtimes use the root workspace toolchains. The project re-exports pip and npm with separate extension identities so unrelated Python/npm targets do not fetch firmware to read those lockfiles. The isolated pip extension declares the Linux x86_64 host platform used by the pinned ARM compiler archive. bazel mod deps deliberately evaluates all extensions and can still fetch it.

Validate the firmware with bazel test //projects/infinitime:build_test.

  • Install Gadgetbridge
  • Download the firmware:
    oras pull docker.io/alwaldend/src:projects_infinitime_pinetime_mcuboot_app_dfu_1_15_0_zip_head
    
  • Pair the watch in Gadgetbridge
  • Install the firmware

11.1 - Releases

Releases

11.1.1 - head

Release head

12 - Kustomization

Kubernetes resources for Flux, Traefik, and cert-manager

This project contains Kubernetes Kustomization resources for Flux, Traefik, and cert-manager. It is still in progress.

12.1 -

project-dns Specification

Record the retirement of this project’s landing DNS infrastructure while preserving its repository documentation and builds.

The project SHALL have no dedicated landing DNS declaration, Terraform root, or operational source export. Its landing page SHALL be published by the main site under /projects/kustomization/ instead of a dedicated hostname.

  • WHEN the project tree is consumed
  • THEN it contains no landing DNS declaration, Terraform DNS stage, or landing build target, and the main site owns its landing page.

12.2 -

Kustomization Specification

Provide in-progress Kubernetes resource definitions for Flux, Traefik, and cert-manager. This baseline records declared resources at revision 550d7e79b1f5fdbc2b6017b75178471d6914082f, observed on 2026-09-08. It does not assert successful rendering, reconciliation, or a deployed cluster state.

Sources: project README, Flux source, Traefik release, Traefik remote resources, and cert-manager release.

The Flux GitRepository declaration SHALL select the repository’s master branch, refer to the flux-git-src credential secret, and include only infra and projects/kustomization from the repository through its ignore rules.

  • WHEN the checked-in Flux GitRepository is inspected
  • THEN its branch, secret reference, and inclusion paths SHALL match the declared source scope.

The Traefik definitions SHALL declare an OCI chart source and HelmRelease that enable the Kubernetes Gateway provider, disable the Kubernetes Ingress provider, and configure HTTP redirection to HTTPS with a named TLS certificate secret.

  • WHEN the Traefik HelmRelease values are inspected
  • THEN they SHALL enable HTTP and HTTPS gateway listeners and reference traefik-gateway-websecure-tls for HTTPS termination.

The cert-manager definitions SHALL declare an OCI chart source and HelmRelease with Gateway API support, CRD installation, Helm tests, and drift detection enabled.

  • WHEN the cert-manager HelmRelease is inspected
  • THEN its values SHALL enable Gateway API support and CRDs, and its release settings SHALL enable tests and drift detection.

12.3 - Releases

Releases

12.3.1 - head

Release head

13 - Leetcode downloader

LeetCode submission export and documentation tools

This project exports LeetCode submissions and generates documentation from submission files using a CLI and Bazel rules. A Tampermonkey script provides a browser-based download path; direct CLI downloads are currently blocked by LeetCode bot protection.

  • CLI and bzl code to generate submission docs
  • Tampermonkey script to download submissions
  • CLI to download submissions (Doesn’t work because of bot protection)
bazel run //projects/leetcode_downloader -- \
    --submissions-file "${PWD}/out/submissions.json" \
    --root-dir "${PWD}" \
    generate
Usage of flags:
  -base_url string
    	 (default "https://leetcode.com")
  -cookie string

  -limit uint
    	 (default 20)
  -offset uint

  -root-dir string
    	 (default "${PWD}")
  -submissions-file string

13.1 - Bzl

Bazel code

13.1.1 - al_leetcode_submissions

al_leetcode_submissions

load("@com_alwaldend_src//projects/leetcode_downloader/main/bzl:al_leetcode_submissions.bzl", "al_leetcode_submissions")

al_leetcode_submissions(name, srcs, visibility, **kwargs)

Generate leetcode submission targets

PARAMETERS

Name Description Default Value
name generated md archive name none
srcs leetcode submission configs none
visibility visibility None
kwargs kwargs for template_files none

13.2 - Proto

Protobuf contracts

13.2.1 - contracts

Proto docs for contracts.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//projects/leetcode_downloader/main/proto/contracts:contracts_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//projects/leetcode_downloader/main/proto/contracts:contracts",
    ],
)
syntax = "proto3";

option go_package = "git.alwaldend.com/alwaldend/src/projects/leetcode_downloader/main/proto/contracts";

enum CliAction {
  DOWNLOAD = 0;
  GENERATE = 1;
  UPDATE = 2;
}

message Config {
  string base_url = 1;
  string cookie = 2;
  repeated string action_args = 4;
  CliAction action = 5;
  uint64 offset = 6;
  uint64 limit = 7;
  map<string, SubmissionConfig> submissions = 8;
  string root_dir = 9;
  map<string, string> headers = 11;
  string submissions_file = 12;
  bool write_code = 13;
}

message SubmissionConfig {
  string dir = 1;
  string extension = 2;
  repeated string types = 3;
}

message Submission {
  uint64 id = 1;
  string status_display = 2;
  string lang = 3;
  uint64 question_id = 4;
  string title_slug = 5;
  string code = 6;
  string title = 7;
  string url = 8;
  string lang_name = 9;
  // string time = 10;
  uint64 timestamp = 11;
  uint64 status = 12;
  string runtime = 13;
  string is_pending = 14;
  string memory = 15;
  string compare_result = 16;
  bool has_notes = 17;
  uint64 flag_type = 18;
}

message SubmissonsResponse {
  repeated Submission submissions_dump = 1;
  bool has_next = 2;
  string last_key = 3;
}
message SubmissonsStorage {
  repeated Submission submissions = 1;
}

13.3 - Releases

Releases

13.3.1 - head

Release head

14 - MCP Cordis

Workspace-local runtime packages behind a stable MCP server

mcp_cordis is a standalone stdio MCP server that mounts runtime JavaScript packages through Cordis. It is intentionally an MCP server, not a Codex plugin bundle.

Reusable definitions are ordinary ESM files in projects/mcp_cordis/plugins, listed by projects/mcp_cordis/cordis.yaml. Disposable definitions use the same layout under out/<task>/mcp_cordis/runs/<run>/. Each run writes a bounded manifest with explicit task, run, worker, information, budget, retention, lock, and cleanup fields. AGENT_TASK_ID, AGENT_RUN_ID, and AGENT_WORKER_ID may provide stable identities; the launcher otherwise creates process-scoped identities. Every package is addressed by both scope and name, so a scratch package never silently shadows a reusable package.

The repository’s .codex/config.toml registers mcp_cordis as a project-scoped stdio server. Codex loads that file for a trusted workspace and finds the active Git worktree before starting the server. Separate clones and worktrees therefore use their own source, projects/mcp_cordis packages, and task/run-namespaced scratch packages. Trusting the repository’s root checkout also covers its linked worktrees; a glob trust entry is neither needed nor supported. A new Codex session is needed after the MCP registration itself is first added; package changes after that do not require another session.

The registration calls cmd/mcp_cordis/launch.sh. With a current installed bazel_agent, the launcher selects a content-addressed runtime from the per-user tool cache and executes it directly. The first exact source version is built and atomically installed under a per-key lock; subsequent worktrees with the same inputs do not start Bazel or load a configured graph. An older runner falls back to asking Bazel for a launch script under the task’s ignored out directory. Either path releases Bazel’s output-base lock before the long-lived stdio server starts, so builds and tests can run normally while Codex remains connected.

The cached artifact contains the stable server runtime and pinned JavaScript dependencies, but not cordis.yaml or reusable plugins. It always reads those from the explicit active workspace, so editing a package changes live behavior without repackaging the runtime or selecting a new cache key.

The same project configuration starts an optional asynchronous SessionStart hook that starts the worktree’s Bazel server and warms repo_delivery. It produces no session context, ignores failure, and never queries the whole workspace graph. Cordis itself is already warmed by its MCP launch path, so the hook does not start a duplicate Cordis build.

To build and run the server directly from the repository root:

bazel_agent bazel run //projects/mcp_cordis:mcp_cordis -- \
  --workspace-root "$PWD" \
  --task-id example-task \
  --run-id example-run

The workspace root is mandatory unless BUILD_WORKSPACE_DIRECTORY is present. The checked-in launcher resolves the current Git worktree explicitly and supplies that path to the server.

The fixed cordis_* tools define, start, inspect, invoke, update, stop, remove, and promote packages without reconnecting the MCP client. Package handlers are called through cordis_invoke; this remains reliable even when an MCP client caches its initial tool list.

cordis.yaml uses the standard Cordis Include entry-list format:

- id: hello
  name: ./plugins/hello.mjs

The referenced file is a normal ESM Cordis plugin:

const plugin = {
  description: "Provide a greeting.",
  apply(ctx) {
    ctx.tool(
      {
        name: "hello_world",
        description: "Return a greeting.",
        inputSchema: {
          type: "object",
          properties: { name: { type: "string" } },
          additionalProperties: false,
        },
      },
      ({ name = "world" }) => ({ greeting: `Hello, ${name}!` }),
    );
  },
};

plugin.apply.description = plugin.description;

export default plugin;

Cordis normalizes an object plugin to its apply callback. Attaching the optional package description to that callback exposes it through cordis_list and cordis_inspect; tool descriptions remain part of each ctx.tool() definition.

The server mounts the official Cordis Loader, Include, and HMR services. cordis_define syntax-checks and atomically persists the ordinary module. Creating or enabling an entry refreshes any cached module through Cordis HMR, then uses the public Include refresh API and waits for activation. Updating an already-running entry returns activation: "pending"; poll cordis_invoke or cordis_list_tools until the new behavior is visible. The reproducibly pinned HMR package carries a focused pnpm patch that serializes module reloads and drains source changes arriving during an in-flight reload, so the latest persisted source is not lost.

Syntax errors are rejected before the file changes. Evaluation and apply() failures follow native Cordis HMR behavior; the wrapper does not add a second activation transaction around them. It also does not inject source markers, inspect Loader caches, correlate watcher events, or maintain its own source rollback/version store. Reusable history is normal Git history. Manual edits to watched plugin files are also picked up by Cordis HMR.

Runtime modules use normal Cordis semantics, including static imports, top-level await, and asynchronous apply(ctx, config). Package code is trusted: a never-settling module evaluation or activation can therefore stall Cordis lifecycle work. The stdio launcher reserves its protocol stream and redirects package stdout to stderr, keeping accidental console.log() calls off the JSON-RPC wire.

The package context exposes ctx.workspaceRoot, ctx.resolveWorkspace(), ctx.readText(), and structured ctx.exec() in addition to ctx.tool(). ctx.exec() returns code, signal, stdout, stderr, truncated, and outputLimitExceeded; maxBytes is a combined stdout/stderr budget. By default, exceeding that budget or producing invalid UTF-8 rejects with EXEC_OUTPUT_LIMIT or EXEC_INVALID_UTF8. Packages that explicitly set allowTruncatedOutput: true instead receive the valid retained prefix with truncated set; outputLimitExceeded distinguishes the byte cap from UTF-8 loss. A Fiber-owned supervisor admits each launch atomically, and results settle only after the direct child and every live member of its original Linux process group have stopped. Limits, timeouts, and plugin disposal use the same cleanup path. A process that deliberately creates a new session escapes that group and is outside this trusted-package contract. ctx.exec() therefore fails closed with EXEC_UNSUPPORTED_PLATFORM away from Linux. Package code also has normal Node built-ins; this host is a reliability boundary, not a security sandbox.

cordis_invoke.timeout_ms bounds how long the gateway waits for a result; it does not cancel an already admitted JavaScript handler. The handler keeps its Fiber lease until it finishes, so stop, remove, and shutdown wait for it. Cordis HMR waits for a retired Fiber to finish draining before it activates and publishes the replacement, so a live invocation can delay a reload. Any ctx.exec() launched by a timed-out invocation is cancelled and its process group is confirmed stopped before the timeout response settles.

  • repo_context: bounded repository reads and searches.
  • git_worktree: read-only branch, status, log, and comparison snapshots.
  • network_probe: DNS, TCP/TLS, and HTTP diagnostics.

These were selected from aggregate recurring task categories in recent local sessions. No transcript content, credentials, or private outputs are included.

The completed runtime extensions change preserves acceptance criteria, decisions, failed attempts and supporting evidence. New work uses the project OpenSpec workspace and a new change; the archived acceptance remains historical.

The runtime directly uses @deepseek-ai/cordis, its official Loader, Include, HMR, and Timer plugins, and the Model Context Protocol TypeScript SDK. Their license texts are retained in the resolved package artifacts by the pinned pnpm/Bazel dependency graph.

15 - Nexus security plugin

Security plugin for Sonatype Nexus 3

This plugin allows you to perform a check every time an artifact is requested from a repository

  • A request handler that checks all requests to repositories
  • Capability controlling the request handler
  • A task that periodically updates the capability using a remote source
  • Sonatype Nexus 3 plugin
  • Java

diagram

15.1 - Model

Attributes of some classes
etag: c849a44121f823c806f604d6568d9e89 (class java.lang.String)
last_modified: 2021-10-22T15:57:10.000Z (class org.joda.time.DateTime)
hashCodesMap: (class java.util.HashMap)
    org.sonatype.nexus.common.hash.HashAlgorithm@7ce01bd8: bcbb583a5a4b4767de8ac020dea3d54011fee961
    org.sonatype.nexus.common.hash.HashAlgorithm@5a3efc26: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d
    org.sonatype.nexus.common.hash.HashAlgorithm@5b0c0740: c849a44121f823c806f604d6568d9e89
org.sonatype.nexus.repository.storage.Asset:
  metadata: (AttachedEntityMetadata)
    schema: assetPath
    document:
      "#74:0": >-
        bucket:#57:1,format:pypi,last_updated:Fri Jul 01 12:46:21 UTC 2022,attributes:[5],component:#65:0,
        name:packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl,size:1723581,content_type:application/zip,created_by:anonymous,
        created_by_ip:80.78.253.49,blob_ref:default@E1F281C2-0A159DAD-4208CEFD-524F990B-0B4DDE11:739a4ecb-73fc-4422-a7d7-c93c8ad069c6,
        last_downloaded:Fri Jul 01 04:44:03 UTC 2022,blob_created:Wed Jun 29 07:01:34 UTC 2022,blob_updated:Wed Jun 29 07:01:34 UTC 2022
    name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
org.sonatype.nexus.repository.cache.CacheInfo:
  lastVerified: 2022-07-01T12:46:21.457Z
  cacheToken: 'null'
org.apache.shiro.subject.support.DefaultSubjectContext.SESSION_CREATION_ENABLED: false (class java.lang.Boolean)
Key[type=org.sonatype.nexus.security.SecurityFilter, annotation=[none]].FILTERED: true (class java.lang.Boolean)
authcAntiCsrf.FILTERED: true (class java.lang.Boolean)
nx-authc.FILTERED: true (class java.lang.Boolean)
org.apache.shiro.web.servlet.ShiroHttpServletRequest_SESSION_ID_URL_REWRITING_ENABLED: false (class java.lang.Boolean)
javax.servlet.include.servlet_path: /repository/pypi/packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl (class java.lang.String)
nexus.user.principal: admin (class java.lang.String)
nx-anonymous.FILTERED: true (class java.lang.Boolean)
nexus.user.id: admin (class java.lang.String)
nx-apikey-authc.FILTERED: true (class java.lang.Boolean)
security.authorized: true (class java.lang.Boolean)
nexus.analytics.format_request_rates.marked: true (class java.lang.Boolean)
com.sonatype.nexus.repository.pypi.AssetKind: PACKAGE (class com.sonatype.nexus.repository.pypi.AssetKind)
local.attribute.org.sonatype.nexus.repository.view.handlers.HandlerContributor.extended: true (class java.lang.Boolean)
org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$State: >-
  org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$1@19f23c0b ((class org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$1))
proxy: (class java.util.HashMap)
  contentMaxAge: 0.0
  remoteUrl: https://pypi.org
  metadataMaxAge: 0.0
negativeCache: (class java.util.HashMap)
  timeToLive: 0.0
  enabled: false
storage: (class java.util.HashMap)
  strictContentTypeValidation: false
  blobStoreName: default
httpclient: (class java.util.HashMap)
  blocked: false
  connection:
    useTrustStore: true
    autoBlock: false
checksum: (class org.sonatype.nexus.common.collect.DetachingMap)
  sha1: bcbb583a5a4b4767de8ac020dea3d54011fee961
  sha256: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d
  md5: c849a44121f823c806f604d6568d9e89
cache: (class org.sonatype.nexus.common.collect.DetachingMap)
  last_verified: Fri Jul 01 13:07:08 UTC 2022
provenance: (class org.sonatype.nexus.common.collect.DetachingMap)
  hashes_not_verified: false
pypi: (class org.sonatype.nexus.common.collect.DetachingMap)
  summary: The PyPA recommended tool for installing Python packages
  author: The pip developers
  description: ...
content:
  etag: c849a44121f823c806f604d6568d9e89
  last_modified: Fri Oct 22 15:57:10 UTC 2021
etag: c849a44121f823c806f604d6568d9e89
last_modified: 2021-10-22T15:57:10.000Z (class org.joda.time.DateTime)
hashCodesMap: (class java.util.HashMap)
  org.sonatype.nexus.common.hash.HashAlgorithm@3d97cbd0: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d, org.sonatype.nexus.common.hash.HashAlgorithm@675317cb=c849a44121f823c806f604d6568d9e89
  org.sonatype.nexus.common.hash.HashAlgorithm@67bcbee7: bcbb583a5a4b4767de8ac020dea3d54011fee961
  org.sonatype.nexus.repository.storage.Asset: (class org.sonatype.nexus.repository.storage.Asset)
    metadata: (AttachedEntityMetadata)
      schema: assetPath
      document: (#74:0)
        bucket: #57:1
        format: pypi
        last_updated: Fri Jul 01 13:25:15 UTC 2022
        attributes: [5]
        component: #65:0
        name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
        size: 1723581
        content_type: application/zip
        created_by: anonymous
        created_by_ip: 80.78.253.49
        blob_ref: default@E1F281C2-0A159DAD-4208CEFD-524F990B-0B4DDE11:739a4ecb-73fc-4422-a7d7-c93c8ad069c6
        last_downloaded: Fri Jul 01 04:44:03 UTC 2022
        blob_created: Wed Jun 29 07:01:34 UTC 2022
        blob_updated: Wed Jun 29 07:01:34 UTC 2022
      name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
org.sonatype.nexus.repository.cache.CacheInfo: (class org.sonatype.nexus.repository.cache.CacheInfo)
  lastVerified: 2022-07-01T13:25:14.841Z
  cacheToken: 'null'

15.2 - Releases

Releases

15.2.1 - head

Release head

16 - Renders

Repository-owned render assets and their acceptance evidence

This project owns reusable Blender assets, their controlling references, and acceptance evidence bound to exact candidate bytes. Maintained work uses the project OpenSpec workspace.

The Reimu Fumo work lives under assets/reimu_fumo/. Its reusable asset target will be added only after a candidate passes the visual, structural, animation, and exact-byte delivery gates in Reimu Fumo change. That change preserves the open outcome, blocked execution and original goal history.

Working candidates and intermediate renders belong under the repository-root out/reimu_fumo_finish/ directory. They are not accepted or durable merely because they exist there. A historical packet may move into the source tree only when exact bytes and provenance are verified and it is labeled with its actual rejected or accepted state.

17 - Sri

Command-line Subresource Integrity calculator using OpenSSL

sri calculates Subresource Integrity hashes for files using OpenSSL. Its command-line interface accepts an input file and a digest algorithm, such as SHA-256.

  • Cli app that calculates SRI using OpenSSL
  • C, OpenSSL
Usage: sri [OPTION...]
Generate sri of a file

Example:
    bazel run //projects/sri -- --digest sha256 --file ${PWD}/README.md

  -d, --digest=String        Digest type (sha256, for example)
  -f, --file=Path            Path to the file to parse
  -?, --help                 Give this help list
      --usage                Give a short usage message

17.1 - Releases

Releases

17.1.1 - head

Release head

18 - Tf modules

Reusable Terraform modules for Vault, virtual machines, and storage

This project contains reusable Terraform modules for Vault configuration, Proxmox virtual machines, backup storage, and related infrastructure. The module collection is still in progress.

  • Terraform modules

18.1 -

dns-records Specification

Provide one canonical DNS transformation for project-local Terraform resources and offline inspection, preserving declared names, values, and view ownership.

The module SHALL accept decoded owner DNS documents and a zone, flatten every supported type member, expand and deduplicate destinations, and expose one normalized map without provider configuration. It SHALL reject unsupported types, destinations, malformed members, and absolute names outside the zone.

  • WHEN an entry contains A and AAAA with destinations all and global
  • THEN normalization produces exactly four records, one per type and view

Normalized and provider resource keys SHALL use logical declaration key, type, and view without mutable record values. Separate logical keys SHALL preserve multiple records at the same name and type, including MX priority and TXT values. Explicit TTLs SHALL override the type-specific compatibility defaults.

  • WHEN an A member changes its address without changing its logical key
  • THEN its normalized and provider resource keys remain unchanged

The module SHALL accept provider instances from its caller and create individual Cloudflare global and RouterOS dc1 records only when explicitly enabled. It SHALL default to disabled provider ownership while preserving normalized outputs. Cloudflare records SHALL remain unproxied. Disabled ownership SHALL NOT imply that operational provider initialization or credential prerequisites are suppressed.

  • WHEN a root calls the module without enabling ownership
  • THEN it declares no provider record resources and still exposes every normalized declaration

18.2 -

project-dns Specification

Record the retirement of this project’s landing DNS infrastructure while preserving its repository documentation and builds.

The project SHALL have no dedicated landing DNS declaration, Terraform root, or operational source export. Its landing page SHALL be published by the main site under /projects/tf_modules/ instead of a dedicated hostname.

  • WHEN the project tree is consumed
  • THEN it contains no landing DNS declaration, Terraform DNS stage, or landing build target, and the main site owns its landing page.

18.3 -

Reusable Terraform modules

Provide reusable infrastructure declarations for Vault, virtual machines, storage, and related services. This baseline was observed at repository revision 550d7e79 on 2026-09-08. The collection remains in progress according to its README. Sources for the representative module contracts below are the AppRole module, transit-key module, backup-bucket module, and module packaging. These are declarative source contracts; no live provisioning is asserted.

The AppRole, transit-key, backup-bucket, and Proxmox VM module packages SHALL each expose their main.tf through a same-named Bazel filegroup available to repository subpackages.

  • WHEN a target depends on //projects/tf_modules/vault_approle:vault_approle
  • THEN its declared source input includes the AppRole module’s main.tf

The AppRole module SHALL declare an identity entity, backend alias, internal group, and named AppRole with configurable token and secret-ID limits. Its role policies SHALL combine the shared and AppRole-secret policies with caller policies and the Yandex-folder policy unless that policy is disabled for the role.

  • WHEN disable_yc_folder_policy is true
  • THEN the role’s policy list excludes the module’s Yandex-folder policy while preserving shared, AppRole-secret, and caller policies

The transit-key module SHALL declare a named Vault transit key, an encryption policy and group, and a decryption policy and group. Decryptor member groups SHALL also be included in the encryption group.

  • WHEN a caller adds a group ID to decryptors_member_group_ids
  • THEN the module includes that group in both transit permission groups

The backup-bucket module SHALL declare a versioned Yandex storage bucket with default KMS encryption, grant read and write permissions to the supplied service accounts, and store bucket identifiers in the caller-selected Vault KV v2 location.

  • WHEN the caller supplies the bucket name components, folder, service accounts, and Vault destination
  • THEN the declarations bind bucket encryption to the module’s KMS key and publish the bucket ID, folder ID, and bucket name to that Vault destination

18.4 - Backup bucket

S3 bucket for backups

18.5 - DNS records

Canonical DNS declarations for Cloudflare and RouterOS

This reusable module translates an owner’s decoded dnsconfig.json through its provider-free normalizer, then manages individual global Cloudflare and dc1 RouterOS records with caller-provided providers. Owners with only global records use the global entrypoint, which needs only Cloudflare. The combined entrypoint delegates Cloudflare resources to that same module and consumes its normalization for RouterOS. Repository infrastructure roots may consume its Bazel source filegroups; the child normalizer also supports provider-free inspection.

module "dns" {
  source             = "../../../projects/tf_modules/dns_records"
  document           = jsondecode(file("${path.module}/../dnsconfig.json"))
  cloudflare_zone_id = var.dns_cloudflare_zone_id
  enabled            = var.dns_enabled
}

zone defaults to alwaldend.com. An explicit cloudflare_zone_id is optional; when it is null or empty, enabled global records resolve exactly one Cloudflare zone matching zone. The token must permit zone listing and reading. Disabled ownership and declarations without global records skip this lookup. enabled defaults to false so a prepared root owns no provider records. Keep it true after adoption: setting it false in a state that already owns records plans deletion and is not a rollback procedure. Disabling ownership does not suppress provider initialization. Operational Terraform commands still require the caller’s real provider configuration and the owning Vault/AppRole prerequisites. In particular, the pinned RouterOS provider probes its configured API even when no DNS records are enabled. Use the provider-free normalizer for offline inspection. The migration runbook owns cutover, import, and rollback ordering. This module supplies no provider credentials or state backend.

The input contains exactly one records object. Each stable logical key contains one or more scalar type members and a nonempty dsp list. Supported destinations are global, dc1, and all; repeated destinations are deduplicated.

Type Required member fields Default TTL
A name, address 300
AAAA name, address 600
CNAME name, target 600
NS name, address 300
MX name, target, priority 300
TXT name, content 300

Every member accepts an integer ttl from 60 through 86400 seconds. MX priorities range from 0 through 65535. Multiple scalar values at the same name and type use distinct logical keys; changing values never changes resource identity. Unsupported fields and malformed members are rejected.

Names accept @, relative names, or zone-qualified names. Absolute owner names ending with a dot must be inside the zone. CNAME, MX, and NS targets accept @, relative names, zone-qualified names, or absolute external names ending with a dot. Normalization lowercases domain names and omits final dots; address and TXT bytes are preserved. relative_name is @ at the apex.

normalized_records maps logical_key/type/view to key, name, relative_name, type, value, priority (null except MX), ttl, view, and proxied (always false). This output remains available while disabled. The same keys index module.global.cloudflare_dns_record.records and module.dc1[0].routeros_ip_dns_record.records in the combined entrypoint; the global-only entrypoint uses cloudflare_dns_record.records. import_addresses exposes these addresses relative to the selected module, including while staged. The pinned providers import Cloudflare records by zone_id/record_id and RouterOS records by static IDs such as *1A.

Terraform tests use mocked providers and pinned local provider packages. The global-only test root has no RouterOS provider dependency. Normalization tests require no providers. Both run without network access; they establish declaration and resource mapping behavior, not live adoption.

18.5.1 - DNS normalization

Provider-free canonical DNS declaration transformation

This child module owns the canonical transformation described by the DNS module. Its document and zone inputs produce normalized_records without a provider, backend, or managed resources. Terraform writers and provider-free inspection consume this output.

18.5.2 - DNS test providers

Pinned provider packages for offline Terraform tests

The test target uses the public rules_terraform wrapper with the same Cloudflare, RouterOS, and Proxmox provider labels as infrastructure targets. The shared extension owns provider versions, release URLs, and checksums. Bazel fetches the declared archives before tests execute; Terraform uses the wrapper’s packaged filesystem mirror without a registry fallback.

Each regression runs Terraform in a caller-owned temporary module directory. Tests retain an explicit environment without inherited provider credentials; provider installation and mocked lifecycles require no network access.

The targeted import regression matches the owning Proxmox provider block by omitting pm_api_url. It checks both empty state and existing Proxmox resource state with no credentials. Without PM_API_URL, provider validation fails before target pruning; supplying only a loopback endpoint permits the DNS operation. The endpoint must receive zero requests.

The test imports a built-in Terraform resource through a root map into module.dns, checks the exact no-op import, applies that saved plan, and verifies the next targeted plan has no changes. Existing Proxmox resource attributes remain unchanged. An untargeted control must fail authentication before contacting the endpoint. These checks cover provider selection and state preservation; live DNS adoption retains its separate inventory and plan checks.

18.5.3 - Global DNS records

Cloudflare-only entrypoint for canonical DNS declarations

Global-only owners use this entrypoint with the shared module API to avoid requiring RouterOS configuration. The combined module also delegates its Cloudflare resources here, so both entrypoints share one implementation. Normalization returns all declared views, but this entrypoint owns only global records. Mixed-view owners use the parent module to manage dc1 as well.

Enabled global records use the explicit cloudflare_zone_id when supplied. Otherwise, the pinned cloudflare_zone data source resolves the configured zone name and rejects missing or ambiguous matches. This requires zone-list and zone-read access in addition to record permissions. Disabled ownership and declarations without global records perform no zone lookup.

The optional zone ID must be known during planning so Terraform can select whether discovery is needed. The repository’s AL injection supplies a known value or an empty string before Terraform starts. Zone-name discovery uses the normalizer’s canonical name, including case and final-dot handling.

import_addresses contains global addresses relative to this entrypoint. record_ids exposes bound Cloudflare IDs for adoption and identity checks.

18.6 - Pve vm qemu

Create a proxmox vm

18.7 - Releases

Releases

18.7.1 - head

Release head

18.8 - Terraform backend

Module that sets up an S3 terraform backend

18.9 - Vault approle

Create a vault approle

18.10 - Vault approle

Create a vault approle

18.11 - Vault OIDC provider

Vault OIDC provider

18.12 - Vault pki server

Create a pki config for a server

18.13 - Vault ssh server role

Create an ssh role for a server

18.14 - Vault transit key

Vault transit key

18.15 - Yc folder

Folder for Yandex Cloud

19 - Useless QT GUI

Desktop GUI application built with C++ and Qt

Useless QT GUI is a desktop application built with C++ and Qt. Its Bazel build uses a pinned Qt distribution without requiring a system Qt installation.

  • Desktop GUI
  • C++, Qt

The Bazel build downloads a SHA-256-pinned Qt 6.8.3 distribution through rules_qt; a system Qt installation is not required. The project previously targeted Qt 6.9.0. Using 6.8.3 is a deliberate downgrade to the LTS version supported and tested by the pinned rules_qt release.

  • Add some screenshots