Debug School

rakesh kumar
rakesh kumar

Posted on • Edited on

How I Integrated Flask and Laravel on One Server Using Apache Reverse Proxy

Step1:Create one git hub repository

step2:give production path

    GCP_CREDENTIALS_JSON = "/opt/lampp/htdocs/motoshare.jp/motoshare-web/gcp-service.json"
Enter fullscreen mode Exit fullscreen mode

step3: git clone repository

git clone git@github.com:Motosharein/motoshare_flask.git
Enter fullscreen mode Exit fullscreen mode

Also install system dependencies in Linux server

sudo apt-get update
sudo apt-get install -y tesseract-ocr libtesseract-dev
Enter fullscreen mode Exit fullscreen mode

Check binary path:

which tesseract

Should return:

/usr/bin/tesseract
Enter fullscreen mode Exit fullscreen mode

Install python
specific version

sudo apt update
sudo apt install python3-pip -y
Enter fullscreen mode Exit fullscreen mode

Check python version

python3 --version
apt install python3.12-venv
Enter fullscreen mode Exit fullscreen mode

Use Python 3.12 safely (venv)

# Check 3.12 exists
which python3.12 || sudo apt install -y python3.12 python3.12-venv

# Create venv with 3.12
cd /opt/lampp/htdocs/motoshare_flask
python3.12 -m venv venv
source venv/bin/activate

# Verify you're inside the venv
which python
python --version

# Install deps inside the venv
pip install --upgrade pip
pip install -r requirements.txt


pip install gunicorn

# 4A) run with gunicorn (recommended)
gunicorn --bind 127.0.0.1:5000 "app:create_app()"
Enter fullscreen mode Exit fullscreen mode

sudo apt install -y libgl1 libglib2.0-0 libsm6 libxext6 libxrender1
Enter fullscreen mode Exit fullscreen mode

Notes

See what your module actually exposes

Run this in your project folder:

cd /opt/lampp/htdocs/motoshare.jp/motoshare_flask
source venv/bin/activate
python -c "import app; print('attrs:', [a for a in dir(app) if a in ('app','application','create_app')])"
Enter fullscreen mode Exit fullscreen mode

Virtual host setup
http_vhost

<VirtualHost *:80>
    ServerName motoshare.jp
    ServerAlias www.motoshare.jp
    DocumentRoot "/opt/lampp/htdocs/motoshare.jp/motoshare-web/public"

    # ...your existing Directory + Alias blocks...

    # --- Proxy /image/* to Flask on localhost:5000 ---
    ProxyRequests Off
    ProxyPreserveHost On

    # Put these BEFORE any other ProxyPass lines; keep trailing slashes
    ProxyPass        /image/ http://127.0.0.1:5000/image/
    ProxyPassReverse /image/ http://127.0.0.1:5000/image/

    # No X-Forwarded-Prefix or Location rewrites (prevents double prefix)
    ProxyTimeout 120
    Timeout 120
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

httpd-ssl.conf

<VirtualHost *:443>
    ServerName motoshare.jp
    ServerAlias www.motoshare.jp
    DocumentRoot "/opt/lampp/htdocs/motoshare.jp/motoshare-web/public"

    SSLEngine On
    SSLCertificateFile      "/opt/lampp/etc/certs/motoshare.jp/motoshare.jp.cer"
    SSLCertificateKeyFile   "/opt/lampp/etc/certs/motoshare.jp/motoshare.jp.key"
    SSLCACertificateFile    "/opt/lampp/etc/certs/motoshare.jp/fullchain.cer"

    # ...your existing Directory + Alias blocks...

    # --- Proxy /image/* to Flask on localhost:5000 ---
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass        /image/ http://127.0.0.1:5000/image/
    ProxyPassReverse /image/ http://127.0.0.1:5000/image/
    ProxyTimeout 120
    Timeout 120
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

Run it directly in your Ubuntu server terminal (SSH or local):

# paths you already use 
APP_DIR=/opt/lampp/htdocs/motoshare.jp/motoshare_flask
VENV=$APP_DIR/venv

# write the unit file
sudo bash -c 'cat >/etc/systemd/system/motoshare-flask.service' <<EOF
[Unit]
Description=MotoShare Flask (Gunicorn)
After=network-online.target
Wants=network-online.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=$APP_DIR

Environment=FLASK_ENV=production
Environment=UPLOAD_FOLDER=$APP_DIR/uploads
Environment=GOOGLE_APPLICATION_CREDENTIALS=/opt/lampp/htdocs/motoshare-web/gcp-service.json
Environment=TESSERACT_CMD=/usr/bin/tesseract
Environment=SECRET_KEY=change-me-to-a-strong-secret

