EAS Station™ logo

Help & Operations Guide

Complete documentation for operating and maintaining your EAS Station™

Operations Flow

  • 1
    Monitor & Capture

    CAP polling + SDR ingest keep alerts flowing in.

  • 2
    Analyze & Verify

    Rule filters, analytics, and operator review.

  • 3
    Broadcast & Notify

    Builder, audio playout, GPIO, and displays.

  • 4
    Audit & Improve

    Archive, compliance, and analytics feedback.

Safety Expectations

  • Isolated Networks: Operate the stack in isolated development or staging networks disconnected from broadcast transmitter controls.
  • No Live Credentials: Do not ingest live IPAWS credentials, dispatch feeds, or mission-critical telemetry into this environment.
  • Validated Workflows: Validate any workflows on certified FCC equipment before using them in real-world alerting scenarios.
  • Legal Review: Review the repository Terms of Use and Privacy Policy with your operators prior to onboarding.

Getting Started

  1. Review Documentation
    The About page covers system goals, core services, and the complete software stack. The Attribution & Credits page lists every open-source dependency, data source, and licensing detail.
  2. Run Installation Script
    Run cd bare-metal && sudo bash scripts/install.sh to install all dependencies and set up systemd services.
  3. Configure Environment
    Edit /opt/eas-station/.env, set secure secrets, and update database connection details.
  4. Start Services
    Run sudo systemctl start eas-station.target to launch all EAS Station™ services.

Routine Operations

Navigate to http://<host>:5000 in a modern browser.

Log in with administrator credentials created during initial setup.

Tip: Bookmark the dashboard for quick access during operations.

EAS Station™ lets each operator pick how positional and motion values are displayed across the UI. Selections are saved in your browser's localStorage (per-device, per-browser) and apply immediately wherever the affected values appear.

Configurable units
  • Coordinates: D.dddd (decimal degrees, e.g. 41.450123°) or DMS (degrees / minutes / seconds, e.g. 41°27'00.4"N).
  • Altitude: meters (m) or feet (ft).
  • Speed: knots (kn), miles per hour (mph), kilometers per hour (km/h) or meters per second (m/s).
  • Distance: meters (m), feet (ft), miles (mi) or nautical miles (nmi).
Where to change them
  1. Settings → Personalization → Display Units in the top navigation bar opens the global picker from any page.
  2. Help → Display Units exposes the same picker even when not signed in.
  3. Each affected page also has an inline Units button:
Tip: Changes take effect instantly — every dashboard with cached telemetry re-renders the moment you flip a unit, so you don't need to wait for the next poll or reload the page.
Scope: the preference is stored in your browser only — it's not synced server-side, so each browser/device you use can have its own setting, and clearing site data will reset to defaults (D.dddd, m, kn, m).

  1. Open the Dashboard to view active CAP products on the interactive map.
  2. Use the Statistics tab to analyze severity, event types, and historical counts.
  3. Check System Health for CPU, memory, disk, receiver, and audio pipeline heartbeat metrics.
Interactive Map: Geographic visualization
Statistics: Historical analysis

  • Navigate to Alert Verification (/admin/alert-verification) to inspect delivery timelines and per-target outcomes.
  • Upload captured WAV or MP3 files to decode SAME bursts directly in the browser.
  • Store decoded results for future comparison from the sidebar list.
Note: The verification dashboard helps validate that generated alerts match expected EAS formats.

Every audit log entry — logins, configuration changes, alerts received, EAS broadcasts, manual activations — is hash-chained to the entry before it and signed with the station's Ed25519 key. Any edit, deletion, or insertion (even directly against the database) is cryptographically detectable.

  • Navigate to System Logs → Audit tab (/logs?type=audit).
  • To see who changed a setting: use the Logs → Configuration Changes menu shortcut, or pick Configuration Changes in the Audit Action dropdown on the Audit tab. This shows every config.updated event with the user, timestamp, IP address, and which fields changed. The filter is preserved in CSV/PDF exports.
  • In the Chain Integrity card, choose a scope (entire chain, or the newest N rows on very large logs) and click Verify Chain Integrity.
  • A green result proves the log has not been modified; a red result reports the first bad row and why it failed.
  • Expand any entry's details to see its entry_hash, prev_hash, and signature.
  • Each verification run is itself recorded in the chain as audit.chain.verified — your receipt that the check happened.
Ephemeral key warning: if verification warns that an ephemeral signing key is in use, the station has no persistent key and signatures will not survive a restart. The installer normally provisions one at /opt/eas-station/secrets/audit_signing.key; the path is configurable under Settings → Environment → Core Settings.
Full design, threat model, and key management: Audit Log Integrity documentation.

The Security Center (Tools → Analytics → Security Center, /security/center) brings four related security views together on one tabbed page:

  • Traffic — the full Traffic Analytics dashboard (described below), embedded inline.
  • Malicious Logins — SQL/command-injection login attempts, with per-IP attack statistics and a one-click Ban button for any attacking source.
  • Global Ban List — the single source of truth for banned IPs, enforced by multiple layers (the application gate, the host firewall, and fail2ban). Manage the allowlist and blocklist: ban an IP or CIDR range (permanently or for a set number of hours), toggle entries on/off, and clean up expired ones. Each entry shows a Source badge (Manual, Login Brute Force, SSH Brute Force, Malicious Request, …) and a Location column (country flag, city, region) when a MaxMind GeoLite2 database is configured under Traffic Analytics — IPv4 and IPv6. The tab also shows an Enforcement Status card, Security Metrics (failed logins 24h, IPs banned 24h, active bans, SSH attacks blocked, mirrored-to-firewall), and a firewall sync indicator with one-click Resync. A ban blocks the IP from the entire application, not just the login page. Loopback (127.0.0.1) is always exempt for bans so you can never lock the appliance out of itself. Allowlist caution: adding any allowlist entry switches sign-in to allowlist-only mode — only listed IPs may log in, and loopback is not exempt there. To prevent self-lockout, the system refuses an allowlist entry that doesn't cover your current IP (you can confirm to override); add your own IP first if you intend to restrict access.
  • fail2ban — optional host-firewall enforcement of the single ban list. fail2ban ships pre-installed; there is only one ban list (the Banned IPs tab), and when you enable firewall enforcement here every application ban (manual or automatic) is also dropped at the host firewall before traffic reaches the web app. Toggle enforcement from the UI — no SSH needed; nothing is managed twice. You can also enable an optional sshd jail to protect the host's SSH daemon; because an IP hammering port 22 is a bad actor everywhere, those offenders are automatically added to the global ban list (blocked at the web layer and all firewall ports), listed here, and cleared globally when you unban them here.

The remainder of this section describes the Traffic tab in detail.

A webalizer/awstats-style dashboard for the station's web traffic. Use the time-range selector in the header to switch between the last 24 hours and the last year, or pick Custom range… to choose explicit start/end dates.

  • Custom date ranges & drill-down: pick a custom start/end window, then click any country, path, status code, browser, OS, HTTP method, or visitor IP to filter the entire dashboard to matching traffic. Active filters appear as removable chips at the top; click ✕ on a chip (or "Clear all") to remove them. The big tables (Top Pages, Top Visitors, Recent Requests, Error URLs) also have a live text filter box.
  • Anomaly detection: a banner highlights operationally interesting deviations — elevated error rate, 5xx surges, likely vulnerability scanners (many 4xx from one IP), login brute-force bursts, and traffic spikes. Thresholds are tunable under Settings → Anomaly Detection, and the same data is available at /api/traffic/anomalies.
  • Privacy / GDPR tools (Settings → Privacy): turn on Anonymize visitor IPs to mask addresses at capture time (so a raw IP is never stored), or erase/mask the records for a specific visitor on request — Anonymize keeps the rows but masks the IP/hostname, Purge deletes them entirely. No shell access needed.
  • At-a-glance strip & charts: page views, unique visitors, total hits, successful logins, active sessions, average response time, bandwidth served, and bounce rate. Key tiles show a "vs previous period" delta and a sparkline. Charts include traffic-over-time, status codes, browsers, operating systems, device types (desktop/mobile/tablet), HTTP methods, authenticated vs anonymous, search engines, hour-of-day, day-of-week, and login activity.
  • Visitor map: a world map with a marker over each country sized by traffic (needs a GeoLite2 Country/City database for non-local visitors).
  • Visitor detail tables: top pages, slowest endpoints, top visitor hosts (with reverse-DNS hostname when enabled), operating systems and browsers (with brand logos), screen resolutions, countries/networks (with flags), cities with state/region (e.g. "Springfield, IL"), languages (with flags), referrers and search engines (with brand logos), file types and robots/spiders (with logos).
  • Errors & scanners: top error URLs (4xx/5xx) and the source IPs generating them — each error source also shows the single path it errors on most and that status code, so a scanner probing /wp-login.php (404) is obvious versus a dashboard hammering a 403/500 endpoint. Plus a Recent Requests table showing the full User-Agent string and parsed browser version.
  • Login security: successful vs. failed logins over time, top login source IPs, and the most recent login attempts — so you can spot brute-force activity.

IPv6 visitors: country, city, ASN/ISP and reverse-DNS all work for IPv6. Because IPv6 privacy addresses rotate per device, unique-visitor counts group IPv6 by its /64 network so one device isn't counted as many visitors (IPv4 is counted per address). An IPv4 vs IPv6 breakdown panel shows hits, visitors and distinct addresses per family alongside a reverse-DNS coverage figure (resolved / addresses) — handy because most IPv6 hosts publish no PTR record, so a low v6 coverage number is normal, not a fault. Reverse-DNS is also resilient: an authoritative "no PTR record" is remembered, but a slow or timed-out IPv6 lookup is retried on a later background pass (with a longer v6 timeout) instead of being given up on permanently.

Why source IPs now read correctly: the app sits behind nginx, so it now trusts the proxy's X-Forwarded-For header. Logins and sessions show the real client address instead of localhost.

Configure collection from the dashboard's Settings button: enable/disable logging, set the retention window, choose whether to record API requests or authenticated traffic only, exclude bots, turn on reverse-DNS hostname lookups, and enable country/flag resolution by either pointing at a MaxMind GeoLite2 .mmdb path or uploading the database right from the browser (validated and stored automatically — no shell access needed).

Keeping it fast & purging data: traffic is stored in the station database (the web_request_logs table), so a busy site can build up a large table that makes the dashboard slow to load. Two controls in Settings keep it in check: "Auto-purge records older than (days)" deletes old rows automatically (the background recorder prunes hourly — lower it, e.g. 30, for a smaller, faster table), and the Danger Zone → "Purge all traffic data" button wipes every recorded request in one click for an immediate reset. Both keep your settings and GeoIP databases; purging cannot be undone. The dashboard also caches its assembled view for a few seconds so repeated/auto-refreshes and multiple open tabs don't re-run every query.

Reverse DNS & flags (awstats-style): enabling "Resolve hostnames (reverse DNS)" shows each visitor's hostname instead of a bare IP. With a GeoLite2 database configured, public visitors also show their country flag. Hostname lookups happen in the background (off the request path) and are cached; leave them off if you'd rather not send visitor IPs to your DNS resolver. Hostnames also backfill automatically: rows recorded before you enabled this (or while DNS was briefly unreachable) get filled in by a background pass over the following minutes. An IP that simply has no PTR record will always show as a bare address — that's expected, not a bug.

Export: use the Export menu to download every report as a multi-section CSV (opens in Excel) or as a multi-page PDF report (charts and tables included).

Traffic data is stored locally in the station database and pruned automatically past the retention window; nothing is sent to any third party.

Importing Boundary Data

The system supports two methods for importing geographic boundary data:

  • GeoJSON Files: Upload GeoJSON files directly via the "Upload Files" tab
  • Shapefiles: Upload ESRI Shapefiles (ZIP archives with .shp, .shx, .dbf files) or import existing shapefiles from the server
Using Shapefiles

Navigate to Admin → Upload Files and scroll to the "Upload Shapefiles" section:

  1. View Server Files: Click "Refresh List" to see shapefiles already on the server (e.g., in /streams and ponds)
  2. Import Existing: Click "Import" next to any complete shapefile to convert and load it into the database
  3. Upload New: Upload a ZIP file containing all shapefile components and select the boundary type
Tip: The system automatically detects water features (rivers, lakes) from TIGER/Line shapefiles. Water boundary files for your configured county can be pre-loaded in the streams and ponds directory.
Supported Boundary Types
  • 🌊 Rivers & Streams - Linear water features
  • 💧 Lakes & Ponds - Area water bodies
  • Electric Providers - Utility service areas
  • 🏘️ Villages & Townships - Municipal boundaries
  • 🏫 School Districts
  • 🔥 Fire Districts
  • 🚑 EMS Districts
  • 🚆 Railroads - Rail corridors
  • 📞 Telephone Providers
  • 🗺️ County Outlines
Additional Configuration
  • Alert Configuration: Set up alert routing and notification preferences in the admin panel
  • Filter Settings: Configure geographic and event-based alert filtering
  • Intersection Calculation: After uploading boundaries, calculate intersections via Operations → Calculate Intersections

Purging Received Alerts & Audio

Busy monitoring sources can record thousands of received alerts, and the raw WAV audio captured with each one is the largest storage cost. The Alert Purge page (Admin → Operations → Alert Purge, also reachable from the Purge button on the Received Alerts page) is the single place to clean this up.

  • Filter what to remove by age (older than N days), source, forwarding decision (e.g. everything not forwarded), and/or SAME event code.
  • Choose the scope: Audio only strips the stored WAV but keeps the record for the FCC compliance log; Entire alert deletes the record, and can also delete the generated broadcast message and its on-disk audio so no instance of the audio remains.
  • Preview first to see how many records and how much audio a purge would affect before running it.
  • Automatic Purge can run the same rules in the background (shortly after startup, then roughly every 6 hours).
Purging alerts never touches system, audit, or compliance logs — every purge writes an audit entry recording what was removed.

US County Boundaries (IPAWS SAME Coverage)

The County Boundaries page (Admin → County Boundaries) manages the Census TIGER/Line county shapefile used to draw highlighted county outlines on IPAWS alert coverage maps. IPAWS/NWS alerts carry 6-digit SAME geocodes (e.g. 039137) instead of polygon geometry; EAS Station™ converts those codes to county outlines by looking up this table.

Page Workflow

Sections are ordered top-to-bottom for a natural workflow:

  1. Status Cards — Shows whether the us_county_boundaries table exists, how many counties are loaded, how many states, and whether the bundled Census shapefile is present.
  2. Load County Boundaries — Import data from the bundled Census shapefile (≈3,235 counties, optionally filtered to one state) or upload a custom ZIP shapefile.
  3. Loaded States — Table listing every state that has county data in the database. Each row has two action buttons:
    • View on Map — loads that state's county outlines on the interactive map directly below this table.
    • Delete — removes all county records for that state.
  4. County Boundary Map — Interactive Leaflet map. Use the state dropdown in the card header to choose a state, or click the button in the Loaded States table to jump directly to a state. Click any county outline to see its name, GEOID, and SAME code. Use Clear to reset the map.
  5. Search Counties — Real-time search by county name, 5-digit GEOID, or state abbreviation. Clicking a result loads that state on the map.
  6. Table Lookup / Diagnostics — Enter one or more 6-digit SAME codes or 5-digit GEOIDs (comma-separated) to verify they are present in the database. Useful for confirming coverage before an activation.
One-time setup: EAS Station™ auto-loads the bundled Census shapefile on first startup if the table is empty. You only need to use this page if the auto-load did not run, if you need to reload data, or if you want to inspect or verify the coverage for specific counties.

  • Toggle Auto Start or Enabled to control which receivers the radio manager spins up during poller runs.
  • Use the action menu to request synchronized IQ/PCM captures.
  • Captured files are surfaced alongside status updates in the compliance dashboard.

Manage and control all display outputs from a unified interface.

  • Unified Dashboard: Access LED sign, VFD display, and OLED screen controls from one central page
  • Status Monitoring: View connection status and current content for all displays at a glance
  • Quick Actions: Jump to full control pages for detailed configuration and testing
  • Recent Activity: See a consolidated feed of all display output history
  • Individual Controls: Access advanced features like LED animations, VFD graphics, and OLED screen rotation
Access: Navigate to Broadcast → Display Controls from the main menu or visit /displays
Tip: Use the unified page for quick status checks and the individual control pages (LED, VFD, OLED) for detailed configuration and testing.

Create dynamic content templates for LED signs and VFD displays with API data integration.

  • Screen Templates: Define custom layouts with variable substitution from API endpoints like /api/system_status, /api/alerts, and /api/monitoring/radio
  • LED Displays: Configure text content (4 lines × 20 chars) with color, animation mode, and speed settings
  • VFD Graphics: Build graphical screens with progress bars, VU meters, text, shapes, and images on 140×32 pixel displays
  • Screen Rotation: Set up automatic cycling between multiple screens with configurable durations
  • Dynamic Data: Display system health, CPU/memory usage, alert counts, network info, signal strength, and more
  • Priority Management: Emergency screens override rotation; alerts pause normal displays
Access: Navigate to System → Custom Screens from the main menu or visit /screens
Documentation: See Custom Display Screens Guide for template syntax, variable reference, and examples

Broadcast Builder Console:

Accessible from the top navigation once logged in. Use the browser-based workflow to:

  • Pick a state or territory
  • Choose county/parish or statewide SAME codes
  • Select originator code (EAS, CIV, WXR, PEP)
  • Choose from authorized 47 CFR §11.31(d-e) event types
  • Preview the SAME header in real-time
  • Generate complete packages with SAME bursts, attention tones, and narration
Command Line: For automation, use: python tools/generate_sample_audio.py

Before alert text is sent to the TTS engine it passes through a four-layer normalization pipeline that converts abbreviated and machine-formatted text into natural spoken language.

The Four Layers
  1. Time expansion — compact clock times are converted to fully-spoken equivalents so every TTS backend gives the same natural result.
    1100 PMeleven o'clock PM  ·  9:30 AMnine thirty AM
  2. NWS-specific cleanup — three rules handle formatting conventions unique to NOAA/NWS alert text:
    • Alternate-timezone slash notation — NWS writes /5 PM CDT/ to show a deadline in a second timezone; the slashes are stripped so TTS does not read them literally.
    • Saint abbreviationST. is expanded to Saint before proper nouns (e.g. Saint Joseph).
    • Indiana county disambiguation — NWS appends the state code IN after a county name that appears in more than one watch state (e.g. ALLEN INALLEN Indiana, CASS INCASS Indiana). The substitution is applied only when the preceding word is a recognised Indiana county name and the following word is not a directional word or state name, so common phrases like IN EFFECT and section headers like IN MICHIGAN are never altered.
  3. Built-in acronym table — hard-coded expansions for EAS/NWS tokens, all US timezone abbreviations, and US state codes used as county-name markers:
    NWSNational Weather Service  ·  EDTEastern Daylight Time  ·  MIMichigan  ·  OHOhio  ·  AFDAir Force Depot  ·  and more
  4. Custom pronunciation dictionary — your own word-substitution rules, applied last and longest-first so multi-word entries are never masked by shorter ones.
Accessing the Tools
  • TTS Settings & Pronunciation Preview — Navigate to Admin → TTS Settings or visit /admin/tts. Paste any alert text into the Pronunciation Preview panel to see exactly what the TTS engine will receive before going live.
  • Custom Pronunciation Rules — Navigate to Admin → TTS Settings then click Pronunciation Dictionary, or visit /admin/tts/pronunciation. Add entries for place names, call letters, or any term your TTS engine mispronounces. Rules support optional case-sensitive matching and a note field for documentation.
Tip: Use the Normalize & Speak button on the TTS Settings page to hear the normalised text through your configured TTS provider before deploying a change.

Required Weekly Test (RWT) broadcasts can be automatically scheduled to run on specific days and time windows.

Accessing Weekly Test Automation
  1. Navigate to Broadcast → Weekly Test Automation from the navigation menu
  2. Or visit /rwt-schedule directly
Configuration Options
  • Enable/Disable: Toggle automatic RWT broadcasts on or off
  • Days of Week: Select which days to send RWT (Monday through Sunday)
  • Time Window: Set start and end times (e.g., 8:00 AM to 4:00 PM)
  • Coverage: The scheduler always follows the shared Default RWT Counties list that sits next to the form—update it once and Quick RWT, manual defaults, and automation all stay aligned.
Originator & Station: RWT automation reuses the EAS_ORIGINATOR and EAS_STATION_ID environment variables that also feed the Broadcast Builder console.
RWT Broadcast Behavior

Automatic RWT broadcasts are designed to be lean and FCC-compliant:

  • No TTS Narration: RWT contains only SAME headers and EOM tones
  • No Attention Tones: Silent except for required signaling
  • Once Per Day: Only one RWT sent per configured day
  • Time Window: Broadcasts only during configured hours
  • Logged: All broadcasts stored in database for compliance tracking
Testing Your Configuration

Use the "Send Test RWT Now" button to immediately trigger a test broadcast and verify your configuration.

Scheduling Note: The system checks every minute whether to send an RWT. Once configured, it runs automatically in the background.
Default Counties: Systems ship with Allen, Defiance, Hancock, Henry, Paulding, Van Wert, and Wood Counties in Ohio (FIPS codes 039003, 039039, 039063, 039069, 039125, 039161, 039173). Update the Default RWT Counties manager to write your own list into Location Settings—Quick RWT, the Broadcast Builder defaults, and the scheduler will all use it automatically.

Troubleshooting

  1. Check Logs: Run sudo journalctl -u eas-station-web.service -f to see service startup messages.
  2. Database Connection: Verify POSTGRES_* settings in /opt/eas-station/.env match your database deployment.
  3. Secret Key: Ensure SECRET_KEY is set to a non-empty value.
  4. Port Conflicts: Confirm port 5000 isn't already in use.
Common Issue: Database connectivity problems account for 80% of startup failures.

  • PostGIS Extension: Ensure your database has the PostGIS extension enabled: CREATE EXTENSION IF NOT EXISTS postgis;
  • Spatial Indexes: Check that boundary tables have spatial indexes for performance.
  • Geometry Types: Verify imported GeoJSON files use valid geometry types.

  • Audio Drivers: Verify sound card drivers are working on the host system.
  • File Permissions: Check that the application has write access to audio output directories.
  • Azure Speech: If using Azure TTS, verify API keys and regional endpoints.

  • Serial Connection: Verify the serial port device exists and is accessible.
  • Protocol Settings: Check that baud rate and protocol settings match your sign model.
  • Network Access: Ensure the application can reach the sign's IP address if using network control.

Reference Commands

Service Management
# View logs
sudo journalctl -u eas-station-web.service -f

# Restart services
sudo systemctl restart eas-station.target

# Check service status
sudo systemctl status eas-station.target
Database Operations
# Reset database
python tools/reset_database.py

# Check health
python tools/check_db_health.py
Audio & Testing
# Generate test audio
python tools/generate_sample_audio.py

# Test receivers
python tools/test_receivers.py
System Status
# System health
curl http://localhost:5000/api/system_health

# Version info
curl http://localhost:5000/version

Getting Help

  1. 1
    Check Documentation: Review this guide and the About page for system information.
  2. 2
    Review Logs: Run sudo journalctl -u eas-station.target -f to identify error messages.
  3. 3
    Check System Health: Visit System Health for status overview.
  4. 4
    Search Issues: Look for similar problems on GitHub Issues.
  5. 5
    Create New Issue: Provide logs, configuration (redact secrets), and steps to reproduce.

Trusted Field Resources

Curated references from NOAA, FEMA IPAWS, and ARRL to keep operations sharp.

NOAA FEMA IPAWS ARRL
NOAA Weather Service

Primary CAP documentation, glossary, and sample payloads.

FEMA IPAWS Lab

Interoperability, architecture, and test schedule references.

ARRL Field Playbooks

ARES task books, ICS-213 templates, and readiness checklists.