Then you should learn Unix. From an understanding point of view, I think it's probably better to learn something like FreeBSD, NetBSD, Xv6 ... Linux is very pragmatic, and very general, and so it doesn't have the purity that smaller, more focused or curated systems have. Once you have a handle on Unix, look at other OSes: Plan9, Minix, FreeRTOS, L4, etc.
Then networking: I suggest starting with IP, TCP, ARP; then step down to the physical layer: Ethernet, Token Ring, 802.11, hubs, and switches; then static routing, RIP, OSPF, and BGP; maybe look at mesh routing. Then some application layer stuff: DNS, NTP, SSH, NFS, LDAP, HTTP, etc. Reading the RFCs is really valuable, and they're remarkably accessible up until say 2500 or 3000 or so.
Security: symmetric and asymmetric crypto, Kerberos, SSL, SSH, OAuth, etc. Read up on pen testing, social engineering, defensive programmings, fuzzing, etc.
Databases: both relational and otherwise. SQL. Wrap your head around how a filesystem and a database are the same and how they're different.
Messaging: some sub-set of protocol buffers, Cap'n'Proto, Avro, Thrift, XDR; brokers vs. p2p; pub-sub vs. directed. There are hundreds of system you can look at here: pick a few that look different.
Learn about complexity analysis, distributed consensus, locking, concurrency and threads.
so far as tools go, you need to understand a debugger (how to use it, and how it works), packet capture and analysis (Wireshark is good), profiling and performance analysis.
That's probably a decent coverage for the software side. The exact focus will differ depending on embedded/real-time vs enterprise, etc.
From the hardware side, I think it's worth starting with an 80's or earlier, 8 or 16-bit system, and learning how it works to the digital logic level. What a simple microprocessor actually does: fetching, decoding, execution units, etc. A Z80 or 6502 or similar system is a pretty simple circuit, and it's worth really grokking how it works.
From there, you can move forward to more complex CPUs, newer memory architectures, newer buses, etc. But it's much harder to dive straight into a modern x86 or ARM CPU and try to understand how it works.
It's a this point that reading Drepper's memory article, and the "everything you should know about latency" article(s), etc, really start to be useful, because you've got a solid grounding in what's underneath them.
You don't need to do this all at once, or before you start working more on backend or systems level code: I'd guess it took me close to 10 years to feel like I had a decent grasp on most of it.
- Embarrassingly low-level (chip developers): OS, C/VHDL/Verilog, MA, DS, GPH, EE, Apathy, SE
- The in-betweeners (kernel, device, storage developers): OS, C, MA, DS, GPH, Apathy, Crypto, SE
- Low-Low-level systems: OS, C, DS, GPH, Apathy, Crypto, SE, FTDS, MSG, NW.
- Low-High-level systems: C/Rust, DS, GPH, Apathy, HDS, Crypto, SE, FTDS, MSG, NW, TL.
- Unicorn rock-star systems hacker (perhaps only a handful
of these creatures exists :-): Multiple OS, C/Rust/JVM/Erlang/Haskell, Multiple MA, DS, GPH, EE, Crypto, FTDS, MSG, NW, HDS, SSE, TL.
GPH = Good Programming Hygiene
EE = Electronics and Electrical Engineering
OS = Operating System
MA = Modern Assembly
DS = Data Structure
FTDS = Fault-Tolerant Distributed System
MSG = Messaging System
NW = Networking
TL = Toolings (the darlings of UNIX)
HDS = High-Density Systems
SE = Security Engineering