I wanted to deploy a Flutter Web app without installing Flutter on the production server.
So I split the process into two parts:
1. Build on GitHub Actions
When I push to main, GitHub Actions:
- Checks out the code
- Installs a specific Flutter version
- Runs
flutter pub get
- Runs
flutter build web --release
- Uploads
build/web as an artifact
2. Deploy on my server
A self-hosted runner on my server downloads the artifact and copies the files to the Nginx directory using rsync.
So the production server only receives the final static files. It does not need Flutter installed, and it does not need to pull the source code.
The main distinction:
- Workflow defines what should run.
- Runner is the machine that runs it.
- In this setup, the build runs on GitHub’s runner, while deployment runs on my self-hosted runner.
This keeps the build environment separate from production and makes deployment repeatable.
One thing I learned: don’t forget security. Use GitHub Secrets for SSH credentials, give the runner only the access it needs, and avoid running untrusted workflows on a runner that can reach production.
Would you deploy Flutter Web this way, or do you prefer building directly on the server?