Project: LAN previews for Hugo websites#

Goal#

Preview Homelab and DashApps on HP1Docker without publishing changes to GitHub or triggering Cloudflare Pages. First make the previews work on the LAN; Pangolin hostnames are an optional later enhancement.

Current setup#

  • HP1Docker: 10.1.2.202
  • Homelab Hugo project: /home/marc/hugo/homelab; preview port 1313
  • DashApps Hugo project: /home/marc/hugo/dashapps; preview port 1314 (confirmed available)
  • Mac push has a documented --sync-only option that syncs Homelab content without publishing.
  • Normal publish commands push website source to GitHub and trigger Cloudflare. Do not use them for previews.

1. Confirm preview ports on HP1Docker#

  • 1.3 Confirm port 1313 is available for the Homelab preview on HP1Docker.

    Run on HP1Docker. No output after the header means the port is available; a LISTEN row means it is already in use.

    ss -ltn 'sport = :1313'
  • 1.4 Confirm port 1314 is available for the DashApps preview on HP1Docker.

    Run on HP1Docker. No output after the header means the port is available; a LISTEN row means it is already in use.

    ss -ltn 'sport = :1314'

2. Configure and test the Homelab and DashApps preview sites#

  • 2.1 Install and enable the Homelab Hugo preview service on port 1313.

    HP1Docker’s Hugo binary is /usr/local/bin/hugo (recorded in Hugo and Blowfish Update - HP1Docker). Use this path in ExecStart.

    Create /etc/systemd/system/hugo-homelab-preview.service with:

    [Unit]
    Description=Hugo LAN preview - Homelab
    After=network-online.target
    Wants=network-online.target
    StartLimitIntervalSec=60
    StartLimitBurst=3
    
    [Service]
    User=marc
    WorkingDirectory=/home/marc/hugo/homelab
    StateDirectory=hugo-homelab-preview
    StateDirectoryMode=0750
    Environment=HUGO_RESOURCEDIR=/var/lib/hugo-homelab-preview/resources
    ExecStart=/usr/local/bin/hugo server --bind 0.0.0.0 --baseURL http://10.1.2.202 --buildDrafts --disableFastRender --ignoreCache --noHTTPCache --gc --destination /var/lib/hugo-homelab-preview/public --port 1313
    Restart=on-failure
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target

    The service runs as marc. Its first start exposed root-owned generated files: Hugo could not write the existing build lock or the generated asset cache. To keep the production public/ and resources/ trees untouched, systemd gives this service its own /var/lib/hugo-homelab-preview/ state directory; Hugo writes preview output there and uses it for asset resources. Only the generated /home/marc/hugo/homelab/.hugo_build.lock file changed ownership to marc; no other project files changed ownership.

    This retry cap applies only to the Homelab preview service. On failure, systemd waits 5 seconds and retries; it permits at most 3 start attempts within 60 seconds, including the first attempt. After those attempts fail, systemd marks this service failed and stops retrying. Other server services continue running. To recover, check the cause, fix it, then reset and start this service:

    systemctl status hugo-homelab-preview.service
    journalctl -u hugo-homelab-preview.service
    sudo systemctl reset-failed hugo-homelab-preview.service
    sudo systemctl start hugo-homelab-preview.service
  • 2.2 Install and enable the DashApps Hugo preview service on port 1314.

    Create /etc/systemd/system/hugo-dashapps-preview.service with:

    [Unit]
    Description=Hugo LAN preview - DashApps
    After=network-online.target
    Wants=network-online.target
    StartLimitIntervalSec=60
    StartLimitBurst=3
    
    [Service]
    User=marc
    WorkingDirectory=/home/marc/hugo/dashapps
    StateDirectory=hugo-dashapps-preview
    StateDirectoryMode=0750
    Environment=HUGO_RESOURCEDIR=/var/lib/hugo-dashapps-preview/resources
    ExecStart=/usr/local/bin/hugo server --bind 0.0.0.0 --baseURL http://10.1.2.202 --buildDrafts --disableFastRender --ignoreCache --noHTTPCache --gc --destination /var/lib/hugo-dashapps-preview/public --port 1314
    Restart=on-failure
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target

    The service runs as marc. Its first start found root-owned generated files in the existing public/ tree. To leave that production output untouched, systemd gives this service its own /var/lib/hugo-dashapps-preview/ state directory; Hugo writes preview output and asset resources there. No DashApps project-file ownership was changed.

    This retry cap applies only to the DashApps preview service. On failure, systemd waits 5 seconds and retries; it permits at most 3 start attempts within 60 seconds, including the first attempt. After those attempts fail, systemd marks this service failed and stops retrying. Other server services continue running. To recover, check the cause, fix it, then reset and start this service:

    systemctl status hugo-dashapps-preview.service
    journalctl -u hugo-dashapps-preview.service
    sudo systemctl reset-failed hugo-dashapps-preview.service
    sudo systemctl start hugo-dashapps-preview.service

    Enable both services at boot, then start them separately. Each start command addresses only its named service. If one service fails, check and fix it before starting it again; the other preview service remains an independent unit.

    sudo systemctl daemon-reload
    sudo systemctl enable hugo-homelab-preview.service hugo-dashapps-preview.service
    sudo systemctl start hugo-homelab-preview.service
    sudo systemctl start hugo-dashapps-preview.service

    Check status and boot enablement:

    systemctl is-active hugo-homelab-preview.service hugo-dashapps-preview.service
    systemctl is-enabled hugo-homelab-preview.service hugo-dashapps-preview.service

    View logs if either service does not start:

    journalctl -u hugo-homelab-preview.service -u hugo-dashapps-preview.service

    Completed 2026-10-08: both services are enabled at boot and active. LAN checks returned HTTP 200 at http://10.1.2.202:1313 and http://10.1.2.202:1314; each service had zero restarts at verification.

    HP1Docker’s systemd manager default was 5 starts per 10 seconds. Each preview unit explicitly overrides that global default with its own limit of 3 starts per 60 seconds.

