In my previous post, Creating an API with python: Part 10: Integration Tests, I added integration tests, which replaced the test.sh script with python unit tests that test the API functionality. In this post, I will set up the FastAPI API to run as a service, controllable via the systemctl command.
Prerequisites
These prerequisites are assumed for this post, although this post can be used as a guide to setting up any FastAPI python API as a service, even without these specific prerequisites:
- Creating an API with python: Part 1: GET Endpoints
- Creating an API with python: Part 2: MariaDB Database
- Creating an API with python: Part 3: POST Endpoints
- Creating an API with python: Part 4: DELETE Endpoints
- Creating an API with python: Part 5: Authentication
- Creating an API with python: Part 6: HTTPS and Proxying
- Creating an API with python: Part 7: CORS
- Creating an API with python: Part 8: Multiple Account Support
- Creating an API with python: Part 9: Authentication Scopes
- Creating an API with python: Part 10: Integration Tests
As a reminder, the code for the FastAPI API is now on GitHub, with the project name taglink-api. You can checkout the latest copy of the code here: https://github.com/liz-allthecoding/taglink-api.
Step 1: Create a Service User
First up, we will create a service user, which will be the user under which the service will be running.
- On your server, run the following to create a new group called
taglink:$ sudo su $ groupadd -r taglink
-
Now create the
taglinkuser and assign it to the grouptaglink:$ useradd -r -g taglink -d /home/taglink -s /sbin/nologin -c "Taglink service account" taglink
Step 2: Deploy the Code
The code should currently be residing over the shared directory on your server. Create a new directory on your server, which will be the installation location for the code. Then copy the code across to this directory.
- On your server, run the following (replacing
/home/osboxes/vboxshare/taglink-api/with the path to your code, if located elsewhere):$ sudo su $ mkdir -p /opt/taglink-api $ cp -r /home/osboxes/vboxshare/taglink-api/* taglink-api/ $ cd /opt/ $ chown -R taglink:taglink taglink-api
-
Now create the
venv-fastapivenv and install the required python packages to it:$ sudo su $ cd /opt/taglink-api $ python -m venv .venv-fastapi $ . .venv-fastapi/bin/activate (.venv-fastapi) $ pip install --upgrade pip (.venv-fastapi) $ pip install "fastapi[all]" (.venv-fastapi) $ pip install sqlalchemy (.venv-fastapi) $ pip install mariadb (.venv-fastapi) $ pip install python-multipart (.venv-fastapi) $ pip install "python-jose[cryptography]" (.venv-fastapi) $ pip install "passlib[bcrypt]"
-
Change the ownership of the
venv-fastapivenv to thetaglinkuser:$ chown -R taglink:taglink .venv-fastapi
Step 3: Add start.sh
The start.sh file should be in the top directory of /opt/taglink-api if you copied your code from a recent clone of the github repo. If not, create the file:
- Create a file called
start.shin the/opt/taglink-apidirectory, and populate it with these contents:#!/bin/bash . /opt/taglink-api/.venv-fastapi/bin/activate uvicorn --host 0.0.0.0 main:app --root-path /api --reload
-
Add executable permissions:
$ chmod ug+x start.sh
Step 4: Create the Systemd Service Configuration File
Create the systemd service configuration file:
-
Change directory to where the systemd service configuration is located:
$ sudo su $ cd /etc/systemd/system
- Create a file called
taglink-api.servicein the/etc/systemd/systemdirectory, and populate it with these contents:[Unit] Description=TagLink API Service After=network.target ConditionPathExists=/opt/taglink-api/.venv-fastapi [Service] Type=simple SyslogIdentifier=taglink-api WorkingDirectory=/opt/taglink-api Environment="PYTHONPATH=/opt/taglink-api" Environment="SYSLOG_IDENT=taglink-api" ExecStart=/opt/taglink-api/start.sh User=taglink Group=taglink Restart=always RestartSec=20 [Install] WantedBy=multi-user.target
Step 5: Start the Service
Start the service using the systemctl command.
-
$ sudo systemctl start taglink-api
-
Check if the service is running with this command:
$ sudo systemctl status taglink-api
-
If all is well, you should get an output something like this:
[osboxes@osboxes fastapi]$ sudo systemctl status taglink-api ● taglink-api.service - TagLink API Service Loaded: loaded (/etc/systemd/system/taglink-api.service; disabled; vendor preset: disabled) Active: active (running) since Fri 2022-11-18 18:39:09 GMT; 1s ago Main PID: 1474 (start.sh) Tasks: 4 CGroup: /system.slice/taglink-api.service ├─1474 /bin/bash /opt/taglink-api/start.sh ├─1476 /opt/taglink-api/.venv-fastapi/bin/python3.6 /opt/taglink-api/.venv-fastapi/bin/uvicorn --host 0.0.0.0 main:app --root-path /api --reload ├─1479 /opt/taglink-api/.venv-fastapi/bin/python3.6 -c from multiprocessing.semaphore_tracker import main;main(4) └─1480 /opt/taglink-api/.venv-fastapi/bin/python3.6 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=5, pipe_handle=7) --multiprocessing-fork Nov 18 18:39:09 osboxes.org systemd[1]: Started TagLink API Service. Nov 18 18:39:09 osboxes.org taglink-api[1474]: INFO: Will watch for changes in these directories: ['/opt/taglink-api'] Nov 18 18:39:09 osboxes.org taglink-api[1474]: INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) Nov 18 18:39:09 osboxes.org taglink-api[1474]: INFO: Started reloader process [1476] using watchgod Nov 18 18:39:10 osboxes.org taglink-api[1474]: /opt/taglink-api/.venv-fastapi/lib64/python3.6/site-packages/jose/backends/cryptography_backend.py:4: CryptographyDeprecationWarning: Python 3.6 is no longer supported by ... future release. Nov 18 18:39:10 osboxes.org taglink-api[1474]: from cryptography.exceptions import InvalidSignature, InvalidTag Nov 18 18:39:10 osboxes.org taglink-api[1474]: INFO: Started server process [1480] Nov 18 18:39:10 osboxes.org taglink-api[1474]: INFO: Waiting for application startup. Nov 18 18:39:10 osboxes.org taglink-api[1474]: INFO: Application startup complete. Hint: Some lines were ellipsized, use -l to show in full. -
If there are issues, or you want to see the logs, you can run:
$ sudo journalctl -f -n1000 -u taglink-api
-
If you want to stop the service, run:
$ sudo systemctl stop taglink-api
-
If you want to enable the service to run at system boot, run:
$ sudo systemctl enable taglink-api
Step 6: Run the Integration Tests
Run the integration tests to verify that the API is working correctly.
-
Ensure that the service is running:
$ sudo systemctl start taglink-api
- On your server, change to the code directory (
~/vboxshare/fastapishould be replaced with the path to your FastAPI python code):$ cd ~/vboxshare/fastapi
-
Run the integration tests:
$ ./integration_test.sh
Conclusion
You should now have a FastAPI API running as a service, meaning it can be controlled with systemctl, can be configured to start at system boot, and is resilient to crashes (the systemd configuration is set to restart the service 20 seconds after a crash).
If you want to find out about enabling utf-8 character support and preventing database connections from dropping, see my follow-on post, Creating an API with python: Part 12: Database Character Encoding and Connections.
Thanks for reading!

Recent Comments