This does depend heavily on your setting, specifically the details of “what exactly happens to your soul when it dies?” I don’t know the answer to that question for any official setting, but if you’re the DM then you get to choose for your setting. As long as the answer is something like “Your soul travels to a specific plane, and becomes a Celestial, Elemental, Fiend, or Fey, but retains all other statistics” then this method shouldn’t require any fudging of the actual rules, and should work for the players just as well if they choose. I will note that it doesn’t actually involve any necromancy spells though.
Step 1: Getting the creature
The 9th level Conjuration spell Gate has this option:
When you cast this spell, you can speak the name of a specific creature (a pseudonym, title, or nickname doesn’t work). If that creature is on a plane other than the one you are on, the portal opens in the named creature’s immediate vicinity and draws the creature through it to the nearest unoccupied space on your side of the portal. You gain no special power over the creature, and it is free to act as the GM deems appropriate. It might leave, attack you, or help you.
This is where “Other planes as afterlife” is important; if souls go somewhere other than a plane then this doesn’t work in the official rules. That said, as long as the creature is on another plane this spell doesn’t seem to even allow a saving throw. A way to make this somewhat limited for players but not out of reach is that the true name of ancient heroes may be difficult to find, and the Bad Guy only managed after years of “off-screen” research.
Step 2: Containing the creature
So your Legendary Hero is now in front of the Big Bad Necromancer Guy. Generally speaking such a situation is actually not beneficial to the Bad Guy’s plans, so it’s important to contain the Hero until Step 3 is done. The ideal spell for this purpose is the 3rd level Abjuration spell Magic Circle, with its inverted mode:
When you cast this spell, you can elect to cause its magic to operate in the reverse direction, preventing a creature of the specified type from leaving the cylinder and protecting targets outside it.
It also needs to be cast at 4th level or higher to actually work for step 3, and it’s better to cast it at as high a level as you can. This is the first place where the soul having the type Celestial, Elemental, Fiend, or Fey comes in, though Undead would work here if you choose an alternative option for step 3. There may be other methods of protecting the Bad Guy, but this one is approximately tailor-made for the purpose especially if the Hero doesn’t have teleportation or interplanar travel in their stat block.
Step 3: Binding the creature
The best spell for this purpose is Planar Binding, a 5th level Abjuration spell. The casting time is 1 hour, which is why Magic Circle needs to be cast at 4th level; it must be cast before the Gate, but Planar Binding must start casting after the Gate so there would be at least 1 round when the Hero is not contained by the Magic Circle or affected by Planar Binding. Higher levels of Magic Circle allow the Bad Guy to make cast Planar Binding multiple times if the Hero succeeds on the saving throw.
Planar Binding should also be cast at as high a level as possible; a 9th level Planar Binding lasts for a year and a day, giving plenty of time for the Bad Guy to wreak havoc and then order their unwilling servant to return so the Binding can be renewed for the following year. As long as the initial saving throw fails the Hero must follow the Bad Guy’s orders for the duration though it technically has some free will as long as it doesn’t contradict the Bad Guy’s orders.
This is where the main creature type restriction comes in: only Celestials, Elementals, Fey, and Fiends can be affected by Planar Binding. If you want the souls of the dead to be Undead creatures then Magic Circle will still work but you’ll need to deal with one of the Step 3 Alternatives. If you want some other creature type then you need to find your own Step 2 alternative as well (there are a lot of options for “keep someone imprisoned” so I’m not going to try to list them all).
Step 3 alternatives:
If you don’t want dead souls to have one of the four listed creature types for Planar Binding, some of these alternatives might work well enough for your purposes:
- Mass Suggestion doesn’t give such fine control, but phrasing something reasonable like “My secret ritual is necessary to save the world, so you should protect me from anyone who tries to stop it” might be close enough. At 9th level this lasts for a year and a day just like 9th level Planar Binding. Note that regular Suggestion does not get an extended duration from upcasting, so Mass Suggestion must be used even if you only target one creature.
- Modify Memory could work if you cast it enough. At 9th level it can modify any portion of a creature’s memory as needed, replacing real memories with false ones that would make following the Bad Guy seem reasonable. However, each casting only modifies 10 minutes at a time; the Bad Guy will need a LOT of 9th level spell slots to rewrite the Hero’s full history. Some more nuanced applications could cut that down by a lot, but that’s more of a DM-fiat situation.
- Magic Jar isn’t quite there but could be close enough for your purposes and is notable as the only option that involves any Necromancy. It requires that the Hero be Humanoid rather than any of the previously discussed creature types. It doesn’t fully retain the Hero’s statistics though, instead the result has some statistics from the caster and some from the target, but still a “real character sheet” rather than just a generic stat block. This version also grants the most complete control, completely supplanting the Hero’s will, and also has “until dispelled” duration rather than needing periodic refreshes. On the other hand, the caster’s body is left catatonic, so it’s not much of a “servant” as it is a disguise.
- As-written Geas probably isn’t good enough, but it is the type of spell used for this purpose. With a Geas you issue instructions for the duration, which can be indefinite at 9th level. The problem with Geas is that it doesn’t actually force the target to follow those instructions, it just punishes them for not doing so. I personally find it unlikely that a Legendary Hero would do the bidding of a Bad Guy just to avoid some damage.