17 Commits

Author SHA1 Message Date
ed2d4e989e fix(deps): update all dependencies
Some checks failed
renovate/artifacts Artifact file update failure
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build was killed
2025-12-25 04:38:26 +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 2713 additions and 52 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

@@ -8,7 +8,7 @@ edition = "2021"
[dependencies]
chrono = "0.4.26"
color-eyre = "0.6.2"
dagger-sdk = "0.18.3"
dagger-sdk = "0.19.0"
eyre = "0.6.8"
tokio = { version = "1.31.0", features = ["full"] }
tokio-scoped = "0.2.0"

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

@@ -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 %}

View File

@@ -67,13 +67,10 @@
tailwindcss "^2.0.1"
"@tailwindcss/typography@^0.5.9":
version "0.5.9"
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.9.tgz#027e4b0674929daaf7c921c900beee80dbad93e8"
integrity sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==
version "0.5.19"
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.19.tgz#ecb734af2569681eb40932f09f60c2848b909456"
integrity sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==
dependencies:
lodash.castarray "^4.4.0"
lodash.isplainobject "^4.0.6"
lodash.merge "^4.6.2"
postcss-selector-parser "6.0.10"
"@types/parse-json@^4.0.0":
@@ -600,21 +597,6 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
lodash.castarray@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash.topath@^4.5.2:
version "4.5.2"
resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009"