How to run FastAPI on apache2?
Asked Answered
D

3

8

I've developed an api using fastapi that will act as a wrapper that receives sms requests and call the sms api to send said sms and now I'm ready to deploy it. This is the code:

import logging

import uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from fastapi.middleware.trustedhost import TrustedHostMiddleware

import verifier

logging.basicConfig(
    format='%(asctime)s - %(funcName)s - %(levelname)s - %(message)s',
    level=logging.INFO
)

# get logger
logger = logging.getLogger(__name__)


bot_verifier = None


class DataForBot(BaseModel):
    number: str
    msg_txt: str


def get_application():
    app = FastAPI(title='bot_wrapper', version="1.0.0")

    return app


app = get_application()


@app.on_event("startup")
async def startup_event():
    global bot_verifier
    try:
        bot_verifier = await verifier.Verifier.create()
    except Exception as e:
        logger.error(f"exception occured during bot creation -- {e}", exc_info=True)


@app.post('/telegram_sender/')
async def send_telegram_msg(data_for_bot: DataForBot):
    global bot_verifier
    if not bot_verifier:
        bot_verifier = await verifier.Verifier.create()
    else:
        dict_data = data_for_bot.dict()
        try:
            if await bot_verifier.send_via_telegram(dict_data):
                return {'status': "success", 'data': data_for_bot}
            else:
                raise HTTPException(status_code=404, detail="unable to send via telegram, perhaps user has not started the bot")
        except Exception as e:
            logger.error(f"{e}", exc_info=True)
            raise HTTPException(status_code=500, detail="Something went wrong, please contact server admin")

I want to deploy it on apache b/c it's the only thing I can get my hand onto in my country. I'm using python3.8.9 with fastapi version 0.65.2 and apache/2.4.29, but for the life of me I can't get it to work. I've written an apache conf file and enabled that as such:

<VirtualHost *:80>
    ServerName gargarsa.sms.local
    ServerAdmin webmaster@localhost
    ServerAlias gargarsa.sms.local
    
    DocumentRoot /var/www/verify_bot_api/
    ServerAlias gargarsa.sms.local

    <Directory /var/www/verify_bot_api/src/app/>
        Order deny,allow
        Allow from all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/gargarsa.sms.local-error.log
    LogLevel debug
    CustomLog ${APACHE_LOG_DIR}/gargarsa.sms.local-access.log combined
</VirtualHost>

but no avail.

I tried running gunicorn via a screen session but I couldn't access it either.

I tried running it programmatically as such but no avail:

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

I understand this is a very broad way to ask, but I'm truly stumped.

How do I run an api built using fastapi on Apache2?

Thank you for your assistance.

Disinfect answered 29/6, 2021 at 15:35 Comment(0)
D
16

Just incase anybody else stumbles on here, this is what I did and this is how it worked for me. This came about b/c there was not a lot of information on the web -- that I could find -- in regards to deploying fastapi on linux -- specifically ubuntu 18.04.4 -- with apache2 and no other things. When I say no other thing, I mean docker, caddy, or whatever of the sorts.

The usual things must be done before hand, these are:

  1. create the db the api will use
  2. install the virtual environment
  3. install the necessary dependencies from requirements.txt
  4. either scp or clone from github the production code of the api
  5. place the production code of the api in the /var/www/
  6. you can use gunicorn to be the actual server while apache is a reverse proxy that can connect you to it (remember to cd into the actual directory that contains the module 1st also to use screen with it)
  7. set up apache2 as a reverse proxy by "a2enmod proxy proxy_ajp proxy_http rewrite deflate headers proxy_balancer proxy_connect proxy_html"
  8. actually type up the server conf file and enable it (sample provided at the bottom)
  9. ALLWAYS MAKE BACKUPS

Reference: https://www.vioan.eu/blog/2016/10/10/deploy-your-flask-python-app-on-ubuntu-with-apache-gunicorn-and-systemd/

Functioning Sample apache conf file:

<VirtualHost *:80>
    # The ServerName directive sets the request scheme, hostname and port that
    # the server uses to identify itself. This is used when creating
    # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request's Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
    #ServerName www.example.com

    ServerName server-name
    ServerAdmin webmaster@localhost
    ServerAlias server-alias
    
    #DocumentRoot /document/root/

    <Proxy *>
        AuthType none
        AuthBasicAuthoritative Off
        SetEnv proxy-chain-auth On
        Order allow,deny
        Allow from all
    </Proxy>

    ProxyPass / http://127.0.0.1:port/
    ProxyPassReverse / http://127.0.0.1:port/
    #ProxyPass /api http://127.0.0.1:port/api
    #ProxyPassReverse /api http://127.0.0.1:port/api

    <Directory /document/root/>
        Order deny,allow
        Allow from all
    </Directory>

    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    # error, crit, alert, emerg.
    # It is also possible to configure the loglevel for particular
    # modules, e.g.
    #LogLevel info ssl:warn

    ErrorLog ${APACHE_LOG_DIR}/server-error.log
    LogLevel debug
    CustomLog ${APACHE_LOG_DIR}/server-access.log combined

    # For most configuration files from conf-available/, which are
    # enabled or disabled at a global level, it is possible to
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with "a2disconf".
    #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

To run the actual api:

gunicorn api:app -w 1 -k uvicorn.workers.UvicornWorker -b "127.0.0.1:port"

Edit: I have not placed any security mechanism at all here

Disinfect answered 29/6, 2021 at 19:37 Comment(3)
Someone can help me with this error? !!! !!! WARNING: configuration file should have a valid Python extension. !!!Plunge
@MESABO without seeing your code, I can only guess. Perhaps it can't find the python path? or it can't find your virtual environment?Disinfect
@MESABO and it's best to ask your own question instead of commenting on anotherDisinfect
S
0

WSGI servers is not compatible with FastAPI, FastAPI only runs in ASGI server, gunicorn and all the other WSGI servers just implements PEP Standards with ASGI workers in depth they still work as ASGI with the workers.

Sonora answered 29/6, 2021 at 19:53 Comment(1)
Can you please explain this? I understand that FastAPI will not run on WSGI servers and only run on ASGI servers. What I dont understand is what you wrote about gunicorn, how it run FastAPIDisinfect
S
0

It should be possible using ASGIMiddleware that converts ASGI app to WSGI app e.g. with a2wsgi.

Please see the example at https://github.com/fnep/example_fastapi_behind_apache_using_wsgi

Sinhalese answered 3/6 at 22:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.