17 Commits

Author SHA1 Message Date
72619e58b5 fix(deps): update tailwindcss monorepo to v4
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build was killed
2025-11-13 02:12:30 +00:00
9086f7833d feat: add plausible
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2025-08-11 10:48:36 +02:00
cc5b165822 chore: small corrections
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2025-08-05 22:53:55 +02:00
0cf84ffe0e feat: change ports
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2025-08-05 22:48:27 +02:00
61e98064f6 feat: use styles absolute
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 12:18:20 +02:00
f35fbe21c2 feat: set port
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 12:14:44 +02:00
47dfec5e26 feat: add more logging
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 12:13:07 +02:00
e3056382d3 feat: serve for everything
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 12:07:58 +02:00
a24a726a9b faet: remove encode
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 12:05:07 +02:00
ccfcd42d1e feat: move to caddy
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 12:04:16 +02:00
592afe4914 feat: move to serve 2025-07-31 12:04:02 +02:00
bf39c5f42f feat: caddy
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 11:59:35 +02:00
f575351335 missed 'v'
Some checks failed
continuous-integration/drone/push Build is failing
2025-07-31 11:57:04 +02:00
b1a13dad9b feat: download new zola
Some checks failed
continuous-integration/drone/push Build is failing
2025-07-31 11:55:57 +02:00
97986b1bef feat: with stuff
Some checks failed
continuous-integration/drone/push Build is failing
2025-07-31 11:43:39 +02:00
3274120012 feat: add git password
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-31 11:24:57 +02:00
ec9bc7eed8 feat: add cargo.toml
Some checks failed
continuous-integration/drone/push Build is failing
2025-07-31 11:16:31 +02:00
11 changed files with 3118 additions and 565 deletions

View File

@@ -70,6 +70,9 @@ steps:
CUDDLE_SECRETS_PROVIDER: 1password
CUDDLE_ONE_PASSWORD_DOT_ENV: ".env.ci"
CUDDLE_SSH_AGENT: "true"
GIT_USERNAME: "kjuulh"
GIT_PASSWORD:
from_secret: git_password
CI_PREFIX: "/mnt/ci/ci"
CUDDLE_PLEASE_TOKEN:
from_secret: cuddle_please_token
@@ -123,8 +126,11 @@ steps:
CUDDLE_SECRETS_PROVIDER: 1password
CUDDLE_ONE_PASSWORD_DOT_ENV: ".env.ci"
CUDDLE_SSH_AGENT: "true"
GIT_USERNAME: "kjuulh"
GIT_PASSWORD:
from_secret: git_password
SSH_KEY:
from_secret: gitea_id_ed25519
CI_PREFIX: "/mnt/ci/ci"
DOCKER_HOST: "tcp://192.168.1.155:2376"
CUDDLE_PLEASE_TOKEN:

2574
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

3
Cargo.toml Normal file
View File

@@ -0,0 +1,3 @@
[workspace]
members = ["ci/"]
resolver = "2"

84
README.md Normal file
View File

@@ -0,0 +1,84 @@
# Kasper Hermansen's Blog
A personal blog built with Zola (static site generator) and deployed using containerized CI/CD with Dagger.
## Prerequisites
- **mise** - Development environment manager
- **Rust** - For running Dagger CI
- **Docker** - For containerization
## Development
### Quick Start
```bash
# Install dependencies and start dev server
mise run dev
```
This will:
- Start Zola dev server on http://localhost:8000
- Watch and compile Tailwind CSS changes
- Show posts in progress
### Available Commands
```bash
mise run dev # Start development server with live reload
mise run ci:pr # Run CI build for pull requests
mise run ci:main # Run full CI pipeline (build + deploy)
```
## Deployment
The blog uses a fully automated CI/CD pipeline built with Dagger (Rust SDK).
### Manual Deployment
```bash
# Build and deploy to production
(cd ci && cargo build)
./ci/target/debug/ci main
```
This will:
1. Compile Tailwind CSS styles
2. Build static site with Zola
3. Package with Caddy web server
4. Push Docker image to registry
5. Update deployment configuration in git
### Automated Deployment
Pushing to `main` branch triggers automatic deployment via CI.
## Project Structure
```
├── content/posts/ # Blog posts (Markdown with YAML frontmatter)
├── templates/ # Zola templates (Tera)
├── static/ # Static assets
├── styles/ # Tailwind CSS source
├── ci/ # Dagger CI/CD pipeline (Rust)
├── deployment/ # Caddy server configuration
├── config.toml # Zola configuration
└── mise.toml # Development tasks
```
## Adding Content
Create a new post in `content/posts/`:
```markdown
+++
title = "Your Post Title"
description = "Brief description"
date = 2025-01-01
draft = false
[taxonomies]
tags = ["rust", "development"]
+++
Your content here...
```

