Master Networking Skills for DevOps Success


Networking skills for DevOps engineers


Networking skills for DevOps engineers

Linux networking problems rarely announce themselves clearly. A service may become unreachable, DNS may stop resolving, SSH may fail, or a firewall may silently block traffic. The application can appear broken even when the real problem is somewhere in the network layer.

For DevOps engineers, understanding how to identify these failures is essential. Linux networking involves several layers, including interfaces, IP addresses, routing, DNS, sockets, and firewalls, and a problem in any one of them can produce similar symptoms. This guide takes a practical approach to troubleshooting Linux networking, showing you how to investigate problems step by step, verify what is actually happening, and fix issues using evidence instead of guesswork.

Metric Value Source Relevance
Default SSH port 22/TCP IANA port registry First port attackers scan on new hosts
firewalld default zone public Rocky/RHEL/Fedora docs Drives which rules apply on fresh installs
TLS handshake timeout, typical LB default 10s HAProxy/nginx defaults Common cause of intermittent 504 errors
DNS TTL for cloud LB records 60-300s AWS/GCP recommended defaults Governs how fast failover actually propagates

What This Guide Covers:

  • Core Linux networking commands you will actually use in production, not just in interviews
  • How the same networking task differs across Ubuntu, Rocky/RHEL, Fedora, and Arch
  • A layered architecture view of how a request actually travels through a Linux host
  • Real failure modes engineers hit with DNS, firewalls, SSH, and routing
  • A validation script you can run after any network change
  • Hardening steps that hold up under a compliance audit, plus a maintenance cadence
  • Where cloud security groups and IPv6 fit into the same troubleshooting picture

Networking is one of those skills that looks optional right up until it is the only thing standing between you and a resolved incident. Configuration management tools, container orchestrators, and cloud consoles have abstracted a lot of the plumbing away, but the plumbing is still there, and it still breaks in the same handful of predictable ways. This guide walks through the commands, the architecture, and the failure patterns that come up again and again on real Linux fleets, with distro-specific notes where the tooling actually diverges.

If you already know what a socket is, skip ahead to the pitfalls section. If networking still feels like a black box between your app and "the internet," start from the top and work through the steps in order. Everything here assumes a standard cloud VM or bare metal box running a current LTS or enterprise release, and every command shown has been run on a live host, not copied from a man page.

The old net-tools package (ifconfig, netstat, route) is deprecated on most modern distros in favor of iproute2. Knowing which tool actually ships and behaves consistently matters more than picking a favorite. Here is how the common tools stack up on a production Linux host in 2026.

Tool Purpose Default on Modern Distros Speed Notes
ip Interfaces, routes, addresses Yes, all distros Fast Replaces ifconfig and route
ss Socket and port state Yes, all distros Fast Replaces netstat, reads /proc directly
nmcli Connection profiles Rocky/RHEL/Fedora mainly Fast Ubuntu server uses netplan instead, which is a config abstraction that generates the backend YAML for NetworkManager or systemd-networkd, not a direct nmcli equivalent
dig DNS record lookups Needs bind-utils/dnsutils Fast More detail than nslookup
tcpdump Raw packet capture Usually needs install Slower to read The ground truth when everything else lies

Tip:

If a script or runbook still calls netstat or ifconfig, treat it as a maintenance item, not a bug. Both still work on most distros through compatibility packages, but they read from different kernel interfaces than ip and ss, and the numbers can drift apart on busy hosts.

Environment and Prerequisites

# Environment / Distro Type
1 Ubuntu 24.04 / 26.04 LTS Server
2 Rocky Linux 9 / 10, RHEL 9 / 10, AlmaLinux Server
3 Fedora 44 Workstation / Server
4 Arch Linux (rolling) Server / Dev box
5 iproute2, bind-utils/dnsutils, tcpdump, curl Tooling
Requirement Details Status
sudo or root access Needed for firewall and interface changes REQUIRED
Console or out-of-band access In case a firewall or SSH change locks you out REQUIRED
tcpdump / Wireshark For packet-level debugging in Section 06 OPTIONAL
A second SSH session open Safety net before touching firewalld/ufw/iptables REQUIRED

WARNING:

Never test a firewall rule change or an SSH config edit over the only session you have open. Keep a second terminal connected on the side so a bad rule does not lock you out of a box that is three time zones away from the nearest server room.

