Install and configure Hypercorn ASGI server with systemd and reverse proxy for Python web applications

Beginner 25 min Apr 17, 2026 13 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Deploy Python ASGI applications with Hypercorn server, systemd service management, and Nginx reverse proxy for production environments. Complete setup with SSL termination and performance optimization.

Prerequisites

  • Root or sudo access
  • Python 3.8 or higher
  • Basic understanding of web servers

What this solves

Hypercorn is a high-performance ASGI server for Python web applications like FastAPI, Django, and Quart. This tutorial shows you how to deploy ASGI applications with Hypercorn behind an Nginx reverse proxy, manage it with systemd, and configure SSL termination for production environments.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you have the latest versions available.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install Python and pip

Install Python 3 and pip package manager if not already installed.

sudo apt install -y python3 python3-pip python3-venv
sudo dnf install -y python3 python3-pip python3-venv

Create application user and directory

Create a dedicated user to run your application for security isolation.

sudo useradd --system --shell /bin/false --home /opt/myapp myapp
sudo mkdir -p /opt/myapp
sudo chown myapp:myapp /opt/myapp

Create sample FastAPI application

Create a basic FastAPI application to demonstrate the setup.

sudo -u myapp mkdir -p /opt/myapp/app
sudo -u myapp python3 -m venv /opt/myapp/venv
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI(title="Sample API", version="1.0.0")

@app.get("/")
async def read_root():
    return JSONResponse(content={"message": "Hello from Hypercorn!", "status": "running"})

@app.get("/health")
async def health_check():
    return JSONResponse(content={"status": "healthy"})

@app.get("/info")
async def app_info():
    return JSONResponse(content={
        "app": "Sample FastAPI Application",
        "server": "Hypercorn ASGI",
        "version": "1.0.0"
    })

Install Hypercorn and dependencies

Install Hypercorn and FastAPI in the virtual environment.

sudo -u myapp /opt/myapp/venv/bin/pip install --upgrade pip
sudo -u myapp /opt/myapp/venv/bin/pip install hypercorn fastapi uvloop

Create Hypercorn configuration file

Configure Hypercorn with production-ready settings for performance and security.

[hypercorn]
bind = "127.0.0.1:8000"
workers = 4
worker_class = "asyncio"
backlog = 2048
max_requests = 1000
max_requests_jitter = 100
preload_app = true
timeout = 120
keepalive_timeout = 2
max_concurrent = 1000
logger_class = "hypercorn.logging.Config"
accesslog = "/var/log/myapp/access.log"
errorlog = "/var/log/myapp/error.log"
loglevel = "info"
use_reloader = false

SSL settings (uncomment for direct SSL)

certfile = "/etc/ssl/certs/example.com.pem"

keyfile = "/etc/ssl/private/example.com.key"

Security settings

server_name = "Hypercorn" max_buffer_size = 16384 h11_max_incomplete_size = 16384

Create log directory

Create the log directory with proper permissions for the application user.

sudo mkdir -p /var/log/myapp
sudo chown myapp:myapp /var/log/myapp
sudo chmod 755 /var/log/myapp

Create systemd service file

Configure systemd to manage the Hypercorn process with proper resource limits and security settings.

[Unit]
Description=Hypercorn ASGI Server for MyApp
After=network.target
Requires=network.target

[Service]
Type=exec
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
Environment=PATH=/opt/myapp/venv/bin
Environment=PYTHONPATH=/opt/myapp/app
ExecStart=/opt/myapp/venv/bin/hypercorn --config /opt/myapp/hypercorn.toml app.main:app
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/myapp
NoNewPrivileges=true
User=myapp
Group=myapp

Resource limits

LimitNOFILE=65536 LimitNPROC=32768

Restart policy

Restart=always RestartSec=1 StartLimitBurst=3 StartLimitIntervalSec=60 [Install] WantedBy=multi-user.target

Set file ownership and permissions

Ensure all application files have correct ownership and secure permissions.

sudo chown -R myapp:myapp /opt/myapp
sudo chmod -R 755 /opt/myapp
sudo chmod 644 /opt/myapp/hypercorn.toml
sudo chmod 644 /opt/myapp/app/main.py
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions like 755 for directories and 644 for files.

Install and configure Nginx

Install Nginx to act as a reverse proxy with SSL termination and load balancing.

sudo apt install -y nginx
sudo dnf install -y nginx

Configure Nginx reverse proxy

Create an Nginx virtual host configuration with caching, compression, and security headers.

upstream hypercorn_backend {
    server 127.0.0.1:8000;
    keepalive 32;
}

