Platform
This page outlines the standard setup I use across most of my projects - including deployment, infrastructure, and security. Any deviations from this will be noted on individual project pages.
Deployment 🚀
Apps are typically hosted on DigitalOcean’s App Platform, which provides a balance between flexibility and managed infrastructure.
Code is deployed via GitHub Actions. This allows for automated builds and deployments with support for multi-step workflows and easy secret management.
Persistence 💾
I use Supabase for persistence, which provides a managed PostgreSQL database. It’s easy to integrate with and use. The free tier has been sufficient for my needs although there is a limit of 2 active projects.
Infrastructure 🏗️
Infrastructure is provisioned using Terraform. Typically, the infrastructure
code is defined in each individual project’s repository in a infrastructure/environments/...
directory. Code is organised
by environment (e.g., test
, production
) and includes all necessary resources for that environment.
The exception to this is for any shared or more general infrastructure, which is defined in a separate repository. This can include things like Cloudflare Access policies, DigitalOcean or Cloudflare projects, or shared DNS records (email, shared domains, etc.). When needed, this shared infrastructure can be referenced in an individual project.
This has made it easy to manage infrastructure alongside the application code. The Terraform code is also applied using GitHub Actions, which makes it easy to trigger changes and deployments from the same place as the code. It also means that I don’t have to store secrets locally, as they are secured in GitHub secrets.
Terraform state is stored in AWS S3 buckets - one per repository, and each bucket can hold state for multiple environments. It’s cheap (essentially free for low usage) and reliable.
Security 🛡️
For internal apps, I primarily use Cloudflare Access to block public access.
Previously I used a Netbird VPN hosted on a DigitalOcean Droplet (along with some apps). While I enjoyed using this, in time managing this and the Droplet itself became a bit of a hassle. It became easier and cheaper to migrate to DigitalOcean’s App Platform and use Cloudflare Access for security.
For authorization, I currently use AWS Cognito. Cognito issues a JWT access token upon authentication,
which clients include in the Authorization
header of API requests. The receiving service can then validate the token to ensure the
request is made by an authenticated and authorized user.