ExecStart=$VENV/bin/gunicorn --workers 2 --bind 127.0.0.1:5000 "app:create_app()"
Restart=always

[Install]
WantedBy=multi-user.target
EOF

Enter fullscreen mode Exit fullscreen mode

After creating the file, run:

sudo systemctl daemon-reload
sudo systemctl enable motoshare-flask
sudo systemctl start motoshare-flask
sudo systemctl status motoshare-flask --no-pager
Enter fullscreen mode Exit fullscreen mode

To see live logs:

sudo journalctl -u motoshare-flask -f
Enter fullscreen mode Exit fullscreen mode

Give Permission

sudo chown -R www-data:www-data /opt/lampp/htdocs/motoshare.jp/motoshare_flask/uploads

# keep it secure but writable: setgid bit so new files inherit the group
sudo chmod 2775 /opt/lampp/htdocs/motoshare.jp/motoshare_flask/uploads
# if you want to be extra sure:
sudo find /opt/lampp/htdocs/motoshare.jp/motoshare_flask/uploads -type d -exec chmod 2775 {} \;
sudo find /opt/lampp/htdocs/motoshare.jp/motoshare_flask/uploads -type f -exec chmod 664 {} \;
Enter fullscreen mode Exit fullscreen mode

In env

IMAGE_API_BASE=https://motoshare.jp
IMAGE_API_TIMEOUT=20
GOOGLE_APPLICATION_CREDENTIALS=/opt/lampp/htdocs/motoshare-web/gcp-service.json
Enter fullscreen mode Exit fullscreen mode

In services.php

 'image' => [
        // use public domain (HTTPS) in production
        'base_url' => env('IMAGE_API_BASE', 'https://motoshare.jp'),
        'timeout'  => env('IMAGE_API_TIMEOUT', 30),
        // keep the exact Flask route path
        'qr_path'  => env('IMAGE_API_QR_PATH', '/image/qr/scan'),
    ],
Enter fullscreen mode Exit fullscreen mode

finally check:

https://motoshare.jp/image/hello
Enter fullscreen mode Exit fullscreen mode

===========================================================
if my route
C:\IMAGE_VERIFICATION\views_init_.py

Case A — Only /image

Flask


# C:\IMAGE_VERIFICATION\views\__init__.py
from .image_views import image_bp

def register_blueprints(app):
    app.register_blueprint(image_bp, url_prefix="/image")
Enter fullscreen mode Exit fullscreen mode

Apache vhost (works exactly as you wrote)

<VirtualHost *:80>
    ServerName motoshare.jp
    ServerAlias www.motoshare.jp
    DocumentRoot "/opt/lampp/htdocs/motoshare.jp/motoshare-web/public"

    ProxyRequests Off
    ProxyPreserveHost On

    ProxyPass        /image/ http://127.0.0.1:5000/image/
    ProxyPassReverse /image/ http://127.0.0.1:5000/image/

    ProxyTimeout 120
    Timeout 120
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

Case B — /image and /machinelearning

Flask

# in __init__.py
from .image_views import image_bp

def register_blueprints(app):
    app.register_blueprint(image_bp, url_prefix="/image")
    app.register_blueprint(image_bp, url_prefix="/machinelearning")  # ensure spelling
Enter fullscreen mode Exit fullscreen mode

Note: If Flask complains about registering the same blueprint twice, create a second blueprint instance with a different name:

from flask import Blueprint
from .image_views import image_bp as _image_bp

image_bp_ml = Blueprint("image_bp_ml", __name__)
image_bp_ml.deferred_functions = _image_bp.deferred_functions  # reuse routes/handlers

def register_blueprints(app):
    app.register_blueprint(_image_bp, url_prefix="/image")
    app.register_blueprint(image_bp_ml, url_prefix="/machinelearning")
Enter fullscreen mode Exit fullscreen mode

Apache vhost

<VirtualHost *:80>
    ServerName motoshare.jp
    ServerAlias www.motoshare.jp
    DocumentRoot "/opt/lampp/htdocs/motoshare.jp/motoshare-web/public"

    ProxyRequests Off
    ProxyPreserveHost On

    # /image/*
    ProxyPass        /image/ http://127.0.0.1:5000/image/
    ProxyPassReverse /image/ http://127.0.0.1:5000/image/

    # /machinelearning/*
    ProxyPass        /machinelearning/ http://127.0.0.1:5000/machinelearning/
    ProxyPassReverse /machinelearning/ http://127.0.0.1:5000/machinelearning/

    ProxyTimeout 120
    Timeout 120
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)