# Architecture Decisions ## Purpose This document records important architectural and operational decisions made for SilverLinux. The goal is to document not only what was implemented, but also why the decision was made. --- ## 2026-06-17 ### Ubuntu 24.04 LTS Selected Decision: Use Ubuntu Server 24.04 LTS as the operating system. Reason: * Long-term support * Large community * Excellent Docker support * Familiar administration tools Status: Implemented --- ## 2026-06-17 ### Docker Standardization Decision: All services should run in Docker containers whenever possible. Reason: * Consistent deployment * Easier backups * Easier migrations * Better isolation Status: Implemented --- ## 2026-06-17 ### Nginx Proxy Manager Selected Decision: Use Nginx Proxy Manager as the reverse proxy solution. Reason: * Easy SSL management * Simple administration * User-friendly interface * Fast deployment Status: Implemented --- ## 2026-06-17 ### Gitea Selected Decision: Use Gitea for source control. Reason: * Self-hosted * Lightweight * GitHub-like experience * Excellent Docker support Status: Implemented --- ## 2026-06-17 ### PostgreSQL Selected Decision: Use PostgreSQL as the central database platform. Reason: * Reliability * Mature ecosystem * Supports multiple applications * Strong backup tooling Status: Implemented --- ## 2026-06-17 ### OpenProject Selected Decision: Use OpenProject for project management. Reason: * Mature platform * Open source * Strong planning features * Work package management * Time tracking Status: Implemented --- ## 2026-06-21 ### Plane.so Removed Decision: Do not deploy Plane.so. Reason: * OpenProject fully satisfies requirements * Reduces maintenance burden * Avoids duplicate functionality Status: Implemented --- ## 2026-06-21 ### Centralized Secrets Management Decision: Originally store shared credentials in a single secrets file. Location: ```text Legacy local secrets file ``` Reason: * Avoid secrets in Docker Compose files * Easier credential rotation * Easier disaster recovery * Reduced risk of accidental exposure Status: Superseded by Infisical and `slcompose` Current state: * Standard SilverLinux service secrets are stored in Infisical. * `slcompose` injects secrets into Compose stacks at runtime. * The legacy local secrets file should be removed if it still exists. * Sentry is the exception and follows the upstream self-hosted Sentry installation pattern. --- ## 2026-06-21 ### OpenID Disabled in Gitea Decision: Disable OpenID authentication. Reason: * Not required * Reduces attack surface * Simplifies authentication model Status: Implemented --- ## 2026-06-21 ### Gmail SMTP Selected Decision: Use Gmail SMTP for outbound email. Sender: ```text noreply@silveressence.net ``` Reason: * Reliable delivery * Easy setup * Supports application notifications Status: Implemented --- ## 2026-06-21 - Adopt Gitea Actions + Self-Hosted Runner for Package Publishing Decision: * Replace GitHub Actions with self-hosted Gitea Actions. * Execute package publishing on SilverLinux using the global `silverlinux-runner`. * Publish internal NuGet packages to BaGet. * Store the runner registration token in Infisical and publishing credentials in Gitea Actions Secrets. * Use `[Package]` in commit messages to request commit-driven package publishing. Reason: * Keep source control, build execution and package hosting inside SilverLinux. * Avoid storing credentials in repositories. * Provide a simple, explicit package-release convention. Status: ```text Accepted ``` --- ## 2026-06-21 - BaGet Secret Storage Decision: The BaGet API key is currently stored directly in the BaGet Docker Compose configuration. Reason: * Simplicity during initial deployment. Current Plan: Move the API key into the centralized SilverLinux secrets management system: ```text Infisical ``` when the BaGet deployment is fully aligned with the standard `slcompose` pattern. --- ## 2026-06-22 - Deploy Microsoft SQL Server Express Alongside PostgreSQL Decision: * Run Microsoft SQL Server 2022 Express alongside PostgreSQL. * Attach MSSQL only to the `internal` Docker network. * Do not publish port `1433` or route MSSQL through the reverse proxy. * Store `MSSQL_SA_PASSWORD` in Infisical. Reason: * Support Silver projects that require Microsoft SQL Server compatibility. * Allow both database platforms to coexist without exposing database ports. Status: ```text Implemented ``` --- ## 2026-06-22 - Select DbGate for Database Administration Decision: * Use DbGate to administer Microsoft SQL Server and PostgreSQL. * Connect DbGate to both the `internal` and `proxy` Docker networks. * Publish only the DbGate web interface through Nginx Proxy Manager. * Require DbGate authentication and HTTPS. Reason: * Provides one lightweight, modern browser interface for both database platforms. * Keeps PostgreSQL and MSSQL private. Follow-up: Move the DbGate password from any legacy server-side Compose configuration to Infisical. Status: ```text Implemented ``` --- ## 2026-06-24 - Formalize Multi-Network Segmentation Decision: * Treat SilverLinux as a three-layer Docker network architecture. * Use `internal` for private databases and backend service traffic. * Use `proxy` for public HTTP and HTTPS services routed through Nginx Proxy Manager. * Use isolated stack networks for Jitsi, Xray and CI/CD runner traffic where the active runtime attachments support it. Reason: * Keep databases private while allowing selected web interfaces to be public. * Reduce unnecessary cross-service connectivity. * Make specialized infrastructure stacks easier to reason about and audit. Status: ```text Accepted ``` --- ## 2026-06-24 - Confirm Nginx Proxy Manager as the Single Reverse Proxy Decision: Use Nginx Proxy Manager as the sole reverse proxy and SSL termination layer for SilverLinux HTTP and HTTPS services. Reason: * The active platform uses Nginx Proxy Manager for domain routing. * No Traefik or alternate reverse proxy is active. * A single proxy layer keeps exposure and certificate management centralized. Status: ```text Confirmed ``` --- ## 2026-06-24 - Add Xray Connectivity Layer Decision: * Classify Xray as a network tunneling and connectivity layer. * Attach Xray to the `proxy` network for public endpoint access. * Keep `xray_default` documented as the Compose-created Xray stack network. * Monitor the service as an exposed connectivity endpoint rather than as an application backend. Reason: * Improve connectivity stability to SilverLinux. * Support secure long-distance connection paths. * Keep tunneling concerns separate from application and database services. Status: ```text Accepted ``` Runtime Note: The 2026-06-24 Docker snapshot showed the running `xray` container attached to `proxy` only. The `xray_default` network existed but had no running containers attached. --- ## 2026-06-24 - Confirm Jitsi Meet Is Fully Deployed Decision: Treat the Jitsi Meet stack as an operational isolated collaboration stack. Components: * jitsi-web * jitsi-jvb * jitsi-jicofo * jitsi-prosody Networks: * `proxy` * `jitsi-docker-jitsi-meet-aa76415_meet.jitsi` Reason: * Jitsi Web is expected to be public. * Internal Jitsi components should remain isolated inside the Jitsi stack network. Status: ```text Confirmed ``` --- ## 2026-06-24 - Adopt Phased Infrastructure Roadmap Decision: Use a phased roadmap for planned SilverLinux platform improvements. Phases: * Phase 1: Grafana, Prometheus, Loki, Redis and Authelia. * Phase 2: CrowdSec, Sentry, Restic, Fail2Ban upgrade and Cloudflare rate limiting/WAF. * Phase 3: SonarQube, Harbor, Backstage and Nextcloud. Reason: * Prioritize observability, access control and shared runtime foundations first. * Add security and backup maturity before larger platform expansion. * Keep enterprise developer-platform tools grouped together. Status: ```text Accepted ``` Current status: * Sentry is now implemented and documented as the exception to the standard `slcompose` + Infisical service pattern. --- ## 2026-06-25 - Select Prometheus And Grafana Monitoring Stack Decision: Deploy a dedicated monitoring Docker stack using: * Prometheus for metrics collection * Grafana for visualization * Node Exporter for host metrics * cAdvisor for Docker metrics * Alertmanager for alert routing and incident notifications Reason: * Prometheus provides a standard pull-based metrics system. * Grafana provides flexible dashboards and datasource integration. * Node Exporter provides host CPU, memory and disk visibility. * cAdvisor provides Docker container visibility. * Alertmanager provides grouping, deduplication and multi-recipient email routing. Status: ```text Implemented ``` Validation: * Prometheus UI validated * Prometheus targets validated * Grafana datasource connected to Prometheus * Initial monitoring dashboards created and validated * Alertmanager email routing validated --- ## 2026-06-25 - Export Backup Metrics Through Node Exporter Decision: Export SilverLinux backup metrics through the Node Exporter Textfile Collector. Metrics: * `silverlinux_backup_success` * `silverlinux_backup_duration_seconds` * `silverlinux_backup_size_bytes` * `silverlinux_backup_timestamp_seconds` Reason: * Keep backup status visible in the same monitoring stack as host and container metrics. * Avoid a separate metrics service for backup scripts. * Allow Grafana dashboards to show backup health. Status: ```text Implemented ``` --- ## 2026-06-25 - Validate Backup v5.3 And Restore Workflow Decision: Treat Backup v5.3 as the operational SilverLinux backup system. Implemented: * HTML backup reports * Email notifications * Automatic archive creation * Backup logging * Restore validation * MSSQL data inclusion fix * Backup metrics * Automatic low disk space cleanup * Daily cron execution * Lock file protection * Disk space validation * Central logging * Structured failure handling Validation: * Dry-run restore completed * Full archive validation completed * PostgreSQL restore coverage verified * MSSQL backup integrity verified * Gitea backup verified * BaGet backup verified * OpenProject assets verified * Docker configuration verified Status: ```text Implemented ``` --- ## 2026-06-25 - Implement Incident Intelligence Alerting Decision: Use Alertmanager with incident grouping, severity-based routing and alert deduplication for SilverLinux monitoring. Incident groups: * `backup_failure` * `system_pressure` * `storage_pressure` * `database_outage` * `monitoring_failure` * `container_health` Reason: * Merge related alerts into single incidents. * Reduce notification noise. * Route alerts by severity. * Make alerts root-cause oriented. Status: ```text Implemented ``` --- ## 2026-07-08 - Deploy Nextcloud For Private Cloud Storage Decision: Deploy Nextcloud as the SilverLinux private cloud storage and file sharing service at `cloud.silveressence.net`. Implementation: * Run `nextcloud:29-apache` as the web application container. * Run `postgres:16` as the stack-local Nextcloud database. * Run `redis:7-alpine` as the stack-local cache and locking backend. * Attach only the web container to `proxy`. * Keep PostgreSQL and Redis on `nextcloud_nextcloud_internal`. * Persist data in `nextcloud_nextcloud_data` and `nextcloud_nextcloud_db`. * Manage the stack from `/srv/docker/nextcloud` with `slcompose` and Infisical secret injection. Reason: * Provide self-hosted file storage and document sharing. * Keep user files inside SilverLinux infrastructure. * Avoid exposing database or cache ports publicly. * Reuse the standard Nginx Proxy Manager routing model. Status: ```text Implemented ``` --- ## Future Decisions Document future decisions using the following template: Date: Decision: Reason: Alternatives Considered: Status: