cleanup: remove 33 iCloud duplicate(s)
This commit is contained in:
parent
ff6df437f2
commit
29e7d22844
33 changed files with 0 additions and 3190 deletions
|
|
@ -1,314 +0,0 @@
|
|||
---
|
||||
date: 2026-05-09
|
||||
tags: [daily]
|
||||
---
|
||||
|
||||
## Session Log
|
||||
|
||||
- 15:44 (31min) | `aimpress`
|
||||
- **Asked:** Configure AppAPI daemon and NPM proxy hosts for Nextcloud PVE server.
|
||||
- **Done:** Verified HPB and STUN settings, identified NPM admin credentials, and prepared to set up two proxy hosts via API while checking service status.
|
||||
- 16:11 | `aimpress`
|
||||
- **Asked:** Set up NPM proxy hosts for office.ai-impress.com and signaling server after fixing AppAPI daemon errors on Nextcloud.
|
||||
- **Done:** Configured all non-NPM dependent services and verified service status; awaiting NPM credentials to complete proxy host setup via API.
|
||||
- 16:22 | `aimpress`
|
||||
- **Asked:** How to fix AppAPI daemon and signaling connection errors in Nextcloud on PVE server with Cloudflare routing.
|
||||
- **Done:** Created NPM proxy host for signal.ai-impress.com and configured Cloudflare DNS A record to route signaling traffic separately.
|
||||
- 16:24 | `aimpress`
|
||||
- **Asked:** How to resolve Nextcloud AppAPI daemon accessibility and setup warnings on PVE server.
|
||||
- **Done:** Verified daemon configuration, tested admin credentials, and confirmed proxy signaling server responds correctly with 404 (expected for WebSocket-only service).
|
||||
- 17:18 (4min) | `Shumiland-site-dev`
|
||||
- **Asked:** Install and connect the Ruflo MCP server plugin to the marketplace.
|
||||
- **Done:** Successfully added Ruflo marketplace plugin and verified server connection status.
|
||||
- 17:20 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities and provide a JSON report with findings, risk score, and recommendations.
|
||||
- **Done:** Identified high-severity JSON injection and plaintext data storage vulnerability in memory.js, along with security analysis of helper scripts.
|
||||
- 17:22 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Provided performance optimization analysis with identification of N+1 query patterns, unnecessary React re-renders, caching opportunities, memory leak risks, and redundant computation areas.
|
||||
- 17:26 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Added ruflo marketplace plugin to the project | Installed ruvnet/ruflo plugin via marketplace | package.json, .claude-flow/coordination/store.json
|
||||
- **Done:** —
|
||||
- 17:29 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage to identify gaps in unit, integration, and error handling tests.
|
||||
- **Done:** Identified untested functions, edge cases, missing error handling tests, and integration gaps with test skeletons provided.
|
||||
- 17:30 | `Shumiland-site-dev`
|
||||
- **Asked:** Asked for plugin marketplace integration with ruvnet/ruflo.
|
||||
- **Done:** Added ruflo marketplace plugin and merged remote changes with local codebase.
|
||||
- 17:30 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated JSON security report with vulnerability findings, risk score, and remediation recommendations.
|
||||
- 17:31 | `Shumiland-site-dev`
|
||||
- **Asked:** Set up git repository and add ruflo marketplace plugin to the project.
|
||||
- **Done:** Initialized git repo with 250 files, configured remote SSH connection, and added ruflo marketplace plugin successfully.
|
||||
- 17:33 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** I cannot generate the requested output because the transcript does not contain any concrete development task or accomplishment. The conversation is asking whether "ruflo" is enabled and configured, and mentions working through it, but no actual code changes, features, or file modifications are described.
|
||||
- **Done:** To create an accurate log entry, I would need a transcript that describes:
|
||||
- 17:48 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance issues including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Determined that no source code exists in the codebase to analyze, only configuration files are present.
|
||||
- 17:48 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities and generate a JSON report with findings, risk score, and recommendations.
|
||||
- **Done:** Unable to complete full analysis due to incomplete codebase context provided in transcript.
|
||||
- 17:54 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including secrets, injection risks, XSS, dependencies, and authentication issues.
|
||||
- **Done:** Generated a comprehensive JSON security report identifying vulnerabilities across categories with severity levels, risk score, and remediation recommendations.
|
||||
- 17:56 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Reviewed codebase structure and main source files to identify performance issues and provide actionable suggestions.
|
||||
- 18:01 (1min) | `aimpress`
|
||||
- **Asked:** Check RuFlo session status and explain what the status line means.
|
||||
- **Done:** Reviewed RuFlo memory and configuration to explain the session status indicator.
|
||||
- 18:02 | `Shumiland-site-dev`
|
||||
- **Asked:** Study the PDF document and create a website development plan with a CMS replacement for non-technical marketers to manage content, blocks, photos, and pages.
|
||||
- **Done:** Launched a 3-agent pipeline (architect, coder, reviewer) using B1 Foundation to design specifications and build the project structure with security checks.
|
||||
- 18:02 | `Shumiland-site-dev`
|
||||
- **Asked:** Create a website development plan based on a PDF contract document, replacing TinaCMS with a user-friendly CMS for non-technical marketers.
|
||||
- **Done:** Initiated a 3-agent pipeline (architect, coder, reviewer) to design specifications for ~25 project files with security and configuration validation.
|
||||
- 18:04 | `aimpress`
|
||||
- **Asked:** What does the RuFlo session status line mean and is RuFlo working?
|
||||
- **Done:** Explained RuFlo V3.6 status bar showing session metadata including developer name, git branch, model, and session duration.
|
||||
- 18:05 | `aimpress`
|
||||
- **Asked:** Does RuFlo session work and what does it mean?
|
||||
- **Done:** Explained RuFlo V3.6 status line components and multi-agent pipeline state with architect currently designing Payload 3.0 + Next.js 15 scaffold.
|
||||
- 18:05 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the Shumiland website contract document and create a development plan with a CMS replacement recommendation for non-technical content managers.
|
||||
- **Done:** Project scaffold initialized with Ruflo agent workflow, architect generated 24-file specification, and reviewer confirmed readiness for coder implementation while identifying spec corrections.
|
||||
- 18:08 | `aimpress`
|
||||
- **Asked:** What does "working session with ruflo" mean and does it actually work?
|
||||
- **Done:** Identified that RuFlo's swarm counter tracks CLI processes but the architect is a Claude Code native agent, explaining why it's not counted in the "Swarm 0/15" display.
|
||||
- 18:10 | `Shumiland-site-dev`
|
||||
- **Asked:** Review the PDF document and create a website development plan with a CMS replacement for non-technical content managers.
|
||||
- **Done:** Analyzed the project requirements and set up a Ruflo agent swarm architecture with 4 agents to handle the Shumiland website development workflow.
|
||||
- 18:11 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and auth issues.
|
||||
- **Done:** Generated JSON security report with vulnerability findings, risk score, and remediation recommendations.
|
||||
- 18:11 (<1min) | `aimpress`
|
||||
- **Asked:** Is the RuFlo session working and what does "Swarm 0/15" mean?
|
||||
- **Done:** Identified that RuFlo's process counter only tracks agentic-flow CLI processes via ps aux, not Claude Code native agents, explaining why the architect agent doesn't appear in the Swarm count.
|
||||
- 18:12 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for security vulnerabilities including secrets, SQL injection, XSS, dependencies, and authentication issues.
|
||||
- **Done:** Generated JSON security report identifying vulnerabilities by severity with risk score and remediation recommendations.
|
||||
- 18:14 (2min) | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested a website development plan based on a PDF document with TinaCMS replacement for non-technical content management.
|
||||
- **Done:** Project scaffold was reviewed and 699 packages were installed with zero typecheck errors and 6 corrections applied.
|
||||
- 18:14 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance optimizations including N+1 queries, unnecessary re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Identified performance issues in API routes and provided actionable optimization suggestions with code examples.
|
||||
- 18:22 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities and provide a JSON report with findings, risk score, and recommendations.
|
||||
- **Done:** Conducted security analysis identifying hardcoded secrets, SQL injection risks, XSS vulnerabilities, insecure dependencies, and authentication issues across the codebase.
|
||||
- 18:23 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage and identify gaps in the codebase with suggestions for new test scenarios.
|
||||
- **Done:** Identified untested functions, missing edge cases, error handling gaps, and integration test gaps with test skeleton recommendations.
|
||||
- 18:24 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Reviewed Payload CMS API route structure and identified potential optimization opportunities with actionable suggestions.
|
||||
- 18:28 | `Shumiland-site-dev`
|
||||
- **Asked:** Does Ruflo need to be enabled and will you work exclusively through it, and can you study the PDF contract and create a website development plan with a CMS replacement for non-technical marketers?
|
||||
- **Done:** Ruflo agent framework initialized with task tracking and memory; architect agent (B2) completed full specification with 32 files and Payload 3.0 schema; coder agent queued to begin scaffold implementation.
|
||||
- 18:37 | `Shumiland-site-dev`
|
||||
- **Asked:** Review document and create website development plan with CMS replacement for non-technical content managers.
|
||||
- **Done:** Completed content model scaffold with 37 files including collections, globals, and page builder blocks, all passing typecheck.
|
||||
- 18:42 | `Shumiland-site-dev`
|
||||
- **Asked:** Review project scaffold and identify configuration issues to fix before development.
|
||||
- **Done:** Reviewed scaffold and found one environment variable mismatch requiring manual fix in .env.example.
|
||||
- 18:49 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer asked to analyze a PDF document and create a website development plan with a CMS replacement (replacing TinaCMS with a non-technical user-friendly solution).
|
||||
- **Done:** Analyzed project structure, fixed .env.example, created logger.ts and ezy.ts utilities with retry/cache/zod validation, and configured Telegram bot token handling for production deployment.
|
||||
- 18:49 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested a website development plan based on a PDF contract, replacing TinaCMS with a user-friendly CMS for non-technical marketers.
|
||||
- **Done:** Analyzed document requirements and discussed CMS replacement strategy; completed logger and utility modules (logger.ts, ezy.ts) with retry/cache/zod validation; identified Telegram bot token storage in .env.production for VPS deployment.
|
||||
- 18:50 | `Shumiland-site-dev`
|
||||
- **Asked:** Can you analyze the PDF document and create a website development plan with a CMS replacement for non-technical content managers?
|
||||
- **Done:** Reviewed project structure and identified that scaffold hasn't been built yet; only Claude Flow/Ruflo tooling is present, with some backend modules (b3-binotel completed, others pending).
|
||||
- 18:50 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested analysis of a PDF contract document and a website development plan with content management system recommendations.
|
||||
- **Done:** Project structure initialized with Ruflo tooling; preliminary review completed showing b3-binotel module done with HMAC verification and phone normalization, awaiting b3-notifications, b3-leads, and b3-tickets modules.
|
||||
- 18:52 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a security vulnerability report identifying high-severity HMAC secret default issue and other potential risks with severity ratings and recommendations.
|
||||
- 18:52 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested analysis of a PDF document and a website development plan with CMS replacement for non-technical users.
|
||||
- **Done:** Analyzed the document and reviewed project scaffolding; identified that the scaffold hasn't been built yet and verified dependency corrections (resend package version).
|
||||
- 18:53 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and auth issues.
|
||||
- **Done:** Generated JSON security report with vulnerability findings, risk score, and remediation recommendations.
|
||||
- 18:53 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Create a website development plan based on the PDF document with a CMS replacement that allows non-technical marketers to manage content, pages, and site structure from an admin panel.
|
||||
- **Done:** Reviewed project scaffold and confirmed integration setup with Ruflo tooling; validated typecheck with zero errors across 5 parallel agents and documented deployment configuration for Resend API.
|
||||
- 18:54 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Identified O(n×m) linear scan in tariffs route, N+1 query patterns in access control, and provided optimization suggestions with code examples.
|
||||
- 18:55 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a security vulnerability report in JSON format with severity levels, affected files, line numbers, and recommendations.
|
||||
- 18:55 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested a site development plan based on a PDF document with a CMS replacement to enable non-technical marketers to manage content and pages easily.
|
||||
- **Done:** Security audit completed with 5 fixes applied (webhook validation, token comparison, phone regex, sensitive data removal from logs) and TypeScript typecheck passed with zero errors.
|
||||
- 18:56 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance issues including N+1 queries, unnecessary re-renders, caching opportunities, memory leaks, and redundant computations.
|
||||
- **Done:** Identified access control patterns and began scanning the codebase for React components and rate limiting to provide a complete performance analysis.
|
||||
- 18:59 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage gaps and create test skeletons for access control and API functions.
|
||||
- **Done:** Created 9 test files covering unit and API tests with mocked dependencies, identifying and addressing gaps in HMAC verification, access control, and error handling.
|
||||
- 19:02 (2min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage gaps across the codebase and provide test skeletons for untested functions and edge cases.
|
||||
- **Done:** Identified untested modules (resend.ts), partial gaps (rateLimit.ts, webhook routes), and provided gap analysis with test recommendations.
|
||||
- 19:02 | `Shumiland-site-dev`
|
||||
- **Asked:** Create a development plan for a Shumiland website redesign with a user-friendly CMS replacement for non-technical marketers.
|
||||
- **Done:** Analyzed the project requirements document and initiated framework setup with Telegram integration and deployment checklist for CMS migration.
|
||||
- 19:03 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Asked | Analyze codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and auth issues
|
||||
- **Done:** Done | Identified high-severity vulnerability in webhook endpoint lacking replay attack protection and HMAC timestamp validation
|
||||
- 19:05 | `Shumiland-site-dev`
|
||||
- **Asked:** How should we replace TinaCMS with a user-friendly CMS for non-technical marketers to manage content, blocks, photos, and pages?
|
||||
- **Done:** Analyzed project requirements document and discussed CMS replacement strategy; identified need for headless CMS with intuitive admin interface for content management without technical knowledge.
|
||||
- 19:07 | `Shumiland-site-dev`
|
||||
- **Asked:** Can you analyze the provided PDF document and create a website development plan, replacing TinaCMS with a more user-friendly CMS for non-technical marketers?
|
||||
- **Done:** Project scaffold initialized with Ruflo tooling; B4 typecheck completed (3 files); B5 test suite generation started (9 test files) with parallel environment configuration fixes.
|
||||
- 19:11 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Reviewed access control files and identified that the provided codebase snippet is incomplete, requiring full source files for comprehensive performance analysis.
|
||||
- 19:12 | `Shumiland-site-dev`
|
||||
- **Asked:** Create a website development plan based on the Shumiland contract document with a non-technical CMS replacement for TinaCMS.
|
||||
- **Done:** Analyzed the PDF document and initiated planning discussion; confirmed project scaffold is ready but main development hasn't started yet.
|
||||
- 19:15 | `Shumiland-site-dev`
|
||||
- **Asked:** Create a website development plan based on a PDF document and replace TinaCMS with a user-friendly CMS for non-technical marketers.
|
||||
- **Done:** Reviewed backend scaffold completion (Next.js 15 + Payload CMS 3.0 + integrations) and prepared to discuss CMS alternative options.
|
||||
- 19:16 | `Shumiland-site-dev`
|
||||
- **Asked:** Can you analyze a PDF document and create a website development plan with a CMS replacement for non-technical content managers?
|
||||
- **Done:** Reviewed project structure and pushed 113 files; discussed security best practices for environment variables and GitHub Actions secrets configuration.
|
||||
- 19:17 | `Shumiland-site-dev`
|
||||
- **Asked:** Create a development plan for a website based on a provided PDF document, replacing TinaCMS with a more user-friendly CMS for non-technical marketers.
|
||||
- **Done:** Analyzed project structure and identified that CI/CD pipeline requires secrets configuration in Gitea (VPS_HOST, VPS_USER, VPS_SSH_KEY) before scaffold can be built.
|
||||
- 19:17 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested analysis of a PDF document and creation of a website development plan with CMS replacement options suitable for non-technical users.
|
||||
- **Done:** Completed agent review found project contains only Claude Flow tooling; identified CI/CD configuration issues requiring Gitea runner setup and VPS secrets configuration.
|
||||
- 19:20 | `Shumiland-site-dev`
|
||||
- **Asked:** Should Ruflo be used exclusively and can you analyze the Shumiland contract PDF to create a website development plan with a TinaCMS replacement for non-technical content management?
|
||||
- **Done:** Reviewed project requirements and discussed CMS replacement options for easy content management by non-technical users, with design to be provided via Figma.
|
||||
- 19:22 | `Shumiland-site-dev`
|
||||
- **Asked:** How should TinaCMS be replaced with a more user-friendly CMS for non-technical marketers to manage content, pages, and media?
|
||||
- **Done:** Analyzed the project document and identified that the scaffold needs to be built; provided instructions to commit environment files to the repository.
|
||||
- 19:22 | `Shumiland-site-dev`
|
||||
- **Asked:** Review PDF document and create a website development plan with CMS replacement strategy for non-technical content management.
|
||||
- **Done:** Analyzed requirements and identified scaffold setup blockers with environment configuration issues.
|
||||
- 19:24 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested analysis of a PDF document and a website development plan using Payload CMS instead of TinaCMS for non-technical client content management.
|
||||
- **Done:** Project scaffold was reviewed and `.env` configuration file was identified as incomplete with template values requiring real credentials to be filled in.
|
||||
- 19:26 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested analysis of a PDF contract and a website development plan with CMS replacement strategy for non-technical clients.
|
||||
- **Done:** Project scaffold reviewed; environment configuration (EZY_PARTNER_KEY and EZY_ACTIVITY) added to .env file and awaiting BINOTEL_HMAC_SECRET setup.
|
||||
- 19:27 | `Shumiland-site-dev`
|
||||
- **Asked:** Study the project document and create a website development plan with a CMS replacement for non-technical content managers.
|
||||
- **Done:** Analyzed project requirements and scaffolded initial setup with environment configuration scripts for development and production.
|
||||
- 19:27 | `Shumiland-site-dev`
|
||||
- **Asked:** Create environment setup scripts and plan website development with CMS replacement to enable non-technical content management.
|
||||
- **Done:** Generated environment configuration scripts for dev and production with automated secret generation via openssl and created initial project scaffold.
|
||||
- 19:28 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested website redesign plan analysis based on PDF document with CMS replacement requirements.
|
||||
- **Done:** Project scaffold reviewed and initial setup completed with environment configuration committed.
|
||||
- 19:30 | `Shumiland-site-dev`
|
||||
- **Asked:** Reviewed document and confirmed Payload CMS 3.0 will replace TinaCMS with user-friendly admin interface for marketers to manage content, pages, and media.
|
||||
- **Done:** Project scaffold verified with Next.js 15, Tailwind v4, Payload CMS 3.0, PostgreSQL, and dev tools (ESLint, Prettier, Husky, Vitest) all configured.
|
||||
- 20:17 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested a website development plan based on a PDF document, replacing TinaCMS with a user-friendly CMS for non-technical content managers.
|
||||
- **Done:** Analyzed the document requirements and confirmed the development environment is running on localhost:3005/admin with compiled scaffold ready for testing.
|
||||
- 20:21 | `Shumiland-site-dev`
|
||||
- **Asked:** Reviewed project scaffold and analyzed PDF document to plan Shumiland website development with CMS replacement requirements.
|
||||
- **Done:** Confirmed project structure exists with Docker setup, identified need for user-friendly headless CMS alternative to TinaCMS for non-technical content managers.
|
||||
- 20:24 | `Shumiland-site-dev`
|
||||
- **Asked:** Can you study the document and create a development plan for replacing TinaCMS with a user-friendly CMS for non-technical marketers?
|
||||
- **Done:** Analyzed the project structure, confirmed Postgres database connection, and Payload CMS admin panel is accessible at localhost:3005/admin for first admin user registration.
|
||||
- 20:24 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested analysis of a PDF document and a website development plan with discussion of replacing TinaCMS with a more user-friendly CMS for non-technical clients.
|
||||
- **Done:** Reviewed project scaffold and identified that database migrations haven't been run yet; confirmed Payload CMS configuration needs `push: true` for automatic schema creation in development.
|
||||
- 20:31 (6min) | `Shumiland-site-dev`
|
||||
- **Asked:** How do we fix the health check test that's failing with 503 instead of 200?
|
||||
- **Done:** Diagnosed that health.test.ts calls real handlers without mocks, unlike other tests that properly mock payload and reset modules.
|
||||
- 20:33 | `Shumiland-site-dev`
|
||||
- **Asked:** Load Playwright Expert skill and configure Figma MCP integration.
|
||||
- **Done:** Activated Playwright Expert, NextJS Developer, and React Expert skills; prepared Figma MCP configuration.
|
||||
- 20:35 | `Shumiland-site-dev`
|
||||
- **Asked:** Developer requested Playwright Expert skill activation and Figma MCP configuration with personal access token.
|
||||
- **Done:** Playwright Expert skill loaded alongside nextjs-developer and react-expert; Figma MCP setup instructions provided pending token submission.
|
||||
- 20:38 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Reviewed access control files and requested complete codebase context to provide comprehensive performance analysis with actionable suggestions.
|
||||
- 20:38 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Load Playwright Expert skill and configure Figma API token for integration.
|
||||
- **Done:** Playwright Expert skill loaded; Figma personal access token generated and added to Claude Code global config.
|
||||
- 20:39 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a comprehensive JSON security report identifying vulnerabilities by severity, risk score, and remediation recommendations.
|
||||
- 20:41 (2min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Reviewed access control files and identified need for full codebase exploration to provide actionable performance recommendations with code examples.
|
||||
- 20:43 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for security vulnerabilities including secrets, SQL injection, XSS, dependencies, and auth issues.
|
||||
- **Done:** Generated security vulnerability report with severity levels, risk score, and recommendations for identified issues.
|
||||
- 20:43 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage in the codebase and identify gaps with test skeletons.
|
||||
- **Done:** Identified untested functions, edge cases, and missing error handling tests across access control and integration points.
|
||||
- 20:44 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a JSON security vulnerability report identifying risks by severity level, risk score, and actionable recommendations.
|
||||
- 20:44 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Requested additional codebase context before providing actionable optimization suggestions.
|
||||
- 20:45 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a JSON security report identifying vulnerabilities by severity, risk score, and actionable recommendations.
|
||||
- 20:45 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance issues including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Identified performance optimization opportunities in access control and caching patterns with actionable suggestions.
|
||||
- 20:46 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and auth issues.
|
||||
- **Done:** Generated JSON security report with vulnerability findings, risk score, and recommendations for the provided codebase.
|
||||
- 20:49 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage gaps and add missing test blocks to existing test files, then run full test suite.
|
||||
- **Done:** Identified untested functions in access control modules and added missing test cases; verified full test suite passes.
|
||||
- 20:49 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyzed test coverage and identified gaps in access control, utility, and hook functions | Compiled comprehensive coverage analysis with test skeletons for untested functions including null/undefined handling, role validation, and integration scenarios | isAdmin.ts, isAdminOrEditor.ts, isAuthenticatedOrPublished.ts, binotel.ts, rateLimit.ts, ezy.ts, telegram.ts, utm.ts, slugify.ts
|
||||
- **Done:** —
|
||||
- 20:50 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance issues including N+1 queries, unnecessary re-renders, caching opportunities, memory leaks, and redundant computations.
|
||||
- **Done:** Identified O(n×m) lookup inefficiency in tariffs merge logic and provided optimized solutions using Map and caching strategies.
|
||||
- 20:51 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Asked to analyze codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and auth issues.
|
||||
- **Done:** Completed security audit identifying high-severity authorization bypass in webhook endpoint and other vulnerabilities with JSON report including risk score and recommendations.
|
||||
- 20:51 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a JSON security report identifying vulnerabilities by severity, file location, and provided risk score with recommendations.
|
||||
- 20:52 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Set up frontend testing and design implementation using Figma and Playwright.
|
||||
- **Done:** Initiated Phase D swarm pipeline with custom interfaces, skipping researcher phase to proceed directly with architect-coder-tester-reviewer workflow.
|
||||
- 20:52 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Identified performance issues in access control files and provided optimization recommendations for query patterns and caching strategies.
|
||||
- 20:53 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication/authorization issues.
|
||||
- **Done:** Generated a comprehensive JSON security report identifying high-severity authorization bypass, medium-severity hardcoded API keys, and low-severity issues with risk score and remediation recommendations.
|
||||
- 20:53 (<1min) — session ended | `Downloads`
|
||||
- 20:53 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze test coverage and identify gaps in access control functions and provide test skeletons.
|
||||
- **Done:** Examined access control files (isAdmin.ts, isAdminOrEditor.ts) and identified missing unit tests for role-based access checks and edge cases.
|
||||
- 20:54 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Generated a JSON security vulnerability report identifying high-severity SSRF risk in next.config.ts with recommendations.
|
||||
- 20:54 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Set up frontend testing and design implementation using Figma design specs with MCP Figma integration.
|
||||
- **Done:** Sent architecture specification to coder; initiated testing workflow chain through coder, tester, and reviewer.
|
||||
- 20:54 | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for security vulnerabilities including hardcoded secrets, SQL injection, XSS, insecure dependencies, and authentication issues.
|
||||
- **Done:** Completed security audit and generated JSON report with vulnerability findings, risk score, and recommendations.
|
||||
- 20:56 (1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze codebase for performance optimizations including N+1 queries, re-renders, caching, memory leaks, and redundant computations.
|
||||
- **Done:** Identified performance issues in access control files and provided optimization recommendations for query patterns, caching, and computation efficiency.
|
||||
- 20:57 (<1min) | `Shumiland-site-dev`
|
||||
- **Asked:** Analyze the codebase for security vulnerabilities and provide a JSON report with findings, risk scores, and recommendations.
|
||||
- **Done:** Conducted security analysis identifying critical and high-severity vulnerabilities including missing environment validation, hardcoded secrets, and authentication issues.
|
||||
- 21:05 | `Shumiland-site-dev`
|
||||
- **Asked:** Frontend testing and Figma design integration setup requested | Code testing completed and Figma design patterns documented for frontend implementation | Figma design file, test files, ruflo memory storage
|
||||
- **Done:** —
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
bookmark_id: "wn3cbq1j7uzfzzih8zroxk1j"
|
||||
url: |
|
||||
https://links.ai-impress.com/signin
|
||||
title: Karakeep
|
||||
date: 2026-05-09T14:37:40.000Z
|
||||
modified: 2026-05-09T14:38:56.000Z
|
||||
note:
|
||||
original_note:
|
||||
summary:
|
||||
|
||||
---
|
||||
|
||||
# Karakeep
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
|
||||
[Visit Link](https://links.ai-impress.com/signin)
|
||||
|
||||
[View in Hoarder](https://links.ai-impress.com/dashboard/preview/wn3cbq1j7uzfzzih8zroxk1j)
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
---
|
||||
title: "Apple Mail — 'Trust junk mail headers' Silent Auto-Deletion"
|
||||
aliases: [apple-mail-junk-headers, apple-mail-x-spam, apple-mail-auto-delete, trust-junk-headers]
|
||||
tags: [apple-mail, email, spam, rspamd, junk, macos]
|
||||
sources:
|
||||
- "daily/2026-05-08.md"
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# Apple Mail — "Trust junk mail headers" Silent Auto-Deletion
|
||||
|
||||
Apple Mail has a setting — **Mail → Settings → Junk Mail → "Trust junk mail headers in messages"** — that causes it to read `X-Spam-*` headers set by server-side spam filters (rspamd, SpamAssassin) and silently move or delete messages without showing them in the inbox. Combined with an IMAP agent that expunges deleted messages, this results in permanent email loss.
|
||||
|
||||
## Key Points
|
||||
|
||||
- When enabled, Apple Mail reads `X-Spam-Flag: YES` or similar headers and acts on them **before** displaying the message.
|
||||
- The message goes directly to Junk or Trash — never appearing in the inbox — making the problem invisible.
|
||||
- If the IMAP account also has a client or agent that expunges deleted/junk items, the message is permanently lost.
|
||||
- The setting is on by default in many macOS versions.
|
||||
- Disabling it does **not** recover already-deleted messages (see [[wiki/concepts/dovecot-expunge-irreversible]]).
|
||||
|
||||
## The Failure Chain
|
||||
|
||||
```
|
||||
rspamd scores message as spam
|
||||
→ sets X-Spam-Flag: YES header
|
||||
→ Apple Mail reads header (Trust junk mail headers = ON)
|
||||
→ Apple Mail moves message to Junk/Trash silently
|
||||
→ IMAP agent (e.g. bookkeeper-agent) runs doveadm expunge on Trash
|
||||
→ message permanently deleted
|
||||
```
|
||||
|
||||
Each step is individually "correct" — the catastrophic outcome requires all three.
|
||||
|
||||
## Fix
|
||||
|
||||
### Disable "Trust junk mail headers"
|
||||
|
||||
1. Open **Mail** → **Settings** (⌘,)
|
||||
2. Go to the **Junk Mail** tab
|
||||
3. Uncheck **"Trust junk mail headers in messages"**
|
||||
|
||||
Apple Mail will now use its own local Junk filter (or none), ignoring server-set headers.
|
||||
|
||||
### Add trusted senders to macOS Contacts
|
||||
|
||||
Apple Mail never marks messages from Contacts as junk:
|
||||
|
||||
1. Open **Contacts** → create a contact for the sender's email address
|
||||
2. In Mail Junk settings: ensure **"Sender of message is in my Contacts"** is checked under exceptions
|
||||
|
||||
### Audit IMAP agents
|
||||
|
||||
Any script or service that runs `doveadm expunge`, `IMAP EXPUNGE`, or moves Junk→Trash automatically should be reviewed and disabled if not explicitly needed.
|
||||
|
||||
## Diagnosing the Problem
|
||||
|
||||
If emails are missing:
|
||||
|
||||
```bash
|
||||
# Check rspamd scored them as spam
|
||||
docker logs mailcowdockerized-rspamd-mailcow-1 --since 24h | grep -i "sender@domain"
|
||||
|
||||
# Check if messages were expunged
|
||||
docker exec mailcowdockerized-dovecot-mailcow-1 \
|
||||
doveadm log search "expunge" | tail -50
|
||||
```
|
||||
|
||||
In Apple Mail: **View → Show All Headers** on a received message — look for `X-Spam-Flag` or `X-Spam-Score` headers to confirm rspamd is tagging them.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/rspamd-mailcow-whitelist]] — fix the root cause by whitelisting the sender domain in rspamd
|
||||
- [[wiki/concepts/dovecot-expunge-irreversible]] — why recovery is impossible once expunge runs
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-08.md]] — emails from axilaccountants.co.uk disappeared; root cause: rspamd tagged as spam → Apple Mail auto-deleted (trust junk headers ON) → bookkeeper-agent expunged from Trash; emails permanently lost
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
---
|
||||
title: "Docker Bridge Network (172.x.x.x) Bypasses LAN-Based App Whitelists"
|
||||
aliases: [docker-bridge-whitelist, docker-172-network, docker-container-lan-whitelist, dashbrr-qbittorrent-whitelist]
|
||||
tags: [docker, networking, whitelist, homelab, qbittorrent, media-stack]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Docker Bridge Network (172.x.x.x) Bypasses LAN-Based App Whitelists
|
||||
|
||||
When a Docker container communicates with another service, it uses the Docker bridge network IP (typically in the `172.16.0.0/12` range), not the host machine's LAN IP. If the target application has an IP whitelist that only covers the LAN subnet (e.g., `192.168.1.0/24`), Docker containers cannot connect — even when running on the same physical host.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Docker containers source traffic from 172.x.x.x** when communicating via the Docker bridge — not from the host's LAN IP
|
||||
- **LAN-only whitelists (192.168.1.0/24) don't cover Docker containers** — containers are on a separate virtual network
|
||||
- **Fix:** Add `172.16.0.0/12` (or the specific Docker bridge subnet) to the target app's whitelist
|
||||
- **Affected services:** qBittorrent IP filter, any app with IP-based access control, Grafana auth proxy
|
||||
- This affects monitoring and management tools (Dashbrr, Beszel, Portainer) that connect to media stack applications
|
||||
|
||||
## Details
|
||||
|
||||
### The Problem
|
||||
|
||||
```
|
||||
Dashbrr container (172.17.0.5) → qBittorrent (192.168.1.230:8080)
|
||||
qBittorrent whitelist: 192.168.1.0/24
|
||||
→ 172.17.0.5 is not in 192.168.1.0/24
|
||||
→ qBittorrent returns 403 Forbidden
|
||||
```
|
||||
|
||||
Dashbrr logs show repeated connection failures despite qBittorrent being accessible from the browser.
|
||||
|
||||
### Docker Bridge IP Ranges
|
||||
|
||||
Docker uses RFC-1918 private ranges for bridge networks:
|
||||
|
||||
| Network | Range | Docker usage |
|
||||
|---------|-------|-------------|
|
||||
| `172.16.0.0/12` | 172.16.0.0 – 172.31.255.255 | Default bridge driver range |
|
||||
| `172.17.0.0/16` | First bridge network (`docker0`) | Default network |
|
||||
| Custom networks | Configurable | `docker network create --subnet` |
|
||||
|
||||
The full `172.16.0.0/12` range covers all default Docker bridge networks, making it the safe choice for whitelists.
|
||||
|
||||
### Finding the Actual Docker Bridge IP
|
||||
|
||||
```bash
|
||||
# Check what network a container uses
|
||||
docker inspect <container_name> | grep -A 5 '"Networks"'
|
||||
|
||||
# Find the gateway (Docker bridge) IP
|
||||
docker network inspect bridge | grep Gateway
|
||||
# "Gateway": "172.17.0.1"
|
||||
|
||||
# Check container's IP
|
||||
docker inspect dashbrr | grep IPAddress
|
||||
# "IPAddress": "172.17.0.5"
|
||||
```
|
||||
|
||||
### Fix: Add Docker Bridge to qBittorrent Whitelist
|
||||
|
||||
qBittorrent → Settings → Web UI → IP filter (or Bypass authentication for clients on localhost):
|
||||
|
||||
```
|
||||
Bypass authentication for clients on:
|
||||
192.168.1.0/24 ← existing LAN
|
||||
172.16.0.0/12 ← ADD: covers all Docker bridge networks
|
||||
127.0.0.1 ← loopback
|
||||
```
|
||||
|
||||
Or in qBittorrent's config file (`qBittorrent.conf`):
|
||||
```ini
|
||||
[Preferences]
|
||||
WebUI\AuthSubnetWhitelistEnabled=true
|
||||
WebUI\AuthSubnetWhitelist=192.168.1.0/24, 172.16.0.0/12
|
||||
```
|
||||
|
||||
### When This Applies
|
||||
|
||||
Any app with an IP-based access filter that is accessed from a Docker container:
|
||||
- qBittorrent (Dashbrr monitoring)
|
||||
- Prometheus scrape targets with firewall rules
|
||||
- Any service with `allow from 192.168.1.0/24` style rules
|
||||
|
||||
**Does NOT apply** when containers are on `network_mode: host` — host networking bypasses the bridge and uses the physical LAN IP.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/docker-lxc-dns-configuration]] — another Docker networking difference: containers inherit router DNS, not AdGuard
|
||||
- [[wiki/connections/docker-dns-adguard-split-horizon]] — related Docker networking isolation pattern
|
||||
- [[wiki/homelab/_index]] — homelab media stack context
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — Dashbrr couldn't connect to qBittorrent API; root cause: Dashbrr container on Docker bridge (172.x.x.x), qBit whitelist only had 192.168.1.0/24; fixed by adding 172.16.0.0/12 to qBit whitelist
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
---
|
||||
title: "Docker Bridge Network Bypasses LAN-Based Whitelists"
|
||||
aliases: [docker-bridge-network-whitelist, docker-172-subnet, docker-lan-whitelist]
|
||||
tags: [docker, networking, whitelist, qbittorrent, homelab, subnets]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Docker Bridge Network Bypasses LAN-Based Whitelists
|
||||
|
||||
## The Problem
|
||||
|
||||
Docker containers on the default bridge network are assigned IPs in the `172.16.0.0/12` range (e.g., `172.17.0.2`), **not** your LAN range (e.g., `192.168.1.x`). Services that implement IP-based auth bypass or whitelists using a LAN CIDR will not recognize Docker containers as trusted.
|
||||
|
||||
**Common scenario:** qBittorrent WebUI has `AuthSubnetWhitelist` set to `192.168.1.0/24` to allow LAN access without password. A Docker container (e.g., monitoring agent, Glance dashboard, Homarr) trying to access the qBittorrent API from the same host gets an auth failure because its `172.17.0.x` IP is not in the `192.168.1.0/24` whitelist.
|
||||
|
||||
## Fix: Add Docker Subnet to Whitelist
|
||||
|
||||
Add `172.16.0.0/12` to any service's IP whitelist to cover all Docker bridge addresses:
|
||||
|
||||
```ini
|
||||
# qBittorrent.conf
|
||||
[Preferences]
|
||||
WebUI\AuthSubnetWhitelist=192.168.1.0/24, 172.16.0.0/12
|
||||
WebUI\AuthSubnetWhitelistEnabled=true
|
||||
```
|
||||
|
||||
## Alternative: Use Host Networking
|
||||
|
||||
If the container doesn't need network isolation, `network_mode: "host"` avoids Docker NAT entirely — the container uses the host's `192.168.x.x` IP directly:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
my-service:
|
||||
network_mode: "host"
|
||||
```
|
||||
|
||||
## Docker Bridge IP Ranges
|
||||
|
||||
| Range | Notes |
|
||||
|-------|-------|
|
||||
| `172.17.0.0/16` | Default `bridge` network |
|
||||
| `172.18.0.0/16` | First custom network |
|
||||
| `172.16.0.0/12` | All possible Docker bridge addresses (safe to whitelist) |
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/qbittorrent-slow-speed-checklist]] — qBittorrent full checklist including WebUI auth config
|
||||
- [[wiki/concepts/docker-lxc-dns-configuration]] — Docker containers also need explicit DNS config in LXC
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — Docker container could not access qBittorrent WebUI; fix was adding `172.16.0.0/12` to `AuthSubnetWhitelist` alongside the existing `192.168.1.0/24` entry
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
---
|
||||
title: "Docker LXC GPU Device Node Mismatch — renderD128 vs renderD129"
|
||||
aliases: [docker-gpu-device-node, lxc-gpu-passthrough-mismatch, renderd-mismatch]
|
||||
tags: [docker, lxc, proxmox, gpu, jellyfin, homelab, hardware, debugging]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Docker LXC GPU Device Node Mismatch — renderD128 vs renderD129
|
||||
|
||||
When a Docker Compose volume bind-mounts a GPU device node (e.g., `/dev/dri/renderD129`), if that device file does not exist on the host, Docker creates an empty regular file at that path instead of the expected character device. The container starts but immediately exits with code 255 — silently, with no useful error message — because the "device" it receives is an empty file, not a real GPU.
|
||||
|
||||
## Key Points
|
||||
|
||||
- Docker bind-mounts a non-existent device path → Docker creates an **empty file**, not a char device
|
||||
- Container exits with code 255 immediately on start — no diagnostic message in logs
|
||||
- GPU device node numbers depend on the host hardware: `renderD128` is the first render device, `renderD129` would be a second GPU that may not exist
|
||||
- Always verify available device nodes with `ls -la /dev/dri/` before configuring bind mounts
|
||||
- For Jellyfin in Docker inside LXC: the correct device is almost always `/dev/dri/renderD128` unless the host has multiple GPUs
|
||||
|
||||
## Details
|
||||
|
||||
### How the Bug Manifests
|
||||
|
||||
A typical Jellyfin `docker-compose.yml` includes GPU access for hardware transcoding:
|
||||
|
||||
```yaml
|
||||
devices:
|
||||
- /dev/dri/renderD129:/dev/dri/renderD129
|
||||
```
|
||||
|
||||
If the Proxmox host only has one GPU (most homelab builds), only `renderD128` exists. When Docker starts the container, it tries to bind-mount `renderD129` — which doesn't exist on the host. Docker creates an empty regular file at `/dev/dri/renderD129` and passes it to the container. Jellyfin attempts to open the device, gets an empty file instead of a char device with the right major:minor numbers, and the VA-API or DRI initialization fails. The container exits with code 255.
|
||||
|
||||
**`docker logs jellyfin`** shows nothing useful — the process exits before writing any output.
|
||||
|
||||
### Diagnosing the Problem
|
||||
|
||||
```bash
|
||||
# On the Proxmox host (or LXC host with GPU passthrough) — check available DRI devices
|
||||
ls -la /dev/dri/
|
||||
# Output:
|
||||
# crw-rw---- 1 root video 226, 0 May 3 14:00 card0
|
||||
# crw-rw---- 1 root render 226, 128 May 3 14:00 renderD128
|
||||
# ← renderD129 does NOT appear
|
||||
|
||||
# Check what Docker actually passed to the container
|
||||
docker inspect jellyfin | grep -A 5 "Devices"
|
||||
# Look for empty file instead of char device
|
||||
```
|
||||
|
||||
### The Fix
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml — use renderD128, not renderD129
|
||||
devices:
|
||||
- /dev/dri/renderD128:/dev/dri/renderD128
|
||||
```
|
||||
|
||||
Also confirm in LXC config that the GPU is properly passed through to the LXC container (not just to Docker inside it):
|
||||
|
||||
```bash
|
||||
# /etc/pve/lxc/<CTID>.conf — required for GPU passthrough to LXC
|
||||
lxc.cgroup2.devices.allow: c 226:* rwm
|
||||
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
|
||||
```
|
||||
|
||||
### renderD128 vs renderD129 Explained
|
||||
|
||||
GPU device nodes follow a kernel naming convention:
|
||||
- `card0`, `card1` — primary display interfaces
|
||||
- `renderD128` — first render device (DRM render node, offset 128 from base)
|
||||
- `renderD129` — second render device (would require a second GPU or specific multi-head config)
|
||||
|
||||
For a typical homelab server with a single iGPU (Intel HD/UHD) or discrete GPU, only `renderD128` exists. The `129` variant appears only with multiple GPUs or in specific VGPU setups.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/proxmox-lxc-autostart]] — LXC container configuration and device passthrough
|
||||
- [[wiki/homelab/_index]] — homelab GPU and LXC infrastructure context
|
||||
- [[wiki/concepts/docker-compose-restart-no-code-reload]] — other Docker silent failure patterns where the container appears fine but behaves wrong
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — CT111 Jellyfin down; exit code 255; root cause was `/dev/dri/renderD129` not existing on host, Docker created empty file instead of char device; fixed by changing to `renderD128`
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
---
|
||||
title: "Documenso vs LibreSign — Electronic Signature Legal Validity"
|
||||
aliases: [documenso-libresign, esignature-comparison, aes-ses-esignature, self-hosted-esignature]
|
||||
tags: [documenso, libresign, esignature, legal, homelab, selfhosted, nextcloud]
|
||||
sources:
|
||||
- "daily/2026-05-01.md"
|
||||
created: 2026-05-01
|
||||
updated: 2026-05-01
|
||||
---
|
||||
|
||||
# Documenso vs LibreSign — Electronic Signature Legal Validity
|
||||
|
||||
Documenso and LibreSign are both open-source self-hosted electronic signature solutions, but they serve fundamentally different use cases. Documenso provides AES (Advanced Electronic Signature) via email authentication with a full audit trail — legally valid for external client contracts in the UK and EU. LibreSign provides SES (Simple Electronic Signature) using self-signed PKI certificates via Nextcloud accounts — only practical for internal documents where all signatories already have Nextcloud accounts.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Documenso = AES** — email link authentication + IP/timestamp/QR audit trail = legally valid Advanced Electronic Signature for UK/EU client contracts
|
||||
- **LibreSign = SES** — self-signed certificate via Nextcloud account = Simple Electronic Signature, weaker than AES and requires all parties to have Nextcloud accounts
|
||||
- **For external client contracts**, Documenso is the correct tool; clients sign via browser link with no account required
|
||||
- **For internal documents** (policies, staff sign-offs) where all parties are already in Nextcloud, LibreSign works adequately
|
||||
- **Documenso's signing certificate** includes: signatory name + email, timestamp (sent/viewed/signed), IP address + device, unique signature ID (hash), and a QR code for independent verification
|
||||
|
||||
## Details
|
||||
|
||||
### Electronic Signature Tiers (EU eIDAS / UK)
|
||||
|
||||
| Tier | Abbr | Mechanism | Legal weight |
|
||||
|------|------|-----------|-------------|
|
||||
| Simple Electronic Signature | SES | Any electronic signature (typed name, click) | Lowest — can be challenged |
|
||||
| Advanced Electronic Signature | AES | Uniquely linked to signatory, capable of detecting changes | High — widely accepted for business contracts |
|
||||
| Qualified Electronic Signature | QES | Government-issued PKI certificate | Highest — legally equivalent to handwritten |
|
||||
|
||||
Documenso with email authentication meets AES requirements: the email link is uniquely linked to the signatory (they must access their email), and the audit trail detects any post-signing changes.
|
||||
|
||||
### Documenso Signing Certificate
|
||||
|
||||
After each signing, Documenso generates a Signing Certificate page that contains:
|
||||
|
||||
```
|
||||
Signatory: Name + email address
|
||||
Sent: 2024-03-15 09:00:00 UTC
|
||||
Viewed: 2024-03-15 09:05:00 UTC
|
||||
Signed: 2024-03-15 09:07:00 UTC
|
||||
IP Address: 203.0.113.42
|
||||
Device: Chrome / macOS
|
||||
Signature ID: sha256:a3b8...
|
||||
QR Code: Links to Documenso verification endpoint
|
||||
Authentication Level: Email
|
||||
```
|
||||
|
||||
This audit trail is what elevates the signature from SES to AES — independent verification is possible via the QR code without any Documenso account.
|
||||
|
||||
### LibreSign Limitations for External Use
|
||||
|
||||
LibreSign integrates with Nextcloud and uses Nextcloud accounts for authentication. Signatories must:
|
||||
|
||||
1. Have a Nextcloud account on the same instance
|
||||
2. Log in to Nextcloud to view and sign documents
|
||||
3. Use a PKI certificate (which is self-signed by the Nextcloud instance)
|
||||
|
||||
These requirements make LibreSign impractical for external client contracts: clients won't create Nextcloud accounts just to sign an agreement. The self-signed PKI certificate also has lower external trust than email-authenticated signing.
|
||||
|
||||
### Decision Matrix
|
||||
|
||||
| Scenario | Tool | Reason |
|
||||
|----------|------|--------|
|
||||
| Client contract (UK/EU) | Documenso | AES via email auth; client needs no account |
|
||||
| Vendor NDA with external party | Documenso | Same — external party can't use Nextcloud |
|
||||
| Internal policy sign-off (staff only) | LibreSign | All staff have Nextcloud accounts |
|
||||
| Intra-team approval | LibreSign | Internal workflow; Nextcloud integration convenient |
|
||||
| Legally sensitive high-value contract | DocuSign / Adobe Sign | QES via government-issued certificate |
|
||||
|
||||
### Self-Hosted Setup Comparison
|
||||
|
||||
| Feature | Documenso | LibreSign |
|
||||
|---------|-----------|-----------|
|
||||
| Auth method | Email link | Nextcloud account |
|
||||
| Audit trail | Full (IP, device, timestamps, QR) | Basic |
|
||||
| External signatories | Yes (no account needed) | No (Nextcloud account required) |
|
||||
| Legal tier | AES | SES |
|
||||
| UK/EU client contracts | ✅ Valid | ❌ Impractical |
|
||||
| Internal documents | ✅ Valid | ✅ Valid |
|
||||
| Self-hosting complexity | Docker-based, standalone | Nextcloud app |
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/authentik-homelab-tradeoffs]] — Nextcloud/Authentik integration context for self-hosted services
|
||||
- [[wiki/homelab/_index]] — homelab service stack where both Documenso and LibreSign would run
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-01.md]] — Documenso Signing Certificate reviewed (AES with email auth); LibreSign identified as SES suitable only for internal Nextcloud users; decision: Documenso for client contracts, LibreSign for internal documents only
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
---
|
||||
title: "Dovecot — Expunge Is Permanent; Recovery Requires External Backup"
|
||||
aliases: [dovecot-expunge, imap-expunge-permanent, dovecot-delete-recovery, mailcow-backup]
|
||||
tags: [dovecot, email, imap, backup, mailcow, selfhosted, data-loss]
|
||||
sources:
|
||||
- "daily/2026-05-08.md"
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# Dovecot — Expunge Is Permanent; Recovery Requires External Backup
|
||||
|
||||
`doveadm expunge` and client-triggered IMAP EXPUNGE commands permanently remove messages from disk. Dovecot has no server-side recycle bin or soft-delete. The only recovery path is an external backup (Scaleway snapshots, Backrest, or similar). A Mailcow installation without a backup strategy has zero recovery options after accidental expunge.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **IMAP DELETE** marks a message with the `\Deleted` flag — message still exists on disk.
|
||||
- **IMAP EXPUNGE** (or `doveadm expunge`) removes the flagged messages from disk permanently.
|
||||
- Dovecot does not have a server-side trash/recycle bin that persists past EXPUNGE.
|
||||
- There is no `doveadm undelete` — once expunged, the message is gone from the Maildir.
|
||||
- Recovery is only possible from:
|
||||
1. External filesystem snapshots (Scaleway, Proxmox, ZFS)
|
||||
2. Backup tools that copy Maildir (Backrest + restic, rsync off-site)
|
||||
3. The sender re-sending the email
|
||||
|
||||
## What Triggers Expunge
|
||||
|
||||
| Trigger | Who runs it |
|
||||
|---------|------------|
|
||||
| `doveadm expunge -u user mailbox Trash 1:*` | Admin / automation script |
|
||||
| IMAP client "Empty Trash" action | Mail app |
|
||||
| IMAP agent (`imaplib`, `imapclient`) calling `expunge()` | Custom Python/JS script |
|
||||
| Apple Mail "Erase Deleted Messages" | macOS Mail |
|
||||
|
||||
Any IMAP client that calls `EXPUNGE` after `STORE \Deleted` produces the same result.
|
||||
|
||||
## Setting Up Backrest for Mailcow
|
||||
|
||||
Backrest (web UI for restic) is the recommended backup solution for self-hosted Mailcow:
|
||||
|
||||
```yaml
|
||||
# docker-compose addition for Mailcow
|
||||
backrest:
|
||||
image: garethgeorge/backrest:latest
|
||||
volumes:
|
||||
- /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1:/data/vmail:ro
|
||||
- backrest-config:/config
|
||||
- backrest-cache:/cache
|
||||
ports:
|
||||
- "9898:9898"
|
||||
```
|
||||
|
||||
Configure a repository pointing to Scaleway Object Storage (or any S3-compatible) and schedule hourly snapshots of the vmail volume.
|
||||
|
||||
## Recovery from Scaleway Snapshot
|
||||
|
||||
If a Proxmox VM-level or Scaleway block volume snapshot exists:
|
||||
|
||||
1. Restore the snapshot to a temporary volume
|
||||
2. Mount the volume on a rescue instance
|
||||
3. Locate the Maildir at `/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/`
|
||||
4. Copy the missing EML files to the live server's Maildir
|
||||
5. Run `doveadm index` to make Dovecot aware of restored messages (see [[wiki/concepts/mailcow-maildir-import]])
|
||||
|
||||
## Checking if Messages Were Expunged
|
||||
|
||||
```bash
|
||||
# Check Dovecot logs for expunge events
|
||||
docker exec mailcowdockerized-dovecot-mailcow-1 \
|
||||
doveadm log errors | grep -i expunge
|
||||
|
||||
# Or search recent mail log entries
|
||||
docker logs mailcowdockerized-dovecot-mailcow-1 --since 24h | grep expunge
|
||||
```
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/apple-mail-trust-junk-headers]] — how Apple Mail + rspamd headers + an IMAP agent chains into accidental expunge
|
||||
- [[wiki/concepts/rspamd-mailcow-whitelist]] — prevent the spam mis-scoring that starts the chain
|
||||
- [[wiki/concepts/mailcow-maildir-import]] — how to restore Maildir files and re-index after recovery
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-08.md]] — bookkeeper-agent (IMAP Python script) expunged Trash folder after Apple Mail moved rspamd-tagged emails there; no Scaleway snapshot existed at the time; emails from axilaccountants.co.uk permanently lost; agent was removed post-incident
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
---
|
||||
title: "Glance — Go-Binary Homelab Dashboard"
|
||||
aliases: [glance-homelab, glance-dashboard, glanceapp]
|
||||
tags: [homelab, dashboard, glance, docker, self-hosted]
|
||||
sources:
|
||||
- "daily/2026-04-29.md"
|
||||
created: 2026-04-29
|
||||
updated: 2026-04-29
|
||||
---
|
||||
|
||||
# Glance — Go-Binary Homelab Dashboard
|
||||
|
||||
Glance is a lightweight, single-binary homelab dashboard written in Go. It replaces heavier alternatives like Homarr and Homepage with a ~50 MB RAM footprint. Configuration is a single `glance.yml` file; there is no database. The UI is tab-based, each tab containing a column layout of widgets (bookmarks, RSS feeds, iframes, monitoring, etc.).
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Minimal resource usage** — ~50 MB RAM in practice; single Go binary with no database
|
||||
- **`$include` directive merges YAML at the same mapping level** — cannot be used to separate page definitions into separate files; all pages must be inlined directly in `glance.yml`
|
||||
- **Monitor widgets must use internal IPs** (192.168.1.x), not Cloudflare-proxied public domains — Cloudflare overhead causes widget timeouts
|
||||
- **qBittorrent widgets require "bypass auth for subnet 192.168.1.0/24"** — otherwise widgets receive 401 and show no data
|
||||
- **Password minimum is 6 characters** — "admin" is rejected; use "admin1" or longer
|
||||
|
||||
## Details
|
||||
|
||||
### Setup and Configuration
|
||||
|
||||
Glance runs as a Docker container with a single bind-mounted `glance.yml`. The recommended 5-tab layout covers: Home / Services / Energy / Media / News.
|
||||
|
||||
Password management uses a hash stored in the environment:
|
||||
|
||||
```bash
|
||||
# Generate a bcrypt hash for the admin password
|
||||
docker run --rm glanceapp/glance password:hash <new_password>
|
||||
# Copy the output hash into ADMIN_PASSWORD_HASH in your .env file
|
||||
```
|
||||
|
||||
The `$include` directive is commonly misunderstood — it performs a YAML merge at the same mapping level, not a file include at arbitrary depth. This means pages cannot be split into separate files and included under `pages:`; the full page tree must live in `glance.yml` directly.
|
||||
|
||||
### Widget Gotchas
|
||||
|
||||
**Monitor widgets and Cloudflare:** Glance's monitor widgets make HTTP HEAD requests to check uptime. When services are exposed via Cloudflare proxy (orange cloud), the extra DNS resolution and TLS handshake overhead regularly causes widget timeouts — even when the service itself is healthy. Fix: use the direct internal IP (`http://192.168.1.x:PORT`) in monitor widget URLs.
|
||||
|
||||
**AdGuard stats widget:** The `/control/stats` endpoint requires Basic Auth credentials. The Glance AdGuard widget has limited auth support; if it returns errors, skip it and use a direct iframe or bookmark instead.
|
||||
|
||||
**Energy tab:** An iframe embed of a Power Cost dashboard combined with Prometheus RAPL metrics works well. Key Prometheus queries:
|
||||
- CPU power: `rate(node_rapl_package_joules_total[1m])` (returns watts directly — no multiplication needed; see [[wiki/concepts/prometheus-joules-watts-gotcha]])
|
||||
- CPU temperature: `node_hwmon_temp_celsius`
|
||||
|
||||
### Migration from Homarr
|
||||
|
||||
Homarr installation is retained at `/opt/services/homarr/` for rollback. Glance does not import Homarr configuration — widgets and bookmarks must be recreated manually in `glance.yml`. The migration is straightforward because Glance's YAML config is simpler than Homarr's SQLite-backed UI.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/homarr-proxmox-integration]] — previous dashboard; kept for rollback; Proxmox cert trust pattern
|
||||
- [[wiki/concepts/prometheus-joules-watts-gotcha]] — RAPL rate() already returns watts; don't multiply by 1000
|
||||
- [[wiki/concepts/docker-lxc-dns-configuration]] — Docker containers need explicit DNS for internal domains
|
||||
- [[wiki/homelab/_index]] — homelab media and infrastructure stack context
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-29.md]] — Glance deployed as Homarr replacement; 5-tab layout; `$include` gotcha; monitor widget internal IP requirement; qBittorrent 401 fix; bcrypt password hash workflow; Energy tab iframe + Prometheus RAPL metrics
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
---
|
||||
title: "Glance Dashboard — Config Patterns and Homelab Setup"
|
||||
aliases: [glance-dashboard, glance-yaml-config, glance-homarr-replacement]
|
||||
tags: [glance, dashboard, homelab, monitoring, yaml, self-hosted]
|
||||
sources:
|
||||
- "daily/2026-04-29.md"
|
||||
created: 2026-04-29
|
||||
updated: 2026-04-29
|
||||
---
|
||||
|
||||
# Glance Dashboard — Config Patterns and Homelab Setup
|
||||
|
||||
Glance is a Go-binary self-hosted dashboard with rich widget support (RSS, Reddit, YouTube, monitors, weather). It was chosen as a replacement for Homarr due to lower RAM overhead, no Node.js runtime dependency, and richer feed-style widgets. Two non-obvious configuration constraints caught during setup: the `$include` directive cannot be used to split pages across files, and monitor widgets must use internal IPs to avoid Cloudflare-induced timeouts.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **`$include` merges at the same YAML mapping level** — it cannot be used to separate `pages:` entries into individual files; all pages must be inlined directly in `glance.yml`
|
||||
- **Monitor widgets must use internal IPs** (`192.168.x.x`), not public Cloudflare-proxied domains — Cloudflare proxy overhead causes timeouts that look like host-down false positives
|
||||
- **Minimum 6-character password** — `admin` (5 chars) is rejected at first login; use `admin1` or longer
|
||||
- **Homarr replacement rationale:** Go single binary, lower RAM overhead than Homarr's Node.js stack, native RSS/Reddit/YouTube/Hacker News widgets, no Docker socket required for basic use
|
||||
- **Prometheus RAPL power metrics** can be embedded via iframe using `rate(node_rapl_package_joules_total[1m])` for CPU package power draw and `node_hwmon_temp_celsius` for temperature
|
||||
|
||||
## Details
|
||||
|
||||
### `$include` Directive Limitation
|
||||
|
||||
Glance supports a `$include: path/to/file.yml` directive to merge external YAML into the config. The merge happens **at the same mapping level** as the `$include` line — it does not wrap the included content in a sub-key.
|
||||
|
||||
This means:
|
||||
|
||||
```yaml
|
||||
# THIS DOES NOT WORK — cannot split pages this way
|
||||
pages:
|
||||
$include: pages/home.yml
|
||||
$include: pages/media.yml
|
||||
```
|
||||
|
||||
The `$include` is not a list item; it replaces the content at that level. Attempting to use it to include separate page definitions results in only the last include being loaded, or a YAML parse error.
|
||||
|
||||
**Correct approach:** inline all pages directly in `glance.yml`:
|
||||
|
||||
```yaml
|
||||
pages:
|
||||
- name: Home
|
||||
columns:
|
||||
- ...
|
||||
- name: Media
|
||||
columns:
|
||||
- ...
|
||||
```
|
||||
|
||||
If the file becomes large, manage it with editor folding rather than file splitting.
|
||||
|
||||
### Monitor Widget — Use Internal IPs
|
||||
|
||||
Glance's `monitor` widget makes HTTP HEAD/GET requests from the server to check uptime. When services are behind Cloudflare proxy, the check goes: Glance server → public DNS → Cloudflare edge → origin. Cloudflare's proxy introduces 200–500 ms overhead and occasionally rate-limits or challenges automated requests.
|
||||
|
||||
**Symptom:** All monitors show timeout/down even when services are clearly reachable in a browser.
|
||||
|
||||
**Fix:** Use the internal IP directly:
|
||||
|
||||
```yaml
|
||||
- type: monitor
|
||||
title: Prowlarr
|
||||
url: http://192.168.1.100:9696
|
||||
```
|
||||
|
||||
This bypasses Cloudflare entirely. AdGuard DNS rewrites are not needed for monitor widgets since they use IPs, not hostnames.
|
||||
|
||||
### NPM Password Reset (SQLite bcrypt Injection)
|
||||
|
||||
If the Nginx Proxy Manager admin password is lost, reset it directly in the SQLite database:
|
||||
|
||||
```bash
|
||||
# Backup first
|
||||
cp /opt/npm/data/database.sqlite /opt/npm/data/database.sqlite.bak.$(date +%Y%m%d)
|
||||
|
||||
# Install bcrypt tool if needed
|
||||
pip install bcrypt
|
||||
|
||||
# Generate hash
|
||||
python3 -c "import bcrypt; print(bcrypt.hashpw(b'admin', bcrypt.gensalt()).decode())"
|
||||
|
||||
# Inject into NPM DB
|
||||
sqlite3 /opt/npm/data/database.sqlite \
|
||||
"UPDATE user SET password = '<bcrypt_hash>' WHERE email = 'admin@ai-impress.com';"
|
||||
```
|
||||
|
||||
### Prometheus RAPL Power Metrics
|
||||
|
||||
Glance can embed Grafana panels via iframe. For CPU power draw and thermal monitoring:
|
||||
|
||||
- **CPU package power:** `rate(node_rapl_package_joules_total[1m])` — returns watts directly (joules/second); do NOT multiply by 1000 (see [[wiki/concepts/prometheus-joules-watts-gotcha]])
|
||||
- **CPU temperature:** `node_hwmon_temp_celsius{chip=~"coretemp.*", sensor="temp1"}`
|
||||
- **RAM power** is not exposed by RAPL on most consumer motherboards
|
||||
|
||||
Power Cost dashboard was also proxied via NPM: `https://power.ai-impress.com → 192.168.1.225:8091`
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/prometheus-joules-watts-gotcha]] — RAPL `rate(joules_total)` is already watts; multiplying by 1000 is a display bug
|
||||
- [[wiki/concepts/adguard-dns-rewrites-homelab]] — AdGuard wildcard DNS rewrites for internal services; not needed for Glance monitor IPs but relevant for browser access
|
||||
- [[wiki/homelab/_index]] — homelab infrastructure overview; Glance is the dashboard layer
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-29.md]] — Glance install session: `$include` page split failure, monitor timeout root cause (Cloudflare IPs), NPM password reset via SQLite bcrypt, RAPL metrics integration, location set to Henley-on-Thames UK
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
---
|
||||
title: "GPU Device Node Mismatch in LXC Docker — Exit Code 255"
|
||||
aliases: [gpu-lxc-docker, renderD-mismatch, gpu-bind-mount-lxc, jellyfin-gpu-lxc]
|
||||
tags: [gpu, lxc, proxmox, docker, jellyfin, passthrough, debugging]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# GPU Device Node Mismatch in LXC Docker — Exit Code 255
|
||||
|
||||
When passing a GPU device node (e.g., `/dev/dri/renderD128`) into a Docker container inside a Proxmox LXC, the device node number in the Docker compose bind mount must exactly match what the host exposes. If the config references `/dev/dri/renderD129` but the host only has `/dev/dri/renderD128`, Docker creates an empty regular file at the mount point instead of a character device — and the container exits with code 255 silently, with no meaningful error message.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Device node numbers are not arbitrary** — `/dev/dri/renderD128` and `/dev/dri/renderD129` are different device nodes; Docker does not auto-fallback to the available one
|
||||
- **Bind mount creates empty file** when the source path doesn't exist as a character device — the container sees a regular file where a GPU device is expected
|
||||
- **Exit code 255** with no error message is the symptom — check if the GPU device path in compose matches the actual host device
|
||||
- **Verify with `ls -la /dev/dri/`** on the host (Proxmox LXC or Proxmox host, depending on your passthrough setup) before writing the compose file
|
||||
- LXC containers need GPU device access explicitly enabled in the container config (`lxc.cgroup2.devices.allow` and device mount) before Docker inside can use it
|
||||
|
||||
## Details
|
||||
|
||||
### How to Check Available Device Nodes
|
||||
|
||||
```bash
|
||||
# Check GPU device nodes available in the LXC container
|
||||
ls -la /dev/dri/
|
||||
# crw-rw---- 1 root video 226, 0 May 3 17:12 card0
|
||||
# crw-rw---- 1 root render 226, 128 May 3 17:12 renderD128
|
||||
# ← renderD128 exists, renderD129 does NOT exist
|
||||
```
|
||||
|
||||
### The Failing Docker Compose
|
||||
|
||||
```yaml
|
||||
# ❌ WRONG — renderD129 doesn't exist; creates empty file
|
||||
services:
|
||||
jellyfin:
|
||||
devices:
|
||||
- /dev/dri/renderD129:/dev/dri/renderD129
|
||||
```
|
||||
|
||||
### The Correct Config
|
||||
|
||||
```yaml
|
||||
# ✅ CORRECT — matches the actual device node
|
||||
services:
|
||||
jellyfin:
|
||||
group_add:
|
||||
- "render"
|
||||
- "video"
|
||||
devices:
|
||||
- /dev/dri/renderD128:/dev/dri/renderD128
|
||||
- /dev/dri/card0:/dev/dri/card0
|
||||
```
|
||||
|
||||
### Diagnosing Exit Code 255
|
||||
|
||||
```bash
|
||||
# Check container logs
|
||||
docker compose logs jellyfin
|
||||
|
||||
# Check if the device is actually a character device inside the container
|
||||
docker compose exec jellyfin ls -la /dev/dri/
|
||||
# If you see: -rw-r--r-- (regular file) instead of crw (char device) → bind mount failed
|
||||
|
||||
# Check what device nodes the LXC actually has
|
||||
ls -la /dev/dri/
|
||||
|
||||
# Verify the LXC has GPU passthrough configured in Proxmox
|
||||
# (on Proxmox host)
|
||||
pct config <CTID> | grep dev
|
||||
```
|
||||
|
||||
### LXC Configuration for GPU Passthrough
|
||||
|
||||
For the LXC to expose GPU devices to Docker, the container config needs:
|
||||
|
||||
```
|
||||
# /etc/pve/lxc/<CTID>.conf
|
||||
lxc.cgroup2.devices.allow: c 226:0 rwm
|
||||
lxc.cgroup2.devices.allow: c 226:128 rwm
|
||||
lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
|
||||
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
|
||||
```
|
||||
|
||||
After editing, restart the container: `pct restart <CTID>`.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/proxmox-container-502-misdiagnosis]] — another case where diagnosing the wrong layer costs time
|
||||
- [[wiki/concepts/docker-compose-restart-no-code-reload]] — Docker container debugging patterns
|
||||
- [[wiki/homelab/_index]] — Proxmox and LXC infrastructure context
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — Jellyfin CT111 down with exit code 255; root cause was LXC config referencing `/dev/dri/renderD129` but host only has `/dev/dri/renderD128`; bind mount created empty file instead of char device; fixed by correcting device node number
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
---
|
||||
title: "Jellyfin ContainerBitrateExceedsLimit — Client-Side Setting, Not Server"
|
||||
aliases: [jellyfin-bitrate-limit, ContainerBitrateExceedsLimit, jellyfin-transcoding-client, jellyfin-4k-lag]
|
||||
tags: [jellyfin, streaming, 4k, bitrate, transcoding, homelab, media]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Jellyfin `ContainerBitrateExceedsLimit` — Client-Side Setting, Not Server
|
||||
|
||||
When Jellyfin shows `ContainerBitrateExceedsLimit` in logs and starts transcoding (or buffering heavily), the cause is a bitrate limit set in the **Jellyfin client app**, not on the Jellyfin server. For 4K HEVC or Dolby Vision content with high bitrates (20-30+ Mbps), the client's default quality setting may cap the bitrate below what the video requires, forcing server-side transcoding — which is CPU-intensive and introduces lag.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **`ContainerBitrateExceedsLimit` is a client-side limit** — the client told the server "max bitrate X Mbps"; content exceeds X → server transcodes
|
||||
- **Fix is in the client app**, not in Jellyfin server settings — go to the TV/phone/browser app's quality settings
|
||||
- **Setting to "Original"** (or max bitrate) tells the server to send the original stream without transcoding
|
||||
- **Direct play vs transcoding:** direct play = no server CPU, no quality loss; transcoding = server CPU overhead, quality may drop
|
||||
- Common triggers: 4K HEVC content (15-30+ Mbps), Dolby Vision streams, HDR10+ content
|
||||
|
||||
## Details
|
||||
|
||||
### The Log Signal
|
||||
|
||||
In Jellyfin server logs or the admin dashboard → Active Sessions:
|
||||
|
||||
```
|
||||
Reason: ContainerBitrateExceedsLimit
|
||||
Transcoding: Video codec: H264, Audio codec: AAC
|
||||
```
|
||||
|
||||
This indicates the client requested a maximum bitrate lower than the source file's bitrate.
|
||||
|
||||
### Fixing in the Jellyfin TV App
|
||||
|
||||
On Android TV / LG webOS / Samsung Tizen Jellyfin app:
|
||||
|
||||
1. Open **Settings** (gear icon in the app)
|
||||
2. Navigate to **Quality** or **Playback Quality**
|
||||
3. Find **Maximum bitrate** or **Video quality**
|
||||
4. Change from auto/numeric value → **Original** or **Maximum**
|
||||
5. Also check **Allow transcoding** → disable if you want to force direct play
|
||||
|
||||
### Fixing in the Jellyfin Web UI
|
||||
|
||||
For browser-based playback:
|
||||
|
||||
1. Click the user avatar → **Settings**
|
||||
2. Go to **Playback**
|
||||
3. Set **Internet streaming video quality** and **Home network video quality** to **Auto** or a high value (e.g., 200 Mbps)
|
||||
|
||||
### Why Transcoding Causes Lag
|
||||
|
||||
For 4K HEVC Dolby Vision content:
|
||||
- Original bitrate: 26 Mbps
|
||||
- Client limit set to: 10 Mbps
|
||||
- Server must decode 4K HEVC DV → re-encode to H264 at 10 Mbps in real time
|
||||
- On a CPU-only server (no GPU transcoding), this uses 100% CPU for 4K
|
||||
- Result: buffering, lag, playback stops
|
||||
|
||||
Direct play bypasses all of this — the server sends the original file bytes directly to the client.
|
||||
|
||||
### When to Keep Transcoding
|
||||
|
||||
Transcoding is appropriate when:
|
||||
- The client device doesn't support HEVC or Dolby Vision natively
|
||||
- The network connection is slow (transcoding to lower bitrate)
|
||||
- The file uses an unsupported audio codec
|
||||
|
||||
For modern smart TVs with HDR10/DV support on a local gigabit LAN, always prefer direct play.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/jellyfin-tmdb-thetvdb-plugin]] — other Jellyfin configuration and plugin patterns
|
||||
- [[wiki/concepts/faster-whisper-startup-memory]] — CPU-intensive operations on the same homelab server context
|
||||
- [[wiki/homelab/_index]] — homelab media stack context
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — Jellyfin transcoding 4K HEVC Dolby Vision (26 Mbps) causing lag on TV; logs showed `ContainerBitrateExceedsLimit`; fix was in Jellyfin TV app Settings → Quality → Max Bitrate → Original; this is a client-side limit, not server config
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
---
|
||||
title: "Jellyfin Library Path Mismatch — Radarr/Sonarr Root Folder vs Jellyfin Library Paths"
|
||||
aliases: [jellyfin-library-mismatch, radarr-root-folder-jellyfin, jellyfin-missing-movies, sonarr-jellyfin-path]
|
||||
tags: [jellyfin, radarr, sonarr, media-stack, library, path, homelab]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Jellyfin Library Path Mismatch — Radarr/Sonarr Root Folder vs Jellyfin Library Paths
|
||||
|
||||
When Radarr or Sonarr download content to a specific path and Jellyfin's library monitors a different path, downloaded media is invisible to Jellyfin — no error is shown, the library is simply missing those items. This is especially common when using multiple library categories (e.g., Movies vs Kids Movies) with different root folders.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Radarr root folder ≠ Jellyfin library path → media is invisible** — no error, just missing items
|
||||
- **Multiple Jellyfin libraries have separate path configurations** — adding `/data/movies` to "Movies" library does not automatically scan `/data/movies/kids`
|
||||
- **Every root folder in Radarr/Sonarr must have a corresponding Jellyfin library** that monitors it
|
||||
- **After fixing the path or adding the library:** do a manual library scan (Jellyfin dashboard → Libraries → Scan)
|
||||
- **The `Refresh Metadata` button** in Jellyfin forces re-examination of existing library paths — it does not discover new paths
|
||||
|
||||
## Details
|
||||
|
||||
### The Silent Failure Pattern
|
||||
|
||||
```
|
||||
Radarr downloads: /data/movies/kids/Moana (2016)/Moana.mkv
|
||||
Jellyfin "Movies" library monitors: /data/movies/films/
|
||||
|
||||
Result: Jellyfin Movies library = empty (can't find Moana)
|
||||
No error in Jellyfin — it just has nothing to show
|
||||
```
|
||||
|
||||
### How to Diagnose
|
||||
|
||||
```bash
|
||||
# 1. Check where Radarr is saving files
|
||||
# In Radarr UI: Movies → any movie → File Path shows actual location
|
||||
|
||||
# 2. Check Jellyfin library paths
|
||||
# Jellyfin Admin → Libraries → (Library Name) → click pencil → Folders
|
||||
|
||||
# 3. Manually verify files exist
|
||||
docker exec jellyfin ls -la /data/movies/kids/
|
||||
# If files are here but Jellyfin doesn't show them → path mismatch
|
||||
```
|
||||
|
||||
### Fixing a Path Mismatch
|
||||
|
||||
**Option A — Add the missing path to an existing Jellyfin library:**
|
||||
|
||||
1. Jellyfin Admin Dashboard → Libraries
|
||||
2. Click the pencil icon on the affected library
|
||||
3. Click **Add Media Folder**
|
||||
4. Add the missing path (e.g., `/data/movies/kids`)
|
||||
5. Save → Library automatically scans
|
||||
|
||||
**Option B — Create a separate Jellyfin library for the subfolder:**
|
||||
|
||||
1. Jellyfin Admin → Libraries → Add Media Library
|
||||
2. Select type (Movies, Shows, etc.)
|
||||
3. Set the folder to the root folder Radarr uses (e.g., `/data/movies/kids`)
|
||||
4. Configure metadata, artwork options
|
||||
5. Save and scan
|
||||
|
||||
Option B is better when the content type warrants a separate library (e.g., "Kids Movies" with age-appropriate content ratings).
|
||||
|
||||
### Multiple Root Folders in Radarr/Sonarr
|
||||
|
||||
Radarr and Sonarr support multiple root folders (e.g., for different quality tiers or content categories). Each root folder must be explicitly monitored by Jellyfin:
|
||||
|
||||
```
|
||||
Radarr root folders: Jellyfin libraries:
|
||||
/data/movies/films → "Movies" library
|
||||
/data/movies/kids → "Kids Movies" library ← must add separately
|
||||
/data/movies/4k → "4K Movies" library ← must add separately
|
||||
```
|
||||
|
||||
When adding a new root folder to Radarr, immediately check if Jellyfin has a library for that path.
|
||||
|
||||
### Post-Fix: Force a Library Scan
|
||||
|
||||
After adding or correcting a library path:
|
||||
|
||||
```bash
|
||||
# Via Jellyfin UI:
|
||||
Admin → Dashboard → Libraries → click "Scan All Libraries"
|
||||
|
||||
# Or scan a specific library:
|
||||
Admin → Libraries → (Library Name) → 3-dot menu → Scan Library
|
||||
```
|
||||
|
||||
New content appears in Jellyfin within seconds to a few minutes depending on library size.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/jellyfin-tmdb-thetvdb-plugin]] — Jellyfin metadata configuration and naming conventions
|
||||
- [[wiki/concepts/sonarr-custom-format-quality-profile]] — Sonarr root folder and quality profile configuration
|
||||
- [[wiki/homelab/_index]] — media stack: Radarr, Sonarr, Jellyfin pipeline
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — Radarr downloading to `/data/movies/kids`, Jellyfin "Фільми" (Films) library only watched `/data/movies/films`; children's movies were in a separate "Мультики" (Cartoons) library; after refresh Jellyfin saw 6 films; fix was verifying each Radarr root folder has a corresponding Jellyfin library
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
---
|
||||
title: "Jellyseerr Setup Wizard Loops and SQLite Gotchas"
|
||||
aliases: [jellyseerr setup, jellyseerr serverType, jellyseerr initialized, jellyseerr wizard loop]
|
||||
tags: [jellyseerr, sqlite, jellyfin, homelab, nginx, npm]
|
||||
sources:
|
||||
- "daily/2026-04-30.md"
|
||||
created: 2026-04-30
|
||||
updated: 2026-04-30
|
||||
---
|
||||
|
||||
# Jellyseerr Setup Wizard Loops and SQLite Gotchas
|
||||
|
||||
Jellyseerr has several sharp edges during initial setup: the wrong `serverType` integer causes the media server connection to silently fail, a `public.initialized = false` flag in SQLite makes the setup wizard reappear on every page load even after completion, and an undefined `urlBase` builds a broken URL. All three issues are fixable via direct SQLite edits.
|
||||
|
||||
## Key Points
|
||||
|
||||
- `serverType: 2` = Jellyfin; `serverType: 4` = NOT_CONFIGURED — using 4 causes the setup wizard to loop
|
||||
- `public.initialized = false` in the `public` table of `db.sqlite3` makes the wizard reappear every time; fix by setting it to `true` directly in SQLite
|
||||
- `urlBase` must be an empty string `""`, not `null` or `undefined` — undefined causes the URL to be built as `http://<ip>:<port>undefined`
|
||||
- SSL error `ERR_SSL_UNRECOGNIZED_NAME_ALERT` during setup usually means the nginx conf is in the wrong path (NPM proxy host conf lives at `/opt/npm/data/nginx/proxy_host/<id>.conf`)
|
||||
|
||||
## Details
|
||||
|
||||
### serverType integer map
|
||||
|
||||
| Value | Meaning |
|
||||
|-------|---------|
|
||||
| `2` | Jellyfin |
|
||||
| `3` | Plex |
|
||||
| `4` | NOT_CONFIGURED (default; breaks wizard) |
|
||||
|
||||
### Fixing the wizard loop via SQLite
|
||||
|
||||
The setup wizard checks `public.initialized` on every load. If Jellyseerr was partially set up but the flag was never flipped, the wizard keeps appearing even though configuration exists.
|
||||
|
||||
```bash
|
||||
# Enter the container or host path
|
||||
sqlite3 /opt/jellyseerr/db/db.sqlite3
|
||||
|
||||
# Check current state
|
||||
SELECT * FROM public;
|
||||
|
||||
# Fix the loop
|
||||
UPDATE public SET initialized = 1 WHERE id = 1;
|
||||
|
||||
.quit
|
||||
```
|
||||
|
||||
After updating, restart Jellyseerr — the wizard will not reappear.
|
||||
|
||||
### urlBase must be empty string
|
||||
|
||||
In `settings.json` (or the DB equivalent), `urlBase` being `null` or JavaScript `undefined` causes string concatenation to produce `http://192.168.1.230:8096undefined`. Set it explicitly:
|
||||
|
||||
```json
|
||||
{
|
||||
"urlBase": ""
|
||||
}
|
||||
```
|
||||
|
||||
### NPM proxy host conf path
|
||||
|
||||
When `ERR_SSL_UNRECOGNIZED_NAME_ALERT` appears, the nginx conf for the proxy host was placed in the wrong location. NPM's proxy host confs live at:
|
||||
|
||||
```
|
||||
/opt/npm/data/nginx/proxy_host/<numeric-id>.conf
|
||||
```
|
||||
|
||||
Placing a custom conf elsewhere means NPM ignores it (or nginx loads an incomplete config). Use the NPM UI to set SSL, or edit the file at the correct path and reload nginx inside the NPM container.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/jellyfin-tmdb-thetvdb-plugin]] — Jellyfin media server setup; plugin and naming gotchas that affect what Jellyseerr can discover
|
||||
- [[wiki/concepts/uptime-kuma-socketio-management]] — Another service managed via SQLite direct edits when the UI is unavailable
|
||||
- [[wiki/homelab/_index]] — Media stack overview: Radarr, Sonarr, Prowlarr, Jellyfin, Jellyseerr
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-30.md]] — Jellyseerr setup wizard looped due to wrong serverType (4 instead of 2) and public.initialized = false; urlBase undefined caused broken URL; SSL error traced to wrong NPM conf path
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
---
|
||||
title: "Linux CPU Frequency Capping for Fan Noise Reduction"
|
||||
aliases: [cpu frequency fan noise, pwm fan control linux, cpufreq homelab, hp elitedesk fan bios]
|
||||
tags: [linux, homelab, cpu, fan-control, systemd, hp-elitedesk, power-management]
|
||||
sources:
|
||||
- "daily/2026-04-30.md"
|
||||
created: 2026-04-30
|
||||
updated: 2026-04-30
|
||||
---
|
||||
|
||||
# Linux CPU Frequency Capping for Fan Noise Reduction
|
||||
|
||||
The HP Elitedesk 800 G3 (and similar small-form-factor business PCs) exposes fan control only through BIOS — Linux `pwm` sysfs entries return `N/A` and writing to them has no effect. The only Linux-side lever for reducing fan noise is capping the CPU's maximum frequency via `cpufreq`, preventing the CPU from boosting to its turbo frequency and generating the heat that spins up the fan.
|
||||
|
||||
## Key Points
|
||||
|
||||
- HP Elitedesk 800 G3 `pwm1` (and similar) returns `N/A` — BIOS controls the fan exclusively
|
||||
- Linux `lm-sensors` / `fancontrol` cannot manage this fan; any attempt silently does nothing
|
||||
- Capping CPU max frequency from 3.8 GHz (boost) to 2.8 GHz is the only Linux-side noise lever
|
||||
- The cap can be set persistently via a `systemd` service that runs at boot
|
||||
- This trade-off reduces fan noise at the cost of peak single-core performance; sustained workloads are largely unaffected
|
||||
|
||||
## Details
|
||||
|
||||
### Confirming fan control is BIOS-only
|
||||
|
||||
```bash
|
||||
# Check available PWM fans
|
||||
cat /sys/class/hwmon/hwmon*/pwm*
|
||||
# Output: N/A ← BIOS-only; Linux cannot write to this
|
||||
|
||||
# Or via sensors
|
||||
sensors
|
||||
# fan1: will show RPM (read-only) but no controllable interface
|
||||
```
|
||||
|
||||
### Checking current CPU frequency limits
|
||||
|
||||
```bash
|
||||
# View current policy
|
||||
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
|
||||
# e.g., 3800000 (3.8 GHz turbo)
|
||||
|
||||
cpufreq-info # if cpufrequtils installed
|
||||
```
|
||||
|
||||
### Setting the cap for the current session
|
||||
|
||||
```bash
|
||||
# Cap all cores to 2.8 GHz
|
||||
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq; do
|
||||
echo 2800000 | sudo tee "$cpu"
|
||||
done
|
||||
```
|
||||
|
||||
### Persistent cap via systemd
|
||||
|
||||
Create `/etc/systemd/system/cpu-freq-cap.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Cap CPU max frequency to 2.8 GHz for fan noise reduction
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash -c 'for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq; do echo 2800000 > $f; done'
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now cpu-freq-cap.service
|
||||
```
|
||||
|
||||
The cap persists across reboots.
|
||||
|
||||
### Alternative: cpupower
|
||||
|
||||
```bash
|
||||
sudo apt install linux-tools-common linux-tools-$(uname -r)
|
||||
sudo cpupower frequency-set -u 2800MHz
|
||||
```
|
||||
|
||||
To make this persistent, add it to `/etc/rc.local` or a systemd `ExecStart`.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/proxmox-lxc-autostart]] — LXC containers on the same host; CPU throttling affects all containers
|
||||
- [[wiki/homelab/_index]] — HP Elitedesk 800 G3 hardware inventory and homelab Proxmox host configuration
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-30.md]] — HP Elitedesk 800 G3 `pwm1` returned N/A confirming BIOS-only fan control; CPU max frequency capped at 2.8 GHz (from 3.8 GHz boost) via systemd to reduce fan noise; verified persistent across reboots
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
# macOS Full Disk Access — External Volumes
|
||||
|
||||
**Source:** daily/2026-05-07.md
|
||||
**Tags:** macos, permissions, fda, claude-code, external-ssd
|
||||
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
Reading files under `/Volumes/SSD/...` (external USB/Thunderbolt drives) from Terminal or Claude Code fails with:
|
||||
|
||||
```
|
||||
Operation not permitted
|
||||
```
|
||||
|
||||
This happens even when the path is correct and the drive is mounted.
|
||||
|
||||
---
|
||||
|
||||
## Cause
|
||||
|
||||
macOS grants Full Disk Access (FDA) on a **per-application** basis. Without FDA, apps cannot read from external SSD volumes — even if launched by the user from the terminal.
|
||||
|
||||
Affected apps: `Terminal`, `Claude Code`, `iTerm2`, any shell-based tool that reads protected paths.
|
||||
|
||||
---
|
||||
|
||||
## Fix
|
||||
|
||||
1. **System Settings → Privacy & Security → Full Disk Access**
|
||||
2. Click `+` → navigate to the app (e.g., `/Applications/Claude Code.app` or `/System/Applications/Utilities/Terminal.app`)
|
||||
3. Toggle it **ON**
|
||||
4. **Restart the application** — FDA is not applied to a running process; the app must be quit and relaunched
|
||||
|
||||
---
|
||||
|
||||
## Restart Requirement
|
||||
|
||||
This is the most common miss: granting FDA while the app is running has no effect on the current session. The app must be **fully quit** (not just the window closed) and reopened.
|
||||
|
||||
For Claude Code specifically: quit via menu or `Cmd+Q`, then relaunch. A new Claude Code session will then be able to read `/Volumes/SSD/...` paths.
|
||||
|
||||
---
|
||||
|
||||
## Scope
|
||||
|
||||
FDA is required for:
|
||||
- External USB/Thunderbolt drives (`/Volumes/*`)
|
||||
- Time Machine volumes
|
||||
- iCloud Drive folders (in some macOS versions)
|
||||
- System folders (`~/Library/Mail`, etc.)
|
||||
|
||||
Normal user home directory files (`~/Documents`, `~/Downloads`) do **not** require FDA.
|
||||
|
||||
---
|
||||
|
||||
## Diagnostic
|
||||
|
||||
If you're unsure whether FDA is the issue:
|
||||
|
||||
```bash
|
||||
# Try reading a file on the volume
|
||||
cat /Volumes/SSD/some-file.txt
|
||||
# → "Operation not permitted" = FDA missing
|
||||
# → content output = access granted
|
||||
```
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
---
|
||||
title: "macOS launchd as Cron Replacement with RunCatchUpIfMissed"
|
||||
aliases: [launchd-cron-replacement, launchd-runcatchupmissed, macos-launchd-agent]
|
||||
tags: [macos, launchd, cron, scheduling, plist]
|
||||
sources:
|
||||
- "daily/2026-05-07.md"
|
||||
created: 2026-05-07
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# macOS launchd as Cron Replacement with RunCatchUpIfMissed
|
||||
|
||||
## Why launchd Instead of Cron
|
||||
|
||||
macOS cron silently drops jobs when the machine is asleep at trigger time. launchd with `RunCatchUpIfMissed=true` fires the job **on wake** if the scheduled window was missed. This is the correct scheduling mechanism for MacBooks.
|
||||
|
||||
See: [[wiki/concepts/macos-cron-sleep-missed-jobs]]
|
||||
|
||||
## Plist Structure
|
||||
|
||||
Create `~/Library/LaunchAgents/com.user.myscript.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.sync-repos</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>/Users/aimpress/scripts/sync_to_forgejo.sh</string>
|
||||
</array>
|
||||
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Hour</key>
|
||||
<integer>2</integer>
|
||||
<key>Minute</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
|
||||
<key>RunCatchUpIfMissed</key>
|
||||
<true/>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/sync-repos.log</string>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/sync-repos-err.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
## launchctl Commands
|
||||
|
||||
```bash
|
||||
# Load (activate) the agent
|
||||
launchctl load ~/Library/LaunchAgents/com.user.sync-repos.plist
|
||||
|
||||
# Unload (deactivate)
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.sync-repos.plist
|
||||
|
||||
# Run immediately (for testing)
|
||||
launchctl start com.user.sync-repos
|
||||
|
||||
# Check status
|
||||
launchctl list | grep com.user.sync-repos
|
||||
|
||||
# Remove old cron entry first
|
||||
crontab -l # list current
|
||||
crontab -e # edit and delete the old line
|
||||
```
|
||||
|
||||
## RunCatchUpIfMissed Behavior
|
||||
|
||||
When `RunCatchUpIfMissed=true`:
|
||||
- If the trigger time was missed (machine asleep), the job fires **once** on next wake
|
||||
- It does not fire multiple times to "catch up" — just once for the most recent missed interval
|
||||
|
||||
## Key Notes
|
||||
|
||||
- Plist files must be in `~/Library/LaunchAgents/` (user-level) or `/Library/LaunchDaemons/` (system-level)
|
||||
- Agents in `~/Library/LaunchAgents/` only run while the user is logged in
|
||||
- `StartCalendarInterval` is the equivalent of cron time expressions
|
||||
- Always use absolute paths in `ProgramArguments` — shell PATH is not inherited
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/macos-cron-sleep-missed-jobs]] — why cron fails on macOS laptops
|
||||
- [[wiki/concepts/macos-python-version-hooks]] — macOS path gotchas in scripts
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-07.md]] — Replaced cron job for sync_to_forgejo.sh with launchd plist using RunCatchUpIfMissed=true; cleared crontab entry; confirmed on-wake catch-up behavior
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
---
|
||||
title: "macOS — Windows 11 USB Creation when install.wim Exceeds 4 GB (wimlib split)"
|
||||
aliases: [macos-windows-usb, wimlib-split, windows-usb-fat32, install-wim-split]
|
||||
tags: [macos, windows, usb, wimlib, fat32, bootable-usb]
|
||||
sources:
|
||||
- "daily/2026-05-08.md"
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# macOS — Windows 11 USB Creation when install.wim Exceeds 4 GB (wimlib split)
|
||||
|
||||
Modern Windows 11 ISOs include an `install.wim` that exceeds 4 GB — above the FAT32 single-file limit. balenaEtcher and `dd` fail silently or produce an unbootable drive. The correct approach is to copy the ISO contents manually and split `install.wim` into `.swm` chunks using `wimlib-imagex`.
|
||||
|
||||
## Key Points
|
||||
|
||||
- FAT32 maximum single-file size is 4 GB; modern `install.wim` is typically 5–6 GB.
|
||||
- `balenaEtcher` on macOS fails silently when the ISO contains files exceeding this limit.
|
||||
- `wimlib-imagex split` produces `.swm` (split WIM) files the Windows installer detects automatically.
|
||||
- The USB must be formatted **FAT32 MBR** (not exFAT, not GPT) for UEFI legacy compatibility.
|
||||
- All ISO contents are copied first; `install.wim` is excluded and replaced with the split `.swm` files.
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Install wimlib
|
||||
|
||||
```bash
|
||||
brew install wimlib
|
||||
```
|
||||
|
||||
### 2. Format the USB as FAT32 MBR
|
||||
|
||||
```bash
|
||||
diskutil list # identify the USB disk, e.g. /dev/disk4
|
||||
diskutil eraseDisk FAT32 WINUSB MBRFormat /dev/disk4
|
||||
```
|
||||
|
||||
### 3. Mount the ISO
|
||||
|
||||
```bash
|
||||
hdiutil attach /path/to/Win11.iso # mounts as /Volumes/CCCOMA_... or similar
|
||||
```
|
||||
|
||||
### 4. Copy ISO contents excluding install.wim
|
||||
|
||||
```bash
|
||||
rsync -avh --exclude=sources/install.wim \
|
||||
/Volumes/CCCOMA_X64FRE_EN-US_DV9/ \
|
||||
/Volumes/WINUSB/
|
||||
```
|
||||
|
||||
Replace the mount path with the actual volume label.
|
||||
|
||||
### 5. Split install.wim into 3 GB chunks
|
||||
|
||||
```bash
|
||||
wimlib-imagex split \
|
||||
/Volumes/CCCOMA_X64FRE_EN-US_DV9/sources/install.wim \
|
||||
/Volumes/WINUSB/sources/install.swm \
|
||||
3000
|
||||
```
|
||||
|
||||
The `3000` argument is the maximum chunk size in MB. This produces `install.swm`, `install2.swm`, `install3.swm`, etc.
|
||||
|
||||
### 6. Eject and boot
|
||||
|
||||
```bash
|
||||
diskutil eject /dev/disk4
|
||||
```
|
||||
|
||||
Boot the target machine from USB. The Windows installer automatically detects `install.swm` alongside the original `install.wim` reference.
|
||||
|
||||
## Why .swm Works
|
||||
|
||||
The Windows Setup loader (`setup.exe` / WinPE) understands Split WIM format natively. When it encounters `install.swm` in `sources/`, it reassembles the parts in memory during installation. No user action is required — the file picker shows a single "Windows 11" entry as normal.
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
| Mistake | Result |
|
||||
|---------|--------|
|
||||
| Using balenaEtcher with a modern ISO | Silent failure or unbootable USB |
|
||||
| Formatting as exFAT | Some older UEFI firmware can't boot exFAT |
|
||||
| Forgetting `--exclude=sources/install.wim` in rsync | Rsync hangs or fails on the oversized file |
|
||||
| Splitting to the wrong destination path | Installer can't find `.swm` files |
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/apple-silicon-usb-passthrough]] — when the USB becomes hardware-locked read-only after a `dd` write, use UTM for recovery
|
||||
- [[wiki/concepts/kingston-usb-readonly-lock]] — Kingston DataTraveler read-only controller lock triggered by macOS `dd`
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-08.md]] — Windows 11 USB creation on macOS Apple Silicon; install.wim was 5.4 GB; balenaEtcher failed silently; wimlib split resolved the issue
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
---
|
||||
title: "Paperless-NGX — docker exec Root-Owned Temp Dirs Break Mail Fetcher"
|
||||
aliases: [paperless-docker-exec-permission, paperless-scratch-dir, paperless-mail-fetcher-permission]
|
||||
tags: [paperless-ngx, docker, permissions, celery, homelab, selfhosted]
|
||||
sources:
|
||||
- "daily/2026-05-01.md"
|
||||
created: 2026-05-01
|
||||
updated: 2026-05-01
|
||||
---
|
||||
|
||||
# Paperless-NGX — docker exec Root-Owned Temp Dirs Break Mail Fetcher
|
||||
|
||||
Running `docker exec paperless-ngx ...` without a `-u paperless` flag executes as root. Python's `tempfile.mkdtemp()` creates temp directories with mode 700 owned by the current user (root). The Paperless celery worker runs as UID 1000 and cannot read or write those root-owned directories — resulting in a `PermissionError` that looks like a genuine mail fetcher bug but is actually a testing artefact.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **`docker exec` without `-u` runs as root** — even if the container normally runs as a non-root user
|
||||
- **`tempfile.mkdtemp()` creates dirs with mode 700** — owned by whoever called it; root-owned dirs are inaccessible to the celery worker (UID 1000)
|
||||
- **The PermissionError is a false positive** — automatic celery-beat runs work fine because they run as the correct user; only manual `docker exec` testing triggers it
|
||||
- **`PAPERLESS_SCRATCH_DIR`** (not `PAPERLESS_TEMP_DIR`) is the correct env var for mail attachment temp dirs — must point to a volume with mode 1777
|
||||
- **Removing `USERMAP_UID`/`USERMAP_GID`** env vars avoids UID remapping conflicts
|
||||
|
||||
## Details
|
||||
|
||||
### The False Positive
|
||||
|
||||
The standard debugging approach of running `docker exec paperless-ngx python manage.py mail_fetcher` triggers the bug:
|
||||
|
||||
```bash
|
||||
# ❌ Runs as root — creates root-owned 700 temp dirs → PermissionError
|
||||
docker exec paperless-ngx python manage.py mail_fetcher
|
||||
|
||||
# ✅ Correct — runs as the service user
|
||||
docker exec -u paperless paperless-ngx python manage.py mail_fetcher
|
||||
```
|
||||
|
||||
The automatic celery-beat task runs as the paperless user and does not hit this issue.
|
||||
|
||||
### The Real Fix
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
paperless-ngx:
|
||||
environment:
|
||||
- PAPERLESS_SCRATCH_DIR=/paperless-tmp # mail attachment temp dir
|
||||
# Remove or don't set USERMAP_UID / USERMAP_GID
|
||||
volumes:
|
||||
- paperless-tmp:/paperless-tmp # must be mode 1777
|
||||
|
||||
volumes:
|
||||
paperless-tmp:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind,uid=1000,gid=1000
|
||||
device: /opt/paperless/tmp
|
||||
```
|
||||
|
||||
For the host directory, ensure permissions allow the container user:
|
||||
```bash
|
||||
mkdir -p /opt/paperless/tmp
|
||||
chmod 1777 /opt/paperless/tmp
|
||||
```
|
||||
|
||||
### Env Var Distinction
|
||||
|
||||
| Env Var | Purpose | Notes |
|
||||
|---------|---------|-------|
|
||||
| `PAPERLESS_SCRATCH_DIR` | Mail attachment temp processing | Must be writable by UID 1000 |
|
||||
| `PAPERLESS_TEMP_DIR` | General temp dir (not mail) | Different use case |
|
||||
| `PAPERLESS_DATA_DIR` | Database and index files | Persistent storage |
|
||||
| `PAPERLESS_MEDIA_ROOT` | Imported documents | Persistent storage |
|
||||
|
||||
### Diagnosing PermissionError
|
||||
|
||||
```bash
|
||||
# Check if the PermissionError is real or a test artefact
|
||||
# 1. Run with correct user
|
||||
docker exec -u paperless paperless-ngx python manage.py mail_fetcher
|
||||
# If this works → the error was only triggered by root-exec testing
|
||||
|
||||
# 2. Check temp dir ownership
|
||||
docker exec paperless-ngx ls -la /paperless-tmp/
|
||||
# Should show: drwxrwxrwt (mode 1777) owned by root, writable by all
|
||||
|
||||
# 3. Check celery worker user
|
||||
docker exec paperless-ngx id
|
||||
# Should show: uid=1000(paperless)
|
||||
```
|
||||
|
||||
### Historical ProcessedMail Tracebacks
|
||||
|
||||
After fixing the PermissionError, the Paperless UI may still show historical `ProcessedMail` traceback entries from before the fix. These are cosmetic — they record past failed attempts. They will not block new mail processing and can be ignored or cleared.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/docker-compose-restart-no-code-reload]] — other Docker testing footguns where manual exec gives misleading results
|
||||
- [[wiki/concepts/sudo-git-clone-root-ownership]] — same class of bug: running a command as root creates files inaccessible to the service user
|
||||
- [[wiki/concepts/celery-queue-worker-specialization]] — Celery worker user identity matters for file system access
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-01.md]] — Paperless-NGX mail fetcher PermissionError traced to `docker exec` running as root; `PAPERLESS_SCRATCH_DIR=/paperless-tmp` + mode 1777 volume + removing USERMAP env vars was the correct fix; automatic celery-beat run completed successfully with 5 documents imported
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
---
|
||||
title: "Paperless-NGX Mail Rule — Attachment-Only Processing and Mark-as-Read Gotcha"
|
||||
aliases: [paperless-mail-rule, paperless-attachment-only, paperless-mark-as-read, paperless-duplicate-detection]
|
||||
tags: [paperless-ngx, email, mail-fetcher, homelab, selfhosted, imap]
|
||||
sources:
|
||||
- "daily/2026-05-01.md"
|
||||
created: 2026-05-01
|
||||
updated: 2026-05-01
|
||||
---
|
||||
|
||||
# Paperless-NGX Mail Rule — Attachment-Only Processing and Mark-as-Read Gotcha
|
||||
|
||||
Paperless-NGX mail rules have two non-obvious behaviors: (1) emails already marked as read by a previous fetcher run are permanently skipped even when the attachment filter is later expanded, and (2) the default attachment processing mode imports the email body alongside attachments, causing duplicate detection failures when a later fetch tries to import the same attachment standalone.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Mark-as-read is permanent for fetcher purposes** — once a mail rule marks an email as read (Action: 1), expanding the attachment filter later won't re-process those emails; must mark them as unread in the mail client
|
||||
- **Default attachment mode processes body + attachments** — email body is merged with attachment content into a single document; if the same attachment arrives without body context, it's rejected as a duplicate
|
||||
- **Attachment-only mode (`0`) is safer** — imports only the actual attachments, no email body noise; prevents duplicate detection issues
|
||||
- **Junk documents from body processing** must be deleted manually before clean re-import of the same attachment as a standalone document
|
||||
- **Celery-beat runs every 10 minutes by default** — changes to mail rules take effect on the next scheduled run
|
||||
|
||||
## Details
|
||||
|
||||
### The Mark-as-Read Trap
|
||||
|
||||
When a mail rule runs with `*.pdf` as the attachment filter and Action = "Mark as read":
|
||||
|
||||
1. Fetcher runs → finds emails with PDF attachments → imports PDFs → marks emails as read
|
||||
2. Developer updates filter to `*.pdf, *.doc, *.docx`
|
||||
3. Fetcher runs again → emails are already read → **fetcher skips them entirely**
|
||||
4. Word attachments are never imported
|
||||
|
||||
**Fix:** Mark the relevant emails as unread in the mail client (Gmail, Outlook) before the next celery-beat run.
|
||||
|
||||
```bash
|
||||
# Force an immediate re-run after marking emails as unread
|
||||
docker exec -u paperless paperless-ngx python manage.py mail_fetcher
|
||||
```
|
||||
|
||||
### Default Mode — Body + Attachment Merging
|
||||
|
||||
The default `Attachment type` in a Paperless mail rule includes the email body with each attachment. The imported document contains the email subject, body text, and the attachment content all merged.
|
||||
|
||||
Problem scenario:
|
||||
|
||||
1. First fetch: `Invoice Q1.pdf` arrives in email. Paperless imports it as "Re: Invoice Q1" containing body + PDF content.
|
||||
2. Second fetch attempt (after filter change): same `Invoice Q1.pdf` encounters the email again — fetcher tries to import just the PDF.
|
||||
3. Paperless detects the PDF content already exists in document #83 → rejects as duplicate.
|
||||
|
||||
The "document" (#83) is actually the email body + PDF merged — a junk document that prevents clean import.
|
||||
|
||||
### Attachment-Only Mode Fix
|
||||
|
||||
In the mail rule configuration:
|
||||
|
||||
| Setting | Value | Effect |
|
||||
|---------|-------|--------|
|
||||
| Attachment type (default) | Process documents + attachments | Imports email body merged with each attachment |
|
||||
| Attachment type = `0` | Attachments only | Imports attachment files only; no email body |
|
||||
|
||||
Set `Attachment type` to `0` (or the "Attachments only" option in the UI) to prevent body merging.
|
||||
|
||||
### Cleaning Up Junk Documents
|
||||
|
||||
After switching to attachment-only mode, junk documents (email body imports) must be deleted before the attachment can re-import cleanly:
|
||||
|
||||
1. In Paperless UI → Documents → find documents with email notification subject lines (e.g., "Re: Support Case Update", "Invoice Notification")
|
||||
2. Delete them
|
||||
3. Mark the source emails as unread in the mail client
|
||||
4. Wait for next celery-beat run (or trigger manually)
|
||||
|
||||
The clean re-import will then succeed with just the attachment file, properly titled.
|
||||
|
||||
### Mail Rule Configuration Reference
|
||||
|
||||
```
|
||||
Action: Mark as read (1) # Mark emails as read after processing
|
||||
Attachment type: 0 # Attachments only — no email body
|
||||
Filter attachment filename: *.pdf, *.doc, *.docx # Comma-separated globs
|
||||
```
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/paperless-ngx-docker-exec-permission-bug]] — related Paperless-NGX gotcha: docker exec running as root breaks mail fetcher testing
|
||||
- [[wiki/concepts/celery-redis-queue-flush-on-deterministic-error]] — Celery queue management when deterministic errors cause retry loops
|
||||
- [[wiki/concepts/docker-compose-restart-no-code-reload]] — Docker testing patterns
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-01.md]] — Paperless-NGX mail rule: Word files not imported because previous fetch already marked emails as read; attachment type changed to `0` (attachments only) to prevent body+attachment merging and duplicate detection; documents #83–90 identified as junk from body processing, deleted for clean re-import
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
---
|
||||
title: "FlareSolverr GET-Only Limitation and SQLite Cookie Injection"
|
||||
aliases: [flaresolverr-get-only, prowlarr-cookie-injection, rutracker-bb-session]
|
||||
tags: [prowlarr, flaresolverr, sqlite, homelab, torrent, indexer, rutracker]
|
||||
sources:
|
||||
- "daily/2026-04-29.md"
|
||||
created: 2026-04-29
|
||||
updated: 2026-04-29
|
||||
---
|
||||
|
||||
# FlareSolverr GET-Only Limitation and SQLite Cookie Injection
|
||||
|
||||
FlareSolverr intercepts only HTTP GET requests. Prowlarr's `DoLogin()` method sends a POST request to the indexer login endpoint — FlareSolverr cannot intercept it. This means that even when FlareSolverr is correctly tagged and running, Prowlarr's login step bypasses it entirely, causing authentication failures on indexers like RuTracker. The workaround is to inject a valid session cookie directly into Prowlarr's SQLite database.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **FlareSolverr only handles GET requests** — it drives a headless browser that performs page navigation, not form POST submissions
|
||||
- **Prowlarr's `DoLogin()` sends a POST** to the indexer login URL — FlareSolverr's architecture cannot intercept this
|
||||
- **Even with the FlareSolverr tag correctly assigned**, Prowlarr bypasses FlareSolverr for the login step
|
||||
- **Workaround: inject session cookie into Prowlarr's SQLite DB** — `IndexerDefinition` table, `Cookies` column (JSON format)
|
||||
- **RuTracker `bb_session` cookie expires ~30 days** — must be refreshed from browser DevTools periodically
|
||||
|
||||
## Details
|
||||
|
||||
### Root Cause: FlareSolverr Architecture
|
||||
|
||||
FlareSolverr works by running a headless Chromium browser. When Prowlarr calls the FlareSolverr API with `cmd: "request.get"`, FlareSolverr navigates Chromium to that URL, solves any Cloudflare challenge, and returns the rendered page. This pipeline is fundamentally GET-only — it navigates to URLs, it does not submit forms.
|
||||
|
||||
Prowlarr's indexer plugins call `DoLogin()` before any search. `DoLogin()` constructs a form POST request (username, password, anti-CSRF token) and submits it to the indexer's login endpoint. FlareSolverr has no mechanism to intercept or proxy a POST submission — it is simply never in the call path for `DoLogin()`.
|
||||
|
||||
Result: Prowlarr successfully routes GET requests through FlareSolverr (the actual search/browse calls), but the preceding login POST always goes direct. If that direct POST is blocked by Cloudflare, authentication fails and all subsequent searches fail too.
|
||||
|
||||
### Workaround: SQLite Cookie Injection
|
||||
|
||||
Instead of logging in via Prowlarr's login flow, obtain a valid session cookie from a browser session and inject it directly into Prowlarr's database:
|
||||
|
||||
```bash
|
||||
# 1. Stop Prowlarr to avoid DB corruption
|
||||
docker compose stop prowlarr
|
||||
|
||||
# 2. Open the database
|
||||
sqlite3 /path/to/prowlarr/config/prowlarr.db
|
||||
|
||||
# 3. Find the RuTracker indexer row
|
||||
SELECT Id, Name, Cookies FROM IndexerDefinition WHERE Name LIKE '%RuTracker%';
|
||||
|
||||
# 4. Update the Cookies column with the session cookie JSON
|
||||
UPDATE IndexerDefinition
|
||||
SET Cookies = '[{"name":"bb_session","value":"YOUR_BB_SESSION_VALUE","domain":".rutracker.org","path":"/"}]'
|
||||
WHERE Name LIKE '%RuTracker%';
|
||||
|
||||
# 5. Verify
|
||||
SELECT Cookies FROM IndexerDefinition WHERE Name LIKE '%RuTracker%';
|
||||
|
||||
# 6. Exit and restart
|
||||
.quit
|
||||
docker compose start prowlarr
|
||||
```
|
||||
|
||||
**Getting the `bb_session` cookie from the browser:**
|
||||
1. Log into rutracker.org in your browser
|
||||
2. Open DevTools → Application tab → Cookies → rutracker.org
|
||||
3. Copy the `bb_session` cookie value
|
||||
4. Paste into the SQL above
|
||||
|
||||
### Cookie Expiry and Refresh Process
|
||||
|
||||
The `bb_session` cookie expires approximately every 30 days. When searches start failing again:
|
||||
|
||||
1. Log into rutracker.org in a browser
|
||||
2. DevTools → Application → Cookies → rutracker.org → copy new `bb_session` value
|
||||
3. Stop Prowlarr, open SQLite, run the UPDATE again, restart Prowlarr
|
||||
|
||||
### Domain Gotcha
|
||||
|
||||
RuTracker has both `.nl` and `.org` domains. The `.nl` domain returns an HTTP/2 protocol error. Always use `https://rutracker.org/` as the `baseUrl` in Prowlarr indexer settings.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/prowlarr-flaresolverr-limitation]] — parent article: FlareSolverr plugin bug, VPN alternatives, Docker TLS fingerprint blocking
|
||||
- [[wiki/concepts/sonarr-custom-format-quality-profile]] — Sonarr quality profiles; RuTracker audio verification
|
||||
- [[wiki/concepts/uptime-kuma-socketio-management]] — another case of SQLite direct management for self-hosted tools
|
||||
- [[wiki/homelab/_index]] — media stack: Prowlarr, Sonarr, Radarr, qBittorrent
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-29.md]] — FlareSolverr GET-only root cause identified; Prowlarr DoLogin() sends POST; FlareSolverr bypassed for login; bb_session cookie injection into IndexerDefinition.Cookies; 30-day expiry; .nl domain HTTP/2 error; .org is correct
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
---
|
||||
title: "Proxmox LXC Disk Space Recovery via fstrim"
|
||||
aliases: [proxmox-lxc-disk-trim, lxc-disk-cleanup, thin-provisioning-trim]
|
||||
tags: [proxmox, lxc, storage, disk, fstrim, thin-provisioning]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Proxmox LXC Disk Space Recovery via fstrim
|
||||
|
||||
## The Problem
|
||||
|
||||
After deleting large files inside an LXC container, the disk usage shown in `df -h` (and Proxmox UI) does not decrease. This happens because deleting a file updates the filesystem's block map, but does **not** send a TRIM/discard command to the underlying thin-provisioned storage. The thin-provisioned volume still holds the blocks as allocated.
|
||||
|
||||
**Symptom:** LXC disk shows 99% used in Proxmox even after deleting hundreds of GB of files.
|
||||
|
||||
## Immediate Fix: Manual fstrim
|
||||
|
||||
Run inside the LXC container (or via `pct exec`):
|
||||
|
||||
```bash
|
||||
pct exec <CTID> -- fstrim -av
|
||||
# Example output:
|
||||
# /: 64.3 GiB (69020286976 bytes) trimmed
|
||||
```
|
||||
|
||||
This recovers space immediately. In one case: 99.39% → 35.80% after trim.
|
||||
|
||||
## Permanent Fix: Enable Automatic Discards
|
||||
|
||||
### 1. Storage-level: issue_discards in storage.cfg
|
||||
|
||||
Edit `/etc/pve/storage.cfg` on the Proxmox host and add `issue_discards 1` to the relevant storage pool:
|
||||
|
||||
```
|
||||
lvmthin: local-lvm
|
||||
thinpool data
|
||||
vgname pve
|
||||
content rootdir,images
|
||||
issue_discards 1 ← add this line
|
||||
```
|
||||
|
||||
This tells the LVM thin pool to pass discard operations through.
|
||||
|
||||
### 2. Weekly Cron (fallback)
|
||||
|
||||
If `issue_discards` causes performance concerns, run fstrim weekly instead:
|
||||
|
||||
```bash
|
||||
# /etc/cron.weekly/fstrim-lxc
|
||||
#!/bin/bash
|
||||
for ctid in $(pct list | awk 'NR>1 {print $1}'); do
|
||||
pct exec "$ctid" -- fstrim -a 2>/dev/null
|
||||
done
|
||||
```
|
||||
|
||||
## Key Notes
|
||||
|
||||
- This only applies to **thin-provisioned** storage (LVM-thin, ZFS, Ceph). Thick-provisioned volumes don't benefit.
|
||||
- `fstrim` is safe to run on live containers — it doesn't interrupt running processes.
|
||||
- `issue_discards 1` should be set on the storage pool where LXC volumes live (usually `local-lvm`).
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/proxmox-lxc-autostart]] — other Proxmox LXC configuration gotchas
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — LXC disk at 99.39% after Docker cleanup; `pct exec CTID -- fstrim -av` recovered space to 35.80%; permanent fix: `issue_discards 1` in storage.cfg
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
---
|
||||
title: "Proxmox LXC Disk Space Recovery — fstrim and issue_discards"
|
||||
aliases: [proxmox-fstrim, lvm-issue-discards, proxmox-disk-thin-provisioning, lxc-disk-space]
|
||||
tags: [proxmox, lxc, lvm, disk, storage, fstrim, trim, thin-provisioning]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# Proxmox LXC Disk Space Recovery — fstrim and issue_discards
|
||||
|
||||
When a Proxmox LXC container's disk appears full (e.g., 99%) but the container hasn't actually used that much data, the cause is usually that deleted blocks haven't been reclaimed by the thin provisioning layer. LVM thin provisioning allocates blocks on write but doesn't automatically free them on delete. Running `fstrim` inside the container and enabling `issue_discards` in LVM config allows TRIM commands to propagate from the filesystem through LVM to the storage backend.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **LVM thin provisioning doesn't auto-reclaim deleted blocks** — a container that wrote then deleted large files still shows those blocks as used
|
||||
- **`fstrim`** tells the filesystem to send TRIM/DISCARD commands for freed blocks — reclaims space immediately
|
||||
- **`issue_discards = 1`** in `/etc/lvm/lvm.conf` enables LVM to pass DISCARD commands to the underlying storage on every LV delete — prevents future bloat
|
||||
- **Dramatic results:** CT102 went from 99.39% to 35.80% after fstrim + enabling issue_discards
|
||||
- Only works with thin LVM volumes (local-lvm, ZFS zvols) — not with directory storage
|
||||
|
||||
## Details
|
||||
|
||||
### Immediate Recovery: fstrim
|
||||
|
||||
Run inside the LXC container (or from the Proxmox host with `pct exec`):
|
||||
|
||||
```bash
|
||||
# Inside the container
|
||||
fstrim -av
|
||||
# Outputs: /: 45.2 GiB (48,527,572,992 bytes) trimmed
|
||||
|
||||
# Or from Proxmox host
|
||||
pct exec <CTID> -- fstrim -av
|
||||
```
|
||||
|
||||
`-a` = all mounted filesystems, `-v` = verbose (shows space reclaimed).
|
||||
|
||||
### Permanent Fix: issue_discards in LVM
|
||||
|
||||
On the **Proxmox host** (not inside the container):
|
||||
|
||||
```bash
|
||||
# Edit LVM config
|
||||
nano /etc/lvm/lvm.conf
|
||||
|
||||
# Find and change:
|
||||
# issue_discards = 0
|
||||
# to:
|
||||
issue_discards = 1
|
||||
|
||||
# No restart needed — takes effect on next LVM operation
|
||||
```
|
||||
|
||||
With `issue_discards = 1`, LVM sends DISCARD commands to the underlying block device when logical volumes are removed or blocks freed, keeping thin pools lean.
|
||||
|
||||
### Checking Thin Pool Usage
|
||||
|
||||
```bash
|
||||
# On Proxmox host — check thin pool usage
|
||||
lvdisplay pve/data | grep -E "Pool|Used|Allocated"
|
||||
# or
|
||||
pvesm status | grep local-lvm
|
||||
|
||||
# More detailed
|
||||
lvs -o lv_name,data_percent,snap_percent pve
|
||||
```
|
||||
|
||||
If `data_percent` is high but the containers don't have that much actual data, trim is needed.
|
||||
|
||||
### When fstrim Doesn't Help
|
||||
|
||||
fstrim won't help if:
|
||||
- The container is using directory storage (not LVM thin/ZFS)
|
||||
- The underlying storage doesn't support DISCARD (some SSDs, spinning disks without TRIM support)
|
||||
- The container has genuinely large files that haven't been deleted
|
||||
|
||||
In those cases, the data is real and must be cleaned manually:
|
||||
|
||||
```bash
|
||||
# Find large files inside the container
|
||||
pct exec <CTID> -- find / -type f -size +100M 2>/dev/null | sort -k5 -n
|
||||
# or
|
||||
pct exec <CTID> -- du -sh /* 2>/dev/null | sort -rh | head -20
|
||||
```
|
||||
|
||||
### Schedule Regular fstrim
|
||||
|
||||
Add a cron job to prevent disk bloat accumulating:
|
||||
|
||||
```bash
|
||||
# On Proxmox host — trim all containers weekly
|
||||
echo "0 3 * * 0 root pct list | awk 'NR>1{print \$1}' | xargs -I{} pct exec {} -- fstrim -a 2>/dev/null" >> /etc/cron.d/pve-fstrim
|
||||
```
|
||||
|
||||
Or use systemd timer — Proxmox ships with `fstrim.timer` that can be enabled.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/proxmox-lxc-autostart]] — LXC container management basics
|
||||
- [[wiki/concepts/docker-builder-prune-safe]] — another disk space recovery technique (Docker build cache)
|
||||
- [[wiki/homelab/_index]] — Proxmox infrastructure context
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — CT102 at 99.39% disk usage after Docker operations; `fstrim -av` + `issue_discards = 1` in `/etc/lvm/lvm.conf` reduced to 35.80%; fstrim reclaimed ~65% of used space
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
---
|
||||
title: "qBittorrent Proxy Profile Enabled Without Proxy Host Blocks All Connections"
|
||||
aliases: [qbittorrent-proxy-blocking, qbittorrent-slow-proxy, qbittorrent-proxy-misconfiguration]
|
||||
tags: [qbittorrent, proxy, media-stack, homelab, networking, debugging]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# qBittorrent Proxy Profile Enabled Without Proxy Host Blocks All Connections
|
||||
|
||||
When qBittorrent has a proxy configuration enabled (type: SOCKS5 or HTTP) but no valid proxy host is configured, all peer connections are silently blocked — they are routed through the proxy, find nothing, and fail. The symptom is extremely slow speeds (e.g., 250 KiB/s with 30-40 active seeds) that look like network congestion or ISP throttling but are actually configuration-level blocking.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **A proxy profile without a real host blocks all peer connections** — qBit routes traffic through the proxy; empty/invalid host → connection fails silently
|
||||
- **UPnP is useless when the router has UPnP disabled** — check router settings before enabling qBit UPnP; TP-Link AX72 has UPnP disabled by default in some firmware
|
||||
- **Upload limit of 1 KiB/s also tanks download speeds** — tracker scores peers by ratio; an upload-capped client gets deprioritized
|
||||
- **Fix when not using a proxy:** Settings → Connection → Proxy Server → Type → None
|
||||
- **Fix for port forwarding:** set the listening port manually in Settings → Connection; disable UPnP if the router doesn't support it
|
||||
|
||||
## Details
|
||||
|
||||
### The Proxy Blocking Symptom
|
||||
|
||||
```
|
||||
qBit shows: 250 KiB/s download, 30-40 seeds, 100+ peers
|
||||
Expected: 5-10 MB/s for a well-seeded torrent
|
||||
```
|
||||
|
||||
The connection graph shows many peers but very low transfer rates. This is because qBit connects to peers successfully (the TCP handshake works via the proxy attempt), but data transfer fails.
|
||||
|
||||
### Checking Proxy Configuration
|
||||
|
||||
1. Open qBittorrent WebUI → Settings (gear icon)
|
||||
2. Go to **Connection** tab
|
||||
3. Check **Proxy Server** section
|
||||
4. If Type is `SOCKS5` or `HTTP` with empty Host → this is the problem
|
||||
|
||||
```
|
||||
Type: SOCKS5 ← problem
|
||||
Host: [empty]
|
||||
Port: 1080
|
||||
```
|
||||
|
||||
**Fix:** Set Type to `None` (if not using a proxy) or enter a valid proxy host.
|
||||
|
||||
### UPnP with TP-Link AX72
|
||||
|
||||
The TP-Link Archer AX72 has UPnP disabled by default (or disabled in some firmware versions). When qBit tries to use UPnP for automatic port mapping:
|
||||
|
||||
```
|
||||
qBit → UPnP request → router → UPnP disabled → no port forwarded
|
||||
qBit shows "UPnP: mapped" (locally) but port is NOT actually forwarded
|
||||
```
|
||||
|
||||
**Fix:** Disable qBit's UPnP option. Set a specific port (e.g., 50000) and forward it manually in the router under `Advanced → NAT Forwarding → Port Forwarding`.
|
||||
|
||||
### Upload Limit Impact on Download Speeds
|
||||
|
||||
BitTorrent trackers score peers by their upload/download ratio over time. A peer with upload limit of 1 KiB/s is classified as a "leecher" and deprioritized for bandwidth by well-behaved peers.
|
||||
|
||||
- Upload limit 1 KiB/s → download speeds capped by peer reprioritization
|
||||
- Upload limit 0 → unlimited (uses available bandwidth)
|
||||
- Recommended: set upload limit to 70-80% of your upload capacity to avoid being deprioritized
|
||||
|
||||
### TP-Link AX72 Port Forwarding
|
||||
|
||||
TP-Link AX72 uses the term "Port Forwarding" (not "Virtual Server") under `Advanced → NAT Forwarding → Port Forwarding`.
|
||||
|
||||
```
|
||||
Service Name: qBittorrent
|
||||
External Port: 50000
|
||||
Internal IP: 192.168.1.230 ← qBit host IP
|
||||
Internal Port: 50000
|
||||
Protocol: All
|
||||
```
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/prowlarr-flaresolverr-limitation]] — other qBittorrent/media stack configuration issues
|
||||
- [[wiki/homelab/_index]] — media stack context
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — qBittorrent running at 250 KiB/s with 30-40 seeds; root causes: proxy profile enabled (type SOCKS5) with no proxy host + UPnP disabled on TP-Link AX72 + upload limit 1 KiB/s; fixed all three; speeds expected to recover
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
---
|
||||
title: "qBittorrent Slow Speed Checklist — Proxy, UPnP, Port Forwarding"
|
||||
aliases: [qbittorrent-proxy-profile-blocking, qbittorrent-port-forwarding]
|
||||
tags: [qbittorrent, homelab, networking, port-forwarding, proxy, bittorrent]
|
||||
sources:
|
||||
- "daily/2026-05-03.md"
|
||||
created: 2026-05-03
|
||||
updated: 2026-05-03
|
||||
---
|
||||
|
||||
# qBittorrent Slow Speed Checklist
|
||||
|
||||
Three distinct root causes found in practice when qBittorrent shows near-zero download speeds despite good internet connectivity.
|
||||
|
||||
## Cause 1: Proxy Profile Enabled Without Real Proxy
|
||||
|
||||
qBittorrent proxy settings with a profile enabled but no valid proxy host configured will **silently block all peer connections**. No error is shown — downloads just stall at 0 KB/s.
|
||||
|
||||
**Fix:**
|
||||
- Tools → Options → Connection → Proxy Server
|
||||
- Set Type to **None**
|
||||
|
||||
Or edit `qBittorrent.conf` directly:
|
||||
```ini
|
||||
[Connection]
|
||||
ProxyType=0
|
||||
```
|
||||
|
||||
## Cause 2: UPnP Not Working / Port Not Opened
|
||||
|
||||
If your router doesn't support UPnP or it's blocked, qBittorrent may not have a routable incoming port.
|
||||
|
||||
**Fix:**
|
||||
- Tools → Options → Connection
|
||||
- Set a static port (e.g., `50000`)
|
||||
- Disable "Use UPnP / NAT-PMP port forwarding" (avoid relying on auto)
|
||||
- Forward that port manually at the router
|
||||
|
||||
## Cause 3: Router Port Not Forwarded (TP-Link AX72)
|
||||
|
||||
On TP-Link AX72, port forwarding is **not** under "Virtual Server" — it's at:
|
||||
|
||||
> **Advanced → NAT Forwarding → Port Forwarding**
|
||||
|
||||
Add a rule:
|
||||
- Service Name: qBittorrent
|
||||
- External Port: 50000
|
||||
- Internal IP: \<LXC/container IP\>
|
||||
- Internal Port: 50000
|
||||
- Protocol: TCP+UDP
|
||||
|
||||
## Config File Shortcuts
|
||||
|
||||
```ini
|
||||
[Connection]
|
||||
ProxyType=0
|
||||
PortRangeMin=50000
|
||||
|
||||
[Upload]
|
||||
RateLimit=-1
|
||||
```
|
||||
|
||||
Config location (Linux): `~/.config/qBittorrent/qBittorrent.conf`
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/docker-bridge-subnet-whitelist]] — Docker containers appear as 172.x.x.x, not 192.168.x.x; WebUI auth bypass subnets must include Docker range
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-03.md]] — qBit showing 0 KB/s; root causes: proxy profile blocking + UPnP + missing TP-Link port forward; fixed by disabling proxy, setting static port 50000, forwarding at router
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
---
|
||||
title: "rspamd — Sender Whitelist and BAYES Data Reset in Mailcow"
|
||||
aliases: [rspamd-whitelist, rspamd-bayes-reset, mailcow-spam-whitelist, rspamd-score-override]
|
||||
tags: [rspamd, mailcow, email, spam, whitelist, bayes, selfhosted]
|
||||
sources:
|
||||
- "daily/2026-05-08.md"
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# rspamd — Sender Whitelist and BAYES Data Reset in Mailcow
|
||||
|
||||
When a legitimate sender is blocked by rspamd (Spamhaus SBL, BAYES_SPAM, or other rules), the fastest fix is to add the sender domain to rspamd's whitelist with a large negative score override. If BAYES has already been trained on the domain's messages as spam, that training data must also be cleared.
|
||||
|
||||
## Key Points
|
||||
|
||||
- rspamd whitelist assigns a score override — a score of `-100` overrides all positive rule scores and guarantees delivery.
|
||||
- Spamhaus SBL (blocklist) and BAYES_SPAM are independent signals; both must be addressed.
|
||||
- BAYES training data is per-domain in Mailcow's rspamd Redis instance.
|
||||
- The whitelist file lives inside the `rspamd` Docker container at `/etc/rspamd/local.d/`.
|
||||
- Mailcow UI also exposes a whitelist (Mailcow Admin → Spam Filter → Whitelist) but the file-based approach gives score control.
|
||||
|
||||
## Whitelisting a Sender Domain
|
||||
|
||||
### Via Mailcow Admin UI
|
||||
|
||||
1. Mailcow Admin → **Spam Filter** → **Whitelist**
|
||||
2. Add the domain (e.g. `axilaccountants.co.uk`) — sets score to a permissive threshold.
|
||||
|
||||
### Via rspamd config file (score override)
|
||||
|
||||
```bash
|
||||
# Enter the rspamd container
|
||||
docker exec -it mailcowdockerized-rspamd-mailcow-1 bash
|
||||
|
||||
# Create or edit the whitelist map
|
||||
cat >> /etc/rspamd/local.d/whitelist_sender_domain.inc << 'EOF'
|
||||
axilaccountants.co.uk
|
||||
EOF
|
||||
|
||||
# Or use the multimap config for a score override
|
||||
cat >> /etc/rspamd/local.d/multimap.conf << 'EOF'
|
||||
WHITELIST_SENDER_DOMAIN {
|
||||
type = "from";
|
||||
filter = "email:domain";
|
||||
map = "${CONFDIR}/local.d/whitelist_sender_domain.inc";
|
||||
score = -100.0;
|
||||
description = "Trusted sender domains";
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
Reload rspamd after changes:
|
||||
|
||||
```bash
|
||||
docker exec mailcowdockerized-rspamd-mailcow-1 rspamadm control reload
|
||||
```
|
||||
|
||||
## Clearing BAYES Training Data
|
||||
|
||||
If BAYES_SPAM has been trained on a domain's messages, those weights persist in Redis and will continue scoring future messages as spam even after whitelisting.
|
||||
|
||||
```bash
|
||||
# Connect to rspamd Redis
|
||||
docker exec -it mailcowdockerized-redis-mailcow-1 redis-cli
|
||||
|
||||
# List all BAYES keys (to identify the scope)
|
||||
KEYS bayes*
|
||||
|
||||
# Clear BAYES corpus for a specific sender
|
||||
# rspamd uses hashed tokens — easiest fix is resetting the entire BAYES corpus
|
||||
# (only do this if the corpus is small / mostly incorrect)
|
||||
FLUSHDB
|
||||
```
|
||||
|
||||
> **Warning:** `FLUSHDB` resets ALL BAYES training. On an established server, prefer per-message retraining via `rspamc learn_ham` instead.
|
||||
|
||||
### Retraining as Ham
|
||||
|
||||
```bash
|
||||
# From outside the container, pipe the EML through rspamc
|
||||
cat message.eml | docker exec -i mailcowdockerized-rspamd-mailcow-1 \
|
||||
rspamc learn_ham
|
||||
```
|
||||
|
||||
## Verifying the Whitelist Works
|
||||
|
||||
Send a test email from the whitelisted domain and check rspamd logs:
|
||||
|
||||
```bash
|
||||
docker logs mailcowdockerized-rspamd-mailcow-1 --since 5m | grep axilaccountants
|
||||
```
|
||||
|
||||
Look for `WHITELIST_SENDER_DOMAIN` in the symbol list and a negative total score.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/apple-mail-trust-junk-headers]] — even with rspamd fixed, Apple Mail can still auto-delete if "Trust junk mail headers" is enabled
|
||||
- [[wiki/concepts/dovecot-expunge-irreversible]] — emails deleted before whitelisting are gone permanently without a backup
|
||||
- [[wiki/concepts/mailcow-maildir-import]] — procedure for importing recovered emails back into Mailcow
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-05-08.md]] — axilaccountants.co.uk blocked by Spamhaus SBL + BAYES_SPAM 93.84%; domain whitelisted with score -100; BAYES data cleared for the domain
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
---
|
||||
title: "Sonarr Custom Formats — Quality Profile Scoping and 'Any' Bypass"
|
||||
aliases: [sonarr-custom-formats, sonarr-quality-profile, sonarr-any-profile]
|
||||
tags: [sonarr, media-stack, homelab, torrent, custom-formats]
|
||||
sources:
|
||||
- "daily/2026-04-29.md"
|
||||
created: 2026-04-29
|
||||
updated: 2026-04-29
|
||||
---
|
||||
|
||||
# Sonarr Custom Formats — Quality Profile Scoping and "Any" Bypass
|
||||
|
||||
Sonarr Custom Formats apply score-based ranking to downloaded releases. A critical scoping rule: Custom Format scores are only evaluated within the Quality Profile that is explicitly assigned to a series. If that profile is "Any", Custom Format scores are completely ignored — Sonarr treats "Any" as "accept everything regardless of format scoring".
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Custom Formats only score within the assigned Quality Profile** — a format with +500 points has zero effect if the series uses "Any"
|
||||
- **"Any" profile bypasses all Custom Format scores** — it is a catch-all that ignores language and quality preferences
|
||||
- **Always assign an explicit profile when language or quality matters** — use "Russian 1080p", "HD - 720p/1080p", or a custom named profile
|
||||
- **Season packs behave normally** — Sonarr attaches the same torrent to all episodes in a season; 26 identical queue entries for a 26-episode season is expected
|
||||
- **RuTracker releases may lack `[rus]` in the filename** even for Russian audio rips — verify audio tracks in Jellyfin after download
|
||||
|
||||
## Details
|
||||
|
||||
### How Custom Format Scoping Works
|
||||
|
||||
Custom Formats define patterns (release name regex, indexer flags, language tags) and assign a score. Sonarr uses these scores to rank competing releases inside a Quality Profile's cutoff/upgrade logic.
|
||||
|
||||
The scoring pipeline is:
|
||||
|
||||
1. A release matches a Quality Profile's quality tiers (e.g., "HDTV-1080p", "Bluray-1080p")
|
||||
2. Among qualifying releases, Custom Format scores break ties and drive upgrades
|
||||
3. **If the profile is "Any"**, step 1 accepts all qualities and step 2 is skipped — Custom Format scores are not consulted
|
||||
|
||||
This means a Custom Format like "Russian Audio (+500)" can be active and correctly configured, yet have zero effect on series set to "Any".
|
||||
|
||||
### Practical Example
|
||||
|
||||
Setup: Custom Format id=1, name "Russian Audio", score +500, active in profiles "Russian 1080p" and "HD - 720p/1080p".
|
||||
|
||||
- Series A → profile "Russian 1080p" → Custom Format scores evaluated → Russian audio releases preferred
|
||||
- Series B → profile "Any" → Custom Format scores ignored → first available release grabbed regardless of audio
|
||||
|
||||
### Season Pack Queue Behavior
|
||||
|
||||
When Sonarr grabs a season pack torrent (e.g., `ShowName.S01.Complete`), it creates one queue entry per episode in that season — all pointing to the same torrent. A 26-episode season produces 26 identical queue rows. This is normal; Sonarr will extract individual episodes from the single download.
|
||||
|
||||
### RuTracker Audio Verification
|
||||
|
||||
RuTracker releases for Russian-dubbed content often omit `[rus]` or `[RUS]` from the filename. The Custom Format match may fail at the filename-pattern stage. After download completes, open the episode in Jellyfin → check the audio stream list to confirm Russian audio is present.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/prowlarr-flaresolverr-limitation]] — Prowlarr indexer issues including RuTracker; FlareSolverr bypass
|
||||
- [[wiki/concepts/prowlarr-flaresolverr-get-only]] — FlareSolverr GET-only limitation; SQLite cookie injection for RuTracker login
|
||||
- [[wiki/concepts/jellyfin-tmdb-thetvdb-plugin]] — Jellyfin plugin config; episode naming; Prowlarr search-only role
|
||||
- [[wiki/homelab/_index]] — media stack: Radarr, Sonarr, Prowlarr, qBittorrent
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-29.md]] — Sonarr Custom Format "Any" bypass discovered; Russian audio Custom Format (id=1, +500) active in two profiles but not "Any"; season pack 26-queue-entry behavior confirmed normal; RuTracker filename lacks [rus] tag
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
---
|
||||
title: "Sonarr Custom Formats — Quality Profile Scoping and Russian Audio"
|
||||
aliases: [sonarr-custom-formats, sonarr-quality-profile, sonarr-russian-audio]
|
||||
tags: [sonarr, media-stack, homelab, custom-formats, quality-profile, rutracker]
|
||||
sources:
|
||||
- "daily/2026-04-29.md"
|
||||
created: 2026-04-29
|
||||
updated: 2026-04-29
|
||||
---
|
||||
|
||||
# Sonarr Custom Formats — Quality Profile Scoping and Russian Audio
|
||||
|
||||
Sonarr's Custom Formats system assigns preference scores to releases based on regex patterns (codec, language, group, etc.). A critical and non-obvious constraint: **Custom Format scores only apply within the Quality Profile that has them enabled**. The built-in "Any" quality profile ignores all Custom Format scoring entirely, so Russian Audio preferences have no effect unless a specific Russian-targeting profile is selected per series.
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Custom Formats are Quality Profile-scoped** — a format with +500 points in "Russian 1080p" has zero effect if the series uses the "Any" profile
|
||||
- **"Any" profile bypasses Custom Format scoring completely** — it matches any quality without evaluating format scores
|
||||
- **Russian Audio custom format** (id=1, +500 points) only fires in "Russian 1080p" or "HD - 720p/1080p" profiles — must explicitly assign one of these to each series requiring Russian audio
|
||||
- **Season pack torrents create N identical queue entries** — one entry per episode in the season, all pointing to the same download; 26 entries for a 26-episode season is normal Sonarr behavior, not a bug
|
||||
- **RuTracker releases often lack `[rus]` in the filename** even when the release is fully Russian-dubbed — verify actual audio tracks in Jellyfin after download completes
|
||||
|
||||
## Details
|
||||
|
||||
### Custom Format Scoring — How It Works
|
||||
|
||||
Custom Formats in Sonarr are regex-based rules that match against release names. Each format can be assigned a score (positive = preferred, negative = penalised) within each Quality Profile independently.
|
||||
|
||||
The scoring workflow:
|
||||
1. Sonarr finds candidate releases for an episode/season
|
||||
2. For each release, it calculates a Custom Format score by summing all matched format scores **for the active Quality Profile**
|
||||
3. The release with the best combined quality + CF score wins
|
||||
|
||||
If the series is on the "Any" profile, step 2 produces a score of 0 for every release — no differentiation happens.
|
||||
|
||||
### Fixing Russian Audio Selection
|
||||
|
||||
To ensure Russian-dubbed releases are preferred:
|
||||
|
||||
1. In Sonarr → Settings → Quality Profiles — confirm "Russian 1080p" or "HD - 720p/1080p" has the Russian Audio format enabled with a high score (e.g. +500)
|
||||
2. Per series: open the series → Edit → Quality Profile → change from "Any" to "Russian 1080p"
|
||||
3. In Prowlarr → Indexers → set RuTracker to Priority 1 (lower number = higher priority) so it is always searched first before other indexers
|
||||
|
||||
### Season Pack Queue Behavior
|
||||
|
||||
When Sonarr downloads a season pack torrent (e.g. "Merlin S01 Complete"), it attaches the single download to all episodes in that season. In the Activity queue, this appears as one row per episode — all with identical torrent names, identical progress, identical ETA.
|
||||
|
||||
This is intentional: Sonarr tracks completion at the episode level. Once the torrent finishes, it renames and moves each episode file individually. Do not cancel or remove these "duplicate" queue entries — they will all resolve when the single download completes.
|
||||
|
||||
### RuTracker Filename Conventions
|
||||
|
||||
RuTracker release names for Russian dubs frequently omit audio language tags:
|
||||
|
||||
- `Merlin.S01.1080p.BluRay` (no `[rus]` tag) may still contain Russian audio tracks
|
||||
- Some releases include multiple audio tracks (Russian + English) with no indication in the filename
|
||||
- The only reliable way to confirm Russian audio: open the file in Jellyfin → inspect available audio tracks in the player
|
||||
|
||||
This also means Sonarr's Custom Format regex matching on `\brus\b` or `russian` in the filename will not always fire for genuine Russian releases — the +500 score boost works by finding RuTracker releases (via Prowlarr indexer priority) rather than filename matching.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/prowlarr-flaresolverr-limitation]] — RuTracker cookie injection workaround; Prowlarr priority configuration for RuTracker
|
||||
- [[wiki/concepts/jellyfin-tmdb-thetvdb-plugin]] — Jellyfin audio track inspection, TMDb vs TheTVDB plugin behavior, S01E01 naming conventions
|
||||
- [[wiki/homelab/_index]] — media stack overview: Prowlarr → Sonarr → qBittorrent → Jellyfin pipeline
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-29.md]] — Sonarr session: "Russian Audio" Custom Format id=1 confirmed +500 but inactive on "Any" profile; RuTracker set to priority 1 in Prowlarr; Merlin Season 2 downloading at 4.2 MB/s, Season 1 stalled at 0 seeders; season pack queue behavior observed
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
---
|
||||
title: "SSH Keys with Passphrases Require ssh-add"
|
||||
aliases: [ssh-add passphrase, no identity pubkey loaded, ssh agent keychain, ssh AddKeysToAgent]
|
||||
tags: [ssh, git, forgejo, homelab, dotfiles, fish]
|
||||
sources:
|
||||
- "daily/2026-04-30.md"
|
||||
created: 2026-04-30
|
||||
updated: 2026-04-30
|
||||
---
|
||||
|
||||
# SSH Keys with Passphrases Require ssh-add
|
||||
|
||||
An SSH key with a passphrase will not be used automatically even if it is listed in `~/.ssh/config`. The key must be loaded into ssh-agent first via `ssh-add`. The diagnostic signal for a missing agent-loaded key is `no identity pubkey loaded` in verbose SSH output (`ssh -vvv`). The permanent fix is adding `AddKeysToAgent yes` and `UseKeychain yes` to `~/.ssh/config`.
|
||||
|
||||
## Key Points
|
||||
|
||||
- `no identity pubkey loaded` in `ssh -vvv` output means the key has a passphrase and has not been added to ssh-agent
|
||||
- `ssh-add ~/.ssh/<keyname>` loads the key for the current session
|
||||
- `AddKeysToAgent yes` in `~/.ssh/config` auto-loads the key on first use (prompts for passphrase once)
|
||||
- `UseKeychain yes` (macOS) stores the passphrase in the system Keychain so it survives reboots without re-prompting
|
||||
- Forgejo SSH is on **port 222**, not 22 — host: `git.ai-impress.com`; key: `~/.ssh/Forgejo`
|
||||
|
||||
## Details
|
||||
|
||||
### Diagnostic flow
|
||||
|
||||
```bash
|
||||
# Test with verbose output to see what's happening
|
||||
ssh -vvv -T git@git.ai-impress.com -p 222
|
||||
|
||||
# Key symptoms in output:
|
||||
# "no identity pubkey loaded" → key has passphrase, not in agent
|
||||
# "Permission denied (publickey)" → key loaded but not accepted by server
|
||||
```
|
||||
|
||||
### Session fix
|
||||
|
||||
```bash
|
||||
# Load the key into the agent for the current session
|
||||
ssh-add ~/.ssh/Forgejo
|
||||
# Prompts for passphrase once; key is usable for the rest of the session
|
||||
```
|
||||
|
||||
### Permanent fix — `~/.ssh/config`
|
||||
|
||||
```
|
||||
Host git.ai-impress.com
|
||||
HostName git.ai-impress.com
|
||||
User git
|
||||
Port 222
|
||||
IdentityFile ~/.ssh/Forgejo
|
||||
AddKeysToAgent yes
|
||||
UseKeychain yes
|
||||
```
|
||||
|
||||
With `AddKeysToAgent yes`, the first SSH use in a session prompts for the passphrase and loads the key automatically — no manual `ssh-add` needed. With `UseKeychain yes` on macOS, the passphrase is persisted in the Keychain across reboots.
|
||||
|
||||
### Fish shell note
|
||||
|
||||
Fish shell does not source `/etc/profile` or `~/.bashrc`, so `SSH_AUTH_SOCK` may not be set if ssh-agent is started from a bash-style init file. Ensure ssh-agent is started (or the macOS launchd agent is active) before relying on `AddKeysToAgent`. A `~/.config/fish/conf.d/ssh-agent.fish` snippet can handle this:
|
||||
|
||||
```fish
|
||||
# Ensure ssh-agent socket is available in Fish
|
||||
if not set -q SSH_AUTH_SOCK
|
||||
eval (ssh-agent -c)
|
||||
end
|
||||
```
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/fish-shell-path-config]] — Fish shell init files and PATH configuration; relevant when ssh-agent env vars aren't propagating
|
||||
- [[wiki/concepts/remote-server-dotfiles-bootstrap]] — Full dotfiles bootstrap including SSH config deployment to remote servers
|
||||
- [[wiki/concepts/git-includeif-per-remote]] — Per-remote git identity config, which also relies on SSH key selection working correctly
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-30.md]] — Forgejo SSH key `~/.ssh/Forgejo` wasn't loading; `no identity pubkey loaded` diagnosed passphrase+agent issue; `ssh-add` fixed it for the session; `AddKeysToAgent yes` + `UseKeychain yes` added to `~/.ssh/config` for persistence
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
---
|
||||
title: "Vaultwarden Master Password = Encryption Key"
|
||||
aliases: [vaultwarden encryption, bitwarden master password encryption, vaultwarden password reset]
|
||||
tags: [vaultwarden, bitwarden, encryption, homelab, backup, security]
|
||||
sources:
|
||||
- "daily/2026-04-30.md"
|
||||
created: 2026-04-30
|
||||
updated: 2026-04-30
|
||||
---
|
||||
|
||||
# Vaultwarden Master Password = Encryption Key
|
||||
|
||||
Vaultwarden (self-hosted Bitwarden) uses end-to-end encryption where the master password is not just an authentication credential — it IS the encryption key used to encrypt and decrypt all vault data. This means there is no server-side "reset password" operation that preserves vault contents: resetting or losing the master password permanently destroys access to all stored secrets.
|
||||
|
||||
## Key Points
|
||||
|
||||
- The master password is the encryption key — it never leaves the client in plaintext
|
||||
- Resetting the master password (via admin panel or DB) re-keys the account but leaves all existing vault entries encrypted under the old key, making them unreadable
|
||||
- The only recovery path after a lost master password is restoring from a backup that predates the password loss
|
||||
- SSO login (e.g., via Authentik) is layered on top; if SSO is removed, email/password login still works as long as the master password is known
|
||||
- Pre-commit hooks that scan for credential patterns will flag secrets written to disk — always use env vars or session tokens for automation that touches Vaultwarden
|
||||
|
||||
## Details
|
||||
|
||||
### Why reset appears to work but vault is empty
|
||||
|
||||
When an admin resets a user's master password from the Vaultwarden admin panel, the account password hash is updated. The user can log in — but every vault item remains AES-256 encrypted under the original key derived from the old master password. The UI shows an empty vault, not an error.
|
||||
|
||||
### SSO removal doesn't break email login
|
||||
|
||||
If Authentik (or any OIDC provider) is removed from Vaultwarden, the email+password login path continues to work. The SSO flow is an alternative authentication path, not a replacement for local credentials.
|
||||
|
||||
### Backup restore procedure
|
||||
|
||||
If the master password is forgotten:
|
||||
|
||||
1. Stop Vaultwarden container
|
||||
2. Restore the `/data/` volume from a Backrest (or equivalent) backup taken before the password was changed/forgotten
|
||||
3. Start Vaultwarden — the old master password unlocks the vault again
|
||||
|
||||
```bash
|
||||
# Stop container first
|
||||
docker compose stop vaultwarden
|
||||
|
||||
# Restore from Backrest snapshot (adjust snapshot ID and path)
|
||||
backrest restore --snapshot <snap-id> --target /opt/vaultwarden/data/
|
||||
|
||||
# Restart
|
||||
docker compose start vaultwarden
|
||||
```
|
||||
|
||||
### Homelab service password reset context
|
||||
|
||||
In a homelab bulk reset (all services to `admin`), Vaultwarden's admin panel "change master password" should NOT be used to reset a user's vault password unless the vault data is expendable — the data will become inaccessible. Use the admin panel only for account management tasks that don't require decrypting vault items.
|
||||
|
||||
## Related Concepts
|
||||
|
||||
- [[wiki/concepts/authentik-homelab-tradeoffs]] — Authentik SSO was the IdP layered over Vaultwarden; its removal doesn't affect the master-password encryption flow
|
||||
- [[wiki/homelab/_index]] — Broader homelab service inventory and backup practices
|
||||
|
||||
## Sources
|
||||
|
||||
- [[daily/2026-04-30.md]] — Bulk homelab password reset revealed that Vaultwarden's master password cannot be reset like other service passwords; E2E encryption model and Backrest recovery path documented
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
---
|
||||
title: "Aerospace Tiling Window Manager for macOS"
|
||||
aliases: [aerospace, aerospace-wm, macos-tiling-wm]
|
||||
tags: [dotfiles, macos, tiling-wm, aerospace, productivity, keybindings]
|
||||
sources: [raw/Aerospace Is The Best Tiling Window Manager I've Tried On macOS.md]
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# Aerospace Tiling Window Manager for macOS
|
||||
|
||||
i3-inspired tiling WM for macOS. No SIP disable required (unlike Yabai). Currently in public beta — used daily by the creator and stable enough for daily driving.
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- **No SIP required** — unlike Yabai, Aerospace does not need System Integrity Protection disabled
|
||||
- **i3-style modal keybindings** — main mode + custom modes (e.g. service mode), identical mental model to i3 on Linux
|
||||
- **Reimplements spaces** — bypasses macOS built-in Spaces with its own workspace system for better control
|
||||
- **Tree-based layout engine** — windows are leaf nodes; containers hold tiles or accordions in horizontal/vertical orientations
|
||||
- **Window callbacks** — auto-route new windows to workspaces by app ID; move mouse on focus change
|
||||
- **Mnemonic workspaces** — use letters (B=browser, T=terminal, M=music, N=notes) for instant recall
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
brew install --cask nikitabobko/tap/aerospace
|
||||
```
|
||||
|
||||
Config locations (pick one):
|
||||
- `~/.aerospace.toml`
|
||||
- `~/.config/aerospace/aerospace.toml`
|
||||
|
||||
```sh
|
||||
mkdir -p ~/.config/aerospace
|
||||
touch ~/.config/aerospace/aerospace.toml
|
||||
```
|
||||
|
||||
Paste the [default config](https://nikitabobko.github.io/AeroSpace/guide#default-config) as a starting point.
|
||||
|
||||
### Recommended initial changes
|
||||
|
||||
```toml
|
||||
# Start at login
|
||||
start-at-login = true
|
||||
|
||||
# Gaps between windows and monitor edges
|
||||
[gaps]
|
||||
inner.horizontal = 10
|
||||
inner.vertical = 10
|
||||
outer.left = 10
|
||||
outer.right = 10
|
||||
outer.top = 10
|
||||
outer.bottom = 10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Keybinding Modes
|
||||
|
||||
Aerospace uses **modes** (like i3). Default mode is `main`. Define additional modes with `[mode.<name>.binding]`.
|
||||
|
||||
```toml
|
||||
# Enter service mode
|
||||
alt-shift-semicolon = ['mode service']
|
||||
|
||||
[mode.service.binding]
|
||||
esc = ['reload-config', 'mode main'] # reload + return to main
|
||||
```
|
||||
|
||||
Reload config: `alt-shift-;` → `esc`
|
||||
|
||||
---
|
||||
|
||||
## Focus & Moving Windows
|
||||
|
||||
| Action | Default Keybind |
|
||||
|--------|----------------|
|
||||
| Focus left/down/up/right | `alt-h/j/k/l` |
|
||||
| Move window left/down/up/right | `alt-shift-h/j/k/l` |
|
||||
|
||||
---
|
||||
|
||||
## Layouts
|
||||
|
||||
Aerospace uses a **tree** internally. Windows are always leaf nodes; containers define layout.
|
||||
|
||||
### Two layout types
|
||||
|
||||
| Layout | Toggle | Description |
|
||||
|--------|--------|-------------|
|
||||
| Tiles | `alt-/` | Side-by-side; toggle horizontal ↔ vertical |
|
||||
| Accordion | `alt-,` | One window at a time with peeking padding |
|
||||
|
||||
### Joining windows into a sub-container
|
||||
|
||||
In service mode: `alt-shift-h/j/k/l` (join-with command) — groups two windows under a shared parent container, enabling nested layout control.
|
||||
|
||||
---
|
||||
|
||||
## Resizing
|
||||
|
||||
| Action | Keybind |
|
||||
|--------|---------|
|
||||
| Shrink window | `alt-shift--` |
|
||||
| Grow window | `alt-shift-=` |
|
||||
|
||||
Resize direction is determined by the parent container's orientation (horizontal or vertical).
|
||||
|
||||
---
|
||||
|
||||
## Workspaces
|
||||
|
||||
- Numbered 1–9, lettered A–Z
|
||||
- Switch: `alt-<number/letter>`
|
||||
- Move focused node: `alt-shift-<number/letter>`
|
||||
|
||||
### Mnemonic workspace layout (recommended)
|
||||
|
||||
| Workspace | App |
|
||||
|-----------|-----|
|
||||
| `B` | Browser |
|
||||
| `T` | Terminal |
|
||||
| `M` | Music |
|
||||
| `N` | Notes |
|
||||
| `P` | Photo editing |
|
||||
| `V` | Video editing |
|
||||
|
||||
Optionally combine move + switch in one binding:
|
||||
|
||||
```toml
|
||||
alt-shift-1 = ['move-node-to-workspace 1', 'workspace 1']
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Callbacks
|
||||
|
||||
### Auto-route new windows to workspaces
|
||||
|
||||
```toml
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.googlecode.iterm2' # find IDs with: aerospace list-apps
|
||||
run = 'move-node-to-workspace T'
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.google.Chrome'
|
||||
run = 'move-node-to-workspace B'
|
||||
```
|
||||
|
||||
### Move mouse on focus change
|
||||
|
||||
```toml
|
||||
on-focused-monitor-changed = ['move-mouse monitor-lazy-center']
|
||||
on-focus-changed = ['move-mouse window-lazy-center']
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Floating & Fullscreen
|
||||
|
||||
- **Float/tile toggle:** service mode → `f`
|
||||
- **Fullscreen** (custom keybind):
|
||||
|
||||
```toml
|
||||
alt-shift-f = 'fullscreen'
|
||||
```
|
||||
|
||||
Aerospace auto-floats windows it detects should float (e.g. System Preferences).
|
||||
|
||||
---
|
||||
|
||||
## Multiple Monitors
|
||||
|
||||
- `alt-shift-tab` — move current workspace to next monitor
|
||||
|
||||
---
|
||||
|
||||
## Mission Control Fix
|
||||
|
||||
Aerospace hides inactive workspace windows off-screen. Mission Control shows them tiny.
|
||||
|
||||
**Fix:** System Settings → Desktop & Dock → Mission Control → enable **"Group windows by application"**
|
||||
|
||||
---
|
||||
|
||||
## Related Articles
|
||||
|
||||
- [[wiki/dotfiles/wezterm-workspaces|WezTerm Workspaces]] — WezTerm's own workspace/session system
|
||||
- [[wiki/dotfiles/wezterm-key-tables|WezTerm Key Tables]] — modal keybinding layers, similar concept to Aerospace modes
|
||||
- [[wiki/dotfiles/linux-terminal-ricing|Linux Terminal Ricing]] — full ricing guide including window management
|
||||
- [[wiki/dotfiles/fish-shell-intro|Fish Shell Intro]] — shell that pairs well with this WM setup
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- Raw: `raw/Aerospace Is The Best Tiling Window Manager I've Tried On macOS.md`
|
||||
- Original video: Josean Martinez, YouTube, 2024-08-10
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
---
|
||||
title: "Gemini Model Catalog"
|
||||
aliases: [google-gemini-models, gemini-api-models]
|
||||
tags: [llm, google, gemini, api, models]
|
||||
sources: [raw/Gemini API Google AI for Developers.md]
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Google's Gemini API model lineup spans text, audio, image, video, music, embeddings, and robotics. Models are grouped by generation (2.5, 3.x) and tier (Pro > Flash > Flash-Lite). All available via [Google AI for Developers](https://ai.google.dev/gemini-api/docs/models).
|
||||
|
||||
---
|
||||
|
||||
## Gemini 2.5 Family (Current Stable)
|
||||
|
||||
| Model | Tier | Status | Best For |
|
||||
|-------|------|--------|----------|
|
||||
| `gemini-2.5-pro` | Pro | Stable | Complex tasks, deep reasoning, coding |
|
||||
| `gemini-2.5-flash` | Flash | Stable | Price-performance, low-latency, high-volume |
|
||||
| `gemini-2.5-flash-lite` | Flash-Lite | Stable | Fastest + cheapest multimodal in 2.5 family |
|
||||
| Gemini 2.5 Flash Live | Flash | Preview | Real-time conversational agents, sub-second audio |
|
||||
| Gemini 2.5 Flash TTS | Flash | Preview | Controllable text-to-speech, fine style/pacing control |
|
||||
| Gemini 2.5 Pro TTS | Pro | Preview | High-fidelity TTS for podcasts, audiobooks |
|
||||
| Imagen 4 (Nano Banana) | Flash | Stable | Native image gen/editing, fast creative workflows |
|
||||
|
||||
---
|
||||
|
||||
## Gemini 3 Family (Preview / Upcoming)
|
||||
|
||||
| Model | Status | Best For |
|
||||
|-------|--------|----------|
|
||||
| `gemini-3.1-pro-preview` | Preview | Advanced reasoning, agentic, vibe coding |
|
||||
| `gemini-3-flash-preview` | Preview | Frontier-class perf at lower cost |
|
||||
| `gemini-3.1-flash-lite` | Stable | Frontier-class, budget-friendly |
|
||||
| `gemini-3.1-flash-live-preview` | Preview | Real-time dialogue, voice-first AI |
|
||||
| `gemini-3.1-flash-tts-preview` | Preview | Low-latency speech generation |
|
||||
| Nano Banana 2 (image) | Preview | High-efficiency production image gen + editing |
|
||||
| Nano Banana Pro (image) | Preview | Studio-quality 4K, complex layouts, text rendering |
|
||||
|
||||
> **Note:** "Nano Banana" appears to be Google's display alias for Imagen-series image generation models (Imagen 4 family).
|
||||
|
||||
---
|
||||
|
||||
## Audio Models
|
||||
|
||||
| Model | Latency | Use Case |
|
||||
|-------|---------|----------|
|
||||
| Gemini 3.1 Flash Live | Low | A2A real-time dialogue, voice-first apps |
|
||||
| Gemini 3.1 Flash TTS | Low | TTS with expressive audio tags |
|
||||
| Gemini 2.5 Flash Live | Low | Bidirectional voice + video agents, native audio reasoning |
|
||||
| Gemini 2.5 Flash TTS | Low | Cost-efficient real-time TTS |
|
||||
| Gemini 2.5 Pro TTS | High fidelity | Structured workflows (podcasts, audiobooks) |
|
||||
|
||||
---
|
||||
|
||||
## Generative Media Models
|
||||
|
||||
| Model | Type | Status |
|
||||
|-------|------|--------|
|
||||
| Nano Banana 2 | Image gen/edit | Preview |
|
||||
| Nano Banana Pro | Image gen/edit | Preview |
|
||||
| Nano Banana (2.5) | Image gen/edit | Stable |
|
||||
| Imagen 4 | Text-to-image (up to 2K) | Stable |
|
||||
| Veo 3.1 | Video + synced audio | Preview |
|
||||
| Veo 3.1 Lite | Low-cost video gen/edit | Preview |
|
||||
|
||||
---
|
||||
|
||||
## Music Generation Models
|
||||
|
||||
| Model | Use Case |
|
||||
|-------|----------|
|
||||
| Lyria 3 Pro | Full-length songs, structural coherence |
|
||||
| Lyria 3 Clip | Short clips, loops, ≤30 sec previews |
|
||||
| Lyria RealTime Experimental | Granular control, real-time streaming |
|
||||
|
||||
---
|
||||
|
||||
## Tool & Agent Models
|
||||
|
||||
| Model | Capability |
|
||||
|-------|-----------|
|
||||
| Computer Use Preview | Screen vision + UI actions (click, type, navigate) — browser automation |
|
||||
| Gemini Deep Research Preview | Agentic multi-step research across hundreds of sources, cited reports |
|
||||
| Gemini Deep Research Max Preview | Maximum comprehensiveness version of Deep Research |
|
||||
|
||||
---
|
||||
|
||||
## Specialized Task Models
|
||||
|
||||
| Model | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| Gemini Embedding 2 | Multimodal embedding | Text + image + video + audio + PDF → unified vector space |
|
||||
| Gemini Embedding | Text embedding | High-dimensional vectors for semantic search, RAG |
|
||||
| Gemini Robotics-ER 1.6 | Embodied reasoning | Physical space understanding, multi-step robotic tasks |
|
||||
|
||||
---
|
||||
|
||||
## Model Version Naming Conventions
|
||||
|
||||
| Channel | Example ID | Behavior |
|
||||
|---------|-----------|----------|
|
||||
| **Stable** | `gemini-2.5-flash` | Fixed version, rarely changes. Recommended for production |
|
||||
| **Preview** | `gemini-2.5-flash-preview-09-2025` | Production-eligible, billing enabled, ≥2 weeks deprecation notice |
|
||||
| **Latest** | `gemini-flash-latest` | Auto-updates to newest release; 2-week email notice before swap |
|
||||
| **Experimental** | `gemini-*-exp-*` | Not for production, restricted rate limits, may disappear |
|
||||
|
||||
---
|
||||
|
||||
## Deprecated / Shut Down
|
||||
|
||||
| Model | Status | Notes |
|
||||
|-------|--------|-------|
|
||||
| Gemini 2.0 Flash | Deprecated | 1M context, native tool use |
|
||||
| Gemini 2.0 Flash-Lite | Deprecated | Fastest gen-2 |
|
||||
| Gemini 3 Pro Preview | Shut down | |
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- **2.5 Flash** is the current go-to for cost/performance balance; **2.5 Pro** for complex reasoning
|
||||
- **Gemini 3.x** is in preview — 3.1 Flash-Lite is already stable, rest require preview access
|
||||
- Gemini has dedicated **audio Live models** for real-time voice agents (A2A streaming)
|
||||
- **"Nano Banana"** = Google's display name for Imagen-series image models in the API console
|
||||
- **Computer Use** model can automate browser UIs natively — similar to Anthropic's computer use
|
||||
- **Gemini Embedding 2** is multimodal — handles text, images, video, audio, PDF in one embedding space
|
||||
- Use `gemini-flash-latest` alias with caution — it hot-swaps on new releases with only 2-week notice
|
||||
- Experimental models have no stability guarantees and restrictive rate limits
|
||||
|
||||
---
|
||||
|
||||
## Related Articles
|
||||
|
||||
- [[wiki/llm-models/claude-model-catalog|Claude Model Catalog]] — Anthropic Opus/Sonnet/Haiku comparison
|
||||
- [[wiki/llm-models/openai-model-catalog|OpenAI Model Catalog]] — GPT-5.x, o-series, audio models
|
||||
- [[wiki/tech-patterns/_index|Tech Patterns]] — RAG, embeddings, AI patterns used in projects
|
||||
- [[wiki/architecture/_index|Architecture]] — Multi-agent AI, RAG system design
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- Raw: `raw/Gemini API Google AI for Developers.md`
|
||||
- Original: https://ai.google.dev/gemini-api/docs/models (captured 2026-05-08)
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
---
|
||||
title: "OMG Platform REST API"
|
||||
aliases: [omg-api, oliver-omg-api, omg-marketing-ops-api]
|
||||
tags: [api, oliver, omg, briefs, deliverables, tasks, rest]
|
||||
sources: [raw/Scalar API Reference.md]
|
||||
created: 2026-05-08
|
||||
updated: 2026-05-08
|
||||
---
|
||||
|
||||
# OMG Platform REST API
|
||||
|
||||
REST API for the **OMG marketing operations platform** (Oliver internal). Manages briefs, deliverables, projects, tasks, file uploads, and library batch operations.
|
||||
|
||||
- **Version:** v2.0.0 (OAS 3.0.3)
|
||||
- **Base URL:** `https://api.omg.dev.oliver.solutions/{tenantID}/v2`
|
||||
- **Gateway:** TYK — resolves tenant + user context from the API key before forwarding
|
||||
|
||||
## Authentication
|
||||
|
||||
Every request requires an `X-Api-Key` header. The TYK gateway uses this key to derive the tenant and user context. No Bearer token or OAuth flow.
|
||||
|
||||
```bash
|
||||
--header 'X-Api-Key: YOUR_SECRET_TOKEN'
|
||||
```
|
||||
|
||||
## Response Format
|
||||
|
||||
**Success:**
|
||||
```json
|
||||
{ "data": { ... }, "message": "..." }
|
||||
```
|
||||
HTTP `200` (read/update/delete) or `201` (created).
|
||||
|
||||
**Error — RFC 7807 Problem Details:**
|
||||
```json
|
||||
{ "type": "about:blank", "title": "...", "status": 422, "detail": "..." }
|
||||
```
|
||||
|
||||
## HTTP Status Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| `200` | Read, update, delete succeeded |
|
||||
| `201` | Resource created |
|
||||
| `400` | Invalid or missing request parameters |
|
||||
| `403` | Auth failure — missing or invalid `X-Api-Key` |
|
||||
| `404` | Resource not found or not in tenant scope |
|
||||
| `422` | Parameters valid but business logic rejected |
|
||||
| `500` | Unexpected server error |
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Briefs `/briefs`
|
||||
|
||||
CRUD for marketing briefs.
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/briefs` | Create a brief |
|
||||
| `GET` | `/briefs/{id}` | Get a brief by ID |
|
||||
| `PATCH` | `/briefs/{id}` | Partial update; include `status: "change_request"` to trigger status transition (all other fields ignored) |
|
||||
| `DELETE` | `/briefs/{id}` | Delete a brief |
|
||||
|
||||
**Create brief fields:** `brief_title`, `slipstream`, `brief_summary`, `brief_deadline` (date), `external_reference`, `business_area`
|
||||
|
||||
**PATCH note:** Two modes — status transition (`status` field only) vs field update (any other fields). They are mutually exclusive.
|
||||
|
||||
### Tasks `/tasks`
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/tasks` | Create a planning task |
|
||||
|
||||
**Fields:** `name`, `start_date` (ISO 8601), `end_date` (ISO 8601), `parent_planning_id`
|
||||
|
||||
### Users `/user` and `/users`
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/user?email=&staffid=` | Lookup by email **or** staffid (exactly one required) |
|
||||
| `GET` | `/user/{id}` | Get user by ID (404 if outside tenant) |
|
||||
| `PUT` | `/user/{id}` | Update user fields (partial — omitted fields unchanged) |
|
||||
| `POST` | `/user/{id}/avatar` | Upload JPEG avatar (`multipart/form-data`); returns new avatar URL; thumbnails generated async |
|
||||
| `GET` | `/users?search=` | List all active users; `search` filters by contains match on name/email/agency/role |
|
||||
|
||||
**User fields:** `first_name`, `last_name`, `email_address`, `owning_agency_id`, `owning_agency_name`, `job_role`, `job_role_name`
|
||||
|
||||
`owning_agency_id` and `job_role` are validated against FK values on PUT.
|
||||
|
||||
### Other Resource Groups (Collapsed in Scalar)
|
||||
|
||||
- **Deliverables** — read and update job deliverables
|
||||
- **Projects** — create and read planning projects and their deliverables
|
||||
- **Library** — client-specific library batch operations
|
||||
- **Debug** — development and smoke-test endpoints
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- **TYK gateway** handles auth and tenant resolution — pass `X-Api-Key`, nothing else
|
||||
- **Multi-tenant**: all paths include `{tenantID}` — scoping is automatic from the key + path combo
|
||||
- **PATCH briefs** has a two-mode design: status transition OR field update, not both
|
||||
- **`422`** is the business-logic rejection code — distinct from `400` (bad params)
|
||||
- **User list** returns `user_dom_small` objects (id, names, email, agency, job_role)
|
||||
- **Avatar upload** is async — thumbnails are generated by background workers after the POST returns
|
||||
- Deliverables, Projects, Library are read/update only (no full CRUD visible in this snapshot)
|
||||
|
||||
## Usage Example
|
||||
|
||||
```bash
|
||||
# Create a brief
|
||||
curl 'https://api.omg.dev.oliver.solutions/{tenantID}/v2/briefs' \
|
||||
--request POST \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'X-Api-Key: YOUR_SECRET_TOKEN' \
|
||||
--data '{
|
||||
"brief_title": "Q3 Campaign Brief",
|
||||
"brief_summary": "Overview of Q3 requirements",
|
||||
"brief_deadline": "2026-06-30",
|
||||
"business_area": "UK/Marketing/Digital"
|
||||
}'
|
||||
|
||||
# List users with search
|
||||
curl 'https://api.omg.dev.oliver.solutions/{tenantID}/v2/users?search=jane' \
|
||||
--header 'X-Api-Key: YOUR_SECRET_TOKEN'
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [[wiki/client-knowledge/ferrero|Ferrero]] — uses OMG platform for AC Booking Tool (`CSV/OMG`)
|
||||
- [[wiki/client-knowledge/3m|3M]] — OMG Portal project (One2Edit + OMG)
|
||||
- [[wiki/tech-patterns/box-api-integration|Box API Integration]] — often paired with OMG for asset workflows
|
||||
- [[wiki/tech-patterns/azure-ad-msal-auth|Azure AD MSAL Auth]] — Oliver's standard auth (contrast: OMG uses X-Api-Key via TYK)
|
||||
|
||||
## Sources
|
||||
|
||||
- `raw/Scalar API Reference.md` — Scalar-rendered OpenAPI spec snapshot, v2.0.0, captured 2026-05-07
|
||||
Loading…
Add table
Reference in a new issue