If your team is still manually SSHing into boxes to check interface state one at a time, this is also the point where configuration drift starts creeping in. Pairing this networking baseline with a solid server hardening checklist keeps both the network and the OS layer honest at the same time.

Architecture Overview: How a Request Actually Travels

Before touching commands, it helps to have the mental model straight. Here is a simplified path of a request hitting a typical Linux web server, from DNS resolution down to the application socket.

REQUEST PATH: CLIENT TO APPLICATION SOCKET

  Client
    |
    v
  [ DNS Resolution ]              port 53/UDP+TCP, resolves name to IP
    |
    v
  [ NIC ]                         packet physically arrives on the interface
    |
    v
  [ Netfilter: firewalld / ufw ]  kernel-level allow/deny, first gatekeeper
    |
    v
  [ Kernel Routing: ip route ]    decides local delivery vs forwarding
    |
    v
  [ Load Balancer / L7, if any ]  routes by host + path
    |
    v
  [ Application Socket ]          TLS handshake + bound port, e.g. 8080/TCP
    |
    v
  Response returns the same path in reverse

  KEY PORTS:  53 DNS   22 SSH   80 HTTP   443 HTTPS   8080 App

Engineer Note:

Most "the app is down" incidents actually die at one of the middle boxes in that diagram, not the socket itself. Check DNS and the firewall layer before you touch application logs. It saves time nine times out of ten. On cloud hosts, there is also a layer above this diagram that this article does not control: the provider's security group or network security group. It sits in front of the NIC and can drop traffic before it ever reaches netfilter, so a host firewall that looks completely correct is not proof the packet ever arrived. Check the cloud console's security group rules before assuming the problem is on the box.

Step-by-Step: Building a Working Network Baseline

Step 1 - Check the Current Interface and Address State

Before changing anything, get a baseline of what interfaces exist, what IPs are assigned, and what state they are in. This is the first command I run on any unfamiliar box.

Ubuntu 24.04 / 26.04 LTS

bash
LinuxTeck.com
# List every interface and its assigned address
ip addr show
# Show the kernel routing table
ip route show
OUTPUT
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
default via 10.0.2.2 dev eth0 proto dhcp metric 100

Rocky Linux 9 / 10 - RHEL 9 / 10 - AlmaLinux

bash
LinuxTeck.com
# NetworkManager owns interfaces on RHEL-family distros
nmcli connection show
nmcli device status
OUTPUT
NAME UUID TYPE DEVICE
eth0 a1b2c3 ethernet eth0

DEVICE TYPE STATE CONNECTION
eth0 ethernet connected eth0

Fedora 44

bash
LinuxTeck.com
# The brief flag gives a compact one-line-per-interface view
ip -brief address
ip -brief link
OUTPUT
lo UNKNOWN 127.0.0.1/8
eth0 UP 192.168.1.42/24

Arch Linux

bash
LinuxTeck.com
# Arch installs default to systemd-networkd for servers
systemctl status systemd-networkd
networkctl status
OUTPUT
● systemd-networkd.service - Network Configuration
Active: active (running)
● 2 eth0 ether routable configured

Interface state only tells you if the link is up, not whether it is healthy. On any distro, ip -s link shows per-interface error and drop counters, which catch a failing NIC or a saturated link before it shows up as an application timeout.

bash
LinuxTeck.com
# -s adds RX/TX packet, error, and drop counters
ip -s link show eth0
OUTPUT
RX: bytes packets errors dropped
482910234 391022 0 0
TX: bytes packets errors dropped
291004821 288114 0 0

Step 2 - Verify DNS Resolution End to End

DNS is the single most common root cause I have traced production incidents back to. Always check resolution before assuming an app or database problem. This works the same across all four distros once bind-utils or dnsutils is installed.

bash
LinuxTeck.com
# Quick lookup, short output only
dig +short api.internal.example.com
# Check which resolver and cache systemd is using
resolvectl status
# Clear a stale cache after a record change
resolvectl flush-caches
OUTPUT
10.20.4.11
Link 2 (eth0)
Current Scopes: DNS
DNS Servers: 10.20.0.2

For a deeper walkthrough of resolver chains and caching layers, our dedicated DNS troubleshooting guide covers stub resolvers, split-horizon setups, and what to do when dig and the browser disagree.

