Let's build a blog page with Axum, Askama, HTMX and Tailwind. I like to write articles in Markdown files, so I'm checking in markdown files in the repo and I parse and ingest them into a postgres database. The parser assumes that articles metadata is provided at the top of the document:
% id: 1
% title: Some blog title 🤖ðŸ§
% date: 1970-01-01
% tags: ml, devops, rust
This project is deployed on serverless compute (AWS Lambda), using the Rust runtime. To make things easier, it uses cargo-lambda
to run, build and deploy.
brew tap cargo-lambda/cargo-lambda
brew install cargo-lambda
Run Postgres locally:
docker run -d \
--name webrs-postgres \
-e POSTGRES_DB=webrs \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=admin \
-p 5432:5432 \
postgres:latest
Run the server locally:
cargo lambda watch
Run Tailwind (styling):
yarn install
yarn dev
The corresponding database URL would be postgresql://admin:admin@localhost/webrs
which is expected to be passed as environment variable DATABASE_URL
. Just for development purposes, this variable can also be set in ./.env
.
Likewise, OPENAI_API_KEY is set to generate summaries of the articles. This is only needed for initial ingestion.
cargo lambda build --release
Or build Docker image and deploy wherever you like.
docker build -t webrs .
Compile and copy assets to target:
yarn prod
I'm using the AWS Serverless Application Model (SAM) to deploy the Rust binary, along with assets, on S3 and AWS Lambda:
AWS_ACCESS_KEY_ID={...} AWS_SECRET_ACCESS_KEY={...} sam deploy --parameter-overrides DatabaseUrl="$DATABASE_URL"
Retrieve the API gateway domain name to route traffic from a custom domain name:
aws apigateway get-domain-names --region eu-central-1 | jq '.items.[0].regionalDomainName'
Copy files to cloudfront s3 bucket
aws s3 cp ./cloudfront/ s3://danielsteman.com/ --recursive
Cloudfront is the AWS CDN solution and requires a certificate in us-east-1, since it's a global service that kind of makes sense.
Create a certificate in Cloudflare and import it in AWS ACM along with the Cloudflare root certificate as chain certificate.
Install artillery
globally with npm install -g artillery@latest
.
If the page is not loading, check if sqlx
made a connection and didn't timeout. A timeout indicates that local Postgres is not up.
CockroachDB doesn't support locking the database prior to migrations. Hence, sqlx::migrate!().set_locking(false)
.
CockroachDB is going to log warnings on startup due to sqlx
migration queries that take time to execute. This is only on startup though, so it shouldn't be an issue.
aide
, or something like that, to generate openapi specshiki
code snippets on the server