How to create a nextjs + mongoDB SaaS fully self-hosted
I wanted to build a SaaS that allow users to view, edit and share docker-compose files easily. If you don't know anything about docker, that's totally okay. This article is focused about the stack behind the SaaS.
So, my needs where :
- A user system
- Somes analytics
- A blog sytem
- A documentation system
- A database that allow me to quickly try new things
- The stack has to be self-hostable easily
Choose a database
The database, is a though choice. First should i go SQL or No-SQL ?
In my opinion, we should choose a database that fit our data shape, and not shape our data to fit in the database. And if you know a little of the docker-composes, that's a very complex data shape to store, as is it quite inconsistent (I mean, even if this is based on yaml, there is so much differents possibilities). To store it in an sql database would be a nightmare, the only "easy way" would to just considere it as a raw text and store it in a text cell (or byte but anyway).
Yes i could use the postgresql JSON cell to create a way to store it convientently, but remember our need : keep it simple
.
So i choosed No-SQL for the ability to store non structured data.
But what No-SQL database ?
Choosing a No-SQL database is just half the way to choose a database. There is still so much questions to pick one.
But always remember this when you are a small team or solo dev : keep it simple
.
So i will restrict my questions to :
- Is there an easy to use TypeScript Driver ?
- Is the database secure ?
- Can i self-host it ?
- Is there a big community ?
I thought about surealDB and mongoDB. They both have a TS sdk, they dont' have new CVE each morning, and they are fully self-hostable.
SurrealDB
SurrealDB could be a really good way to go, has it can be used as an sql db for my user part and noSQL for my data-processing and job part.
But the big drawback is the lack of maturity. Even if the devs are quite fast on issue peoples submits, their is not so much stack-overflow or any knowledge place about it.
The final choice : MongoDB
So, at the end i choosed mongoDB as it would allow me to quickly change the dataModel of my entities, and there is a much stronger documentation knowledge about it.
At this point i knew i will use nextJS + mongoDB, but what about the bloging system, the documentation, and the analytics ?
The self hosting part
Before going further i started my first beta with very few user. So i needed to self-host the stack. My two biggest concern where : I want it cheap, and i want it easy.
I choosed hetzner.com has they are really cheap and reliable. 4.51 € /month for 2 Cpu, 4Gb Ram 20Tb bandwith and 40gb SSD. To manage my VPS i choosed coolify, has it's fully open-source and allow me to easily deploy new services.
The analytics, blog and documentation :
The analytics choice was really straigth forward for me as i use Umami analytics from 2020. It's fully self-hosted, open source and GDPR complient.
My blog need where a little bit weird as i needed something headless but with an admin UI and self-hostable. I could go for Strapi, but i ended with Directus for no particular reason both could perfectly fit in my use case.
About the documentation, my choice has been pushed by : cheap and fast
. So i could go with any Mardkown based documentation. Here is somes good choices bellow :
- Docusaurus
- Hugo
- mkDocs
- markdoc
I ended with Docusaurus because it's based on react, and in the future, if there is any need i could easily add custom components.
Is'nt there any SEO issues using a different techno for documentation and bloging ?
To avoid SEO issue that are associated with multi-domain website such as could be composecraft.com
, docs.composecraft.com
, blog.composecraft.com
.
I Opted for a different way to go :
First my blog system is more a library system. Directus only help me to manage the entries, my data contains a markdown field and directly feed my nextJS, so for the blog part (or library as you want) everything is under composecraft.com/library and nextJS handle it with the next-remote-mdx library.
But although i could used the same patern for my documentation, i choosed docusaurus. Why ? Because my documentation will quickly evolve, and i don't want to mess with any nextjs question when writting documentation. I just want to writte mardown file and do not care about mobile responsive, about performance or anything. Using Docusaurus automaticly enforce my documentation to be structured, easy to edit and easy to use by my users.
So i just setted my reverse-proxy to send any request under /doc to the Docusaurus docker that running managed by my coolify.
The reverse proxy :
In my opinion, especialy for choosing a reverse-proxy for low/medium load website go with the one you love. There is no "compute" better choice between ngninx, trafeik, apache or caddy as you stay with a simple server and no load balancing or complex routing.
The backups ?
How does i ensure my self-hosted database won't desapear when my server will burn because of my to many users ?
Until now my server is far away from burning from my to many user, but anyway i have integrated a backup mechnism. Which one ? Every day at 3 am a complete database backup is schedule and stored in a distant S3 on a cloud provider (a different from my VPS one to prevent from them putting the S3 bucket in the same datacenter as my production server).
Last concern : the CDN
As a small product that is used worldwide i faced a problem : my US users complains about latency, and indeed the server is located in Europe.
Easy answer : i could have a US instance !
But ... remember it's a small projet and i want it cheap and easy
. So i choosed to call cloudflare to help me with their free CDN. Yes it's not a fully self hosted privacy powered stack. But as a small product team it's the best cost/performance chose i cloud make.
The final scheme :
Somes thoughts
Could i builded it simpler ?
Yes i definitly clould : If my final client was someone non tech at all i would have worked more on the docs and reused directly directus to manage my docs in the same time as my libraries. And if the client do not want to infere at all with linux server : using mongoDb atlas and cloud solution for analytics, and something like vercel, netifly or fly.io to deploy my stateless nextjs app.
But as I am a linux lover and i am really not afraid of getting my hand on code, i thinks this is the most cost efficient and easy maintainable stack that fit me.
Wana go deeper ?
I will soon create article about the CI/CD pipeline, and another one about the internal nextjs logic. keep updated about new blogs posts subscribing to the newsletter bellow :