IPv6 Note:

Everything above only checks the A record. On dual-stack hosts, also run dig AAAA "$HOST" and ss -6 -tulnp. A service that only listens on the IPv4 socket will silently fail for clients that resolve the AAAA record first and prefer IPv6, which is now the default happy-eyeballs behavior on most modern clients.

Step 3 - Confirm Which Ports Are Actually Listening

Before blaming the firewall, confirm the process is actually bound to the port you expect. This step is identical on all distros since ss reads directly from the kernel.

bash
LinuxTeck.com
# t=tcp u=udp l=listening n=numeric p=process name
sudo ss -tulnp
OUTPUT
Netid State Local Address:Port Process
tcp LISTEN 0.0.0.0:22 sshd
tcp LISTEN 0.0.0.0:8080 java (pid=1842)
tcp LISTEN 127.0.0.1:5432 postgres

Notice the last row above. Postgres is bound to 127.0.0.1, which means nothing outside the host can reach it, no matter what the firewall says. That single detail has saved me from chasing phantom firewall bugs more than once. A deeper reference on the flag combinations lives in our ss command guide. When you need the bigger picture instead of a single port, ss -s gives a one-screen summary of total sockets, TCP states, and connection counts, which is useful for spotting a socket leak before it exhausts the ephemeral port range.

Step 4 - Open the Right Port Through the Firewall

Ubuntu ships ufw by default. RHEL-family and Fedora ship firewalld. Arch usually leaves it to you, commonly nftables directly or firewalld if installed. Here is opening port 8080 on each.

Ubuntu 24.04 / 26.04 LTS

bash
LinuxTeck.com
sudo ufw allow 8080/tcp
sudo ufw status verbose
OUTPUT
Rule added
Status: active
To Action From
8080/tcp ALLOW Anywhere

Rocky Linux 9 / 10 - RHEL 9 / 10 - AlmaLinux - Fedora 44

bash
LinuxTeck.com
# --permanent writes to config but does not apply live
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
OUTPUT
success
success

Arch Linux

bash
LinuxTeck.com
# Assumes an existing inet filter table and input chain
sudo nft add rule inet filter input tcp dport 8080 accept
# A rule added with "nft add rule" only lives in memory, save it or it is gone on reboot
sudo nft list ruleset | sudo tee /etc/nftables.conf
sudo systemctl enable --now nftables
OUTPUT
table inet filter {
chain input {
tcp dport 8080 accept
}
}
Created symlink /etc/systemd/system/multi-user.target.wants/nftables.service

If firewalld and ufw feel unfamiliar, our firewall-cmd command reference covers zones, rich rules, and permanent versus runtime state in more depth than fits here.

Step 5 - Trace a Connection Path With Traceroute and Curl

Once DNS resolves and the port is open, confirm the actual path works end to end, including TLS. This step is distro-agnostic once traceroute and curl are installed.

bash
LinuxTeck.com
# Shows every hop the packet takes
traceroute api.internal.example.com
# -I head only, -v verbose, shows TLS handshake details
curl -Iv https://api.internal.example.com
OUTPUT
1 10.0.2.2 0.412 ms
2 10.20.0.1 1.203 ms
* Connected to api.internal.example.com port 443
* TLSv1.3, handshake finished

Production Pitfalls and Fixes

These are patterns that have actually shown up on production hosts, not textbook edge cases. Each one includes the command that confirms it and the fix that clears it.

Issue 01
SSH Lockout After a Firewall Rule Change

Environment: Rocky/RHEL boxes with firewalld, hit most often right after a hardening pass.

Failure pattern: An engineer removes the default zone's SSH service before adding a replacement rule, then the reload cuts the active session mid-command. Running firewall-cmd --reload without a second session open turns a thirty second config change into a console recovery ticket.

bash
LinuxTeck.com
# Always re-add SSH before reloading if it was ever removed
sudo firewall-cmd --zone=public --add-service=ssh --permanent
sudo firewall-cmd --reload
OUTPUT
success
success
Issue 02
App Listening on 127.0.0.1 Instead of 0.0.0.0

Environment: Any distro, most common with containerized apps behind a reverse proxy.

Failure pattern: The firewall is open, the DNS resolves, and curl from the host works fine, but external requests time out. The app framework's default bind address is localhost only, so nothing outside the box can reach the socket at all.

