This guide explains how to install AllSkyHyde as a production service using Gunicorn and systemd.
The production installation uses:
- Gunicorn - Production WSGI HTTP server for Flask applications
- systemd - Linux service manager for auto-start and management
- Virtual Environment - Isolated Python environment for dependencies
- Linux system with systemd (Raspberry Pi OS, Ubuntu, Debian, etc.)
- Python 3.7 or higher
- User account with sudo privileges
- Internet connection for package installation
-
Navigate to the AllSkyHyde directory:
cd /home/yourusername/AllSkyHyde -
Run the installation script:
./install_production.sh
-
Follow the interactive prompts:
- Confirm removal of any previous installations
- Verify the installation directory
- Choose whether to enable shutdown/restart from web interface
-
Access the web interface:
http://your-pi-ip-address:5000
- Verifies not running as root
- Detects and removes previous installations
- Confirms installation directory
- Ensures installation is in user's home directory
- Checks for Python3 and pip
- Creates Python virtual environment (if not exists)
- Installs all required packages from requirements.txt
- Verifies Gunicorn installation
- Creates image directory at
~/allsky_images - Verifies all required files are present
- Creates systemd service file:
/etc/systemd/system/allskyhyde.service - Configures Gunicorn with:
- 2 worker processes
- 4 threads per worker
- Automatic restart on failure
- Logging to application directory
- Allows web interface to restart/shutdown system
- Grants sudo access for specific commands only
- Completely optional and can be skipped
- Enables service to start on boot
- Starts the service immediately
- Verifies service is running
The script is designed to work with installations in your home directory (e.g., /home/pi/AllSkyHyde).
sudo systemctl status allskyhydesudo systemctl stop allskyhydesudo systemctl start allskyhydesudo systemctl restart allskyhydesudo journalctl -u allskyhyde -fsudo systemctl disable allskyhydesudo systemctl enable allskyhydeThe AllSkyHyde service is configured to automatically restart if it crashes or stops unexpectedly. This section explains how to set up and configure this behaviour.
The systemd service file includes these restart-related settings:
| Setting | Value | What it Does |
|---|---|---|
Restart=always |
always | Restarts the service whenever it stops (crash or clean exit) |
RestartSec=10 |
10 seconds | Waits 10 seconds before attempting to restart |
StartLimitBurst=5 |
5 attempts | Maximum number of restart attempts allowed |
StartLimitIntervalSec=300 |
5 minutes | Time window for the restart limit |
- If the service crashes: systemd waits 10 seconds, then restarts it automatically
- If it crashes repeatedly: After 5 restarts within 5 minutes, systemd stops trying (prevents infinite loops)
If your service file doesn't have these settings, follow these steps:
sudo nano /etc/systemd/system/allskyhyde.serviceYou will be prompted for your password. Type it and press Enter.
Replace the entire contents with this configuration (adjust paths if your username is different):
[Unit]
Description=AllSkyHyde Web Application
After=network.target
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=simple
User=kickpi
Group=kickpi
WorkingDirectory=/home/kickpi/AllSkyCode
Environment=PATH=/home/kickpi/AllSkyCode/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Gunicorn configuration
ExecStart=/home/kickpi/AllSkyCode/venv/bin/gunicorn --bind 0.0.0.0:5000 --workers 1 --threads 4 --timeout 120 --access-logfile /home/kickpi/AllSkyCode/gunicorn-access.log --error-logfile /home/kickpi/AllSkyCode/gunicorn-error.log --log-level info flask_app:app
# Restart configuration
Restart=always
RestartSec=10
# Security settings
PrivateTmp=true
[Install]
WantedBy=multi-user.targetImportant: Change kickpi to your actual username and /home/kickpi/AllSkyCode to your actual installation path.
- Press
Ctrl + O(letter O) to save - Press
Enterto confirm the filename - Press
Ctrl + Xto exit the editor
After editing the service file, tell systemd to reload its configuration:
sudo systemctl daemon-reloadsudo systemctl restart allskyhydeCheck that the restart settings are applied:
systemctl show allskyhyde.service | grep -E "Restart=|RestartUSec|StartLimit"You should see output like:
Restart=always
RestartUSec=10s
StartLimitIntervalSec=5min
StartLimitBurst=5
To test that automatic restart is working:
# Find the process ID
sudo systemctl status allskyhyde | grep "Main PID"
# Kill the process (simulates a crash)
sudo kill -9 <PID>
# Wait 15 seconds, then check status
sleep 15
sudo systemctl status allskyhydeThe service should show as "active (running)" with a new PID.
To see if the service has restarted recently:
sudo journalctl -u allskyhyde --since "1 hour ago" | grep -E "Started|Stopped|Starting"AllSkyHyde includes a built-in network monitoring feature that automatically detects network disconnections and attempts to recover connectivity.
- Regular Connectivity Checks: Every 60 seconds (configurable), the system pings Google's DNS server (8.8.8.8)
- Connection Loss Detection: If the ping fails, the system knows the network is down
- Reconnection Attempts: The system tries to restart network interfaces (up to 3 attempts)
- Automatic Reboot: If reconnection fails, the system reboots to restore connectivity
- Rate Limiting: Maximum 5 reboots per hour to prevent endless reboot loops
- Automatic Recovery: When connection is restored, all counters reset
These values are defined at the top of flask_app.py:
STAY_ALIVE_PING_HOST = "8.8.8.8" # Host to ping (Google DNS)
STAY_ALIVE_PING_PORT = 53 # Port to connect to
STAY_ALIVE_CHECK_INTERVAL_SECONDS = 60 # How often to check (seconds)
STAY_ALIVE_MAX_REBOOT_ATTEMPTS = 5 # Max reboots per tracking period
STAY_ALIVE_TRACKING_PERIOD_SECONDS = 3600 # Tracking period (1 hour)
STAY_ALIVE_CONNECTION_TIMEOUT_SECONDS = 10 # Connection timeout
STAY_ALIVE_RETRY_DELAY_SECONDS = 30 # Delay between reconnection attempts
STAY_ALIVE_MAX_RECONNECT_ATTEMPTS = 3 # Reconnection attempts before rebootNavigate to System Status page - the Network Monitor card shows:
- Current connection status (Connected/Degraded/Disconnected)
- Last successful ping time
- Number of reboot attempts in the current hour
- Recent activity log
curl http://localhost:5000/api/stay_alive/statusReturns JSON with all status information.
ssh kickpi@192.168.0.102 "curl -s http://localhost:5000/api/stay_alive/status | python3 -m json.tool"| Endpoint | Method | Description |
|---|---|---|
/api/stay_alive/status |
GET | Get current monitor status and statistics |
/api/stay_alive/start |
POST | Start the network monitor |
/api/stay_alive/stop |
POST | Stop the network monitor |
/api/stay_alive/test_connection |
GET | Test network connectivity now |
/api/stay_alive/logs |
GET | Get all stay-alive log entries |
To change the stay-alive settings, edit flask_app.py:
nano ~/AllSkyCode/flask_app.pyFind the section starting with # ==================== STAY-ALIVE CONSTANTS ==================== and modify the values.
After making changes, restart the service:
sudo systemctl restart allskyhydeTo disable the network monitor, you can either:
-
Via API (temporary - until next restart):
curl -X POST http://localhost:5000/api/stay_alive/stop
-
Permanently: Edit
flask_app.pyand change:stay_alive_enabled = False # Change from True to False
The application creates two log files in the installation directory:
- gunicorn-access.log - HTTP access logs (all requests)
- gunicorn-error.log - Application errors and output
View logs:
tail -f ~/AllSkyHyde/gunicorn-error.log
tail -f ~/AllSkyHyde/gunicorn-access.log- app_config.json - Application settings (location, API keys, capture settings)
- requirements.txt - Python dependencies
By default, the application runs on port 5000.
To change the port:
- Edit the service file:
sudo nano /etc/systemd/system/allskyhyde.service - Change the
--bind 0.0.0.0:5000line to your desired port - Reload and restart:
sudo systemctl daemon-reload sudo systemctl restart allskyhyde
If you have a firewall enabled, allow port 5000:
# For UFW (Ubuntu/Debian)
sudo ufw allow 5000/tcp
# For firewalld (CentOS/RHEL)
sudo firewall-cmd --permanent --add-port=5000/tcp
sudo firewall-cmd --reloadTo remove the service:
cd /home/yourusername/AllSkyHyde
./uninstall_production.shThe uninstall script will:
- Stop and disable the service
- Remove the systemd service file
- Optionally remove sudo configuration
- Optionally remove logs and config files
- Optionally remove Python virtual environment
Note: Image files in ~/allsky_images are NOT removed automatically.
The installation includes several helper scripts:
install_production.sh- Main installation scriptuninstall_production.sh- Complete removal scriptfix_venv.sh- Fix virtual environment issues (WSL/Windows compatibility)fix_paths.sh- Fix hardcoded paths in configuration file
If you moved the installation directory or see path-related errors, run:
cd ~/AllSkyHyde
./fix_paths.shThis will update app_config.json with the correct paths based on your current directory.
If you see an error like /home/user/AllSkyHyde/venv/bin/pip: No such file or directory:
This happens when you have a Windows-style virtual environment on WSL. The installation script will automatically detect and fix this, or you can run:
cd ~/AllSkyHyde
./fix_venv.shThis will recreate the virtual environment for Linux.
Check the service status:
sudo systemctl status allskyhydeView recent errors:
sudo journalctl -u allskyhyde -n 50 --no-pagerCheck error log:
tail -n 50 ~/AllSkyHyde/gunicorn-error.logEnsure the installation directory is owned by your user:
ls -la ~/AllSkyHydeFix permissions if needed:
sudo chown -R $USER:$USER ~/AllSkyHydeReinstall dependencies:
cd ~/AllSkyHyde
source venv/bin/activate
pip install -r requirements.txtCheck what's using port 5000:
sudo lsof -i :5000Kill the process or change the port in the service file.
-
Verify service is running:
sudo systemctl status allskyhyde
-
Check if port is listening:
sudo netstat -tlnp | grep 5000 -
Test locally:
curl http://localhost:5000
-
Check firewall settings
-
Verify IP address:
hostname -I
To upgrade after pulling new code:
cd ~/AllSkyHyde
git pull # if using git
sudo systemctl restart allskyhydeIf new dependencies were added:
source venv/bin/activate
pip install -r requirements.txt
sudo systemctl restart allskyhydeEdit the service file to tune Gunicorn:
sudo nano /etc/systemd/system/allskyhyde.serviceGuidelines:
- Workers: (2 x CPU cores) + 1
- Threads: 2-4 per worker
- Timeout: Increase if captures take longer
Example for Raspberry Pi 4 (4 cores):
--workers 4
--threads 4
--timeout 180
After changes:
sudo systemctl daemon-reload
sudo systemctl restart allskyhyde- Sudo Configuration: Only enable if you trust all users who can access the web interface
- Firewall: Consider restricting access to port 5000 to your local network
- HTTPS: For remote access, consider using a reverse proxy (nginx) with HTTPS
- Updates: Keep your system and Python packages updated
For production deployments, consider using Nginx as a reverse proxy:
-
Install Nginx:
sudo apt-get install nginx
-
Create Nginx configuration:
sudo nano /etc/nginx/sites-available/allskyhyde
-
Add configuration:
server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
-
Enable and restart:
sudo ln -s /etc/nginx/sites-available/allskyhyde /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx
If you encounter issues:
- Check the troubleshooting section above
- Review log files for error messages
- Ensure all prerequisites are met
- Verify file permissions
- Gunicorn Documentation: https://docs.gunicorn.org/
- systemd Documentation: https://www.freedesktop.org/wiki/Software/systemd/
- Flask Deployment: https://flask.palletsprojects.com/en/latest/deploying/