Author: jpw

  • Mounting CIFS File Shares at Boot

    I had the following setup:

    A NUC running debian 13 configured with a DHCP static lease. A NAS drive serving multiple file shares over CIFS.

    The problem was that whenever the nuc booted, the file shares were not mounted automatically. I followed several of the ‘recommended’ approaches

    • _netdev didn’t make any difference
    • Configuring systemd mount on first use (x-systemd.automount) – I didn’t try this because it wasn’t what I really wanted. Also I’ve heard it causes issues when using the mount within namespaces.
    • Using systemd-mount(1) units to mount the share including specifying After=network-online.target – no difference

    Ultimately I think the problem lay with the fact that the network-online.target had completed before dhcpcd had completed. Leaving subsequent units in a state where networking was “up” there’s a race condition since dhcp had not completed retrieving an address. This could be seen in systemctl status media-mount.mount with the following line:

    mount[954]: mount error: could not resolve address for <nasdrive>.....

    I think the “correct” solution for this is dbus integration for dhcpcd so that systemd can be notified when network autoconfiguration has been completed. I’ve had a look and it’s available as a separate package for some distros and it’s unclear if it is shipped by debian. I’ll have more of a dig and update this post if I find anything.

    My Solution

    The solution that worked for me was to move the NUC off DHCP and on to a static address whilst continuing to use the systemd-mount(1) style mounts. Although this worked it did not fix the problem entirely. DNS was still failing and I needed to change the mount to use IP rather than DNS.

    So all in all it’s a bit sloppy. I feel like there’s a better solution for all of this but it’s not obvious.

    Here is my working unit

    # /etc/systemd/system/media-mount.mount
    [Unit]
    Description = mount
    After = network-online.target
    
    [Mount]
    What = //192.168.1.2/mount
    Where = /media/mount
    Type = cifs
    Options = credentials=/etc/mount.creds,vers=2.0,uid=user,gid=user
    
    [Install]
    WantedBy = multi-user.target

    And then mount with systemctl enable --now media-mount.mount

  • Mapproxy Configuration for Ordinance Survey Leisure Maps

    This config took a while to get working for me. I needed to get this configuration in to mapproxy because I needed to reproject the tiles for the software I was using. from EPSG:3857 to webmercator style. This configuration will provide the legendary leisure maps for free thanks to the £1000 free api credits per month from the os data hub (THANK YOU). It also contains some of the other map styles.

    To use this configuration you will first need an api key from https://osdatahub.os.uk/. Then replace snip with the api key within the sources section and you should be good to go.

    Please ensure you use the tiles inline with the license.

    Enjoy!

    services:
      demo:
      tms:
        use_grid_names: true
        origin: nw
      #wmts:
      #wms:
      #  srs: ['EPSG:3857', 'EPSG:27700']
      #  md:
      #    title: iShare Base Maps
      #    abstract: OS Maps API base mapping
    
    layers:
      - name: osgb__osmaps_leisure_webmercator
        title: OS Maps API Leisure
        sources: [osgb__osmaps_leisure_webmercator__cache]
      - name: osgb__osmaps_road_webmercator
        title: OS Maps API Road
        sources: [osgb__osmaps_road_webmercator__cache]
      - name: osgb__osmaps_outdoor_webmercator
        title: OS Maps API Outdoor
        sources: [osgb__osmaps_outdoor_webmercator__cache]
      - name: osgb__osmaps_light_webmercator
        title: OS Maps API Light
        sources: [osgb__osmaps_light_webmercator__cache]
    
    caches:
      osgb__osmaps_leisure_webmercator__cache:
        grids: [webmercator]
        sources: [osgb__osmaps_leisure_27700__cache]
        meta_buffer: 0
        minimize_meta_requests: true
        cache:
          type: file
          directory: /mapproxy/cache/osmaps_leisure_webmercator
      osgb__osmaps_leisure_27700__cache:
        grids: [osgb__osmaps_epsg27700_leisure_premium__grid]
        sources: [osgb__osmaps_leisure_27700__tiles]
        meta_buffer: 0
        minimize_meta_requests: true
        disable_storage: true
        cache:
          type: file
          directory: /mapproxy/cache/osmaps_leisure_epsg27700
      osgb__osmaps_road_webmercator__cache:
        grids: [webmercator]
        sources: [osgb__osmaps_road_3857__tiles]
        meta_buffer: 0
        minimize_meta_requests: true
        cache:
          type: file
          directory: /mapproxy/cache/osmaps_road_webmercator
      osgb__osmaps_outdoor_webmercator__cache:
        grids: [webmercator]
        sources: [osgb__osmaps_outdoor_3857__tiles]
        meta_buffer: 0
        minimize_meta_requests: true
        cache:
          type: file
          directory: /mapproxy/cache/osmaps_outdoor_webmercator
      osgb__osmaps_light_webmercator__cache:
        grids: [webmercator]
        sources: [osgb__osmaps_light_3857__tiles]
        meta_buffer: 0
        minimize_meta_requests: true
        cache:
          type: file
          directory: /mapproxy/cache/osmaps_light_webmercator
    
    sources:
      osgb__osmaps_leisure_27700__tiles:
        type: tile
        grid: osgb__osmaps_epsg27700_leisure_premium__grid
        url: https://api.os.uk/maps/raster/v1/zxy/Leisure_27700/%(z)s/%(x)s/%(y)s.png?key=snip
      osgb__osmaps_road_3857__tiles:
        type: tile
        grid: webmercator
        url: https://api.os.uk/maps/raster/v1/zxy/Road_3857/%(z)s/%(x)s/%(y)s.png?key=snip
      osgb__osmaps_outdoor_3857__tiles:
        type: tile
        grid: webmercator
        url: https://api.os.uk/maps/raster/v1/zxy/Outdoor_3857/%(z)s/%(x)s/%(y)s.png?key=snip
      osgb__osmaps_light_3857__tiles:
        type: tile
        grid: webmercator
        url: https://api.os.uk/maps/raster/v1/zxy/Light_3857/%(z)s/%(x)s/%(y)s.png?key=snip
    
    grids:
      
      webmercator:
        base: GLOBAL_WEBMERCATOR
    
      # OS Maps API WMTS EPSG:27700 grid with full resolutions, used as
      # a base for the other OS Maps API WMTS EPSG:27700 grids
      osgb__osmaps_epsg27700_premium__grid:
        origin: nw
        srs: 'EPSG:27700'
        bbox: [-238375.0000149319, 0.0, 900000.00000057, 1376256.0000176653]
        bbox_srs: 'EPSG:27700'
        res: [896.0, 448.0, 224.0, 112.0, 56.0, 28.0, 14.0, 7.0, 3.5, 1.75, 0.875, 0.4375, 0.21875, 0.109375]
      # OS Maps API WMTS EPSG:27700 grid with resolutions for open data only
      osgb__osmaps_epsg27700_open__grid:
        base: osgb__osmaps_epsg27700_premium__grid
        res: [896.0, 448.0, 224.0, 112.0, 56.0, 28.0, 14.0, 7.0, 3.5, 1.75]
      # OS Maps API WMTS EPSG:27700 grid for Leisure premium and open data resolutions
      osgb__osmaps_epsg27700_leisure_premium__grid:
        base: osgb__osmaps_epsg27700_premium__grid
        res: [896.0, 448.0, 224.0, 112.0, 56.0, 28.0, 14.0, 7.0, 3.5, 1.75]
      # OS Maps API WMTS EPSG:27700 grid for Leisure open data resolutions
      osgb__osmaps_epsg27700_leisure_open__grid:
        base: osgb__osmaps_epsg27700_premium__grid
        res: [896.0, 448.0, 224.0, 112.0, 56.0, 28.0]
  • Initial thoughts on WordPress in 2025

    What better way to kick off a new blog than by documenting the migration to it.

    Previously this blog was created using GoHugo. I had a repository within github where I’d write some posts using markdown, hit commit and a github action would pick up the changes, build a container, push it to dockerhub and send a signal to my kubernetes deployment at home to deploy it. I’m not going to lie, the setup was pretty slick and it worked well. The problem with it is that it wasn’t very impulsive. I couldn’t simply throw out some thoughts as it required me to fire up my IDE and do the whole development thing just to put a few words on a website. Over time I grew to resent it and eventually stopped posting. Hopefully, good old reliable WordPress will fix that.

    So I started with needing a WordPress blog, simple I thought but being the cheapskate I am, I didn’t want to pay the ~£15 a month to get a professionally hosted instance when I can do it myself for a fraction of the cost.

    The setup is simple. It’s a single droplet hosted within digital ocean running Debian, nginx, mariadb and php. The setup is automated using terraform and ansible up to the point of deploying WordPress. I did this step manually since WordPress has a self updater, I didn’t want the automation and WordPress tripping over each other. I’ll post the automation on github once i’ve tidied it up a bit. But interesting little factoid. This is the first project i’ve really dug in to AI for and it was an experience. I was able to quickly bootstrap a repo creating the basis of what I wanted to create and it worked; except it all fell apart very quickly providing hallucinated features or not updating the code to work how I wanted it to. It was about the time that I spent longer trying to explain what the issue was than just doing it myself; that I took what it had produced and continued manually. This honestly saved a lot of time. It took probably about an hour to get a reasonable basis and probably another hour of tweaks. It was cool when it was doing what I wanted but since there wasn’t anything new that couldn’t already be found and copied from the docs I won’t be signing up for a paid account just yet.

    With all the setup bits done I copied over the WordPress zip, extracted it, fixed up the permissions, ran the wordpress setup and took it for a whirl.

    That looks broken I think as I reach for the inspector. Nope it all loaded OK so where’s the rest of it? It turns out this is how the 2025 theme looks now. Its all configurable with blocks it would seem to they can diverge from previous releases that come with a more complete theme out of the box. This is the first time I’ve used WordPress since about 2015 and it would seem its come a long way. After acquainting myself with how everything hangs together I was able to get something that resembled a blog thrown together – its not perfect but it’ll do as a starting point. I quite like the WYSIWYG approach to construction allowing some degree of flexibility without having to resort to code. As someone who is allergic to frontend the more it can be abstracted away from me the better.

  • Hello world!

    Time for a reboot. Wire48 has been my blog for the last several years that I occasionally posted on. This has become increasingly hard to find a place for this blog to live lunging between self hosted options, different blog frameworks (shout out to hugo) and after all of that…… i just can’t be bothered any more with all of the code, pipelines, repos etc… All I actually want is somewhere to throw up my thought and hit post. So… back to wordpress I go with a small, dedicated hosting platform that sits Independently from my home lab it ticks all of the boxes.

    I think it’s more important than ever that the independent web remains relevant given the recent onslaught of everything AI. Everything’s turned to mush on social media and rarely do I see content that interests me any more. I’ve turned back to RSS feeds for most of my discovery and I want to participate in that too.

    Just a short post to get something up to get started. Now time to go theme wordpress.