bash
LinuxTeck.com
sudo ss -tlnp | grep 8080
OUTPUT
tcp LISTEN 127.0.0.1:8080 java

Note: Docker and Podman produce the exact same symptom if the port mapping is written as -p 127.0.0.1:8080:8080 instead of -p 8080:8080. The container's internal service is fine, the host port is published, and it is still only reachable from the host itself.

Issue 03
Stale DNS Cache After a Record Cutover

Environment: Any distro running systemd-resolved, common during blue-green cutovers.

Failure pattern: A team updates a CNAME record pointing to a new load balancer, but hosts that resolved the old record before the TTL window keep hitting the retired target for minutes past the expected cutover time.

bash
LinuxTeck.com
resolvectl flush-caches
dig +noall +answer old-lb.example.com
OUTPUT
old-lb.example.com. 45 IN A 203.0.113.9
Issue 04
MTU Mismatch Breaking Large Payloads Only

Environment: VPN or overlay networks (WireGuard, VXLAN tunnels), across all distros.

Failure pattern: Small requests work fine, but anything with a larger payload, like a file upload or a big API response, hangs or drops. This is a classic symptom of an MTU that is too large for the tunnel, causing fragmentation issues that firewalls silently swallow.

bash
LinuxTeck.com
# -M do disables fragmentation, finds the real limit
ping -M do -s 1472 10.20.4.11
ip link set dev wg0 mtu 1420
OUTPUT
ping: local error: message too long, mtu=1420
Issue 05
SELinux Silently Blocking a Port firewalld Already Allows

Environment: Rocky/RHEL/AlmaLinux with SELinux in enforcing mode.

Failure pattern: The port shows as allowed in firewalld and the app is listening correctly, but connections still refuse. SELinux has its own port context list, separate from the firewall, and a nonstandard port the policy does not know about gets blocked with no obvious log line unless you check audit.log.

bash
LinuxTeck.com
# Confirm SELinux is actually the cause before changing any policy
sudo ausearch -m avc -ts recent
# Once confirmed, add the port to the correct SELinux context
sudo semanage port -a -t http_port_t -p tcp 8880
OUTPUT
type=AVC denied { name_connect } for pid=1842 comm="java" dest_port=8880

Note: If port 8880 already belongs to a different SELinux port type, semanage port -a fails with a "port already defined" error. Use semanage port -m -t http_port_t -p tcp 8880 to modify the existing mapping instead of adding a new one.

Issue 06
Wrong Default Route After Adding a Second NIC

Environment: Any distro on a host with a management NIC and a data NIC.

Failure pattern: After attaching a second interface for storage or backend traffic, outbound internet traffic starts routing through the wrong NIC because the new interface grabbed the default route with a lower metric than expected.

bash
LinuxTeck.com
ip route show
sudo ip route replace default via 10.0.2.2 dev eth0 metric 50
OUTPUT
default via 10.0.2.2 dev eth0 metric 50
10.30.0.0/24 dev eth1 metric 100

Note: ip route replace only updates the live kernel routing table. It does not survive a reboot. Persist the change in Netplan on Ubuntu, through nmcli connection settings on RHEL-family distros, or in the matching systemd-networkd .network file on Arch, or the box will boot back into the wrong default route.

Issue 07
Cloud Security Group Blocks Traffic the Host Firewall Never Sees

Environment: Any distro running as a cloud VM behind an AWS security group, GCP firewall rule, or Azure NSG.

Failure pattern: firewall-cmd --list-all or ufw status shows the port wide open, and the process is confirmed listening with ss. It still times out from outside. tcpdump on the host is the way to prove the packet never arrives at all, which means the block is happening upstream at the provider's network layer, not on the box.

bash
LinuxTeck.com
# -n skips DNS lookups so the capture stays readable and fast
sudo tcpdump -i eth0 port 8080 -n
OUTPUT
tcpdump: listening on eth0, link-type EN10MB
0 packets captured
0 packets received by filter

Note: Zero packets captured while a client is actively connecting means the traffic is being dropped before it reaches this NIC at all. Host-level tools like firewall-cmd or ufw cannot see this layer at all, since it sits outside the guest operating system entirely. Go check the security group or NSG rules in the cloud console next.

Post-Change Validation Script

