Dalius's blog

Monday, January 20, 2025

Kamal & Astro

I am writing this blog using Astro. I have found out recently about Kamal and decided to migrate my projects to it. Before that I was using Ansible.

What I liked about Kamal: it is quite simple, defaults are sane, I can keep deployment’s configuration in repo near project, because of Docker I get more security and I guess I can think of more benefits.

I have found one repository how astro and kamal can be used together, but I found it too complicated as it can be done simpler. Here is what I am using.

Docker part

First you can do Docker part and you can actually test if this is working without Kamal. I am using nginx:alpine-slim for production as it is enough for blog and makes resulting Docker image quite small.

Dockerfile file:

# Build Stage
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm exec astro build

# Production Stage
FROM nginx:alpine-slim AS production
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

As well we need proper .dockerignore file:

node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore

Kamal part

This is almost default Kamal file from documentation.

service: blog

image: username/blog

servers:
  web:
    - 195.201.143.78

proxy:
  ssl: true
  host: blog.ffff.lt

registry:
  username: username

  password:
    - KAMAL_REGISTRY_PASSWORD

builder:
  arch: amd64

As I am using passwordstore I have simply put registry password into it. So my .kamal/secrets looks simply like this:

KAMAL_REGISTRY_PASSWORD=$(pass show dockerhub)

NOTE: you should use non dockerized Kamal version for this to work properly.

Astro part

Lastly we need to add src/pages/up.astro with any content, e.g.:

<p>
  Status: OK
</p>

We need to do this because Kamal relies on /up returning 200 OK.

I think I will write more in the future about Kamal.

Inspiration for this: