Hello strange world


My blog lives again! Resurrected, enhanced and extra cursed. Served from the maddening depths of The Generic Wizard Tower

Its been a hot second since I’ve built a website or written any markup or css, so picking up Hugo was an interesting challenge. I have to say the learning curve was a little steep and the documentation all over the place but if you’re here to stay in the world of high tech then learning new stuff comes with the territory. The Go ecosystem has a lot of really neat tools that I’m a fan of like Traefik and Jellyfin, so picking this static site builder was an easy choice. The main value-prop for me is publishing content in markdown: I create a file with some frontmatter in the content/ dir of my project (whose structure can vary depending on the url, asset and i18n paths), and deploy with ansible. Eventually blog posts will be deployed with a simple commit to my Gitlab repo but I’m still in the process of migrating off github.

The .md frontmatter is also used to populate and filter content for the site, very neat. There are a bunch of other cool features like the easy i18n integration and shortcodes for doing custom layout rendering, so you could say this project is a batteries-included tool and the batteries are really big! I’ve only scratched the surface but as with all these other projects it can be an endless rabbit-hole, enough for now.

Since traefik is designed as a reverse-proxy for containers, serving static content unfortunately requires the use of yet another tool: Static Web Server. Not a huge deal, just deploy another container, mount the volume and update the dynamic configuration all with ansible:

~/projects/gwt/sws-playbook.yml

---
- hosts: gwt
  gather_facts: false
  vars:
    application: sws
    podman_network: "{{ networks.luxurious_lair }}"
    domain: rpavlov.com
  tasks:
    - name: Purge public dir
      ansible.builtin.file:
        path: "{{ common_directory_storage }}/{{ application }}/{{ domain }}"
        state: absent
        
    - name: Create folder for static site contents
      ansible.builtin.file:
        path: "{{ common_directory_storage }}/{{ application }}/{{ domain }}"
        state: directory
        owner: "{{ common_user }}"
        group: "{{ common_group }}"
        mode: "770"

    - name: Copy static files
      ansible.builtin.copy:
        src: "hugo/{{ domain }}/public/"
        dest: "{{ common_directory_storage }}/{{ application }}/{{ domain }}"
        owner: "{{ common_user }}"
        group: "{{ common_group }}"
        mode: '770'
        
    - name: Create sws container
      ansible.builtin.include_role:
        name: podman_container
      vars:
        image: joseluisq/static-web-server:2
        state: created
        env:
          SERVER_PORT: 8888
          SERVER_ROOT: /public
          SERVER_LOG_LEVEL: info
        volumes:
          - "{{ common_directory_storage }}/{{ application }}/{{ domain }}:/public"
        generate_systemd:
          path: "/home/{{ common_user }}/.config/systemd/user"

    - name: "Ensure {{ application }} container is started and enabled"
      ansible.builtin.systemd: 
        name: "container-{{ application }}"
        scope: user
        enabled: true
        state: started
        daemon_reload: true

~/projects/gwt/templates/traefik/conf.d/sws.yml

http:
  services:
    sws:
      loadBalancer:
        servers:
          - url: "http://sws:8888"

  routers:
    sws-public-router:
      rule: 'Host(`rpavlov.com`)'
      service: sws@file
      entryPoints:
        - web-secure
      middlewares: 
        - chain-no-auth
      tls:
        certResolver: letsencrypt
        options: modern@file
        domains:
          - main: 'rpavlov.com'
            sans:
              - '*.rpavlov.com'

Ah yes, this also reminds me about this really cool trick I learned for provisioning SSL certs for multiple domains, across different accounts (although still in the same registrar. Have not tested it with different DNS providers but I suspect it should work the same way).

Automatic SSL with multiple domains

I use https://joker.com for my DNS, and they offer the ability to automatically update Dynamic DNS records via some credentials. However, these credentials are different for each tld, and traefik doesn’t support this yet. But of course there is a workaround:

In my case, the Joker api credentials are for myotherdomain.tld and the _acme-challenge.rpavlov.com CNAME record points to challenge.myotherdomain.tld. Neat.

The end?

The site is up, good stuff, but it’s not over yet. A lot of other thoughts have been percolating in my head that I haven’t had time to type out. Stay tuned.

Welcome to my digital domain


You clicked the link. Now you too are a part of this place.

By rpavlov, 2025-05-27


Contents: