ServiceStack templates now support deployment using Kamal, a CLI tool from the BaseCamp team that simplifies containerized application deployments. Kamal wraps SSH and Docker to streamline self-hosting while maintaining GitHub Actions as the CI runner.
Overview​
Kamal enables simple commands to deploy containerized applications to Linux hosts, handling:
- Bootstrap configuration
- Reverse proxy setup
- SSL certificate provisioning
- Zero-downtime deployments
- Health checks on deploy
- Rolling back changes
INFO
Kamal is built by the BaseCamp team, developers of Hey email service and BaseCamp project management tool. For comprehensive documentation on all Kamal features, visit https://kamal-deploy.org/
Getting Started​
Prerequisites​
- A domain name
- A Linux host (e.g., VPS from providers like Hetzner)
- GitHub account for CI/CD
Initial Setup​
- Create a new ServiceStack application:
x new blazor-vue MyApp
- Generate deployment SSH key:
ssh-keygen -t ed25519 -C "deploy@myapp" -f ./deploy-key
- Configure server access:
cat ~/my-deploy-key.pub | ssh <user>@<your-ip-address> "cat >> ~/.ssh/authorized_keys"
GitHub Actions​
The template includes a GitHub Actions workflow that is broken up into 3 steps that trigger on push to the main
branch, and then on successful build and test, it will deploy the application to your server.
Once you create your GitHub repository, add the SSH_PRIVATE_KEY
secret to your repository settings with the contents of your private key file.
gh secret set PRIVATE_SSH_KEY < ~/my-deploy-key
Configuration​
Update config/deploy.yml
with your deployment settings:
service: myapp
image: your-github-username/myapp
servers:
web:
- <your-server-ip-address>
proxy:
ssl: true
host: myapp.example.com
INFO
The image
value should match your GitHub repository path on ghcr.io. For example: ghcr.io/username/repository
Once you make these changes, commit and push to your repository to trigger the GitHub Actions workflow.
Kamal will deploy the required services including Docker and Kamal Proxy if you server doesn't already have them installed.
INFO
When using ASP.NET Core applications with Kamal-Proxy, ensure your application is running with the environment variable ASPNETCORE_FORWARDEDHEADERS_ENABLED
set to true
.
The template has this by default, but if you are getting errors with 302 redirects, ensure this is set.
The authentication between GitHub Container Registry (ghcr.io) and your server is handled by the GitHub Actions workflow, the deploy.yml
and Kamal Secrets.
INFO
You can still use the Kamal CLI locally, but if you want to directly push deployments with kamal deploy
, you will need to locally populate KAMAL_REGISTRY_USER
and KAMAL_REGISTRY_PASSWORD
with your GitHub username and a GitHub Personal Access Token with read:packages
scope.
Common Kamal Commands​
Kamal provides several useful commands for managing your deployment:
# View deployment details
kamal details
# Check application logs
kamal app logs
# Deploy new version
kamal deploy
# Restart application
kamal app boot
INFO
Kamal commands are context-aware and will use the configuration from your current application directory. This makes managing multiple applications across different servers a lot easier as more applications are added.
Additional Containers​
Kamal supports extensive configuration options including "accessories" for additional features like databases, caches, and more. See the Kamal documentation for more information.
Troubleshooting​
Initial deployment fails​
If you are having issues with the initial deployment, an earlier bootstrap of the server via GitHub Actions may have failed.
Delete the .<app-name>
file in your deployment user's home directory and re-run the GitHub Actions workflow to re-bootstrap the server.
Missing the service label​
If you are getting:
Image ghcr.io/netcoreapps/northwindauto:latest is missing the 'service' label
Ensure that your AppHost csproj file has ContainerLabel
with the value matching the service
in your deploy.yml
file.