Run this after any networking change, whether it is a firewall rule, a route change, or a DNS cutover. It checks the four things that break most often and prints a clear PASS or FAIL for each. It calls dig for the DNS check, so make sure bind-utils (Rocky/RHEL/Fedora) or dnsutils (Ubuntu/Debian/Arch) is installed on the host before running it.

bash
LinuxTeck.com
#!/bin/bash
HOST="api.internal.example.com"
PORT=443

echo "Checking DNS resolution..."
if dig +short "$HOST" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "DNS: PASS"
else
echo "DNS: FAIL"
exit 1
fi

echo "Checking port $PORT..."
if timeout 3 bash -c "cat < /dev/null > /dev/tcp/$HOST/$PORT" 2>/dev/null; then
echo "PORT: PASS"
else
echo "PORT: FAIL"
exit 1
fi

echo "All checks passed"
exit 0

OUTPUT
Checking DNS resolution...
DNS: PASS
Checking port 443...
PORT: PASS
All checks passed

Usage:

Save this as validate-net.sh, chmod +x it, and drop it into any post-deploy pipeline step. A nonzero exit code fails the pipeline before traffic gets routed to a host that cannot actually be reached. Always invoke it as bash validate-net.sh, not sh validate-net.sh. The /dev/tcp pseudo-device used for the port check is a Bash built-in and silently fails or errors out under dash or other POSIX-only shells.

Security and Compliance

CIS Benchmark Aligned
SOC 2 Network Controls
PCI-DSS Segmentation

Network hardening is one of the first things auditors check, and it is one of the fastest to drift out of compliance since firewall rules pile up over time. Here is the baseline pass on each distro family.

Rocky Linux / RHEL / AlmaLinux (SELinux)

bash
LinuxTeck.com
# Default deny, then explicitly allow only what is needed
sudo firewall-cmd --set-default-zone=drop
sudo firewall-cmd --zone=public --add-service=ssh --permanent
sudo firewall-cmd --reload
getenforce
OUTPUT
success
success
success
Enforcing

Ubuntu (AppArmor)

bash
LinuxTeck.com
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo aa-status
OUTPUT
Firewall is active and enabled on system startup
apparmor module is loaded
34 profiles are in enforce mode

SELinux and AppArmor solve overlapping but different problems compared to the firewall layer. The firewall decides what can reach a port. SELinux and AppArmor decide what a process is allowed to do once traffic gets there. Skipping either one leaves a real gap, which our Linux security tools roundup and dedicated passwordless SSH hardening guide both cover in more depth. For the man page level detail on socket states referenced throughout this article, the official ss(8) man page is worth bookmarking, and the official firewalld documentation covers zone and rich rule syntax in more detail than fits in this section.

Every command in this section works fine typed by hand once. It stops scaling the moment there is more than one host. Teams running a real fleet should push these firewalld zones, SELinux port contexts, and sysctl-style hardening settings through Ansible or Terraform instead of SSHing in and running them manually. Codifying the baseline means a new host comes up compliant on day one, drift shows up as a diff in version control instead of a surprise during an audit, and the exact commands in this article become the source material for the playbook rather than a one-time checklist.

Monitoring and Maintenance Checklist

Networking configuration is not something you set once. Interfaces get added, firewall rules pile up, and certificates expire quietly in the background. Here is a cadence that keeps drift from becoming an incident.

On Alert:

  • Run sudo ss -tulnp to confirm the affected port is actually listening
  • Check dig against both the internal and public resolver
  • Pull the last five lines of firewalld or ufw logs for denied connections

Weekly:

  • Review new firewall rules added since the last review
  • Check for TLS certificates expiring in the next 30 days
  • Confirm no service is unexpectedly bound to 0.0.0.0 instead of a specific interface

Monthly:

  • Audit firewalld zones and ufw rules for stale entries nobody remembers adding
  • Re-run the validation script from Section 07 against every production host
  • Rotate SSH keys for any service accounts still on password auth

Quarterly:

  • Full SELinux/AppArmor policy review against current running services
  • Penetration test or external port scan against production edge
  • Review DNS TTL strategy against last quarter's actual incident response times

Frequently Asked Questions

Why does my app work with curl on the host but not from outside?

Almost always a bind address problem. Check with ss -tlnp and look at the local address column. If it says 127.0.0.1 instead of 0.0.0.0, the app is only accepting connections from itself.

