All three ways will work (modules mentioned in answers as third answer), in some cases better, in some - well.
But the exercise you have to do is you have to think, how your infrastructure will look in the nearest future. This is, as it was mentioned, a design and architecture decision. For sure you have some goals to achieve and this should be a base for your design.
You have to find the answers to couple of questions:
- how your infrastructure will be multiplied?
- do you allow to re-use of specific elements of the infrastructure (for example VPC)?
- are you going to serve these templates through Platform Engineering teams - self-service solutions?
- how do you deal with multiple environments?
- how do you manage the state?
- how do you orchestrate different modules/templates/environments?
- how do you want to manage the whole SDLC of your infrastructure?
These questions are the starting point for your design. I know, it sounds like I complicate things, but I try to think about big picture. And believe me, it will be very important later.
For example: if my solution is simple and I will run it generally only once, I will go with the simplest solution. If I know I will re-use some components, I will go with modules. If I will re-use my modules in wider way (many projects, env, etc), I will go with modules stored in registry. If I go even further, it is time to think about dedicated tools, like Spacelift (disclosure: I am Developer Advocate there). But if you want to orchestrate very complicated setup, with multiple teams, projects, accounts (or subscriptions), modules, dependencies, you should, really, look at tools like this.