logo

ZeroClaw in an Incus LXC Container

# zeroclaw-profile.yaml
config:
  cloud-init.user-data: |
    #cloud-config
    ssh_genkeytypes: []
    ssh_pwauth: false
    package_update: true
    packages:
      - curl
      - ca-certificates
      - tzdata

    users:
      - name: zeroclaw
        shell: /bin/sh
        home: /home/zeroclaw
        system: true
        setup_home: true

    write_files:
      - path: /etc/init.d/zeroclaw
        permissions: '0755'
        owner: root:root
        content: |
          #!/sbin/openrc-run
          name="zeroclaw"
          description="ZeroClaw daemon"
          supervisor=supervise-daemon
          command="/usr/local/bin/zeroclaw"
          command_args="daemon"
          command_user="zeroclaw:zeroclaw"
          directory="/home/zeroclaw"

          depend() {
              need net
              after firewall
          }

          start_pre() {
              checkpath -d -m 0750 -o zeroclaw:zeroclaw /home/zeroclaw/.zeroclaw
          }

    runcmd:
      - ln -sf /usr/share/zoneinfo/Europe/Helsinki /etc/localtime
      - |
        curl -sSL -o /tmp/zeroclaw.tar.gz \
          https://github.com/zeroclaw-labs/zeroclaw/releases/latest/download/zeroclaw-x86_64-unknown-linux-musl.tar.gz
        tar -xzf /tmp/zeroclaw.tar.gz -C /usr/local/bin
        chmod 0755 /usr/local/bin/zeroclaw
        rm /tmp/zeroclaw.tar.gz

  limits.cpu: "2"
  limits.memory: 1GB        # runtime is a few MB; 1GB is generous headroom
  # security.nesting not needed — Landlock sandbox requires no userns

description: ZeroClaw trial on Alpine Edge
devices:
  root:
    path: /
    pool: default
    type: disk
    size: 4GB
  eth0:
    name: eth0
    nictype: bridged
    parent: br77
    type: nic
# incus profile edit zeroclaw < zeroclaw-profile.yaml

incus launch images:alpine/edge/cloud zeroclaw –profile zeroclaw

config tweaks

# incus exec zeroclaw -- su - zeroclaw -s /bin/sh -c 'zeroclaw doctor'
# incus exec zeroclaw -- vi /home/zeroclaw/.zeroclaw/config.toml
# incus exec zeroclaw -- rc-service zeroclaw restart
One minute to read

OpenWrt AP with dynamic vlans (update)

A small update to the previous dynamic vlan setup . The goal is the same: a single ssid where each device gets dropped into the vlan assigned by the radius server, based on its mac address.

The change follows switching to a new device (cudy ap3000), with a more recent version of openwrt. The change moves to a single vlan99 interface for the AP’s own management traffic, while other vlan handling is dealt by the dynamic vlan setup.

2 minutes to read

2026 04 03 Incus notes

Notes from setting up Incus LXC containers on Alpine Linux with VLAN bridges
3 minutes to read

quick ldap setup with glauth

Overview

Replaced OpenLDAP with GLauth, because I was looking for minimalistic setup. I noticed a bit too late that lldap might have been a better match…

Files Created

/usr/local/bin/glauth              # Binary
/etc/glauth/glauth.cfg             # Configuration
/etc/systemd/system/glauth.service # Systemd service
/var/log/glauth/                   # Logs (optional)

Configuration Highlights

  • Domain: dc=121013,dc=dpdns,dc=org
  • LDAPS Port: 636
  • Certificates: /etc/letsencrypt/live/mydomain/
    • cert: fullchain.pem
    • key: privkey.pem
  • Users: admin, mikael, etc , observer
  • Groups: parents (5001), kids (5002), services (5003)

DN Format

GLauth uses primary group as OU:

One minute to read

Local debian repo

Overview

nasrepo automatically downloads .deb packages from builds.sr.ht and uses local-apt-repository to make them available via APT.

Architecture

Timer (daily 3 AM)
  ↓
pull-artifacts
  ↓
/srv/local-apt-repository/ (.deb files)
  ↓ (systemd path monitoring)
local-apt-repository (metadata generation)
  ↓
/var/lib/local-apt-repository/ (APT repository)
  ↓
apt install

Components

nasrepo package:

  • /usr/lib/nasrepo/pull-artifacts - Downloads from builds.sr.ht
  • /etc/nasrepo/.srht-token - OAuth token
  • nasrepo-update.timer - Daily automation (3 AM)
  • nasrepo-update.service - Runs pull-artifacts

local-apt-repository package:

  • Monitors /srv/local-apt-repository/ for new .deb files
  • Generates metadata in /var/lib/local-apt-repository/
  • Configures APT source automatically

Key Locations

  • Token: /etc/nasrepo/.srht-token
  • Downloads: /srv/local-apt-repository/ (input)
  • Repository: /var/lib/local-apt-repository/ (output)
  • APT source: /etc/apt/sources.list.d/local-apt-repository.list

Manual Operations

Download latest packages:

One minute to read

Fixing Arch Linux System Freezes

After experiencing multiple complete system freezes over two months on Arch Linux, I traced the issue to OOM (Out of Memory) events. The system would become completely unresponsive - no mouse, no keyboard, forcing hard reboots.

Root Cause

Checking journalctl revealed the smoking gun:

journalctl -b -1 --no-pager | grep -i "oom"

The OOM killer had terminated systemd-journald and user processes. With 27GB RAM + 16GB swap, memory exhaustion shouldn’t happen often, but when it does, the kernel freezes everything before killing processes.

2 minutes to read

2025 08 09_mybibliotheca


title: “Self-Hosting MyBibliotheca: A Family Reading Tracker Without Docker” date: 2025-08-09 description: “Complete guide to installing MyBibliotheca on a Debian NAS with systemd, nginx reverse proxy, and maximum security hardening - no Docker required.” tags: [“self-hosting”, “books”, “family”, “debian”, “nginx”, “systemd”] categories: [“tutorials”, “self-hosting”]

Warning : this post has been generated by claude llm, after installing it myself going through trial and errors.

Looking for a simple, privacy-focused way to track your family’s reading habits? MyBibliotheca is an excellent self-hosted alternative to Goodreads that’s perfect for families. Unlike most guides that rely on Docker, this tutorial shows you how to install it directly on Debian with some security hardening.

4 minutes to read

vlan bound service isolated in network namespace

This memo is about running a systemd service isolated in a network namespace on linux, inside which a vlan interface has been moved.

Network setup

Create namespace

sudo ip netns add torrentns

Create the vlan interface

/etc/network/interfaces

auto enp5s0.33
iface enp5s0.33 inet manual
    post-up /root/bin/move-to-namespace enp5s0.33

helper script

#!/bin/bash
# Usage: move-to-namespace <iface>
set -e

iface="$1"
ns="torrentns"

# Create namespace if not exists
if ! ip netns list | grep -q "^$ns"; then
    ip netns add "$ns"
fi

# Move interface into namespace
ip link set "$iface" netns "$ns"

# Bring up interfaces inside namespace
ip netns exec "$ns" ip link set lo up
ip netns exec "$ns" ip link set "$iface" up

# Start DHCP client inside namespace
ip netns exec "$ns" dhclient -v "$iface"

# Optional: Set up DNS
mkdir -p /etc/netns/$ns
echo "nameserver 1.1.1.1" > /etc/netns/$ns/resolv.conf

Activation

run : sudo ifup enp5s0.33

2 minutes to read