View File

@@ -1,13 +1,14 @@
use cuddle_ci::{Context, MainAction, PullRequestAction};
use dagger_sdk::{
Container, HostDirectoryOptsBuilder, PortForward, QueryContainerOptsBuilder,
ServiceUpOptsBuilder,
};
use dagger_sdk::{Container, HostDirectoryOptsBuilder, PortForward, ServiceUpOptsBuilder};
const UPDATE_DEPLOYMENT_IMAGE: &str = "docker.io/kasperhermansen/update-deployment:1690401410";
const ZOLA_VERSION: &str = "0.17.2-1";
const DEBIAN_EDITION: &str = "bullseye";
const CADDY_IMAGE: &str = "caddy:2.10.0";
const ZOLA_PLATFORM: &str = "x86_64";
const ZOLA_VERSION: &str = "v0.21.0";
const DEBIAN_EDITION: &str = "bookworm";
const DEBIAN_PLATFORM: &str = "amd64";
#[derive(Clone)]
@@ -24,7 +25,7 @@ impl BlogComponent {
.up_opts(
ServiceUpOptsBuilder::default()
.ports(vec![PortForward {
backend: 8000,
backend: 80,
frontend: 8000,
protocol: dagger_sdk::NetworkProtocol::Tcp,
}])
@@ -64,7 +65,7 @@ async fn build(client: dagger_sdk::Query) -> eyre::Result<(i64, Container)> {
.build()?,
);
let github_zola_download: String = format!("https://github.com/barnumbirr/zola-debian/releases/download/v{ZOLA_VERSION}/zola_{ZOLA_VERSION}_{DEBIAN_PLATFORM}_{DEBIAN_EDITION}.deb");
// let github_zola_download: String = format!("https://github.com/barnumbirr/zola-debian/releases/download/v{ZOLA_VERSION}/zola_{ZOLA_VERSION}_{DEBIAN_PLATFORM}_{DEBIAN_EDITION}.deb");
let node_cache = client.cache_volume("node_cache");
let debian_cache = client.cache_volume("debian_cache");
@@ -72,14 +73,16 @@ async fn build(client: dagger_sdk::Query) -> eyre::Result<(i64, Container)> {
.container()
.from("node:16")
.with_workdir("/app")
.with_directory(".", src.id().await?)
.with_mounted_cache("node_modules", node_cache.id().await?)
.with_directory(".", src.clone())
.with_mounted_cache("node_modules", node_cache)
.with_exec(vec!["yarn"])
.with_exec(vec!["yarn", "compile"])
.file("static/styles/styles.css");
let tag = chrono::Utc::now().timestamp();
let zola_download_link = format!("https://github.com/getzola/zola/releases/download/{ZOLA_VERSION}/zola-{ZOLA_VERSION}-{ZOLA_PLATFORM}-unknown-linux-gnu.tar.gz");
let dist_dir = client
.container_opts(
dagger_sdk::QueryContainerOptsBuilder::default()
@@ -87,29 +90,32 @@ async fn build(client: dagger_sdk::Query) -> eyre::Result<(i64, Container)> {
.build()?,
)
.from(format!("debian:{DEBIAN_EDITION}"))
.with_exec(vec!["apt", "update"])
.with_exec(vec!["apt", "install", "wget", "-y"])
// .with_exec(vec!["apt", "update"])
// .with_exec(vec!["apt", "install", "wget", "-y"])
.with_workdir("/mnt")
.with_mounted_cache("/mnt", debian_cache.id().await?)
.with_exec(vec!["wget", &github_zola_download])
.with_exec(vec![
"dpkg",
"-i",
format!("zola_{ZOLA_VERSION}_{DEBIAN_PLATFORM}_{DEBIAN_EDITION}.deb").as_str(),
])
.with_file("/mnt/zola.tar.gz", client.http(zola_download_link))
.with_exec(vec!["tar", "-xvf", "/mnt/zola.tar.gz"])
.with_exec(vec!["mv", "/mnt/zola", "/usr/local/bin/zola"])
// .with_mounted_cache("/mnt", debian_cache)
// .with_exec(vec!["wget", &github_zola_download])
// .with_exec(vec![
// "dpkg",
// "-i",
// format!("zola_{ZOLA_VERSION}_{DEBIAN_PLATFORM}_{DEBIAN_EDITION}.deb").as_str(),
// ])
.with_workdir("/app")
.with_directory(".", src.id().await?)
.with_file("static/styles/styles.css", styles_file.id().await?)
.with_directory(".", src)
.with_file("static/styles/styles.css", styles_file)
.with_exec(vec!["zola", "build"])
.directory("public");
let caddy_file = client.host().directory("deployment").file("Caddyfile");
let dep_image = client
.container_opts(QueryContainerOptsBuilder::default().build().unwrap())
.from("caddy")
.with_directory("/usr/share/caddy", dist_dir.id().await.unwrap())
.with_file("/etc/caddy/Caddyfile", caddy_file.id().await.unwrap());
.container()
.from(CADDY_IMAGE)
.with_directory("/srv", dist_dir)
.with_file("/etc/caddy/Caddyfile", caddy_file);
Ok((tag, dep_image))
}

View File

@@ -1,8 +1,13 @@
{
debug
log default {
output stdout
level DEBUG
}
}
http://blog.kasperhermansen.com {
root * /usr/share/caddy
:80 {
root * /srv
file_server
}

View File

@@ -3,7 +3,7 @@ dir = "./ci"
run = "cargo build"
[tasks."ci:run"]
run = "./ci/target/debug/ci"
run = "./target/debug/ci"
[tasks."ci:main"]
depends = ["ci:build"]

View File

@@ -14,10 +14,10 @@
},
"dependencies": {
"@tailwindcss/typography": "^0.5.9",
"tailwindcss": "^3.3.1"
"tailwindcss": "^4.0.0"
},
"devDependencies": {
"@catppuccin/tailwindcss": "^0.1.1",
"@tailwindcss/cli": "^0.1.2"
"@tailwindcss/cli": "^4.0.0"
}
}

View File

@@ -12,7 +12,8 @@
{{ post_macros::styles() }}
<script defer data-domain="blog.kasperhermansen.com" src="https://plausible.front.kjuulh.io/js/script.js"></script>
<script defer data-domain="blog.kasperhermansen.com" src="https://plausible.front.kjuulh.io/js/script.file-downloads.hash.outbound-links.pageview-props.tagged-events.js"></script>
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
<meta name="description" content="Kasper Hermansen's blog is a hub of insights on platform engineering. ">
<meta name="keywords" content="Kasper Hermansen, kjuulh, blog, technology, platform engineering, cloud native">

View File

@@ -36,5 +36,5 @@
{% endmacro list_posts %}
{% macro styles() %}
<link rel="stylesheet" href="{{ get_url(path="styles/styles.css") | safe }}" />
<link rel="stylesheet" href="{{ get_url(path="/styles/styles.css") | safe }}" />
{% endmacro styles %}

940
yarn.lock

File diff suppressed because it is too large Load Diff