Files
full-stack-fastapi-template/deployment.md
T
Sebastián Ramírez 9d541082a3 ♻️ Run database setup explicitly before startup (#2426)
## AI Disclaimer

Using Codex with gpt-5.6-sol. Reviewed manually.
2026-08-10 23:09:54 +02:00

243 lines
9.3 KiB
Markdown

# FastAPI Project - Deployment
You can deploy the project using Docker Compose to a remote server.
The deployment Docker Compose configuration includes Traefik to handle HTTPS and route incoming traffic to the application.
You can use CI/CD (continuous integration and continuous deployment) systems to deploy automatically, there are already configurations to do it with GitHub Actions.
But you have to configure a couple things first. 🤓
## Preparation
* Have a remote server ready and available. Use a separate server for each environment, for example one for staging and one for production.
* Configure DNS records pointing to the server for the application domain and any supporting service subdomains you want to expose, e.g. `fastapi-project.example.com` and `adminer.fastapi-project.example.com`.
* Install and configure [Docker](https://docs.docker.com/engine/install/) on the remote server (Docker Engine, not Docker Desktop).
## Deploy the FastAPI Project
You can deploy your FastAPI project with Docker Compose.
**Note**: You might want to jump ahead to the section about Continuous Deployment with GitHub Actions.
## Copy the Code
```bash
rsync -av --exclude=".git/" --filter=":- .gitignore" ./ root@your-server.example.com:/root/code/app/
```
Note: `--filter=":- .gitignore"` tells `rsync` to use the same rules as git, ignore files ignored by git, like the Python virtual environment.
## Environment Variables
You need to set some environment variables first.
### Generate secret keys
Some environment variables in the `.env` file have a default value of `changethis`.
You have to change them with a secret key, to generate secret keys you can run the following command:
```bash
python -c "import secrets; print(secrets.token_urlsafe(32))"
```
Copy the content and use that as password / secret key. And run that again to generate another secure key.
### Required Environment Variables
Set the `DOMAIN` to your own domain, for example:
```bash
export DOMAIN=fastapi-project.example.com
```
The deployment Docker Compose configuration also uses `DOMAIN` to set the public frontend URL used in links generated by the backend.
Set the `POSTGRES_PASSWORD` to a secure value:
```bash
export POSTGRES_PASSWORD="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
```
Set the `SECRET_KEY`, used to sign tokens, to a secure value:
```bash
export SECRET_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
```
Set the `FIRST_SUPERUSER_PASSWORD` to a secure value:
```bash
export FIRST_SUPERUSER_PASSWORD="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
```
You can set several other environment variables:
* `PROJECT_NAME`: The name of the project, used in the API for the docs and emails.
* `BACKEND_CORS_ORIGINS`: A list of additional allowed CORS origins separated by commas. The frontend served by FastAPI uses the same origin and doesn't need to be added.
* `FIRST_SUPERUSER`: The email of the first superuser, this superuser will be the one that can create new users.
* `SMTP_HOST`: The SMTP server host to send emails, this would come from your email provider (E.g. Mailgun, Sparkpost, Sendgrid, etc).
* `SMTP_USER`: The SMTP server user to send emails.
* `SMTP_PASSWORD`: The SMTP server password to send emails.
* `EMAILS_FROM_EMAIL`: The email account to send emails from.
* `POSTGRES_USER`: The Postgres user, you can leave the default.
* `POSTGRES_DB`: The database name to use for this application. You can leave the default of `app`.
* `SENTRY_DSN`: The DSN for Sentry, if you are using it.
## GitHub Actions Environment Variables
There are some environment variables only used by GitHub Actions that you can configure:
* `LATEST_CHANGES`: Used by the GitHub Action [latest-changes](https://github.com/tiangolo/latest-changes) to automatically add release notes based on the PRs merged. It's a personal access token, read the docs for details.
* `SMOKESHOW_AUTH_KEY`: Used to handle and publish the code coverage using [Smokeshow](https://github.com/samuelcolvin/smokeshow), follow their instructions to create a (free) Smokeshow key.
### Deploy with Docker Compose
With the environment variables in place, you can deploy with Docker Compose:
```bash
cd /root/code/app/
docker compose -f compose.yml -f compose.deploy.yml build
docker compose -f compose.yml -f compose.deploy.yml run --rm backend bash scripts/prestart.sh
docker compose -f compose.yml -f compose.deploy.yml up -d
```
The `compose.deploy.yml` file adds the deployment settings to the shared configuration in `compose.yml`, including HTTPS and automatic certificate handling. Explicitly listing these files also excludes the local development settings in `compose.override.yml`.
## Continuous Deployment (CD)
You can use GitHub Actions to deploy your project automatically. 😎
There are already two environment deployments configured, `staging` and `production`. Each environment should be deployed to a separate server. 🚀
### Install GitHub Actions Runner
* On your remote server, create a user for your GitHub Actions:
```bash
sudo adduser github
```
* Add Docker permissions to the `github` user:
```bash
sudo usermod -aG docker github
```
* Temporarily switch to the `github` user:
```bash
sudo su - github
```
* Go to the `github` user's home directory:
```bash
cd
```
* [Install a GitHub Action self-hosted runner following the official guide](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/adding-self-hosted-runners#adding-a-self-hosted-runner-to-a-repository).
* When asked about labels, add a label for the environment, e.g. `production`. You can also add labels later.
After installing, the guide would tell you to run a command to start the runner. Nevertheless, it would stop once you terminate that process or if your local connection to your server is lost.
To make sure it runs on startup and continues running, you can install it as a service. To do that, exit the `github` user and go back to the `root` user:
```bash
exit
```
After you do it, you will be on the previous user again. And you will be on the previous directory, belonging to that user.
Before being able to go the `github` user directory, you need to become the `root` user (you might already be):
```bash
sudo su
```
* As the `root` user, go to the `actions-runner` directory inside of the `github` user's home directory:
```bash
cd /home/github/actions-runner
```
* Install the self-hosted runner as a service with the user `github`:
```bash
./svc.sh install github
```
* Start the service:
```bash
./svc.sh start
```
* Check the status of the service:
```bash
./svc.sh status
```
You can read more about it in the official guide: [Configuring the self-hosted runner application as a service](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service).
### Configure GitHub Environments
The deployment workflows use [GitHub Environments](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) for `staging` and `production`. This enables environment-specific secrets, deployment protection rules (e.g. required reviewers, wait timers), and deployment status tracking.
To configure them, go to your repository's **Settings** > **Environments** and create the `staging` and `production` environments.
### Set Secrets
For each GitHub Environment (`staging` and `production`), configure the required secrets as [environment secrets](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets#creating-secrets-for-an-environment). Environment secrets are preferred over [repository secrets](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets#creating-secrets-for-a-repository) because they are scoped to the specific environment, reducing exposure and aligning with any protection rules you configure.
The deployment workflows require these secrets:
* `DOMAIN`
* `FIRST_SUPERUSER`
* `FIRST_SUPERUSER_PASSWORD`
* `POSTGRES_PASSWORD`
* `SECRET_KEY`
To enable emails, configure these additional secrets with the values from your email provider:
* `SMTP_HOST`
* `SMTP_USER`
* `SMTP_PASSWORD`
* `EMAILS_FROM_EMAIL`
To enable Sentry, configure the `SENTRY_DSN` secret.
## GitHub Action Deployment Workflows
There are GitHub Action workflows in the `.github/workflows` directory already configured for deploying to the environments (GitHub Actions runners with the labels):
* `staging`: after pushing (or merging) to the branch `master`.
* `production`: after publishing a release.
Both workflows are associated with their respective GitHub Environments, so deployments will be visible in the repository's **Environments** section and will respect any protection rules you configure.
If you need to add extra environments you could use those as a starting point.
## URLs
Replace `fastapi-project.example.com` with your domain.
### Production
Application (frontend and API): `https://fastapi-project.example.com`
Interactive API docs: `https://fastapi-project.example.com/docs`
Adminer: `https://adminer.fastapi-project.example.com`
### Staging
Application (frontend and API): `https://staging.fastapi-project.example.com`
Interactive API docs: `https://staging.fastapi-project.example.com/docs`
Adminer: `https://adminer.staging.fastapi-project.example.com`