641 lines
12 KiB
Markdown
641 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
|
|
```
|
|
|
|
---
|
|
|
|
## Future Decisions
|
|
|
|
Document future decisions using the following template:
|
|
|
|
Date:
|
|
|
|
Decision:
|
|
|
|
Reason:
|
|
|
|
Alternatives Considered:
|
|
|
|
Status:
|