server {
    listen 80;
    server_name example.com www.example.com;
    
    # Security headers
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options DENY;
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy "strict-origin-when-cross-origin";
    
    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    
    # Client body size limit
    client_max_body_size 16M;
    
    # Timeouts
    proxy_connect_timeout 30s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
    
    location / {
        proxy_pass http://hypercorn_backend;
        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;
        
        # Connection settings
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # Buffer settings
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
    
    location /health {
        proxy_pass http://hypercorn_backend/health;
        access_log off;
    }
    
    location /static {
        alias /opt/myapp/static;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    
    # Log files
    access_log /var/log/nginx/myapp_access.log;
    error_log /var/log/nginx/myapp_error.log;
}

Enable Nginx site

Enable the site configuration and test the Nginx configuration.

sudo ln -sf /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t

Configure log rotation

Set up log rotation to prevent log files from growing too large.

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    create 0644 myapp myapp
    postrotate
        systemctl reload myapp
    endscript
}

Start and enable services

Enable both services to start automatically on boot and start them now.

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl enable --now nginx
sudo systemctl status myapp
sudo systemctl status nginx

Performance tuning

Optimize Hypercorn workers

Adjust worker count based on your server's CPU cores. The general rule is (CPU cores × 2) + 1.

nproc

If you have 4 cores, use 9 workers

sudo sed -i 's/workers = 4/workers = 9/' /opt/myapp/hypercorn.toml

Configure system limits

Increase system limits for file descriptors and processes to handle more concurrent connections.

myapp soft nofile 65536
myapp hard nofile 65536
myapp soft nproc 32768
myapp hard nproc 32768

Optimize kernel parameters

Tune kernel network parameters for better performance with high connection loads.

net.core.somaxconn = 65536
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 120
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
sudo sysctl -p /etc/sysctl.d/99-myapp.conf

SSL configuration

Install Certbot for SSL certificates

Install Certbot to automatically obtain and renew SSL certificates from Let's Encrypt.

sudo apt install -y certbot python3-certbot-nginx
sudo dnf install -y certbot python3-certbot-nginx

Obtain SSL certificate

Get an SSL certificate for your domain. Replace example.com with your actual domain.

sudo certbot --nginx -d example.com -d www.example.com

Monitoring setup

Create monitoring script

Create a simple monitoring script to check application health and restart if needed.

#!/bin/bash

Health check endpoint

HEALTH_URL="http://127.0.0.1:8000/health" MAX_RETRIES=3 RETRY_DELAY=5 for i in $(seq 1 $MAX_RETRIES); do if curl -f -s --max-time 10 "$HEALTH_URL" > /dev/null; then echo "$(date): Application is healthy" exit 0 fi echo "$(date): Health check failed (attempt $i/$MAX_RETRIES)" if [ $i -lt $MAX_RETRIES ]; then sleep $RETRY_DELAY fi done echo "$(date): Application unhealthy, restarting service" logger "myapp: Health check failed, restarting service" sudo systemctl restart myapp exit 1
sudo chmod +x /opt/myapp/monitor.sh
sudo chown myapp:myapp /opt/myapp/monitor.sh

Schedule monitoring with cron

Set up a cron job to run the health check every 5 minutes.

sudo crontab -u myapp -e

Add this line to the crontab:

/5    * /opt/myapp/monitor.sh >> /var/log/myapp/monitor.log 2>&1

Verify your setup

Test your Hypercorn deployment with these verification commands:

# Check service status
sudo systemctl status myapp
sudo systemctl status nginx

Test application directly

curl -i http://127.0.0.1:8000/ curl -i http://127.0.0.1:8000/health

Test through Nginx proxy

curl -i http://your-domain.com/ curl -i http://your-domain.com/health

Check logs

sudo tail -f /var/log/myapp/access.log sudo tail -f /var/log/myapp/error.log sudo tail -f /var/log/nginx/myapp_access.log

Verify SSL (if configured)

openssl s_client -connect your-domain.com:443 -servername your-domain.com

Test worker processes

ps aux | grep hypercorn

Check listening ports

sudo netstat -tlnp | grep -E ':80|:443|:8000'

Common issues

SymptomCauseFix
Service fails to startPermission denied or missing filesCheck sudo journalctl -u myapp and verify file ownership with sudo chown -R myapp:myapp /opt/myapp
502 Bad GatewayHypercorn not running or wrong portVerify service with sudo systemctl status myapp and check port binding in config
High memory usageToo many workers for available RAMReduce workers in /opt/myapp/hypercorn.toml and restart service
Slow response timesInsufficient worker processesIncrease workers to (CPU cores × 2) + 1 in configuration file
Log permission errorsWrong log directory ownershipFix with sudo chown -R myapp:myapp /var/log/myapp
SSL certificate errorsExpired or missing certificatesRenew with sudo certbot renew --dry-run
Connection refused errorsFirewall blocking portsCheck firewall rules and ensure ports 80 and 443 are open

For additional troubleshooting, check our guide on fixing systemd service restart loops or managing systemd services.

Next steps

Running this in production?

Want this handled for you? Setting this up once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed cloud infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.