Skip to content

Security and Networking

Chris Nighswonger edited this page Mar 28, 2026 · 5 revisions

Security and Networking

Kanfei is designed for trusted LAN and self-hosted environments. It includes built-in session and API key authentication (see Authentication Model below), but does not include a TLS termination layer — HTTPS is expected to be provided at the infrastructure level via a reverse proxy. This page covers the authentication design, TLS setup, and hardening guidance.

Transport Security (TLS/HTTPS)

Kanfei serves HTTP on port 8000 by default. All traffic — including API responses containing configuration values, bot tokens, and API keys — is transmitted in cleartext. On a trusted, isolated LAN segment this may be acceptable, but any of the following situations require TLS:

  • The Kanfei host is reachable from untrusted networks
  • The LAN segment has untrusted devices or users
  • Bot tokens, nowcast API keys, or upload credentials are configured
  • Remote access is needed (VPN, Tailscale, Cloudflare Tunnel, etc.)

The recommended approach is a reverse proxy that terminates TLS in front of Kanfei.

Option A: Caddy (automatic TLS)

Caddy automatically obtains and renews Let's Encrypt certificates. This is the simplest path if you have a public domain name pointed at the host. See the Caddy docs for installation and configuration details.

weather.example.com {
    reverse_proxy localhost:8000
}

Caddy handles HTTPS redirect, HSTS, certificate renewal, and WebSocket upgrade automatically. No additional configuration needed for /ws/live.

For LAN-only with a self-signed cert:

https://192.168.12.39 {
    tls internal
    reverse_proxy localhost:8000
}

Option B: nginx

server {
    listen 80;
    server_name weather.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name weather.example.com;

    ssl_certificate     /etc/letsencrypt/live/weather.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/weather.example.com/privkey.pem;

    # HSTS — enable after confirming HTTPS works
    # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /ws/live {
        proxy_pass http://127.0.0.1:8000/ws/live;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400s;
    }
}

Use certbot to obtain and renew Let's Encrypt certificates. See the nginx reverse proxy docs for more on proxying and WebSocket support.

Post-TLS checklist

After enabling HTTPS:

  • Verify the dashboard loads over https://
  • Verify live data updates work (WebSocket at wss://)
  • Verify the session cookie (knf_session) is emitted with the Secure flag — it is set automatically when the app detects HTTPS (directly or via X-Forwarded-Proto header from the proxy)
  • Enable HSTS once stable (Strict-Transport-Security header)
  • If using bots, confirm outbound connections (Telegram/Discord) still work — they connect outbound to platform servers, not through the proxy
  • Update any bookmarks or integrations that reference http://

Network Exposure

Default app bind is 0.0.0.0:8000.

Recommendations:

  1. Restrict inbound access at firewall/router to trusted source IPs.
  2. Use a reverse proxy with TLS (see above).
  3. Do not expose the raw app port directly to the internet.
  4. Bind to 127.0.0.1:8000 if the reverse proxy runs on the same host — this prevents direct access to the unencrypted port.

Secrets and Sensitive Config

Sensitive values include:

  • Bot tokens (bot_telegram_token, bot_discord_token)
  • API keys (anthropic_admin_api_key, nowcast_remote_api_key, WU keys)
  • Station identifiers and callsigns (context-dependent)

Handling guidance:

  • Restrict filesystem permissions on .env and the SQLite database
  • Avoid sharing full config exports publicly
  • Rotate keys immediately if leaked
  • Bot tokens are redacted from API error responses, but are stored in plaintext in the database — protect database file access

Authentication Model

Kanfei uses a two-tier API model:

Tier Auth Examples
Public None /api/current, /api/history, /api/forecast, /api/astronomy, /api/nowcast (GET), /api/metar, /api/aprs, /api/public/weather, /api/station (GET), /api/setup/status, /ws/live
Admin Required /api/config, /api/backup/*, /api/db-admin/*, /api/setup/probe, /api/setup/complete, /api/setup/reconnect, /api/telegram/*, /api/discord/*, /api/station/sync-time, /api/logs/*, /api/auth/* (except login/setup-admin)

Session authentication (primary)

Browser-based access uses a session cookie:

  • Cookie name: knf_session
  • Attributes: HttpOnly, SameSite=Lax, Secure (when HTTPS detected via scheme or X-Forwarded-Proto)
  • Expiry: 72-hour sliding window (extends on each authenticated request)
  • Credentials are bcrypt-hashed; the admin account is created during the setup wizard

API key authentication (programmatic)

For scripts and integrations, generate API keys from the Settings UI:

  • Format: knf_ prefix + 43-character token (47 characters total)
  • Passed via Authorization: Bearer knf_... header
  • Full key is shown once at creation and never retrievable again (SHA-256 hash stored)
  • Keys can be revoked from the Settings UI

Secret masking

GET /api/config masks sensitive values (bot tokens, API keys, upload credentials). Full values are accepted on write but never echoed back.

Additional network-layer hardening

For internet-facing deployments, consider layering additional controls at the proxy boundary:

  • VPN (WireGuard, Tailscale)
  • SSO proxy (Authelia, Authentik, oauth2-proxy)
  • IP allowlisting at the firewall

Host Security

Baseline host hardening:

  • Run under a non-root service user
  • Keep OS and dependencies patched
  • Minimize open ports
  • Isolate service account privileges

Hardware Device Access

  • Serial stations: Grant device access via group membership (for example dialout on Debian/Ubuntu). Do not run broad privileged processes unnecessarily.
  • Network stations: Ensure the station's network port is accessible from the Kanfei host. Consider isolating IoT/weather station devices on a dedicated VLAN or subnet with appropriate firewall rules.

Data Protection

Primary at-rest data:

  • Weather/time-series database (SQLite)
  • Configuration values in station_config (includes bot tokens and API keys)
  • Optional custom asset uploads

Recommendations:

  • Encrypted disk or encrypted backup target
  • Regular backup validation restores
  • Retention policies to limit unnecessary data growth

Availability and Recovery

  • Use service manager restarts for crash recovery
  • Keep backup/restore steps documented and tested
  • Monitor critical endpoints (/api/station, /api/current) for freshness

Related Pages

Clone this wiki locally