Few words about me
Passionate about building products and full-time security engineer. I love building product and doing security bug hunting in my free time.
I'll share about my experience and still investing a considerable amount of time to make a generic tech stack i.e platform independent and cost efficient scalable infrastructure for bootstrapping.
This article will cover a rough overview of the tech stack that almost every indiehacker can adapt for building their company.
Note : i'm not going to sell anything here or force anyone to use this stack or architecture. Suggestions are welcome, so that we could build a opensource stack for everyone who is building a bootstrapped company for next 1000+ customers.
PS : I've adapted this for our sidekick and it's almost successfully running without any hinderance where we spend more time on product management and customer support. ( We have not yet announce officially/ incorporate / no billing setup but we have zero paying customers with 2k potential signups )
Jumping into the stack,
- Any cloud service that sounds cheap for you. Options : AWS Lightsail ( most preferred ), Digital Ocean, Linode, Azure VM
- Namecheap domain and DNS config or use Route 53 with AWS ( faster )
- Mail Setup : Amazon SES / Sparkpost / ElasticEmail
- Static Ip ( mostly free in Aws Lightsail and Digitalocean )
- LetsEncrypt certificate for SSL ( use wildcard for all subdomains for clutter free management and seperate root domain ssl )
- Docker Swarm ( Community Edition )
- Ubuntu VM 16.04 / 18.04
Source Code Management and Build
- Gitlab ( Free organization - private mode )
- Gitlab CI - your own runner ( Don't use shared runner )
This becomes trickiest part, separate your application server, database server, scheduling server ( rabbitmq ), Web server ( nginx or apache ) as docker images with dockerfile and integrate with docker-compose file.
- Nginx image - hosted on gitlab private registry
- Database Image - hosted on gitlab private registry
- Application Image - hosted on gitlab private registry
- Wordpress/blog image - hosted on gitlab private registry
- Other dependant images - hosted on gitlab private registry
You should be able to write your code, test in your development machine and build the image and push it into gitlab registry separate repo's.
Basic Idea of setup, ( Intranet meaning - docker swarm )
- App server - API server running in intranet without exposing port
- Database server - eg : Mysql/Mongo/WhateverDB server 3306 within intranet
- Redis / Memcache server - eg Redis within intranet
- Wordpress server - running in intranet
- Static websites - Blog, help, landing domain and other subdomains which is running as seperate docker instance in intranet
- Sentry Server - Opensource on-premise logs/crash report server with web ui ( you can push server logs, frontend crash logs, or any dependent server log for analysis )
- Minio server - Opensource on-premise S3 implementation to store files, uploaded files safely within the swarm instead of using Third party.
- Nginx Server - scalable one accepts 443 and 80 port and routing traffic into internal servers as reverse proxy based on virtual host
Setup Docker swarm
- choose two preferred VM Ram and memory size.
1 Machine x 8 GB Ram - Manager node for docker swarm
2 Machine x 4 GB Ram - Worker node for docker swarm
- connect the machines with the private intranet IP ( within same same availability zone/ datacenter location ) in the public cloud with docker join token
Now everything is perfect, you can launch the service stack and let docker can scale the service independently using scale command.
Connecting the dots
- Push your code changes to gitlab and build as docker image
- combine all service as docker-compose.yml file with restart, volume mounting to persist data between container updates.
- login into your gitlab registry with read access token in Ubuntu VM from gitlab
- Finally deploy the whole service with docker stack single command.
Possible Open public ports
- 80 - Accept and redirect to HTTPS
- 443 - Accept valid https traffic
- 22 ( public - private key authentication )
- close all other ports with help of UFW or firewall rules.
- If you still need protection, you can point your DNS to Cloudflare to block malicious traffic.
- Use Nginx bad actor block - https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker ( Use it with caution because it may block valid traffic )
- Store your SSH private/public key safer and always have a backup in your offline machines
- Docker swarm by default uses encryption between the machine or containers within the datacenter.
- Never login with actual credentials to your gitlab from your production server, use only Read access token for pulling images from production server.
- Use predefined request params with safe-regex to determine value from client side
- never spit the application logs as response ( use error handler and log error messages and send to sentry server )
- have a middleware check for brute-force attacks and limit ip and session based restriction ( using redis cache )
- Use ORM and clean user inputs before making query to database. ( obviously there will be zeroday attacks but always use regex clearly to prevent unwanted user strings )
- Implement CSRF tokens between the client and server communication
There are a lot of checks here, but i would suggest that it would evolve only when you successfully launch and sell your product for 100+ customers
If you have any questions on application security, go ahead and comment below.
Speed up the website using CDN
- use cloudflare cdn or equivalent cdn for speeding up the js, assets, image loads in your application
Why this approach is scalable ?
- Docker does the scaling for your automatically. When your customer base increases, you can add additional machine to the docker swarm and scale with docker commands automatically.
- Run dedicated instance of docker node for DB server when the load increases with docker placement commands
- Server provisioning and DB maintenance + security overhead will be totally reduced when these kind of stacks are implemented when scaling the business organization.
Good news, you can reuse the stack generically even if you plan for next product, so it's worth investing in infrastructure and engineering for seamless deploying and running it without downtime.
What about monitoring ?
- Signup for website monitor such freshping or even indihacker website monitoring projects to check your app health via nginx server route.
- Use prometheus within swarm service to check for docker container health status. ( I would not recommend this until you have 100+ paying customers )
- Use log server such as raven to find exceptions and fix it as soon as the error happens
- Use Slack Webhook to push critical events to your team members to be aware of any issue or container restart or even lead signup ;)
What about Cost ?
- 3 Machines - 2 x 10 USD + 1 x 20 USD = 40 USD for lightsail AWS * 12 months ( minimal starting setup for 100 customers )
when you get paying customers, you can add more machines to the docker swarm node and scale with docker scale commands.
- Don't run dedicated mail server - use Amazon SES ( cheapest ) to lift the weight
- Namecheap - depends on your domain value.
So, finally this SaaS setup with scalable + secure infrastructure can be helpful for indiehackers community and tech co-founders who needs scale for their next 1000+ customers.
To be Honest, it took me over 1+ year to implement this stack and automate and now we have a product in hand that uses this setup. Now, this becomes easy for us to build the next product in less than a month with these stack and re-using the code + architecture.
If this article goes well, i'll detailed blog post on every topic covered here from analysing the VM cost to the application security, product development.
For doubts/ scalability issues/ security mitigations, ping me or comment below for more discussion.