Should I disable SELinux to fix a networking issue faster?

Set it to permissive temporarily to confirm SELinux is the cause, check audit.log, then fix the actual policy with semanage. Leaving it disabled in production removes an entire security layer and most compliance frameworks will flag it during an audit.

How do I know if a firewall change actually applied without breaking anything?

Keep a second SSH session open, apply the change, then run the validation script from Section 07 from a separate box, not the one you just changed. If it fails, you still have your original session to roll back.

What is the actual difference between ufw and firewalld?

Both sit on top of the kernel netfilter framework. ufw is a simpler wrapper favored on Ubuntu with a smaller command surface. firewalld uses the concept of zones and supports live reloads without dropping existing connections, which is why it is the default on RHEL-family distros.

Why do DNS changes take so long to show up everywhere?

TTL. Every resolver in the chain caches a record for as long as the TTL says. Lowering the TTL an hour before a planned cutover, then raising it back afterward, is standard practice for anything that needs a fast failover.

Is nmcli or netplan the right tool on Ubuntu servers?

Ubuntu server defaults to netplan, which generates the underlying config that either systemd-networkd or NetworkManager applies depending on the install. Check /etc/netplan first before reaching for nmcli directly on a stock Ubuntu server image.

How do I debug a connection that hangs instead of failing outright?

Hanging usually means a packet is being silently dropped rather than actively rejected, often at a security group, MTU, or an overly aggressive firewall rule with no reject response configured. tcpdump on both ends of the connection will show exactly where the packet stops.

What networking knowledge actually matters most for a DevOps interview?

Being able to explain, step by step, how you would debug "the site is down" using only DNS, port state, and routing tools tells an interviewer more than reciting the OSI model from memory. Practice narrating the diagnostic path out loud.

Conclusion

None of the tools covered here are new, and that is exactly the point. ip, ss, dig, and curl have outlived several generations of shinier abstractions because they answer the same question fast: is the network actually the problem, or is it something else wearing a network costume. Ubuntu, Rocky, RHEL, Fedora, and Arch all differ in how they manage interfaces and firewalls, but once you can read ss output and trust a dig answer, switching between them stops being a big deal.

The industry trend over the last few years has been toward more abstraction, not less. Service meshes, managed load balancers, and container networking layers hide raw sockets behind YAML. That abstraction is convenient until it breaks, and when it breaks, the debugging still happens at the layer this guide covers. Teams that keep this skill sharp resolve networking incidents in minutes. Teams that let it atrophy spend hours re-learning it under pressure.

The tooling gap between distros is also narrowing. firewalld now ships as an option on Debian-based systems, nftables has become the common backend under both ufw and firewalld, and iproute2 is standard everywhere. Five years from now, the biggest differences between distros in this space will likely be default policy, not the underlying commands.

If you manage hosts across mixed environments, pair this guide with our RHEL vs Ubuntu server comparison and our network administration guide for the broader picture. And if part of your stack sits on managed hosting rather than raw VMs, our team's honest Kinsta hosting review is worth a look before your next infrastructure decision. For today, the one action that pays off fastest is running the validation script against your current production fleet and fixing whatever it flags before it becomes a 2 a.m. page.

Beyond networking, we publish real-time Linux tips covering everything from shell shortcuts to system tricks, small commands that add up to real time saved every day. Explore the full Linux Tips archive here.

LinuxTeck - Master Linux Networking Skills for DevOps Success in 2026
This guide walked through the commands, architecture, and real failure modes that DevOps engineers hit most often across Ubuntu, Rocky Linux, RHEL, Fedora, and Arch.
LinuxTeck's Enterprise Linux category focuses on production-ready Linux skills including:
Linux networking, firewalld and ufw, DNS troubleshooting, SELinux and AppArmor, SSH hardening, and DevOps network debugging.

Support My Work

Thank you for reading and for being part of this journey. If this article saved you time, consider buying me a coffee. Every contribution helps me keep producing in-depth, practical Linux content for readers like you.

Thank you for your endless support

About Sharon J

Sharon J is a Linux System Administrator with strong expertise in server and system management. She turns real-world experience into practical Linux guides on Linux Teck.

View all posts by Sharon J →

Leave a Reply

Your email address will not be published.

L