- Set security.acme.certs.*.webroot for Let's Encrypt challenges
- Consolidate multi-line Content-Security-Policy to single line
- Fixes build error: exactly one of dnsProvider/webroot/listenHTTP/s3Bucket is required
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set APP_NAME to The Harrow
- Set Kafkaesque description
- Add custom logo and favicon (needle + etched scratches, rusted red)
- Point customDir to custom/ for asset loading
Subagents require the gateway token to be explicitly defined in the config to inherit it correctly. Interpolate the OPENCLAW_GATEWAY_TOKEN env variable in the auth config.
- Change gateway auth mode from "none" to "token", as "none" is no longer supported and enforces device pairing.
- Provide a static OPENCLAW_GATEWAY_TOKEN in the environment to allow local subagents to bypass pairing automatically.
- Add openclaw-superpowers as a flake input.
- Implement superpowers option in openclaw-podman module.
- Automate skill symlinking, state directory creation, and cron registration.
- Ensure PyYAML is installed within the container via a post-startup service.
- Enable superpowers in the main configuration.
- Use 'chown -R 1000:1000' and 'chmod -R u+rwX' in the preStart script.
- This ensures all files in /var/lib/openclaw are accessible by the container's node user.
- Replace read-only bind mount for openclaw.json with a full directory bind mount.
- Use systemd preStart to copy the Nix declarative config file before startup.
- This prevents the EBUSY crash loop when OpenClaw attempts to modify its own config file on launch.
- Remove `internalOnly = true` flag from Vaultwarden, Forgejo, and AdGuard Home to make them publicly accessible again.
- This also re-exposes the DNS-over-HTTPS (DoH) endpoint on the AdGuard Home domain.
- Add DNS rewrites in AdGuard Home for `*.ashisgreat.xyz` to route to the Tailscale IP (`100.64.0.3`).
- Securely expose the AdGuard Home Web UI to the Tailscale network instead of blocking it completely.
- Add `internalOnly` option to nginx module to block public access.
- Apply `internalOnly` flag to Forgejo and Vaultwarden to ensure they are only accessible over the VPN or localhost.
- Configure Headscale to use the VPS Tailscale IP (100.64.0.3) as the global DNS server instead of external providers.
- Add firewall rules to allow DNS requests over the `tailscale0` interface.
- Add iptables PREROUTING rules to redirect standard DNS (port 53) from Tailscale clients to AdGuard Home (port 5353) to resolve port conflicts with `aardvark-dns`.
New module: modules/headscale.nix
- Headscale service listening on localhost with Nginx reverse proxy
- SQLite database (appropriate for personal use)
- Tailscale public DERP relays for NAT traversal fallback
- MagicDNS enabled with Mullvad/Quad9 upstream resolvers
- Optional OIDC authentication (Google, GitHub, etc.)
- Default auth: pre-shared API keys (headscale apikeys create)
- Added to backup paths (SQLite DB)
- headscale CLI tool added to system packages
Configuration:
- Domain: vpn.ashisgreat.xyz
- OIDC disabled by default (documented how to enable in configuration.nix)
To register a device after deploying:
sudo headscale apikeys create
tailscale up --login-server=https://vpn.ashisgreat.xyz --authkey=<key>
DNS record needed: vpn.ashisgreat.xyz → VPS IP
- Drops --network=host from OpenClaw container
- Container now runs on Podman's default bridge network
- Gateway port already mapped via ports config (127.0.0.1:18789:8080)
- Container retains outbound internet access for Discord API, model providers, etc.
- Cannot reach other host services (Forgejo, Vaultwarden, etc.) — principle of least privilege
Note: If OpenClaw needs to reach local services in the future, add explicit
extraOptions like --network=bridge or create a shared Podman network.
- Global rate limit: 10 req/s with burst of 20
- Connection limit: 30 concurrent per IP
- Per-domain override support (requests, burst, enable/disable)
- SearXNG gets higher limits (20/40) to tolerate bot traffic
- Returns 429 when rate limited
- Enable DNS-over-TLS (DoT) on port 853 using Nginx's ACME certificates
- Fix an issue where the native NixOS module dropped SOPS client IDs
- Use sops.templates and yq to inject ClientIDs dynamically before start
- Enable allow_unencrypted_doh to fix Nginx proxying DoH correctly
Replace the Podman container and manual YAML templating with the native NixOS module for better system integration and simpler declarative configuration.