Files

669 lines
12 KiB
Markdown

# 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
```
---
## 2026-07-08 - Document Sentry As Upstream Self-Hosted Deployment
Decision:
Run Sentry using the upstream self-hosted `install.sh` workflow and expose it at `sentry.silveressence.net` through Nginx Proxy Manager.
Implementation:
* Use the upstream Sentry self-hosted installer layout.
* Treat `sentry-self-hosted` as one atomic deployment unit.
* Keep Sentry backing services isolated on `sentry-self-hosted_default`.
* Route public access through the Sentry nginx or web entry layer.
* Do not force Sentry into the standard SilverLinux `slcompose` and Infisical pattern.
Reason:
* Sentry is a large distributed application with many tightly coupled services.
* The upstream self-hosted installer manages required configuration and generated secrets.
* Preserving the upstream layout reduces maintenance risk during upgrades.
Status:
```text
Implemented
```
---
## Future Decisions
Document future decisions using the following template:
Date:
Decision:
Reason:
Alternatives Considered:
Status: