Compare commits

...

10 Commits

Author SHA1 Message Date
89d25e31b4 wip
All checks were successful
Release CI action / build-and-push-container (push) Successful in 3m10s
2024-12-02 18:07:01 +01:00
447214fe8a wip
All checks were successful
Release CI action / build-and-push-container (push) Successful in 3m17s
2024-12-02 18:00:24 +01:00
e786f0af0e wip
Some checks failed
Release CI action / build-and-push-container (push) Has been cancelled
2024-12-02 17:53:31 +01:00
095318ddc2 wip
Some checks failed
Release CI action / build-and-push-container (push) Failing after 1m24s
2024-12-02 17:45:41 +01:00
1450f0c639 wip
Some checks failed
Release CI action / build-and-push-container (push) Failing after 35s
2024-12-02 17:29:33 +01:00
3810942da3 wip
Some checks failed
Release CI action / build-and-push-container (push) Failing after 25s
2024-12-02 17:20:59 +01:00
7cbfef3543 wip
All checks were successful
Release CI action / build-and-push-container (push) Successful in 33s
2024-12-02 16:56:13 +01:00
02a84b7d37 wip
All checks were successful
Release CI action / build-and-push-container (push) Successful in 35s
2024-12-02 16:49:07 +01:00
7e84b198fc fix: add gitignore 2024-11-29 23:24:38 +01:00
cda2e5b41d feat: example post 2024-11-29 23:23:26 +01:00
7 changed files with 174 additions and 8 deletions

View File

@ -0,0 +1,33 @@
name: Release CI action
run-name: ${{ gitea.repository }} release
on:
push:
branches:
- main
jobs:
build-and-push-container:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: qemu setup
uses: docker/setup-qemu-action@v3
- name: dockerx setup
uses: docker/setup-buildx-action@v1
# - name: Cache Docker layers
# uses: actions/cache@v2
# with:
# path: /tmp/.buildx-cache
# key: ${{ runner.os }}-buildx-${{ github.sha }}
# restore-keys: |
# ${{ runner.os }}-buildx-
- name: login
uses: docker/login-action@v3
with:
# NOTE: See https://gitea.com/gitea/docs/pulls/77/files
registry: git.gtz.dk
username: ${{ gitea.actor }}
password: ${{ secrets.PACKAGE_TOKEN }}
- name: build and push container
run: docker buildx build --push --platform linux/amd64,linux/arm64 -t git.gtz.dk/${{ gitea.repository }}:latest .

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/.DS_Store

View File

@ -5,4 +5,8 @@ RUN hugo new site /hugo
RUN git clone https://github.com/yihui/hugo-xmin.git themes/hugo-xmin
ADD hugo.toml /hugo/hugo.toml
ADD content /hugo/content
CMD ["hugo", "serve", "--bind", "0.0.0.0"]
ADD static /hugo/static
ADD shortcodes /hugo/layouts/shortcodes
ENV PORT=1313
EXPOSE $PORT
CMD ["hugo", "serve", "--bind", "0.0.0.0", "--port", "$PORT"]

8
content/posts/example.md Normal file
View File

@ -0,0 +1,8 @@
+++
date = '2024-11-27'
draft = true
title = 'Example'
tags = ['tutorial']
categories = ['technical']
+++
content goes here.

View File

