├── README.md ├── app ├── __init__.py ├── __pycache__ │ └── __init__.cpython-311.pyc ├── configuration │ ├── __pycache__ │ │ ├── api_answers.cpython-311.pyc │ │ └── server.cpython-311.pyc │ ├── api_answers.py │ ├── routes │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-311.pyc │ │ │ └── routes.cpython-311.pyc │ │ └── routes.py │ └── server.py ├── internal │ ├── events │ │ ├── __pycache__ │ │ │ └── startup.cpython-311.pyc │ │ └── startup.py │ └── routes │ │ ├── __pycache__ │ │ └── user.cpython-311.pyc │ │ └── user.py └── pkg │ ├── __init__.py │ ├── __pycache__ │ └── __init__.cpython-311.pyc │ └── ssh_tools │ ├── __pycache__ │ └── ssh_tools.cpython-311.pyc │ └── ssh_tools.py ├── docker-compose.yaml └── docker ├── api └── Dockerfile └── redis └── Dockerfile /README.md: -------------------------------------------------------------------------------- 1 | # FastAPI App Structure Template 2 | 3 | [![Python 3.10](https://img.shields.io/badge/python-3.6+-green.svg)](https://www.python.org/downloads/release/python-360/)\ 4 | ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=for-the-badge&logo=fastapi) 5 | 6 | ##### You can learn more about this structure from this video 7 | 8 | [![Watch the video](https://img.youtube.com/vi/IpSRs6ZNA5k/0.jpg)](https://youtu.be/IpSRs6ZNA5k) 9 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | from app.configuration.server import Server 4 | 5 | 6 | def create_app(_=None) -> FastAPI: 7 | 8 | app = FastAPI() 9 | 10 | return Server(app).get_app() -------------------------------------------------------------------------------- /app/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /app/configuration/__pycache__/api_answers.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/configuration/__pycache__/api_answers.cpython-311.pyc -------------------------------------------------------------------------------- /app/configuration/__pycache__/server.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/configuration/__pycache__/server.cpython-311.pyc -------------------------------------------------------------------------------- /app/configuration/api_answers.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from dataclasses import dataclass 3 | 4 | @dataclass 5 | class servers_setup(): 6 | 7 | auth_failed_ip: str = 'Неверный ip сервера' 8 | auth_failed_pass: str = 'Неверный пароль от сервера' -------------------------------------------------------------------------------- /app/configuration/routes/__init__.py: -------------------------------------------------------------------------------- 1 | from app.configuration.routes.routes import Routes 2 | from app.internal.routes import user 3 | 4 | __routes__ = Routes(routers=(user.router, )) -------------------------------------------------------------------------------- /app/configuration/routes/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/configuration/routes/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /app/configuration/routes/__pycache__/routes.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/configuration/routes/__pycache__/routes.cpython-311.pyc -------------------------------------------------------------------------------- /app/configuration/routes/routes.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from fastapi import FastAPI 3 | 4 | 5 | @dataclass(frozen=True) 6 | class Routes: 7 | 8 | routers: tuple 9 | 10 | def register_routes(self, app: FastAPI): 11 | 12 | for router in self.routers: 13 | app.include_router(router) -------------------------------------------------------------------------------- /app/configuration/server.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi_utils.tasks import repeat_every 3 | from app.configuration.routes import __routes__ 4 | from app.internal.events.startup import test 5 | 6 | class Server: 7 | 8 | 9 | __app: FastAPI 10 | 11 | 12 | def __init__(self, app: FastAPI): 13 | 14 | self.__app = app 15 | self.__register_routes(app) 16 | self.__register_events(app) 17 | 18 | def get_app(self) -> FastAPI: 19 | 20 | return self.__app 21 | 22 | @staticmethod 23 | def __register_events(app): 24 | 25 | #app.on_event('startup')(repeat_every(seconds=2)(test)) 26 | ... 27 | 28 | @staticmethod 29 | def __register_routes(app): 30 | 31 | __routes__.register_routes(app) -------------------------------------------------------------------------------- /app/internal/events/__pycache__/startup.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/internal/events/__pycache__/startup.cpython-311.pyc -------------------------------------------------------------------------------- /app/internal/events/startup.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | async def test(): 4 | print('Hello') -------------------------------------------------------------------------------- /app/internal/routes/__pycache__/user.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/internal/routes/__pycache__/user.cpython-311.pyc -------------------------------------------------------------------------------- /app/internal/routes/user.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Body 2 | from fastapi.responses import JSONResponse 3 | from app.pkg.ssh_tools.ssh_tools import ( 4 | set_vpn_user, send_config_files, configurate_open_vpn, configurate_nginx 5 | ) 6 | from app.configuration.api_answers import servers_setup 7 | import asyncio 8 | from asyncio import sleep 9 | 10 | 11 | router = APIRouter( 12 | prefix='/api/v1' 13 | ) 14 | 15 | @router.get('/set_user') 16 | def set_user(): 17 | 18 | return { 19 | 'hello': 'world' 20 | } 21 | 22 | @router.get('/get_user_file') 23 | def get_user_file(data=Body()): 24 | 25 | return { 26 | 'hello': 'world' 27 | } 28 | 29 | @router.get('/get_users_list') 30 | def get_users_list(): 31 | 32 | return { 33 | 'hello': 'world' 34 | } 35 | 36 | @router.get('/setup_server') 37 | def setup_server(ip: str = Body(embed=True), root_pass: str = Body(embed=True)): 38 | 39 | if set_vpn_user(ip, root_pass) == servers_setup.auth_failed_ip: 40 | return JSONResponse(content={ 41 | 'answer': servers_setup.auth_failed_ip 42 | }, status_code=401) 43 | 44 | if set_vpn_user(ip, root_pass) == servers_setup.auth_failed_pass: 45 | return JSONResponse(content={ 46 | 'answer': servers_setup.auth_failed_pass 47 | }, status_code=401) 48 | 49 | send_config_files(ip, root_pass) 50 | 51 | asyncio.run(configurate_open_vpn(ip, root_pass)) 52 | 53 | return { 54 | 'answer': 'Сервер настроен и добавлен в список ваших серверов. Подождите 10 минут и можете использовать сервер' 55 | } -------------------------------------------------------------------------------- /app/pkg/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/pkg/__init__.py -------------------------------------------------------------------------------- /app/pkg/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/pkg/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /app/pkg/ssh_tools/__pycache__/ssh_tools.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/app/pkg/ssh_tools/__pycache__/ssh_tools.cpython-311.pyc -------------------------------------------------------------------------------- /app/pkg/ssh_tools/ssh_tools.py: -------------------------------------------------------------------------------- 1 | import paramiko 2 | from paramiko import ssh_exception 3 | from app.configuration.api_answers import servers_setup 4 | from asyncio import sleep 5 | 6 | def set_vpn_user(ip: str, root_pass: str) -> None | Exception: 7 | 8 | try: 9 | client = paramiko.SSHClient() 10 | client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 11 | client.connect(hostname=ip, username='root', password=root_pass, port=22) 12 | 13 | channel = client.get_transport().open_session() 14 | channel.get_pty() 15 | channel.settimeout(5) 16 | #channel.exec_command('useradd vpn && $(echo "vpn:lezgivpn" |chpasswd)') 17 | #channel.settimeout(3) 18 | command = f'useradd -m vpn \n usermod -aG sudo vpn \n echo "vpn:lezgivpn" | chpasswd \n' +\ 19 | ' echo "vpn ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \n echo "www-data ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \n' +\ 20 | ' chsh -s /bin/bash vpn' 21 | channel.exec_command(command) 22 | #channel.exec_command('usermod -aG sudo vpn') 23 | #channel.exec_command('echo -e "lezgivpn\nlezgivpn" | passwd vpn') 24 | #channel.exec_command('echo "vpn ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers') 25 | #print(channel.recv(2048).decode('utf-8').replace('\n', '')) 26 | 27 | channel.close() 28 | client.close() 29 | except ssh_exception.BadAuthenticationType: 30 | return servers_setup.auth_failed_ip 31 | except ssh_exception.AuthenticationException: 32 | return servers_setup.auth_failed_pass 33 | 34 | 35 | def send_config_files(ip: str, root_pass: str): 36 | transport = paramiko.Transport((ip, 22)) 37 | transport.connect(username='root', password=root_pass) 38 | sftp = paramiko.SFTPClient.from_transport(transport) 39 | 40 | remotepath = '/home/vpn/openvpn-install.sh' 41 | localpath = 'C:/Test/openvpn-install.sh' 42 | 43 | #sftp.get(remotepath, localpath) 44 | sftp.put(localpath, remotepath) 45 | 46 | remotepath = '/home/vpn/setup.sh' 47 | localpath = 'C:/Test/setup.sh' 48 | 49 | sftp.put(localpath, remotepath) 50 | 51 | sftp.close() 52 | transport.close() 53 | 54 | def configurate_nginx(ip: str, root_pass: str) -> None: 55 | 56 | nginx_conf: str = '' 57 | 58 | with open('C:/Test/nginx_boof.conf', 'r') as f: 59 | nginx_conf = f.read() 60 | 61 | 62 | format_nginx_conf = nginx_conf.replace('ip_addr_here', ip) 63 | 64 | with open('C:/Test/nginx.conf', 'w') as f: 65 | f.write(format_nginx_conf) 66 | 67 | transport = paramiko.Transport((ip, 22)) 68 | transport.connect(username='root', password=root_pass) 69 | sftp = paramiko.SFTPClient.from_transport(transport) 70 | 71 | remotepath = '/etc/nginx/nginx.conf' 72 | localpath = 'C:/Test/nginx.conf' 73 | 74 | sftp.put(localpath, remotepath) 75 | 76 | sftp.close() 77 | transport.close() 78 | 79 | client = paramiko.SSHClient() 80 | client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 81 | client.connect(hostname=ip, username='root', password=root_pass, port=22) 82 | channel = client.get_transport().open_session() 83 | channel.get_pty() 84 | channel.settimeout(5) 85 | #channel.exec_command('useradd vpn && $(echo "vpn:lezgivpn" |chpasswd)') 86 | #channel.settimeout(3) 87 | command = f'dos2unix /etc/nginx/nginx.conf /etc/nginx/nginx.conf \n sudo service nginx restart \n sudo shutdown -r now' 88 | channel.exec_command(command) 89 | #channel.exec_command('usermod -aG sudo vpn') 90 | #channel.exec_command('echo -e "lezgivpn\nlezgivpn" | passwd vpn') 91 | #channel.exec_command('echo "vpn ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers') 92 | #print(channel.recv(2048).decode('utf-8').replace('\n', '')) 93 | channel.close() 94 | client.close() 95 | 96 | 97 | async def configurate_open_vpn(ip: str, root_pass: str) -> None: 98 | 99 | client = paramiko.SSHClient() 100 | client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 101 | client.connect(hostname=ip, username='vpn', password='lezgivpn', port=22) 102 | #channel = client.get_transport().open_session() 103 | #channel.get_pty() 104 | #channel.settimeout(5) 105 | #channel.exec_command('useradd vpn && $(echo "vpn:lezgivpn" |chpasswd)') 106 | #channel.settimeout(3) 107 | command = f'sudo apt install dos2unix \n sudo chown vpn /home/vpn/setup.sh \n sudo chmod 777 /home/vpn/setup.sh \n' +\ 108 | 'sudo chown vpn /home/vpn/openvpn-install.sh \n sudo chmod 777 /home/vpn/openvpn-install.sh \n dos2unix -n setup.sh setup.sh \n' +\ 109 | ' dos2unix -n openvpn-install.sh openvpn-install.sh \n nohup bash /home/vpn/setup.sh >> log.txt &' 110 | client.exec_command(command) 111 | #channel.exec_command('usermod -aG sudo vpn') 112 | #channel.exec_command('echo -e "lezgivpn\nlezgivpn" | passwd vpn') 113 | #channel.exec_command('echo "vpn ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers') 114 | #print(channel.recv(2048).decode('utf-8').replace('\n', '')) 115 | #channel.close() 116 | client.close() 117 | 118 | await sleep(60) 119 | 120 | configurate_nginx(ip, root_pass) 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/docker-compose.yaml -------------------------------------------------------------------------------- /docker/api/Dockerfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/docker/api/Dockerfile -------------------------------------------------------------------------------- /docker/redis/Dockerfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekceo/FastAPI-app-Structure-Template/07f45a3a05c9a2881820d7ae21241330b449bea0/docker/redis/Dockerfile --------------------------------------------------------------------------------