144 lines
6.9 KiB
Markdown
144 lines
6.9 KiB
Markdown
+++
|
||
date = '2024-11-27'
|
||
title = 'How to Host a Simple Blog'
|
||
tags = ['howto', 'tutorial', 'web']
|
||
categories = ['technical']
|
||
+++
|
||
|
||
No. I don't want to have a git repository with a million billion files that are auto generated by [hugo](https://gohugo.io/), [jekyll](https://jekyllrb.com/).
|
||
No. I don't want to use some non-official, homebrew, backwater, docker image made by some random guy that stopped maintaining the image in 2011.
|
||
I want my own dockerfile that is based on `alpine` or even use an image official to the framework.
|
||
No. I **definitely** don't want to use a WYSIWYG (What You See Is What You Get) editor - I have my own local markdown editor that works just fine thank you.
|
||
All I want i one (1) - i repeat - ONE fucking goddamn configuration file for the entire site (toml, conf, yaml I don't care) and blog posts should be written in markdown.
|
||
|
||
If you are like me, read on.
|
||
|
||
Additionally, there should be community made themes available - but I shouldn't have to fucking add them as a git submodule, god damn.
|
||
The blog should be hostable through a docker image that just takes your markdown and config file, builds the static website, and serves it using some standard server
|
||
(e.g. nginx or python's `http.server` I don't care which, as long as it is somewhat standard - If I am managing a docker container, I will manage the networking in docker)
|
||
|
||
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
|
||
├── 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:
|
||
|
||
```sh
|
||
docker build .
|
||
```
|
||
|
||
Then you should just be able to insert the docker image into some docker-compose or kubernetes stack - or even just `docker run -d` if you'd like.
|
||
The point of this is that you should really just focus on writing the blog entries - not the blog website.
|
||
|
||
If you want to use this workflow - this blog is written using this approach, so see my [gitea](https://git.gtz.dk/agj/blog) instance or the [github](https://github.com/sillydan1/blog) mirror for reference.
|
||
|
||
The `Dockerfile` I have settled on goes like this:
|
||
|
||
```dockerfile
|
||
FROM alpine
|
||
RUN apk add hugo git
|
||
WORKDIR /hugo
|
||
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
|
||
ADD static /hugo/static
|
||
CMD ["hugo", "serve", "--bind", "0.0.0.0"]
|
||
```
|
||
|
||
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
|
||

|
||
```
|
||
|
||

|
||
|
||
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
|
||
```
|
||
|
||
Make sure to replace the `git.gtz.dk` website mentions with your own github hosting service (whether self-hosted, or `github.com`).
|
||
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.
|
||
|
||
|
||
## Continuous Delivery
|
||
With a docker image readily available
|
||
|
||
### Orchestration
|
||
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.
|
||
I might write another post on how to set portainer up in the future.
|