395 lines
10 KiB
Markdown
395 lines
10 KiB
Markdown
# Security
|
|
|
|
## Overview
|
|
|
|
SilverLinux hosts critical infrastructure for Silver Solutions.
|
|
|
|
This document describes the security measures implemented on the server and operational security requirements.
|
|
|
|
---
|
|
|
|
## Access Control
|
|
|
|
### SSH Access
|
|
|
|
SSH access is limited to authorized administrators.
|
|
|
|
Authentication:
|
|
|
|
* SSH key authentication
|
|
* Password login discouraged
|
|
* Root login disabled
|
|
|
|
Primary user:
|
|
|
|
```text
|
|
ubuntu
|
|
```
|
|
|
|
---
|
|
|
|
## Firewall
|
|
|
|
### UFW
|
|
|
|
UFW is enabled and used as the primary host firewall.
|
|
|
|
Verified allowed incoming ports from `sudo ufw status verbose`:
|
|
|
|
| Port | Purpose |
|
|
| ---- | ------- |
|
|
| 22 | SSH |
|
|
| 80 | HTTP |
|
|
| 443 | HTTPS |
|
|
| 2222 | Gitea Git SSH |
|
|
| 10000/udp | Jitsi JVB media |
|
|
| 8085 | Explicitly allowed non-standard TCP port |
|
|
| 8443 | Explicitly allowed non-standard HTTPS port |
|
|
| 8444 | Explicitly allowed non-standard TCP port |
|
|
| 8080 | Explicitly allowed non-standard TCP port |
|
|
| 32443 | Xray public tunneling endpoint |
|
|
|
|
Default policy:
|
|
|
|
* deny incoming
|
|
* allow outgoing
|
|
* deny routed
|
|
|
|
All other ports should remain blocked unless explicitly required.
|
|
|
|
Known runtime-published non-standard ports from the 2026-06-24 Docker snapshot:
|
|
|
|
| Port | Service | UFW state | Notes |
|
|
| ---- | ------- | --------- | ----- |
|
|
| 81 | Nginx Proxy Manager | Not listed as allowed | Admin interface is published by Docker, but not allowed by UFW snapshot |
|
|
| 2222 | Gitea | Allowed | Git SSH |
|
|
| 32443 | Xray | Allowed | Public tunneling endpoint |
|
|
| 5555 | BaGet | Not listed as allowed | Direct HTTP port is published by Docker, but not allowed by UFW snapshot |
|
|
| 8000 | Jitsi Web | Not listed as allowed | Direct HTTP port is published by Docker, but not allowed by UFW snapshot |
|
|
| 8443 | Jitsi Web | Allowed | Direct HTTPS port |
|
|
| 10000/udp | Jitsi JVB | Allowed | Required media bridge traffic |
|
|
| 8082 | OpenProject | Not listed as allowed | Direct HTTP port is published by Docker, but not allowed by UFW snapshot |
|
|
|
|
These ports must either be intentionally allowed and documented in UFW, or blocked at the host firewall if only Nginx Proxy Manager should be public.
|
|
|
|
UFW also allows `8080`, `8085` and `8444`, but no matching Docker-published service was identified in the 2026-06-24 Docker snapshot. These rules should be reviewed and removed if they are no longer required.
|
|
|
|
---
|
|
|
|
## Intrusion Protection
|
|
|
|
### Fail2Ban
|
|
|
|
Fail2Ban is enabled.
|
|
|
|
Purpose:
|
|
|
|
* Detect brute-force attacks
|
|
* Automatically block malicious IP addresses
|
|
* Protect SSH access
|
|
|
|
Planned improvements:
|
|
|
|
* Upgrade Fail2Ban coverage
|
|
* Add CrowdSec for collaborative intrusion detection
|
|
* Add Cloudflare rate limiting and WAF for exposed administrative endpoints
|
|
|
|
---
|
|
|
|
## Secrets Management
|
|
|
|
Shared secrets are stored in:
|
|
|
|
```text
|
|
Infisical
|
|
```
|
|
|
|
Examples:
|
|
|
|
* SMTP credentials
|
|
* PostgreSQL passwords
|
|
* MSSQL SA password
|
|
* OpenProject secrets
|
|
* Future OAuth secrets
|
|
|
|
Rules:
|
|
|
|
* Never commit secrets to Git
|
|
* Never share secrets in documentation
|
|
* Never hardcode passwords in Docker Compose files
|
|
* Remove `/srv/secrets/company.env` if it still exists after confirming all values are present in Infisical
|
|
|
|
See:
|
|
|
|
```text
|
|
docs/secrets.md
|
|
```
|
|
|
|
---
|
|
|
|
## SSL Certificates
|
|
|
|
SSL certificates are managed through Nginx Proxy Manager.
|
|
|
|
Certificates are automatically renewed.
|
|
|
|
All public services should be accessible through HTTPS only.
|
|
|
|
---
|
|
|
|
## Public Exposure
|
|
|
|
Public HTTP and HTTPS services are routed through the `proxy` Docker network and Nginx Proxy Manager.
|
|
|
|
Publicly exposed services:
|
|
|
|
* Gitea
|
|
* OpenProject
|
|
* Portainer
|
|
* DbGate
|
|
* Xray
|
|
* Jitsi Web
|
|
* BaGet
|
|
* Nextcloud
|
|
|
|
High-sensitivity exposure:
|
|
|
|
* DbGate exposes a database administration interface and must always require authentication and HTTPS.
|
|
* Xray exposes tunneling capability and must be monitored for abuse, unexpected traffic and unauthorized use.
|
|
* Portainer exposes Docker management and must be restricted to trusted administrators.
|
|
* Nextcloud exposes private file storage and must require strong user authentication, HTTPS and prompt security updates.
|
|
|
|
Nginx Proxy Manager findings from the 2026-06-24 proxy-host snapshot:
|
|
|
|
* No proxy host had an Nginx Proxy Manager access list assigned.
|
|
* DbGate was enabled without SSL Force, HTTP/2 or HSTS.
|
|
* Gitea, Jitsi Meet and BaGet were enabled without SSL Force.
|
|
* Plane.so has been removed from containers, Nginx Proxy Manager and server certificate storage.
|
|
* `cicd.silveressence.net` is intentionally enabled as a frequently changing prototype deployment endpoint.
|
|
* `exactsyncer.silveressence.net` is intentionally enabled as a client-facing Exact Online syncer demo endpoint.
|
|
* `cloud.silveressence.net` is enabled for Nextcloud with WebSocket and Block Exploits enabled, but SSL Force, HTTP/2 and HSTS disabled and no access list.
|
|
|
|
Priority hardening:
|
|
|
|
1. Enable SSL Force for all HTTPS public service routes unless there is a documented exception.
|
|
2. Enable SSL Force, HTTP/2 and HSTS for Nextcloud unless there is a documented exception.
|
|
3. Add an access list or equivalent restriction for DbGate and Portainer.
|
|
4. Define explicit exposure and authentication expectations for prototype and demo endpoints.
|
|
|
|
---
|
|
|
|
## Email Security
|
|
|
|
Outgoing email is provided through Gmail SMTP.
|
|
|
|
Credentials are stored in:
|
|
|
|
```text
|
|
Infisical
|
|
```
|
|
|
|
Requirements:
|
|
|
|
* Use Gmail App Passwords only
|
|
* Never store personal account passwords
|
|
* Rotate credentials if exposure is suspected
|
|
|
|
Sender address:
|
|
|
|
```text
|
|
noreply@silveressence.net
|
|
```
|
|
|
|
---
|
|
|
|
## Authentication
|
|
|
|
### Current
|
|
|
|
* Local user accounts
|
|
* Strong passwords
|
|
|
|
### Planned
|
|
|
|
Future OAuth providers:
|
|
|
|
* Google OAuth2
|
|
* GitHub OAuth2
|
|
* Authelia SSO for exposed admin areas
|
|
|
|
Requirements:
|
|
|
|
* Store client secrets in Infisical
|
|
* Use least-privilege scopes
|
|
* Disable unused authentication providers
|
|
|
|
Planned protected areas:
|
|
|
|
* DbGate
|
|
* Portainer
|
|
* Gitea administrator areas
|
|
* OpenProject administrator areas
|
|
|
|
### Disabled
|
|
|
|
* OpenID authentication
|
|
|
|
Reason:
|
|
|
|
OpenID is not required and increases attack surface.
|
|
|
|
---
|
|
|
|
## Two-Factor Authentication
|
|
|
|
Where supported:
|
|
|
|
* Enable 2FA for administrator accounts
|
|
* Encourage 2FA for all users
|
|
|
|
Priority:
|
|
|
|
1. Gitea administrators
|
|
2. OpenProject administrators
|
|
|
|
---
|
|
|
|
## Database Security
|
|
|
|
PostgreSQL and Microsoft SQL Server are not exposed publicly.
|
|
|
|
Database access is restricted to Docker internal networks.
|
|
|
|
Applications and DbGate communicate with the database containers through the `internal` Docker network.
|
|
|
|
DbGate is the public administration entry point and must require authentication and HTTPS. Its web interface is routed through Nginx Proxy Manager; database ports `5432` and `1433` remain private.
|
|
|
|
Nextcloud uses a stack-local PostgreSQL container named `nextcloud-db` on `nextcloud_nextcloud_internal`. Its `5432/tcp` port is not published to the host and is not routed through Nginx Proxy Manager.
|
|
|
|
Nextcloud Redis uses `nextcloud-redis` on `nextcloud_nextcloud_internal`. Its `6379/tcp` port is not published to the host.
|
|
|
|
---
|
|
|
|
## Connectivity Layer Security
|
|
|
|
Xray is classified as a network tunneling and connectivity layer, not as an application service.
|
|
|
|
Requirements:
|
|
|
|
* Keep the Xray service isolated from private database networks unless a documented need exists.
|
|
* Monitor logs and traffic patterns for abuse.
|
|
* Review access policy after configuration changes.
|
|
* Keep secrets, UUIDs, keys and endpoint credentials outside the repository.
|
|
|
|
---
|
|
|
|
## Docker Security
|
|
|
|
Services are isolated through Docker containers.
|
|
|
|
Principles:
|
|
|
|
* Public services should be exposed only through Nginx Proxy Manager
|
|
* Internal services should not expose ports publicly
|
|
* Services should communicate through Docker networks
|
|
* Containers should run with the minimum required privileges
|
|
|
|
Networks:
|
|
|
|
* proxy
|
|
* internal
|
|
* jitsi-docker-jitsi-meet-aa76415_meet.jitsi
|
|
* xray_default
|
|
* gitea-runner_default
|
|
* nextcloud_nextcloud_internal
|
|
|
|
Network model:
|
|
|
|
* `internal` is for private database and backend traffic.
|
|
* `proxy` is for public HTTP and HTTPS services controlled by Nginx Proxy Manager.
|
|
* Isolated stack networks are used for Jitsi, Xray and CI/CD runner separation.
|
|
* `xray_default` currently exists without a running container attached; the active `xray` container is attached to `proxy`.
|
|
* `nextcloud_nextcloud_internal` isolates Nextcloud database and Redis traffic from the public proxy layer.
|
|
|
|
---
|
|
|
|
## System Updates
|
|
|
|
The operating system and containers should be updated regularly.
|
|
|
|
Recommendations:
|
|
|
|
* Apply Ubuntu security updates
|
|
* Update Docker images periodically
|
|
* Remove unused containers and images
|
|
* Review security advisories for critical services
|
|
|
|
---
|
|
|
|
## Backup Security
|
|
|
|
Backups must include:
|
|
|
|
* Configuration files
|
|
* Docker Compose files
|
|
* Application data
|
|
* PostgreSQL databases
|
|
* Shared secrets
|
|
|
|
Backups must never be stored inside public repositories.
|
|
|
|
---
|
|
|
|
## Security Review Checklist
|
|
|
|
Periodically verify:
|
|
|
|
* SSH keys are current
|
|
* Unused accounts are removed
|
|
* Fail2Ban is active
|
|
* Planned CrowdSec and Cloudflare WAF status is reviewed
|
|
* UFW is active
|
|
* SSL certificates are valid
|
|
* Secrets are not stored in repositories
|
|
* Backups are functioning
|
|
* Administrator accounts have 2FA enabled
|
|
* DbGate login is enforced
|
|
* DbGate proxy route has SSL Force and an access restriction policy
|
|
* Xray exposure policy is still valid
|
|
* Nextcloud security advisories are reviewed and the image is updated promptly
|
|
* Nextcloud database and Redis ports remain internal-only
|
|
* Nextcloud proxy route uses HTTPS with SSL Force, HTTP/2 and HSTS enabled unless there is a documented exception
|
|
* Public services are still routed only through Nginx Proxy Manager
|
|
* Removed proxy hosts and unused certificates stay removed unless explicitly approved
|
|
* Prototype and demo proxy hosts have documented owners and exposure expectations
|
|
* Direct host-published ports are intentional or blocked by UFW
|
|
* UFW rules `8080`, `8085` and `8444` still have a documented owner
|
|
* Review application logs
|
|
* Review Docker logs
|
|
* Review authentication failures
|
|
* Review Fail2Ban bans
|
|
|
|
---
|
|
|
|
## Incident Response
|
|
|
|
If a credential is exposed:
|
|
|
|
1. Rotate the credential immediately.
|
|
2. Rotate or update the value in Infisical.
|
|
3. Restart affected services.
|
|
4. Review logs for unauthorized access.
|
|
5. Update documentation if required.
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
* docs/server.md
|
|
* docs/secrets.md
|
|
* docs/backups.md
|
|
* docs/email.md
|
|
* docs/network.md
|
|
* docs/roadmap.md
|
|
* nginx-proxy-manager/README.md
|