Deployments
Deployments with GitHub Actions, Kamal, Docker and SSH
Docker + Kamal
All project templates includes the necessary GitHub Actions for CI/CD with automatic Docker image builds and production deployment with Kamal to any Linux server with SSH.
If you don't have a Linux Server, we recommend Hetzner who we've found offers the best value US Cloud VMs offering $15/mo for a dedicated VM with 2vCPU / 8GB RAM which is being used to host 30 Docker Apps, including all project template live demos - using the GitHub Actions included in each template.
- Create the SSH Private and Public Keys
ssh-keygen -t ed25519 -C "deploy@myapp" -f ./deploy-key- Copy Public Key to deployment server to enable SSH access
cat ~/deploy-key.pub | ssh <user>@<your-ip> "cat >> ~/.ssh/authorized_keys"- Configure GitHub Secrets for Kamal to access your deployment server
# SSH private key to access the server: ssh-rsa ...
gh secret set SSH_PRIVATE_KEY < ~/deploy-key
# IP address of the server to deploy to: 100.100.100.100
gh secret set KAMAL_DEPLOY_IP <your.ip>
# Email for Let's Encrypt SSL certificate: me@example.org
gh secret set LETSENCRYPT_EMAIL <your@email>These Required variables can be globally configured in your GitHub Organization or User secrets which will enable deploying all your Repositories to the same server.
Optionally configure any other global secrets to be shared by all Apps here:
gh secret set SERVICESTACK_LICENSE <license-key>- Configure GitHub Secrets for your App
The only secret that needs to be configured per App is:
# Hostname used for SSL certificate and Kamal proxy: www.example.org
gh secret set KAMAL_DEPLOY_HOST <www.example.org>You could register any App-specifc secrets here, althouth our preference is instead of polluting each
GitHub Reposity with multiple App-specific GitHub Action Secrets, you can save all your secrets in a single
APPSETTINGS_PATCH GitHub Action Secret to patch appsettings.json with environment-specific configuration
using JSON Patch. E.g:
# JSON Patch to apply to appsettings.json:
gh secret set APPSETTINGS_PATCH [json-patch]JSON Patch example:
[
{
"op":"replace",
"path":"/ConnectionStrings/DefaultConnection",
"value":"Server=service-postgres;Port=5432;User Id=dbuser;Password=dbpass;Database=dbname"
},
{ "op":"add", "path":"/SmtpConfig", "value":{
"UserName": "SmptUser",
"Password": "SmptPass",
"Host": "email-smtp.us-east-1.amazonaws.com",
"Port": 587,
"From": "noreply@example.org",
"FromName": "MyApp",
"Bcc": "copy@example.org"
}
},
{ "op":"add", "path":"/Admins", "value": ["admin1@email.com","admin2@email.com"] },
{ "op":"add", "path":"/CorsFeature/allowOriginWhitelist/-", "value":"https://servicestack.net" }
]Inferred Variables
These variables are inferred from the GitHub Action context and don't need to be configured.
| Variable | Source | Description |
|---|---|---|
GITHUB_REPOSITORY | ${{github.repository}} | acme/example.org - used for service name and image |
KAMAL_REGISTRY_USERNAME | ${{github.actor}} | GitHub username for container registry |
KAMAL_REGISTRY_PASSWORD | ${{secrets.GITHUB_TOKEN}} | GitHub token for container registry auth |
Kamal deploy.yml
The /config/deploy.yml configuration is designed to be reusable across projects as it dynamically derives service names, image paths, and volume mounts from environment variables, so you only need to configure your server's IP and hostname using GitHub Action secrets.
To also be able to use kamal locally to inspect logs or deploy from your own server you can add the GitHub Action
Secrets into a local .env file, e.g:
# Required for Kamal deploy.yml template processing
GITHUB_REPOSITORY=acme/example.org
# Server deployment details
KAMAL_DEPLOY_IP=100.100.100.100
KAMAL_DEPLOY_HOST=example.org
# Container registry credentials (for ghcr.io)
KAMAL_REGISTRY_USERNAME=my-user
GITHUB_TOKEN=ghp_xxx
# Login to GitHub Container Registry
#echo $KAMAL_REGISTRY_PASSWORD | docker login ghcr.io -u my-user --password-stdinYou can then load the environment variables into your shell with:
. ./load-env.shWhich will allow you to use kamal locally to access your deployment server, e.g:
kamal app logs -fHard code App specific variables
Alternatively if you don't want to maintain a .env with GitHub Action Secrets you can hard-code all
App-specific variables in your deploy.yml file so it doesn't need to perform any template processing
for its Environment Variable substitutions.
Features
- Docker containerization with optimized .NET images
- SSL auto-certification via Let's Encrypt
- GitHub Container Registry integration
- Volume persistence for App_Data including any SQLite database