3. Create the Mac-side preview sync scripts#

  • 3.1 Create /Users/marc/Scripts/MacOS/sync-obsidian-homelab-hugo-preview.sh. It delegates to the existing Homelab --sync-only workflow, which prepares and copies preview files to HP1Docker without starting Hugo, building, committing, or pushing.
  • 3.2 Create /Users/marc/Scripts/MacOS/sync-obsidian-dashapps-hugo-preview.sh. It syncs DashApps notes and images to HP1Docker, then runs the existing content converter so the Hugo preview server sees the updated generated content. It does not run Hugo directly, build, commit, or push. The Hugo server detects the changed files and refreshes the preview.

4. Add the Mac aliases#

  • 4.1 Add the testlab alias to run the Homelab preview sync script.

    Add the alias to /Users/marc/Scripts/MacOS/Aliases/MacOS-Aliases.zsh. Point it to the Homelab script created in 3.1, using the script’s full path. The alias should only invoke that script; it should not include a build, commit, or push command.

  • 4.2 Add the testdash alias to run the DashApps preview sync script.

    Add the alias to /Users/marc/Scripts/MacOS/Aliases/MacOS-Aliases.zsh. Point it to the DashApps script created in 3.2, using the script’s full path. The alias should only invoke that script; it should not include a build, commit, or push command.

    The aliases were added to the tracked Mac alias file and verified in a separate Zsh process. To load them in a terminal that is already open, run source ~/.zshrc.

5. Verify the previews#

  • 5.1 Verify the Homelab preview is available at http://10.1.2.202:1313 and its sync script copies the intended files.
  • 5.2 Verify the DashApps preview is available at http://10.1.2.202:1314 and its sync script copies the intended files.
  • 5.3 Verify testlab does not commit or push website source or trigger a Cloudflare build.
  • 5.4 Verify testdash does not commit or push website source or trigger a Cloudflare build.
  • 5.5 Update the Homelab setup note with its final command, port, and LAN URL.
  • 5.6 Update the DashApps setup note with its final command, port, and LAN URL.

6. Optional later: Pangolin access#

Only start this after the LAN preview workflow is complete and working.

  • 6.1 Confirm Pangolin can reach HP1Docker and record its custom-domain DNS instructions for mmmo.app.
  • 6.2 Choose Pangolin access: private for personal previews (requires Pangolin client), or public with access controls if browser access without the client is needed. Previews can contain drafts.
  • 6.3 Add a Pangolin HTTP(S) resource and DNS for lab.mmmo.app → Homelab preview.
  • 6.4 Set the Homelab preview base URL to https://lab.mmmo.app and confirm links, images, drafts, and HTTPS work.
  • 6.5 Add a Pangolin HTTP(S) resource and DNS for dash.mmmo.app → DashApps preview.
  • 6.6 Set the DashApps preview base URL to https://dash.mmmo.app and confirm links, images, drafts, and HTTPS work.