# Deploying mini-shop-server with Gunicorn: Production Structure and Configuration

> Learn to deploy mini-shop-server with Gunicorn. Discover the production structure, Supervisor process management, and Nginx reverse proxy configuration for a robust Flask application.

- Repository: [A粒麦子/mini-shop-server](https://github.com/allen7d/mini-shop-server)
- Tags: architecture
- Published: 2026-02-24

---

**The mini-shop-server uses a Flask application factory pattern where [`server.py`](https://github.com/allen7d/mini-shop-server/blob/main/server.py) exposes a WSGI-compatible `app` object, loads production configuration from [`app/config/secure.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/secure.py) via the `ENV_MODE` environment variable, and runs under Gunicorn with process management through Supervisor and reverse-proxying via Nginx.**

The **mini-shop-server** by allen7d is a Flask-based RESTful API designed for production scalability through clean separation of configuration and the WSGI server interface. Understanding its directory structure and deployment pipeline is essential for reliable production hosting behind reverse proxies.

## Project Structure and Application Factory

The repository follows the **application factory** pattern, centralizing application initialization in [`app/__init__.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/__init__.py) while exposing a standard WSGI entry point through [`server.py`](https://github.com/allen7d/mini-shop-server/blob/main/server.py).

### Entry Point and WSGI Interface

The [`server.py`](https://github.com/allen7d/mini-shop-server/blob/main/server.py) file serves as the minimal bootstrap script that Gunicorn imports as a module. It calls `create_app()` and exposes the resulting Flask instance as the `app` variable:

```python

# app/__init__.py (lines 24-34)

def create_app():
    app = Flask(__name__, static_folder="./static", template_folder="./templates")
    load_config(app)          # ← chooses secure or local config based on ENV_MODE

    register_blueprint(app)   # ← registers all API blueprints

    register_plugin(app)      # ← installs JSON encoder, CORS, DB, error handling, etc.

    return app

```

When launching Gunicorn with the pattern `server:app`, the server imports [`server.py`](https://github.com/allen7d/mini-shop-server/blob/main/server.py), triggering `create_app()` to instantiate the fully configured Flask application.

### Environment-Based Configuration

The `load_config()` function dynamically selects configuration classes based on the `ENV_MODE` environment variable:

```python

# app/__init__.py (lines 35-42)

def load_config(app):
    if os.environ.get('ENV_MODE') == 'dev:local':
        app.config.from_object('app.config.local_secure')
        app.config.from_object('app.config.local_setting')
    else:
        app.config.from_object('app.config.secure')
        app.config.from_object('app.config.setting')

```

For production deployments, set `ENV_MODE` to any value other than `dev:local` (such as `prod`) to force loading of **production-grade settings** from [`app/config/secure.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/secure.py). This file contains critical production parameters including `DEBUG = False`, database connection URIs, and secret keys.

## Gunicorn Configuration and Dependencies

The project pins **Gunicorn** as a core dependency and provides specific launch patterns optimized for both direct execution and process manager integration.

### Dependency Declaration

Gunicorn is explicitly declared in the project manifest:

```toml

# pyproject.toml (line 29)

"gunicorn==21.2.0",

```

This ensures consistent WSGI server behavior across environments when using `uv` as the package manager.

### WSGI Entry Point Specification

The standard Gunicorn invocation uses the `server:app` pattern, where:
- **module**: `server` (referencing [`server.py`](https://github.com/allen7d/mini-shop-server/blob/main/server.py))
- **callable**: `app` (the Flask instance returned by `create_app()`)

### Worker and Binding Options

The repository README documents two primary binding strategies. For direct TCP binding during testing or containerized deployments:

```bash

# README.md (lines 36-45)

uv run gunicorn -w 4 -b 127.0.0.1:8080 server:app

```

For high-performance production deployments behind Nginx, use a **Unix domain socket** to avoid TCP overhead:

```bash

# Example from README (lines 55-61)

uv run gunicorn -w 4 -b unix:/home/workspace/mini-shop-server/server.sock server:app

```

The `-w 4` flag initializes four worker processes. Adjust this value based on available CPU cores using `$(nproc)` for optimal request handling.

## Production Process Management with Supervisor and Nginx

Running Gunicorn directly is insufficient for production reliability; the project integrates with **Supervisor** for process supervision and **Nginx** for static file serving and reverse proxying.

### Supervisor Configuration

The README provides a complete Supervisor program definition that ensures automatic restarts and log management:

```ini
[program:server]
environment=PATH='/root/.local/share/virtualenvs/server-4o3oDD8t/bin/python'
command = /root/.local/share/virtualenvs/server-4o3oDD8t/bin/gunicorn -w 4 -b unix:/home/workspace/morning-star/server/server.sock server:app
directory = /home/workspace/morning-star/server
user = root

```

This configuration binds Gunicorn to a Unix socket at `server.sock`, monitors process health, and redirects logs to `/tmp/blog_*` files.

### Nginx Reverse Proxy Setup

Nginx handles client connections and forwards dynamic requests to the Gunicorn socket while serving static assets directly:

```nginx

# README.md (lines 28-34)

location / {
    include proxy_params;
    proxy_pass http://unix:/home/workspace/mini-shop-server/server.sock;
    ...
}
location /static/ {
    alias /home/workspace/mini-shop-server/app/static/;
}

```

The `proxy_pass` directive targets the Unix socket path defined in the Supervisor command, creating a secure, high-throughput connection between the web server and the Flask application.

## Step-by-Step Production Deployment

Follow this sequence to deploy the mini-shop-server on a production host:

1. **Clone the repository and enter the directory:**

   ```bash
   git clone https://github.com/Allen7D/mini-shop-server.git
   cd mini-shop-server
   ```

2. **Install the `uv` package manager if not present:**

   ```bash
   curl -LsSf https://astral.sh/uv/install.sh | sh
   ```

3. **Synchronize dependencies including Gunicorn:**

   ```bash
   uv sync
   ```

4. **Configure the production environment:**

   ```bash
   export ENV_MODE=prod
   export FLASK_APP=server.py
   # Database credentials should be set via environment variables or hardcoded in secure.py

   ```

5. **Launch with Gunicorn via process manager or directly:**

   ```bash
   # Direct launch (development or Docker)

   uv run gunicorn -w 4 -b 0.0.0.0:8080 server:app
   
   # Production launch with Unix socket (use with Supervisor)

   uv run gunicorn -w 4 -b unix:/opt/mini-shop/server.sock server:app
   ```

6. **Configure Nginx** to proxy to the Unix socket and serve static files from `app/static/`.

## Summary

- The **application factory** pattern in [`app/__init__.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/__init__.py) centralizes Flask app creation, while [`server.py`](https://github.com/allen7d/mini-shop-server/blob/main/server.py) exposes the WSGI entry point as `app`.
- **Environment-based configuration** loads [`app/config/secure.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/secure.py) when `ENV_MODE` is set to production values, ensuring `DEBUG=False` and secure credentials.
- **Gunicorn** is pinned in [`pyproject.toml`](https://github.com/allen7d/mini-shop-server/blob/main/pyproject.toml) and invoked via `uv run gunicorn -w 4 server:app`, supporting both TCP and Unix socket bindings.
- **Supervisor** manages the Gunicorn process lifecycle, binding to Unix sockets for Nginx integration.
- **Nginx** serves as the reverse proxy and static file server, completing the production stack.

## Frequently Asked Questions

### How does mini-shop-server handle different configuration environments?

The `load_config()` function in [`app/__init__.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/__init__.py) checks the `ENV_MODE` environment variable. When set to `dev:local`, it loads development settings; otherwise, it loads production configuration from [`app/config/secure.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/secure.py) and [`app/config/setting.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/setting.py). This allows the same codebase to run in development and production modes without code changes.

### What is the correct Gunicorn command for production deployment behind Nginx?

Use the Unix socket binding with multiple workers: `uv run gunicorn -w 4 -b unix:/path/to/server.sock server:app`. This command creates four worker processes and binds to a filesystem socket, which Nginx proxies via the `proxy_pass http://unix:/path/to/server.sock;` directive. Unix sockets provide better performance than TCP loops for local reverse proxying.

### Where are the production secrets and database credentials stored?

Production secrets reside in [`app/config/secure.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/secure.py), which is loaded when `ENV_MODE` is not set to `dev:local`. This file should contain `DEBUG = False`, SQLAlchemy database URIs, and secret keys. For containerized deployments, override these values using environment variables that Flask's configuration system reads at runtime.

### Why is Supervisor recommended for running Gunicorn in production?

Supervisor ensures the Gunicorn process remains active through server reboots and application crashes. According to the repository's README, the Supervisor configuration specifies the Gunicorn command, working directory, user permissions, and log file locations. This eliminates the need for manual restarts and provides centralized logging for the WSGI server output.