A whitelist flips your server from "anyone with the address can join" to "only these named accounts can join". It takes two commands, it costs nothing, and an un-whitelisted server shared in even one Discord gets visited by strangers faster than you would believe. Here is the complete setup for every kind of server.
Java Edition: the five commands
Run these in the server console, or in chat as an operator with a / prefix:
whitelist on # enable the list whitelist add StePlays # allow one account (exact in-game name) whitelist remove StePlays # un-invite them whitelist list # show who's allowed whitelist reload # re-read whitelist.json after hand-editing
Names are matched against Mojang's account database, so friends don't need to have joined before, but the spelling must match a real account. The list itself is stored in whitelist.json next to your world; you can edit it by hand, but the commands are safer because they also record each account's UUID, which is what actually identifies a player after a name change.
The two settings people miss
In server.properties:
white-list=true enforce-whitelist=true
The first is the same switch as whitelist on, persisted. The second is the one people miss: without it, enabling the whitelist stops new joins but leaves anyone currently online connected. With it, non-listed players are disconnected the moment enforcement applies. Turn both on and the server behaves the way you expect a locked door to behave. The server.properties generator sets both in its friends preset.
Whitelist vs ops (don't confuse the two lists)
The whitelist answers "who can come in?"; the ops list answers "who can run admin commands?". op StePlays gives a player command access up to the level in op-permission-level (4 by default, which includes /stop). Every friend goes on the whitelist; ops should be you plus at most one trusted deputy. Griefing by a bored friend with op powers is a more common ending than griefing by strangers.
Bedrock servers: it's called an allowlist
Bedrock Dedicated Server renamed the same feature: the file is allowlist.json and the commands are allowlist add "Gamertag", allowlist remove, allowlist list, with allow-list=true in server.properties. Gamertags with spaces need the quotes. Behavior is otherwise identical to Java's.
Crossplay servers: Floodgate players need fwhitelist
On a Java server with GeyserMC crossplay, Bedrock friends join through Floodgate and appear with a prefixed name (a leading dot by default). The vanilla whitelist cannot add them, because their gamertag isn't a Java account Mojang can look up. Floodgate ships its own command for exactly this:
fwhitelist add TheirGamertag # whitelist a Bedrock player whitelist add TheirJavaName # Java friends: vanilla command as usual
Run both kinds of adds and the one server stays locked for both kinds of players. More on the crossplay setup itself in the crossplay guide.
On a hosted server
Everything above works unchanged on SpawnFort: open your server's console tab and run the same commands, no / needed. The point of doing it early is the same everywhere: whitelist first, then share the address, and the invite list is exactly your friend group, forever.