@ -1,6 +1,5 @@
+++
date = '2024-11-27'
draft = false
title = 'How to Host a Simple Blog'
tags = ['howto', 'tutorial', 'web']
categories = ['technical']
@ -24,11 +23,13 @@ Ideally, the directory structure should look like this:
blog
├── Dockerfile // dockerfile to build and host the site
├── README.md // info about the repository, not a blogpost
├── config.toml // blog-framework configuration file
└── content
├── about.md // the "about" page
└── posts // actual blog posts go here
└── example.md
├── hugo.toml // blog-framework configuration file
├── content
│   ├── about.md // the "about" page
│   └── posts // actual blog posts go here
│   └── example.md
└── static // non-markdown files
└── example.png
```
And then to build the site, simply build the container:
@ -52,9 +53,125 @@ RUN hugo new site /hugo
RUN git clone https://github.com/yihui/hugo-xmin.git themes/hugo-xmin
ADD hugo.toml /hugo/hugo.toml
ADD content /hugo/content
CMD ["hugo", "serve", "--bind", "0.0.0.0"]
ADD static /hugo/static
ENV PORT=1313
EXPOSE $PORT
CMD hugo serve --bind 0.0.0.0 --port $PORT
```
For now, I am just using the built-in server in `hugo`, but it should be possible to serve using `nginx`.
I mentioned `hugo` before, but I was mostly mad that I had to add the autogenerated stuff in git - with this approach... I don't have to 🎊!
## Images
Just put images in the `static` directory, and reference to them in your blogposts like you would normally in a `hugo` project:
```markdown
![example](/example.png)
```
![example](/example.png#center)
This is not centered, and there's no built-in [shortcode](https://gohugo.io/content-management/shortcodes/) for centering images (why not, hugo? You have a shortcode for figures, but no css class for centering - you cant even add a `style` tag? Such an oversight)...
So we have to add one dirty thing to this setup. We have to add a `shortcodes` directory, that is then also added to the docker container in `/hugo/layouts/shortcodes`:
```
blog
├── Dockerfile
├── README.md
├── hugo.toml
├── content
│   ├── about.md
│   └── posts
│   ├── example.md
│   └── how-to-blog.md
├── shortcodes
│   └── centered.html // <-- Added
└── static
└── example.png
```
```html
<!-- centered.html -->
<p align="center">
<img alt="example" src="{{.Get `image`}}" style="max-width: 100%;">
</p>
```
Then we can use this new shortcode like so:
```markdown
{{</* centered image="/example.png" */>}}
```
{{< centered image="/example.png" >}}
Yes! Now we're cooking with gas! ... or atleast cooking with something. Note that this image centering trick does not work in [reader mode](https://support.mozilla.org/en-US/kb/firefox-reader-view-clutter-free-web-pages).
## Conclusion
We have made a docker file for automatically downloading, generating and serving a simple `hugo` blog site.
Personally, I would've liked the `static` and `shortcodes` directories to not exist, but blogposts need images and it needs to center them, so they are a necessary evil.
Could we make the directory structure better and cleaner? Probably yes.
Will I make it better for this blog in the future? Probably yes.
Will I make another post when I do that? Probably yes!
If you want to just manually build and run docker image on your website server, feel free to stop reading here.
The next section concerns about hosting, orchestrating and deploying the site automatically, but it's totally not required.
# Deployment
Being able to build and launch the docker image is nice and can suffice for smaller projects.
Yes, this blog is a small project and the manual method should be more than enough, but I also play [factorio](https://store.steampowered.com/app/427520/Factorio/) (highly recommend it!), so I _hvae_ to automate everything that is tedious.
I also have other projects that I host on my VPS (Virtual Private Server) such my portfolio site [gtz.dk](https://gtz.dk) and a [gitea instance](https://git.gtz.dk/) amongst other things.
## Continuous Integration
I am using my personal [gitea instance](https://git.gtz.dk/agj/blog) to host the source code for this blog - which means that I will be using the integrated CI system there, but you can use whichever CI service you'd like.
The general concepts of the workflow should be fairly easy to translate to any kind of CI, but this is how my setup looks like:
```yaml
name: Release CI action
run-name: ${{ gitea.repository }} release
on:
push:
branches:
- main
jobs:
build-and-push-container:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: build container
run: docker build -t git.gtz.dk/${{ gitea.repository }}:latest .
- name: login
uses: docker/login-action@v3
with:
# NOTE: See https://gitea.com/gitea/docs/pulls/77/files
registry: git.gtz.dk
username: ${{ gitea.actor }}
password: ${{ secrets.PACKAGE_TOKEN }}
- name: push container
run: docker push git.gtz.dk/${{ gitea.repository }}:latest
```
This may look a bit overwhelming if you don't know [Github Actions](https://docs.github.com/en/actions), but it is really quite straight forward.
Every time we push a commit to the `main` branch, we run the job named `build-and-push-container`.
In the job, we first download our repository with the `actions/checkout@v4` action, then we build the container using `docker build` (we make sure to accurately tag the image), then we log in to the container registry that we want to host the container at using the `docker/login-action@v3` action, and the we simply `docker push` the container image.
Make sure to replace the `git.gtz.dk` website mentions with your own github hosting service (whether self-hosted, or `github.com`) and replace the `gitea/GITEA` mentions with `github/GITHUB` instead.
Note that the syntax is extemely similar to GitHub Actions - in fact Gitea Actions are trying to be 1 to 1 compatible with GitHub Actions, so it should be relatively straight forward.
This setup also gives us the possibility of performing traditional code-review before releasing by using [pull requests](https://docs.gitea.com/next/usage/pull-request?_highlight).
This should empower us to identify and correct issues (e.g. spelling mistakes or whatever) before they are pushed to the official website.
I will probably make a post about how to host a private gitea instance with an actions runner and all that jazz. For now, I will consider that particular rabbit hole out-of-scope.
This was the most difficult thing to do. We are _almost_ there.
## Continuous Delivery
With a docker image readily available, we can automatically deploy the blog when we push it!
I personally am a big fan of the simplicity of [portainer](https://www.portainer.io/), as it scales really well when doing perosnal server stuff.
## P.S.
You may notice that the build script on the real

3
shortcodes/centered.html Normal file
View File

@ -0,0 +1,3 @@
<p align="center">
<img alt="example" src="{{.Get `image`}}" style="max-width: 100%;">
</p>

BIN
static/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB