Portainer Deployment Guide for EAS Station
> Complete instructions for deploying, maintaining, and upgrading EAS Station using Portainer
Table of Contents
- Overview
- Prerequisites
- Initial Setup
- Preparing the Environment File
- Creating the Stack in Portainer
- Stack Configuration
- Using External PostgreSQL Database
- Using Embedded PostgreSQL Database
- Deploying the Stack
- Post-Deployment Configuration
- Updating to Latest Build
- Method 1: Pull and Redeploy (Recommended)
- Method 2: Using Watchtower
- Method 3: In-App Upgrade Tool
- Maintenance Tasks
- Backup and Restore
- Monitoring and Health Checks
- Troubleshooting
- Advanced Configuration
Overview
This guide provides complete instructions for deploying and maintaining EAS Station using Portainer, a popular Docker management UI. Portainer simplifies Docker operations through a web interface, making it ideal for managing emergency alerting infrastructure.
What you'll learn:- How to deploy EAS Station as a Portainer stack
- How to configure environment variables through Portainer
- How to update to the latest builds
- How to monitor and maintain your deployment
- How to backup and restore your data
Prerequisites
Before deploying EAS Station in Portainer, ensure you have:
Required
- Portainer installed and running (Community Edition or Business Edition)
- Portainer CE 2.19+ recommended
- Access to the Portainer web interface
- Docker Engine 24+ on the host system
- Sufficient resources:
- 4GB RAM minimum (8GB recommended for heavy workloads)
- 20GB free disk space (more if storing many audio files)
- Network access for pulling Docker images and NOAA/IPAWS feeds
Database Options (Choose One)
- Option A (Recommended): External PostgreSQL 15+ with PostGIS 3.x extension
- Can be a managed database service (AWS RDS, Azure Database, etc.)
- Can be a separate PostgreSQL container
- Provides better data persistence and backup options
- Option B: Embedded PostgreSQL using the
embedded-dbprofile - Simpler setup, database runs in the same stack
- Requires configuring volume backups
Optional Hardware (for full functionality)
- SDR devices for alert verification (RTL-SDR, Airspy, etc.)
- Raspberry Pi GPIO for relay control (if using hardware transmitter keying)
- Alpha Protocol LED sign for display integration
Initial Setup
Preparing the Environment File
Before creating the stack in Portainer, understand the environment configuration:
If deploying from Git (recommended):- Portainer automatically loads
stack.envfrom the repository with default values - You only need to override critical variables (SECRET_KEY, database credentials, location)
- See Stack Configuration section below
- You'll need to configure all environment variables manually
- Download
.env.examplefrom the repository as a reference:
https://github.com/KR8MER/eas-station/blob/main/.env.example
Required preparation (both methods):- Generate a secure SECRET_KEY:
python3 -c "import secrets; print(secrets.token_hex(32))"
Save this value - you'll need it for the Portainer environment configuration.- Prepare your database credentials:
- If using external PostgreSQL: note your host, port, database name, user, and password
- If using embedded PostgreSQL: decide on a strong password for the database
- Note your deployment preferences:
- Timezone (e.g.,
America/New_York) - Default location (county, state, SAME codes)
- Whether you want EAS broadcasting enabled
- LED sign IP (if applicable)
Creating the Stack in Portainer
Step 1: Access Portainer Stacks
- Log in to your Portainer instance
- Select your Environment (usually "local" or the name of your Docker host)
- Navigate to Stacks in the left sidebar
- Click + Add stack
Step 2: Stack Name
Field: Name Value:eas-station (or your preferred name)Guidelines:
- Use lowercase letters, numbers, hyphens, and underscores only
- Must be unique within your Portainer environment
- Suggestion:
eas-stationoreas-station-prod
> ๐ก Tip: The stack name becomes part of container names (e.g., eas-stationapp1)
Step 3: Build Method
Field: Build method Recommended: Git RepositoryOptions:| Method | When to Use | Pros | Cons |
|---|---|---|---|
| Git Repository โ | Standard deployment | Easy updates, version control, auto-loads stack.env |
Requires internet access |
| Web editor | Quick testing, custom modifications | No external dependencies | Manual updates required |
| Upload | Offline deployments | Works without Git | Must manually upload files |
| Custom template | Reusable configurations | Standardized deployments | Initial setup complexity |
Step 4: Git Repository Configuration
4.1 Authentication
Field: Authentication Value: Leave unchecked (public repository)If you fork the repository and make it private:
- Check Authentication
- Enter your GitHub username
- Generate and enter a Personal Access Token (not your password)
4.2 Repository URL
Field: Repository URL Value:https://github.com/KR8MER/eas-stationImportant:
- โ Use HTTPS URL (not SSH)
- โ Ensure you can access this URL from your browser
- โ Double-check for typos
4.3 Skip TLS Verification
Field: Skip TLS Verification Value: Leave uncheckedOnly check this if:
- You're using a private Git server with self-signed certificates
- You understand the security implications
4.4 Repository Reference
Field: Repository reference Value:refs/heads/main (recommended)Format: refs/heads/<branch> or refs/tags/<tag>Common Values:| Value | Description | When to Use |
|---|---|---|
refs/heads/main |
Latest stable code | Production (recommended) |
| (leave blank) | Same as refs/heads/main |
Also acceptable |
refs/tags/v2.3.12 |
Specific version | Pin to exact version |
refs/heads/develop |
Development branch | Testing new features |
refs/heads/main # Track main branch
refs/tags/v2.3.12 # Pin to version 2.3.12
refs/heads/feature-branch # Track specific branch
> ๐ Production Tip: Use tagged releases (e.g., refs/tags/v2.3.12) for production to prevent unexpected changes.
4.5 Compose Path
Field: Compose path Value:docker-compose.yml OR docker-compose.embedded-db.ymlWhich one to use:| File | Database | When to Use |
|---|---|---|
docker-compose.yml |
External | You have existing PostgreSQL/PostGIS (recommended) |
docker-compose.embedded-db.yml |
Embedded | All-in-one stack with database included |
- Relative to repository root
- Must include file extension (
.ymlor.yaml) - Case-sensitive on Linux systems
docker-compose.yml # Standard
docker-compose.embedded-db.yml # With embedded database
docker-compose.production.yml # Custom production file (if you create one)
4.6 Additional Paths (Optional)
Field: Additional paths Value: Leave empty (not needed for EAS Station)This field is for including additional compose files to override or extend the main file. For example:
docker-compose.override.yml
Step 5: GitOps Updates (Formerly "Automatic Updates")
Field: GitOps updates Recommended: Enable for automatic updatesWhat is GitOps Updates?
GitOps updates automatically redeploy your stack when the Git repository changes. This keeps your deployment synchronized with your repository without manual intervention.
Configuration Options
Option 1: Webhook Method (Recommended)- โ Check GitOps updates
- Select Webhook mechanism
- Click Show webhook URL (appears after enabling)
- Copy the webhook URL
- In GitHub:
- Go to repository Settings โ Webhooks โ Add webhook
- Paste webhook URL as Payload URL
- Content type:
application/json - Select Just the push event
- Click Add webhook
- โ Check GitOps updates
- Select Polling mechanism
- Set polling interval:
- 5 minutes - Frequent updates (uses more resources)
- 15 minutes - Balanced (recommended)
- 60 minutes - Minimal resource usage
- โฌ Leave GitOps updates unchecked
- You must manually click "Pull and redeploy" to update
| Environment | GitOps Setting | Reason |
|---|---|---|
| Production | Polling (15-60 min) | Controlled, predictable updates |
| Staging | Webhook | Immediate testing of changes |
| Development | Disabled | Manual control over deployments |
> โ ๏ธ Warning: Automatic updates will restart your stack. For critical systems, test updates in staging first.
Step 6: Enable Relative Path Volumes
Field: Enable relative path volumes Value: Leave unchecked (not needed)This option allows volume paths relative to the compose file location. EAS Station uses absolute paths and named volumes, so this isn't required.
Step 7: Alternative - Web Editor Method
If you chose Web editor instead of Git Repository:
- Copy the contents of
docker-compose.ymlfrom the repository:
https://github.com/KR8MER/eas-station/blob/main/docker-compose.yml
- Paste into the Web editor in Portainer
- Modify as needed for your environment
- Note: You won't get automatic
stack.envloading - must configure all variables manually
Stack Configuration
Step 8: Environment Variables
Understanding stack.env File Operation
Important: The behavior ofstack.env differs based on deployment method:| Deployment Method | stack.env Behavior |
|---|---|
| Git Repository | File must already exist in the Git repo (โ it does!) |
| Web editor | Auto-created from what you configure below |
| Upload | Auto-created from what you configure below |
| Custom template | Auto-created from what you configure below |
- โ
Portainer automatically loads
stack.envfrom the repository - โ All default values are already set
- โ You only override critical variables
- All Flask application settings
- Default database connection parameters
- CAP poller configuration
- Logging settings
- Location defaults
- EAS broadcast settings (disabled by default)
- TTS provider settings
- Docker/infrastructure metadata
> ๐ก Key Point: When deploying from Git, you only need to override 5-7 variables. Everything else uses sensible defaults from stack.env!
> ๐ฆ Versioning: The running release number now comes directly from the repository VERSION manifest. You no longer need to set APPBUILDVERSION in your stack environment.
Configuration Options
In the Portainer stack configuration, scroll down to Environment variables. You have three options:
Option A: Advanced Mode (Recommended)
Click "Advanced mode" and paste your environment variables in .env format:
CORE APPLICATION SETTINGS
SECRET_KEY=your-generated-secret-key-here
NOAAUSERAGENT=Your-Organization Emergency Alert Hub/2.1
FLASK_DEBUG=false
FLASK_ENV=productionDATABASE CONNECTION
POSTGRES_HOST=your-database-host
POSTGRES_PORT=5432
POSTGRES_DB=alerts
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your-secure-database-passwordCAP POLLER SETTINGS
POLLINTERVALSEC=180
CAP_TIMEOUT=30LOGGING
LOG_LEVEL=INFOLOCATION DEFAULTS
DEFAULTTIMEZONE=America/NewYork
DEFAULTCOUNTYNAME=Your County
DEFAULTSTATECODE=OH
DEFAULTZONECODES=OHZ016,OHC137SAME/EAS BROADCAST (if enabled)
EASBROADCASTENABLED=false
EAS_ORIGINATOR=WXR
EASSTATIONID=EASNODES
EASATTENTIONTONE_SECONDS=8DOCKER/INFRASTRUCTURE
TZ=America/New_York
WATCHTOWERLABELENABLE=true
Option B: Simple Mode
Click "+ Add environment variable" for each setting and enter them individually.
Option C: Use Auto-Loaded Defaults (Easiest) โ Recommended for Git Deployments
If deploying from Git, Portainer automatically loads stack.env. You only need to override critical variables:
- Leave the advanced mode OFF - stay in simple mode
- Click "+ Add environment variable" for each variable below
- Add only these essential variables:
| Name | Value | Example |
|---|---|---|
SECRET_KEY |
Your generated secret | 9d821419d2b70c5a5572cd8e73f1e1d0f7ac4b65b6ac77684c517106c8079498 |
POSTGRES_HOST |
Database hostname | host.docker.internal or alerts-db or postgres.example.com |
POSTGRES_PASSWORD |
Database password | your-secure-password |
POSTGRES_DB |
Database name | alerts (or your preferred name) |
POSTGRES_USER |
Database username | postgres (or your preferred user) |
| Name | Value | Example |
|---|---|---|
DEFAULTCOUNTYNAME |
Your county | Putnam County |
DEFAULTSTATECODE |
Your state | OH |
DEFAULTTIMEZONE |
Your timezone | America/NewYork |
DEFAULTZONECODES |
NOAA zones | OHZ016,OHC137 |
- Do NOT add: Variables you want to keep at their defaults -
stack.envhandles them automatically!
Name: SECRET_KEY
Value: 9d821419d2b70c5a5572cd8e73f1e1d0f7ac4b65b6ac77684c517106c8079498Name: POSTGRES_HOST
Value: host.docker.internal
Name: POSTGRES_PASSWORD
Value: casaos
Name: POSTGRES_DB
Value: casaos
Name: POSTGRES_USER
Value: casaos
Name: DEFAULTCOUNTYNAME
Value: Your County Name
Name: DEFAULTSTATECODE
Value: OH
> โ
Result: You configure 5-7 variables instead of 40+. The rest use defaults from stack.env.
Critical Variables Reference
Must configure:SECRET_KEY- Generated secure random stringPOSTGRES_HOST- Database hostnamePOSTGRES_PASSWORD- Secure database password
DEFAULT_TIMEZONE- Your local timezoneDEFAULTCOUNTYNAME- Your county nameDEFAULTSTATECODE- Your state abbreviationDEFAULTZONECODES- Your NOAA zone codes
EASBROADCASTENABLED- Set totrueif you want audio generationLEDSIGNIP- If you have an LED signIPAWSCAPFEED_URLS- If using IPAWS feeds
Step 9: Registries
Field: Registries Value: None (leave empty)What are Registries?
Registries are Docker container registries where images are stored (e.g., Docker Hub, GitHub Container Registry, private registries).
For EAS Station:
- โ No registry selection needed
- Images pull from Docker Hub (public)
- The Dockerfile builds the image locally from the git repository
When to Configure Registries:
You would configure registries if:
- You're using a private Docker registry
- You're pulling from GitHub Container Registry (ghcr.io)
- You need authentication to pull images
- You're in an air-gapped environment with a local registry
Step 10: Access Control
Field: Enable access control Recommended: Enable for multi-user Portainer installationsOption 1: Administrators Only (Recommended)
โ Check "Enable access control" โ Select "Restrict to administrators only"
Effect:- Only Portainer administrators can view/manage this stack
- Regular users won't see the stack
- Best for production deployments
- Production EAS Station deployments
- Sensitive emergency alert systems
- Multi-tenant Portainer environments
Option 2: Specific Users/Teams
โ Check "Enable access control" โ Select "Restrict to a set of users and/or teams"
Configuration:- Select users from dropdown
- Select teams from dropdown
- Choose access level for each:
- View - Read-only access
- Manage - Can restart, update, view logs
- Full control - Can delete and reconfigure
- Team-based management
- Training environments
- Shared emergency management operations
Option 3: No Restrictions
โฌ Leave "Enable access control" unchecked
Effect:- All Portainer users can view and manage the stack
- Suitable for single-user installations
- Personal/home labs
- Single-administrator Portainer setups
- Development environments
Recommendation for EAS Station:
| Environment | Access Control | Setting |
|---|---|---|
| Production | โ Enabled | Administrators only |
| Staging | โ Enabled | Specific operations team |
| Development | โฌ Optional | No restrictions OK |
> ๐ Security Tip: Always enable access control for production emergency alerting systems to prevent unauthorized modifications.
Using External PostgreSQL Database
If you're using an external PostgreSQL database:
Database Setup
- Create the database:
CREATE DATABASE alerts;
- Enable PostGIS:
\c alerts
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;
- Verify PostGIS installation:
SELECT PostGIS_Version();
Environment Configuration
Set these variables in Portainer:
POSTGRES_HOST=your-db-host.example.com
POSTGRES_PORT=5432
POSTGRES_DB=alerts
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your-database-password
For Docker Desktop users: If the database is on your host machine, use:
POSTGRES_HOST=host.docker.internal
Using Embedded PostgreSQL Database
To use the embedded PostgreSQL database that runs within the stack:
Step 1: Use the Embedded Compose File
When creating the stack, use:
- Compose path:
docker-compose.embedded-db.yml
Or if using web editor, copy the embedded compose file from:
https://github.com/KR8MER/eas-station/blob/main/docker-compose.embedded-db.yml
Step 2: Configure Database Variables
POSTGRES_HOST=alerts-db
POSTGRES_PORT=5432
POSTGRES_DB=alerts
POSTGRES_USER=postgres
POSTGRES_PASSWORD=change-this-to-secure-password
Step 3: Enable the Profile (if needed)
If using the standard docker-compose.yml with profiles:
- Scroll to Advanced deployment settings
- Find Profiles
- Add:
embedded-db
This activates the alerts-db service defined in the compose file.
Step 11: Actions (Final Review)
Field: Actions section at the bottom of the formBefore clicking "Deploy the stack," take a moment to review what you've configured:
Pre-Deployment Checklist
โ
Stack name is set correctly
โ
Git Repository method selected (or your chosen method)
โ
Repository URL is correct: https://github.com/KR8MER/eas-station
โ
Repository reference is set: refs/heads/main (or your chosen ref)
โ
Compose path is correct: docker-compose.yml or docker-compose.embedded-db.yml
โ
GitOps updates configured (if desired)
โ
Environment variables are set:
SECRET_KEY- secure random valuePOSTGRES_HOST- database hostnamePOSTGRES_PASSWORD- secure password- Database credentials (DB, USER)
- Location settings (optional overrides)
Available Actions
At the bottom of the form, you'll see:
- ๐๏ธ Cancel - Discard changes and return to stacks list
- ๐ Copy - Copy configuration to clipboard (useful for backup)
- ๐ Deploy the stack - Create and start the stack
Deploying the Stack
Step 1: Click Deploy the Stack Button
Once you've completed all configuration steps and reviewed the checklist above:
- Scroll to the bottom of the form
- Click the green "Deploy the stack" button
- Wait - do not close the browser window
> ๐ก Pro Tip: Before clicking deploy, use the Copy button to save your configuration to a text file for your records.
Step 2: Monitor Initial Deployment
Portainer will now:
- Pull the repository (if using Git method)
- Clones the Git repository
- Loads the compose file
- Reads
stack.envautomatically
- Load environment variables
- Combines
stack.envwith your overrides - Validates variable substitutions
- Pull/Build Docker image
- First deployment: Builds image from Dockerfile (may take 5-10 minutes)
- Subsequent deployments: Rebuilds only if code changed
- Create containers
- Creates:
app,poller,ipaws-pollercontainers - Also creates
alerts-dbif using embedded database
- Set up networking and volumes
- Creates default bridge network
- Creates named volumes (if using embedded DB)
Step 3: Monitor Deployment
- Watch the Logs tab to see the deployment progress
- Look for these success indicators:
Successfully built eas-station:latestDatabase connection successfulStarting Gunicorn workersListening at: http://0.0.0.0:5000
Step 4: Verify Containers
Navigate to Containers and verify all services are running:
- โ
eas-station_app- Status: Running - โ
eas-station_poller- Status: Running - โ
eas-station_ipaws-poller- Status: Running - โ
eas-station_alerts-db- Status: Running (if using embedded DB)
Post-Deployment Configuration
Step 1: Access the Application
- Open your web browser
- Navigate to:
http://your-server-ip:5000 - You should see the EAS Station dashboard
Step 2: Complete First-Time Setup
If SECRET_KEY wasn't configured, you'll be redirected to the setup wizard:
- Follow the on-screen prompts
- Set a secure
SECRET_KEY - Configure database connection
- Save configuration
- Restart the stack in Portainer
Step 3: Create Admin Account
- Navigate to:
http://your-server-ip:5000/admin - Complete the First-Time Administrator Setup:
- Enter a username (letters, numbers,
.,_,-only) - Create a strong password (minimum 8 characters)
- Confirm password
- Click Create Account
- Sign in with your new credentials
Step 4: Configure Location Settings
- Go to Admin โ Location Settings
- Set your:
- County name and state code
- NOAA zone codes
- Area search terms
- Map center coordinates
- SAME location codes for broadcasting
Step 5: Upload Geographic Boundaries (Optional)
If you have GeoJSON boundary files:
- Go to Admin โ Boundaries
- Select boundary type (county, district, etc.)
- Upload your GeoJSON file
- Verify boundaries appear on the map
Step 6: Configure SDR Receivers (Optional)
If you have SDR hardware:
- Go to Settings โ Radio Receivers
- Click Auto-Detect Devices
- Add detected receivers or create manual configurations
- Test each receiver
- Enable auto-start for automatic monitoring
Updating to Latest Build
Method 1: Pull and Redeploy (Recommended)
This is the safest method for Portainer-managed stacks:
Step 1: Pull Latest Changes
- In Portainer, navigate to Stacks
- Select your
eas-stationstack - Click Pull and redeploy (if using Git repository method)
- Or click Editor โ Pull latest changes
Step 2: Review Changes
- Review any changes to the compose file
- Check for new environment variables in
.env.example - Add any new required variables to your stack environment
Step 3: Redeploy
- Click Update the stack
- Portainer will:
- Pull the latest code from Git
- Rebuild the Docker image if needed
- Recreate containers with updated code
- Preserve volumes and data
Step 4: Verify Update
- Check container logs for successful startup
- Visit the web interface
- Check Admin โ System Operations for the new version number
- Run a test poll: Admin โ Manual Trigger Poll
Method 2: Using Watchtower
Watchtower can automatically update your containers:
Setup Watchtower (One-Time)
Add Watchtower to your stack or as a separate container:
watchtower:
image: containrrr/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWERPOLLINTERVAL=86400 # Check daily
- WATCHTOWER_CLEANUP=true
- WATCHTOWERLABELENABLE=true
command: --label-enable --cleanup
Enable Auto-Update Labels
Ensure your stack environment has:
WATCHTOWERLABELENABLE=true
Watchtower will automatically check for and apply updates daily.
Method 3: In-App Upgrade Tool
For advanced users with terminal access:
- Access the app container through Portainer:
- Containers โ
eas-station_appโ Console - Select
/bin/bashand click Connect
- Run the upgrade tool:
python tools/inplace_upgrade.py
- The tool will:
- Fetch the latest code from Git
- Rebuild the Docker image
- Apply database migrations
- Restart services
- Preserve your data
Maintenance Tasks
Regular Maintenance Schedule
Daily
- Check Health Dashboard:
http://your-server:5000/system_health - Review Latest Alerts: Verify poller is fetching new alerts
- Monitor Container Status: Ensure all containers are running in Portainer
Weekly
- Review Logs: Check for any errors or warnings
- In Portainer: Containers โ Select container โ Logs
- Test Manual Broadcast: If using EAS features
- Check Disk Space: Verify sufficient space for database and audio files
- Review Compliance Dashboard:
http://your-server:5000/admin/compliance
Monthly
- Backup Database: See Backup and Restore
- Update Stack: Pull latest changes and redeploy
- Review User Accounts: Remove unused accounts
- Check SDR Health: Verify receiver functionality
- Required Monthly Test (RMT): If operating as certified station
Quarterly
- Review Documentation: Check for updated guides
- Security Audit: Review passwords, update credentials
- Performance Review: Check resource usage trends
- Disaster Recovery Test: Verify backup restoration process
Routine Operations via Portainer
Restarting Services
To restart a specific service:
- Containers โ Select container
- Click Restart
- Monitor logs for successful restart
To restart the entire stack:
- Stacks โ Select
eas-station - Click Stop
- Wait for all containers to stop
- Click Start
Viewing Logs
- Containers โ Select container
- Click Logs
- Use search/filter to find specific events
- Adjust lines (50, 100, 500, 1000)
- Toggle Auto-refresh to monitor in real-time
Checking Resource Usage
- Containers โ Select container
- View Quick stats panel:
- CPU usage percentage
- Memory usage
- Network I/O
- Block I/O
Or use Stats page for all containers:
- Dashboard โ Stats
Backup and Restore
Automated Backup via Web UI
- Navigate to Admin โ System Operations
- Click Run Backup
- Enter an optional label (e.g., "pre-upgrade")
- Click Start Backup
- Download the backup files when complete
Manual Database Backup
Using Portainer Console
- Containers โ Select
eas-station_alerts-db(or your database container) - Click Console
- Select
/bin/bashโ Connect - Run backup command:
pgdump -U postgres alerts > /tmp/backup$(date +%Y%m%d_%H%M%S).sql
- Copy backup file from container:
- Containers โ Select database container
- Click Copy from container
- Path:
/tmp/backup_*.sql - Download to your local machine
Using Portainer Exec Feature
- Containers โ
eas-station_app - Console โ
/bin/bash - Run backup script:
python tools/create_backup.py --label portainer-backup
Scheduling Automated Backups
Method 1: Portainer Webhooks + External Cron
- In your stack, click Webhooks
- Create a webhook for backup operations
- Use external cron or scheduled task to call webhook
Method 2: Add Backup Container to Stack
Add to your docker-compose.yml:
backup:
image: eas-station:latest
command:
- /bin/bash
- -c
- |
while true; do
sleep 86400 # Daily backups
python tools/create_backup.py --label daily-auto
done
volumes:
- ./backups:/app/backups
env_file:
- .env
Restoring from Backup
Via Portainer Console
- Upload backup file to container:
- Containers โ Select database container
- Copy to container
- Upload your
.sqlbackup file to/tmp/
- Access database console:
- Containers โ Select
eas-station_alerts-db - Console โ
/bin/bash
- Restore database:
psql -U postgres -d alerts < /tmp/your_backup.sql
Full Stack Restore
- Stop the stack:
- Stacks โ
eas-stationโ Stop
- Remove old volumes (if needed):
- Volumes โ Select
eas-station_alerts-db-data - Remove volume (โ ๏ธ This deletes all data!)
- Restore .env file:
- Update stack environment variables from backup
- Restart stack:
- Stacks โ
eas-stationโ Start
- Restore database:
- Follow database restore steps above
Monitoring and Health Checks
Built-in Health Endpoints
EAS Station provides several monitoring endpoints:
| Endpoint | Purpose | Expected Response |
|---|---|---|
/health |
Basic health check | {"status": "ok"} |
/ping |
Simple ping test | {"status": "pong"} |
/api/system_status |
System status summary | JSON with stats |
/api/system_health |
Detailed health metrics | JSON with all metrics |
Portainer Health Monitoring
Container Health Status
Portainer shows health status for each container:
- Containers โ View list
- Look for health indicator icons:
- ๐ข Green: Healthy
- ๐ก Yellow: Starting/Unhealthy
- ๐ด Red: Failed/Stopped
Setting Up Alerts (Portainer Business)
If using Portainer Business Edition:
- Settings โ Notifications
- Create notification webhook (Slack, email, etc.)
- Set alerts for:
- Container stopped
- Container health check failed
- High resource usage
- Stack update failures
External Monitoring Integration
Prometheus Metrics (Future Enhancement)
Add Prometheus exporter to stack:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
Uptime Monitoring
Use external services to monitor:
- HTTP endpoint:
http://your-server:5000/health - Expected response:
200 OK - Alert if down for > 2 minutes
Log Aggregation
For production deployments, consider:
- Portainer Logs: View directly in Portainer interface
- Docker Logging Drivers: Configure JSON file, syslog, or other drivers
- External Tools: ELK Stack, Grafana Loki, Papertrail, etc.
Troubleshooting
Common Issues in Portainer
Issue: Stack fails to deploy
Symptoms:- Red error message in Portainer
- Containers won't start
- "Failed to create network" errors
- Check compose syntax:
- Use Validate button in web editor
- Ensure YAML indentation is correct
- Review environment variables:
- Verify all required variables are set
- Check for typos in variable names
- Ensure no special characters cause parsing issues
- Check port conflicts:
- In Containers, verify port 5000 isn't already in use
- Change port mapping if needed:
8080:5000
- Review logs:
- Stacks โ
eas-stationโ Logs - Look for specific error messages
Issue: Containers restart loop
Symptoms:- Container status shows "Restarting"
- Logs show repeated startup attempts
- Services never become healthy
- Check database connection:
# In Portainer console for app container
python -c "import psycopg2; print('Testing...')"
- Verify SECRET_KEY is set:
- Check environment variables in Portainer
- Ensure SECRET_KEY exists and is not empty
- Review startup logs:
- Look for Python tracebacks
- Check for missing dependencies
- Disable restart policy temporarily:
- Edit stack, change
restart: unless-stoppedtorestart: "no" - Redeploy to see full error output
Issue: Can't pull latest updates
Symptoms:- "Pull and redeploy" fails
- "Authentication required" errors
- "Repository not found" errors
- Verify Git repository URL:
- Correct:
https://github.com/KR8MER/eas-station - Check for typos
- Check network connectivity:
- Portainer server must have internet access
- Test: Containers โ Any container โ Console โ
ping github.com
- Try manual method:
- Use Editor mode
- Copy updated compose file manually
- Click Update the stack
Issue: Database connection fails
Symptoms:- Errors: "could not connect to server"
- Database unavailable warnings in logs
- Admin panel shows database offline
- Verify database container is running:
- Containers โ Check
alerts-dbstatus - If stopped, click Start
- Check POSTGRES_HOST setting:
- External DB: Use hostname or
host.docker.internal - Embedded DB: Use
alerts-dborpostgres
- Test database connection:
# In app container console
pgisready -h $POSTGRESHOST -U $POSTGRESUSER -d $POSTGRESDB
- Review database logs:
- Containers โ
alerts-dbโ Logs - Look for connection rejections or authentication errors
- Verify PostGIS extension:
# In database container console
psql -U postgres -d alerts -c "SELECT PostGIS_Version();"
Issue: Environment variables not applied
Symptoms:- Changes to
.envdon't take effect - Application uses old/default values
- Features remain disabled after enabling
- Redeploy the stack:
- Environment changes require redeployment
- Stacks โ
eas-stationโ Update the stack
- Verify variables are saved:
- Stacks โ
eas-stationโ Editor - Scroll to environment variables section
- Confirm your changes are present
- Check variable syntax:
- No quotes needed in Portainer advanced mode
- Use
=not:(.envformat, not YAML) - No comments allowed in advanced mode
- Force recreation:
- Enable Re-pull image and redeploy
- Enable Force re-deployment
- Click Update the stack
Getting Help
If you encounter issues not covered here:
- Check container logs in Portainer:
- Containers โ Select container โ Logs
- Look for error messages and stack traces
- Review main documentation:
- Check system health:
- Access:
http://your-server:5000/system_health - Look for red indicators
- Search GitHub Issues:
- Visit: https://github.com/KR8MER/eas-station/issues
- Search for similar problems
- Open a new issue:
- Include Portainer version
- Include relevant logs (redact secrets!)
- Describe steps to reproduce
- Include environment details
Advanced Configuration
Custom Docker Networks
If you need to connect EAS Station to other stacks:
- Create a custom network in Portainer:
- Networks โ Add network
- Name:
eas-network - Driver:
bridge
- Modify stack to use custom network:
networks:
default:
external: true
name: eas-network
Resource Limits
To prevent resource exhaustion:
services:
app:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
Volume Mounting for Persistence
To persist generated EAS audio files:
services:
app:
volumes:
- eas-messages:/app/static/eas_messages
- eas-backups:/app/backups
volumes:
eas-messages:
eas-backups:
Using Docker Secrets (Portainer Business)
For enhanced security with Portainer Business:
- Secrets โ Add secret
- Create secrets for sensitive values:
db_passwordsecret_keyazurespeechkey
- Reference in compose file:
services:
app:
secrets:
- db_password
- secret_key
environment:
POSTGRESPASSWORDFILE: /run/secrets/db_password
SECRETKEYFILE: /run/secrets/secret_key secrets:
db_password:
external: true
secret_key:
external: true
Multi-Stack Deployments
For redundancy, deploy multiple instances:
- Create separate stacks:
eas-station-primaryeas-station-backup
- Use different ports:
# Primary
ports:
- "5000:5000"
# Backup
ports:
- "5001:5000"
- Configure load balancer (nginx, HAProxy, etc.)
Webhook Integration
To trigger stack updates via webhook:
- Stacks โ
eas-stationโ Webhooks - Copy webhook URL
- Configure GitHub webhook (optional):
- Repository:
https://github.com/KR8MER/eas-station - Settings โ Webhooks โ Add webhook
- Payload URL: Your Portainer webhook URL
- Content type:
application/json - Events: Push events on
mainbranch
- Stack auto-updates on new commits
Best Practices Summary
โ Do:
- Use Git repository method for easy updates
- Set strong
SECRET_KEYand database passwords - Enable automatic backups
- Monitor container health regularly
- Review logs weekly
- Test updates in non-production first
- Document your configuration changes
- Keep Portainer itself updated
โ Don't:
- Use default passwords in production
- Skip backups before updates
- Ignore container restart loops
- Delete volumes without backups
- Expose sensitive ports to internet
- Run with
FLASK_DEBUG=truein production - Commit secrets to version control
Quick Reference
Essential Portainer Paths
| Task | Navigation |
|---|---|
| View stack | Stacks โ eas-station |
| Update stack | Stacks โ eas-station โ Editor โ Update |
| View containers | Containers |
| View logs | Containers โ Select โ Logs |
| Access console | Containers โ Select โ Console |
| Manage volumes | Volumes |
| Create backup | Containers โ app โ Console โ python tools/create_backup.py |
Key Environment Variables
| Variable | Purpose | Required |
|---|---|---|
SECRET_KEY |
Session security | Yes |
POSTGRES_HOST |
Database hostname | Yes |
POSTGRES_PASSWORD |
Database password | Yes |
EASBROADCASTENABLED |
Enable audio generation | No |
DEFAULT_TIMEZONE |
Local timezone | Recommended |
LEDSIGNIP |
LED sign address | Optional |
Useful Commands (via Console)
Check Python version
python --versionTest database connection
python -c "from app_core import db; db.session.execute('SELECT 1')"Run backup
python tools/create_backup.pyCheck app version
cat VERSIONList environment variables
env | grep EASView disk usage
df -hCheck memory
free -h
Made with โ and ๐ป for Amateur Radio Emergency Communications73 de KR8MER ๐ก
Last updated: 2025-11-02 Version: 2.3.12
This document is served from docs/deployment/PORTAINER_DEPLOYMENT.md in the EAS Station installation.