SEO Metadata
SEO Title Options
- How to Configure SSH on Linux: Keys, Port Change
- How to Configure SSH on Linux: Keys, Port: Practical 2026
- Security Playbook: How to Configure SSH on Linux: Keys
Meta Description Options
- Learn How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup with a practical Security framework, expert mistakes, implementation steps, examples.
- Step-by-step guide to generating SSH key pairs, disabling password authentication, changing the default port, and blocking brute-force attempts with Fail2Ban.
URL Slug
how-configure-ssh-linux-keys-port-change-fail2ban-setup
Focus Keyword
How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup
Additional LSI Keywords
- Security
- Linux
- SSH
- OpenSSH
- Fail2Ban
- How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup
- production checklist
- implementation guide
- best practices
- architecture decisions
- testing strategy
- performance impact
Table of Contents
- Article overview
- What How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup means
- Why it matters now
- Implementation framework
- Practical comparison
- Expert workflow
- Common mistakes
- Media and link plan
- Original technical deep dive
- FAQ
- Structured data
- Conclusion
Article overview
How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup is the kind of topic that looks simple until it reaches production. Teams usually discover the real cost late: unclear boundaries, weak defaults, hidden maintenance work, and decisions that seemed harmless when the codebase was small.
The problem gets worse when the article, tutorial, or implementation guide only explains the happy path. This guide closes that gap with a practical framework, a comparison table, common mistakes, and a deep technical section you can use while planning real work.
Keep reading for the non-obvious part: the safest implementation is rarely the most impressive-looking one. It is the one your team can debug, test, document, and evolve without turning every future change into archaeology.
Key Takeaways
- How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup should be evaluated as a production decision, not only as a syntax or tooling choice.
- The best implementation keeps responsibilities visible, with clear ownership, tests, documentation, and rollback paths.
- Search visibility improves when practical depth, structured answers, and expert examples live on the same page.
[IMAGE: A mobile-first technical article layout showing the main concept, decision table, implementation checklist, and FAQ blocks. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup expert guide for Security]
What How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup means
How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup means applying security knowledge to a concrete engineering decision, then turning that decision into reliable code, documentation, and operational behavior. In practice, it combines the topic's core concepts with trade-off analysis, implementation boundaries, testing strategy, and maintenance discipline.
This is the definition worth optimizing for featured snippets because it avoids hype. It tells the reader what the topic does and what a professional implementation must include.
Why it matters now
The technical web is more crowded than it was a few years ago. Thin tutorials can still get indexed, but they rarely earn trust from senior developers, buyers, AI answer systems, or teams that need production guidance.
For security topics, the strongest content now has three layers:
- a clear answer for fast scanning
- a practical framework for implementation
- expert context that explains what breaks later
That same structure helps search engines understand the page. It also helps readers decide whether the advice fits their project.
Implementation framework
Use this framework before adopting the approach described in this article.
- Define the user problem and the production risk.
- Identify the smallest reliable implementation boundary.
- Keep configuration, secrets, and environment-specific behavior outside the article's core logic.
- Add tests for the behavior that would hurt if it regressed.
- Document the trade-off, not only the final code.
- Measure the result with logs, metrics, or user-facing outcomes.
- Revisit the decision after real usage exposes edge cases.
The sequence is deliberately conservative. It keeps the work grounded in outcomes instead of novelty.
[IMAGE: A seven-step implementation framework with discovery, boundary design, configuration, tests, documentation, measurement, and iteration. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup implementation framework]
Practical comparison
| Decision area | Strong approach | Weak approach | Why it matters |
|---|---|---|---|
| Scope | Solve one clear problem | Mix unrelated concerns | Focus improves testing and search intent |
| Architecture | Put logic in explicit classes or documented boundaries | Hide behavior in templates or incidental callbacks | Future changes stay easier to review |
| Data flow | Pass prepared data into the view or endpoint | Query or compute in presentation code | Reduces regressions and performance surprises |
| Testing | Cover the risky behavior directly | Test only the happy path | Catches production failures earlier |
| Documentation | Explain trade-offs and limits | Repeat generic definitions | Builds E-E-A-T and reader trust |
| Operations | Track logs, metrics, and rollback steps | Ship without measurement | Makes the decision reversible |
This table is intentionally practical. It gives a reviewer something to check before the implementation becomes expensive to change.
Expert workflow
Expert tip: "Treat How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup as a system boundary. If the next developer cannot find where the decision lives, how it is tested, and when it should be avoided, the implementation is not finished."
A useful workflow is simple:
- Start with the smallest working example.
- Add the constraints that exist in your real project.
- Remove anything that only demonstrates cleverness.
- Write down the failure modes.
- Add links to related decisions so future readers can navigate the topic cluster.
That last point matters for both humans and search systems. A single article can answer a question; a cluster proves authority.
Common mistakes
Mistake 1: Copying a pattern without its context
A pattern that works in a small demo can fail in a real application. The missing context is usually data volume, team experience, deployment process, security requirements, or observability.
Before copying the pattern, ask what assumption made it safe in the original example.
Mistake 2: Putting business logic in the wrong layer
This is the fastest way to make future debugging expensive. In Laravel, PHP, and server-rendered websites, presentation should receive prepared data, not discover rules on its own.
Keep decision logic in models, actions, services, policies, requests, jobs, or documented helpers where it can be tested directly.
Mistake 3: Optimizing for novelty instead of maintainability
Newer tools and language features can be valuable. They can also hide simple behavior behind unfamiliar syntax.
Use the option that makes the next production incident easier to understand.
Mistake 4: Publishing without a measurement plan
If the article describes a performance, SEO, security, or architecture improvement, define how success will be checked. Logs, tests, crawl diagnostics, analytics, and user behavior are all stronger than assumptions.
[IMAGE: A common-mistakes board with context loss, wrong layer, novelty bias, and missing measurement highlighted. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup common mistakes]
Media and link plan
Image placeholders
- [IMAGE: A concept diagram for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup with input, decision boundary, implementation, tests, and production feedback. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup concept diagram]
- [IMAGE: A mobile screenshot-style checklist for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup mobile checklist]
- [IMAGE: A comparison table visualization for strong versus weak implementation choices. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup comparison table]
Video placeholder
[VIDEO: Insert a 5-8 minute YouTube walkthrough that demonstrates the main decision, the implementation boundary, the test strategy, and the production caveats for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup.]
Trustworthy outbound links
- Linux manual pages - use this as the trust reference for operating-system reference.
- Google Search quality guidance - use this as the trust reference for people-first content and E-E-A-T alignment.
Internal linking opportunities
- Internal guide: Hardening Linux SSH: 2FA With Google - use this when readers need a related Security follow-up.
- Internal guide: Setting Up a Linux Firewall With UFW: Rules - use this when readers need a related Security follow-up.
Original Technical Deep Dive
The short version
A safe SSH baseline is:
named sudo user + SSH key login + no root login + no password login + firewall + Fail2Ban
Changing the SSH port reduces noisy scans, but it is not the real security control. The real controls are:
- strong SSH keys;
- disabled password authentication;
- disabled direct root login;
- a firewall that allows only the port you intend;
- Fail2Ban or equivalent rate limiting;
- a tested rollback path before closing your current session.
Do not edit SSH over a single remote session and hope it works. Keep one working session open, test a second login after every change, and confirm console or provider recovery access before disabling passwords.
Keep a lockout-safe rollout
Use this order:
- Confirm console, recovery, or cloud serial access.
- Create or verify a non-root sudo user.
- Generate an SSH key on your workstation.
- Install the public key for the target user.
- Test key login in a new terminal.
- Disable password and root login.
- Validate
sshd_config. - Reload SSH, not restart the whole server.
- Test a fresh login again.
- Add the new SSH port while keeping the old one temporarily.
- Open the firewall for the new port.
- Test the new port.
- Update Fail2Ban to watch the new port.
- Remove port
22only after the new path works.
Before editing:
sudo cp /etc/ssh/sshd_config /root/sshd_config.backup.$(date +%F-%H%M%S)
sudo mkdir -p /root/ssh-rollout
sudo sshd -T > /root/ssh-rollout/sshd-effective-before.txt
Find the SSH service name:
systemctl status ssh --no-pager 2>/dev/null || systemctl status sshd --no-pager
Debian and Ubuntu commonly use ssh. Fedora, RHEL, Rocky Linux, and AlmaLinux commonly use sshd.
Create a named sudo user
Do not use direct root SSH for normal administration.
Create a user:
sudo adduser deploy
On Debian or Ubuntu:
sudo usermod -aG sudo deploy
On RHEL-style systems:
sudo usermod -aG wheel deploy
Test locally or through an existing SSH session:
su - deploy
sudo -v
id
exit
Do not disable root login until this user can log in and run sudo.
Generate an SSH key pair
Run this on your workstation, not on the server:
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/deploy_ed25519 -C "deploy@laptop"
Use a passphrase. If you need non-interactive automation, use a separate restricted deployment key, not your personal interactive admin key.
Check the files:
ls -l ~/.ssh/deploy_ed25519 ~/.ssh/deploy_ed25519.pub
The private key stays on your workstation:
~/.ssh/deploy_ed25519
The public key is safe to copy to the server:
~/.ssh/deploy_ed25519.pub
Start an agent if needed:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/deploy_ed25519
List loaded keys:
ssh-add -l
Install the public key
If password login still works temporarily, use:
ssh-copy-id -i ~/.ssh/deploy_ed25519.pub deploy@203.0.113.10
Manual install:
ssh deploy@203.0.113.10 'mkdir -p ~/.ssh && chmod 700 ~/.ssh'
cat ~/.ssh/deploy_ed25519.pub | ssh deploy@203.0.113.10 'cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
If you are already logged into the server as root, install the key explicitly:
sudo install -d -m 0700 -o deploy -g deploy /home/deploy/.ssh
sudoedit /home/deploy/.ssh/authorized_keys
sudo chown deploy:deploy /home/deploy/.ssh/authorized_keys
sudo chmod 0600 /home/deploy/.ssh/authorized_keys
[IMAGE: Supporting visual 1 for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup, showing How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup decisions, examples, and Linux, SSH, OpenSSH. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup how-configure-ssh-linux-keys-port-change-fail2ban-setup visual 1]
[IMAGE: Supporting visual 1 for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup, showing How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup decisions, examples, and Linux, SSH, OpenSSH. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup how-configure-ssh-linux-keys-port-change-fail2ban-setup visual 1]
Test from a new terminal:
ssh -i ~/.ssh/deploy_ed25519 deploy@203.0.113.10
Then test sudo:
sudo -v
Keep this new session open.
Check SSH config include behavior
Modern distributions often load drop-in files from:
/etc/ssh/sshd_config.d/*.conf
Check:
sudo grep -nE '^[[:space:]]*Include[[:space:]]+/etc/ssh/sshd_config.d/\\*.conf' /etc/ssh/sshd_config
If drop-ins are included, prefer a drop-in:
sudoedit /etc/ssh/sshd_config.d/20-baseline.conf
If your distribution does not load drop-ins, edit:
sudoedit /etc/ssh/sshd_config
Put global settings before any Match block. A Match block can change effective configuration for specific users, groups, addresses, or hosts.
Disable password and root login
Use this baseline:
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
PermitRootLogin no
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
Optional user allowlist:
AllowUsers deploy
Use AllowUsers only if you maintain it carefully. If you forget to add the emergency admin account, you can lock yourself out.
Do not disable UsePAM blindly on Linux. PAM is commonly involved in account, session, limits, SELinux, and login policy handling. You can disable password and keyboard-interactive authentication while keeping PAM for session setup.
Validate syntax:
sudo sshd -t
Check effective settings:
sudo sshd -T | grep -E '^(port|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|authenticationmethods|maxauthtries|logingracetime|x11forwarding|allowusers)'
If you use Match, test effective config for the real login:
sudo sshd -T -C user=deploy,host=203.0.113.10,addr=203.0.113.50 | grep -E '^(passwordauthentication|permitrootlogin|authenticationmethods|allowusers)'
Reload SSH:
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Test key login in a new terminal:
ssh -i ~/.ssh/deploy_ed25519 deploy@203.0.113.10
Test that password login fails:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no deploy@203.0.113.10
Expected result:
Permission denied
Do not close the working session until this is confirmed.
Change the SSH port safely
Port changes reduce log noise. They do not replace key-based auth or firewall rules.
Pick a port that is not already used:
sudo ss -tlnp
Example port:
2222
Temporarily listen on both old and new ports:
sudoedit /etc/ssh/sshd_config.d/30-port.conf
Use:
Port 22
Port 2222
If you edit the main config instead of a drop-in, remove or replace any existing Port line carefully.
Open the firewall before reloading SSH.
For UFW:
sudo ufw allow 2222/tcp
sudo ufw status verbose
For firewalld:
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports
On SELinux systems, allow SSH to bind the new port:
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222 2>/dev/null || sudo semanage port -m -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh
Validate and reload:
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Check listeners:
sudo ss -tlnp | grep sshd
Test the new port from your workstation:
ssh -p 2222 -i ~/.ssh/deploy_ed25519 deploy@203.0.113.10
If it works, update your SSH client config:
sudoedit ~/.ssh/config
Example:
Host prod-web-01
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/deploy_ed25519
IdentitiesOnly yes
Test:
ssh prod-web-01
Only after this works should you remove port 22 from SSH and the firewall:
Port 2222
Then:
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
sudo ufw delete allow 22/tcp 2>/dev/null || true
sudo firewall-cmd --permanent --remove-service=ssh 2>/dev/null || true
sudo firewall-cmd --reload 2>/dev/null || true
Confirm:
ssh -p 2222 deploy@203.0.113.10
ssh -p 22 deploy@203.0.113.10
The port 22 test should fail after cleanup.
Install Fail2Ban
On Debian or Ubuntu:
sudo apt update
sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
On Fedora:
sudo dnf install -y fail2ban
sudo systemctl enable --now fail2ban
On RHEL-compatible systems, Fail2Ban commonly comes from EPEL:
sudo dnf install -y epel-release
sudo dnf install -y fail2ban
sudo systemctl enable --now fail2ban
[IMAGE: Supporting visual 2 for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup, showing How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup decisions, examples, and Linux, SSH, OpenSSH. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup how-configure-ssh-linux-keys-port-change-fail2ban-setup visual 2]
Check:
sudo systemctl status fail2ban --no-pager
sudo fail2ban-client version
Fail2Ban reads log events and triggers actions such as firewall bans when a source exceeds the configured failure threshold.
Configure the SSH jail
Do not edit packaged .conf files directly. Use .local files or files under jail.d.
Create:
sudoedit /etc/fail2ban/jail.d/sshd.local
For a journald-based system:
[sshd]
enabled = true
port = 2222
filter = sshd
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1
If your distribution logs SSH failures to files instead of journald, use the right path:
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1
[IMAGE: Supporting visual 2 for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup, showing How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup decisions, examples, and Linux, SSH, OpenSSH. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup how-configure-ssh-linux-keys-port-change-fail2ban-setup visual 2]
RHEL-style systems may use:
logpath = /var/log/secure
If you kept SSH on port 22, set:
port = ssh
If you changed SSH to 2222, set:
port = 2222
The port matters because the ban action needs to know which destination port to block.
Add trusted admin source IPs to ignoreip only when they are stable:
ignoreip = 127.0.0.1/8 ::1 198.51.100.25
Do not whitelist entire office networks unless you actually trust every machine on that network.
Start and inspect Fail2Ban
Check merged configuration:
sudo fail2ban-client -d | less
Reload:
sudo fail2ban-client reload
If the service is not running:
sudo systemctl restart fail2ban
Check status:
sudo fail2ban-client status
sudo fail2ban-client status sshd
Expected shape:
Status for the jail: sshd
|- Filter
| |- Currently failed: ...
| |- Total failed: ...
`- Actions
|- Currently banned: ...
|- Total banned: ...
Check logs:
journalctl -u fail2ban --since today --no-pager
If using file logs:
sudo tail -f /var/log/fail2ban.log
Test without banning yourself
Do not brute-force from your only admin IP unless it is in ignoreip and you have console access.
Use a test host:
ssh -p 2222 fakeuser@203.0.113.10
ssh -p 2222 fakeuser@203.0.113.10
ssh -p 2222 fakeuser@203.0.113.10
Check:
sudo fail2ban-client status sshd
Unban an IP if needed:
sudo fail2ban-client set sshd unbanip 198.51.100.50
If bans never happen:
- Confirm SSH failures are in the log or journal.
- Confirm
backendmatches the logging system. - Confirm
portmatches the SSH port. - Confirm the
sshdjail is enabled. - Check
fail2ban-client -dfor the merged config.
Monitor SSH logs
Useful commands:
journalctl -u ssh --since today --no-pager 2>/dev/null || journalctl -u sshd --since today --no-pager
Authentication logs on Debian or Ubuntu:
sudo tail -f /var/log/auth.log
Authentication logs on RHEL-style systems:
sudo tail -f /var/log/secure
Check accepted logins:
journalctl --since today --no-pager | grep 'Accepted publickey'
Check failed logins:
journalctl --since today --no-pager | grep -E 'Failed password|Invalid user|authentication failure'
Do not treat a quiet Fail2Ban dashboard as proof SSH is secure. The primary controls are still key-only auth, no direct root login, firewall exposure, and account hygiene.
Common mistakes
Changing the port before opening the firewall:
Result: SSH reloads successfully, then every new connection fails.
Disabling passwords before testing the key:
Result: existing session works, but no new session can authenticate.
Editing jail.conf directly:
Result: package upgrades can overwrite or conflict with your changes.
Leaving Fail2Ban on port = ssh after moving SSH to 2222:
Result: bans may target the wrong port.
Putting SSH directives after a Match block:
Result: settings apply only inside that match context or fail validation.
Using one SSH key everywhere:
Result: one leaked key gives access to every server.
[IMAGE: Supporting visual 3 for How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup, showing How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup decisions, examples, and Linux, SSH, OpenSSH. Alt: How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup how-configure-ssh-linux-keys-port-change-fail2ban-setup visual 3]
Rollback
If the new port fails but the old session is still open:
sudo cp /root/sshd_config.backup.* /etc/ssh/sshd_config
sudo rm -f /etc/ssh/sshd_config.d/20-baseline.conf /etc/ssh/sshd_config.d/30-port.conf
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
If Fail2Ban blocks a legitimate IP:
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 198.51.100.50
If SSH is fully unreachable, use console or rescue access:
- Log in through provider console.
- Restore
/etc/ssh/sshd_config. - Remove bad drop-ins.
- Open the correct firewall port.
- Validate with
sshd -t. - Reload or restart SSH.
Production checklist
Before calling SSH configured:
- A named sudo user exists.
- That user can log in with an SSH key.
- That user can run
sudo. - Root SSH login is disabled.
- Password and keyboard-interactive login are disabled.
sshd -tpasses.sshd -Tconfirms the effective settings.- Firewall allows only the intended SSH port.
- The new port works from a fresh terminal.
- Port
22is closed if you intentionally moved away from it. - Fail2Ban
sshdjail is enabled. - Fail2Ban watches the correct backend and port.
- Admin IPs in
ignoreipare intentional and narrow. - Console or rescue access is documented.
- SSH config backups and rollback steps are available.
FAQ
What is How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup?
How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup is a practical security topic that should be evaluated through implementation scope, production risk, testing, documentation, and long-term maintainability.
When should a team use How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup?
Use How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup when it solves a real project constraint, improves clarity, or reduces operational risk. Avoid it when it only adds novelty or hides behavior from future maintainers.
What is the biggest risk with How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup?
The biggest risk is copying a pattern without its context. Production systems need clear boundaries, rollback options, tests, and observability before a technique becomes dependable.
How do you test How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup?
Test the smallest unit that owns the behavior, then add integration coverage for the path users or systems actually rely on. Include failure cases, configuration differences, and regression checks.
How does How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup affect SEO and AI search visibility?
It improves visibility when the article gives a direct answer, expert context, structured headings, internal links, trustworthy references, and FAQ content that matches the visible page.
Conclusion
How to Configure SSH on Linux: Keys, Port Change & Fail2Ban Setup is worth doing when the implementation improves clarity, reliability, or delivery speed. It is not worth doing when it hides ownership, increases operational risk, or makes the system harder to explain.
Use the framework above as a review checklist. Then connect this topic to the rest of the project documentation so readers can move from concept to implementation without losing context.