Version: 0.21.0This documentation is for Spitfire 0.21.0.
Installation, updates and backups
This page covers installing Spitfire on Docker, Kubernetes or Windows (Docker Desktop), creating the first admin, updating, rolling back, backing up and uninstalling. Installing runners in remote locations is a separate topic: Runners and locations.
What it is for
The installer (install.sh, on Windows install.ps1) does all of this with one command:
- Downloads the release's installer bundle (install.sh, uninstall.sh, Compose/Kubernetes files; no source code) from
spitfire.tr/download, checks its SHA-256 and unpacks it into~/spitfire. - Pulls the image from Docker Hub:
algebransoft/spitfire:<VERSION>(public, amd64 + arm64). Go and Node are not needed. - Starts Postgres, the controller (web UI + API) and the runners.
- Generates the secrets (
SPITFIRE_SECRET_KEY,SPITFIRE_JWT_SECRET, the setup code…) once and keeps them as they are on every later run. - Prints the UI address and the setup code for the first admin at the end.
Running the same command again is an update.
When to use it
- At the first installation.
- When a new release is out (the blue "Spitfire X is out" banner in the UI).
- To change the controller's port, the number of runners or the proxy (run it again with the option).
- When an update went wrong (
--rollback). - When support asks for a support bundle and the UI does not open (
--support-bundle).
Requirements
| Installation | Needs |
|---|---|
| Docker (Linux/macOS) | Docker Engine (Linux) or Docker Desktop (macOS), the Docker Compose v2 plugin, curl. The installing user must reach the Docker daemon (on Linux: be in the docker group). |
| Kubernetes | The above plus kubectl and an active context. Nodes pull the image from Docker Hub (internet access needed; otherwise --build --registry). |
| Windows | Docker Desktop, Windows PowerShell 5.1 or PowerShell 7, tar.exe (ships with Windows 10 1803 and later). |
| Remote runner server | Only Docker; on Linux without Docker a systemd service, on Windows without Docker a Windows service. See Runners. |
When the installer finds something missing it stops with a HATA: (error) line followed by a Çözüm: (fix) line; read that first.
Installing with Docker
Check that Docker runs:
docker infomust return without an error.Run the install command:
curl -fsSL https://spitfire.tr/install.sh | bash -s -- dockerThis installs Postgres + controller + 2 runners on one machine. For another release write
SPITFIRE_VERSION=0.5.3, for another folderSPITFIRE_DIR=/opt/spitfire(both beforebash):curl -fsSL https://spitfire.tr/install.sh | SPITFIRE_DIR=/opt/spitfire bash -s -- dockerThe installation ends with the line
Kurulum tamamlandı. Tarayıcıda açın: http://...("Installation complete. Open in your browser"). Copy the Kurulum kodu: XXXX-XXXX-XXXX (setup code) line right below it.Open the address in your browser and continue with First sign-in and setup code.
Default ports: UI and API 8470, gRPC (TLS) for remote runners 8471. To change them:
~/spitfire/install.sh docker --port 8480 --grpc-port 8481 --runners 4Installing on Kubernetes
Check that you are on the right cluster with
kubectl config current-context.Run the install command:
curl -fsSL https://spitfire.tr/install.sh | bash -s -- kubernetesThe default namespace is
spitfire, the context is the current one. Change them with--namespace NSand--context C.By default the UI opens on NodePort 30470 (change with
--node-port N;--service-type LoadBalancerorClusterIPare also possible). If this machine cannot open the UI through the NodePort, the installer starts akubectl port-forwardin the background (deploy/kubernetes/.port-forward.pid).Copy the setup code from the output and open the address.
Security settings of the Kubernetes installation: pods run as non-root with a read-only root filesystem, no capabilities and the RuntimeDefault seccomp profile. NetworkPolicies (where the CNI enforces them) let only the controller reach Postgres and only this installation's runners reach the plaintext runner port (8475). Stopping the controller stops active runs and stores their results first (up to 30 s; the pod gets 45 s).
Common Kubernetes options:
| Option | Meaning |
|---|---|
--namespace NS, --context C |
Target (default spitfire, current-context) |
--service-type T |
NodePort (default), LoadBalancer, ClusterIP |
--node-port N |
UI NodePort (default 30470) |
--storage-class SC, --storage-size S |
Postgres PVC (default: the cluster default, 5Gi) |
--local-port N |
Local port for the port-forward fallback |
--runners N |
Number of always-on runners |
--on-demand-runners N |
Runners started as pods during a run (see Runners) |
--build --registry REG |
Builds the image from source and pushes it to your registry |
An image built with --build is loaded directly into kind, minikube, k3d and Docker Desktop; other clusters need --build --registry REG. --build only works in the source tree; the bundle from spitfire.tr carries no source code.
Installing on Windows
Start Docker Desktop.
In PowerShell:
irm https://spitfire.tr/install.ps1 | iexThis installs in
dockermode; the bundle is unpacked into%USERPROFILE%\spitfire(change it with$env:SPITFIRE_DIR, pick a release with$env:SPITFIRE_VERSION).To pass options, call the script as a scriptblock:
& ([scriptblock]::Create((irm https://spitfire.tr/install.ps1))) docker -Port 8480 -GrpcPort 8481 -Runners 4
The install.ps1 options mean the same as those of install.sh: -Runners N, -Location NAME, -Version V, -Image IMAGE, -AdminEmail/-AdminPassword, -Port N, -GrpcPort N, -GrpcPublicAddr H:P, -NoBackup, -Rollback, -SupportBundle, -Yes, -Help.
To install only a runner on a Windows server without Docker, use the command on the Windows tab of the key dialog on the Runners page: Runners.
Installer options
~/spitfire/install.sh --help lists them all. The most used:
| Option | Meaning |
|---|---|
--port 8480 --grpc-port 8481 |
Docker: UI and runner ports (default 8470/8471) |
--runners N |
Number of local runners (default 2) |
--location NAME |
Location of the local runners (default local; a-z 0-9 - _ .) |
--grpc-public-addr HOST:PORT |
The address runners in other locations dial (shown in the UI's command; on Docker the LAN IP by default) |
--version V |
Pull another release from Docker Hub |
--image IMAGE |
Use a specific ready-made image |
--admin-email E --admin-password P |
Create the first admin during installation (password at least 8 characters) |
--no-backup |
Do not back up the database when updating |
--rollback [DUMP] |
Roll the last update back |
--support-bundle |
Installs nothing; prepares a support bundle (zip) |
-y, --yes |
Do not ask for confirmation |
First sign-in and setup code
On the first visit the UI shows the Create the first admin screen. It appears only once, while there are no users at all.
The Create the first admin screen: Setup code, Name, Email, Password and Confirm password fields
- Paste the
XXXX-XXXX-XXXXcode printed at the end of the installation into Setup code. - Enter Name, Email and Password (at least 8 characters), and repeat it in Confirm password.
- Click Create admin and sign in.
The new account is the installation admin: installation settings such as the license, users, SSO and system events belong to this role only. The code stops working once the first admin exists.
Lost the code? (It stays valid until the first admin exists and is never regenerated.)
Docker:
grep SPITFIRE_SETUP_CODE ~/spitfire/deploy/docker/.envKubernetes:
kubectl -n spitfire get secret spitfire-secrets -o jsonpath='{.data.SPITFIRE_SETUP_CODE}' | base64 -dThe
setup_code=line in the controller log:docker compose -p spitfire -f deploy/docker/docker-compose.yml logs controller | grep -i setup kubectl -n spitfire logs deploy/spitfire-controller | grep -i setupRunning the install command again shows it again (the code does not change).
To create the first admin during installation without the code: install.sh docker --admin-email admin@example.com --admin-password '...' (Windows: -AdminEmail/-AdminPassword).
Do not share the setup code with anyone but the person installing. Whoever uses it first becomes the installation's admin.
After signing in, the next step is usually the license: License.
Updating
How you notice a new release
Once a day the controller asks spitfire.tr whether there is a newer release (it sends only its own version). If there is, admins see the Spitfire X is out banner at the top of every page:
- What's new and how to update opens the release notes and the update command for this installation (separately for Linux/macOS Docker, Windows PowerShell, Kubernetes and runner servers in other locations).
- Hide for this release closes the banner for that release. A Security update banner (red) cannot be hidden; it shows again on every visit.
The Version and updates card on the License page shows the installed version, the installation type, the last check's result, the Outbound proxy and the Update command; Check now checks without waiting.
The Version and updates card on the License page: installed version, installation type, update check and the Check now button
Updating step by step
Make sure no run is in progress (the update restarts the controller).
On the server the controller is installed on, run the same command as at installation:
curl -fsSL https://spitfire.tr/install.sh | bash -s -- docker curl -fsSL https://spitfire.tr/install.sh | bash -s -- kubernetes --context C --namespace NSOn Windows:
irm https://spitfire.tr/install.ps1 | iex.The script unpacks the latest bundle into the same folder and pulls the image. Generated keys (
deploy/docker/.envor thespitfire-secretsSecret) and data are kept.If the version changes, the database is first dumped to
~/spitfire/backups/*.dump(the newest 5 are kept;--no-backupskips it).Update the runners in other locations too: Runners → Updating runners. The Runners page marks runners on another release than the controller with a yellow older release tag.
Rolling back
If an update goes wrong:
~/spitfire/install.sh docker --rollback # Kubernetes: install.sh kubernetes --rollbackOn Windows .\install.ps1 -Rollback. The script first dumps the current database, restores the newest dump under backups/ (or the file you give: --rollback backups/<file>.dump) and returns to the release that took that dump. Changes made after the dump are lost. Without a terminal it needs --yes.
Installing behind a proxy
Behind a corporate HTTPS proxy, run the install command with HTTPS_PROXY (and if needed HTTP_PROXY, NO_PROXY) set:
export HTTPS_PROXY=http://proxy.example.com:3128
export NO_PROXY=.example.local
curl -fsSL https://spitfire.tr/install.sh | bash -s -- dockerThe script passes these values on to the controller (Docker: deploy/docker/.env; Kubernetes: the spitfire-proxy Secret). The controller makes the update check, webhooks and SSO calls through this proxy. The installation's own names (localhost, postgres, controller…) are added to NO_PROXY automatically. Add the names of an SSO provider or webhook targets on your internal network to NO_PROXY yourself. If a later run gives no proxy, the earlier setting is kept.
On an installation without internet access, turn the update check off: SPITFIRE_UPDATE_CHECK=off on the controller, and follow the release notes on spitfire.tr/surum-notlari. If you use your own mirror, give it with SPITFIRE_UPDATE_FEED; the mirror must also carry releases.json.sig.
Backups and SPITFIRE_SECRET_KEY
Spitfire's data lives in Postgres; connection secrets are encrypted with SPITFIRE_SECRET_KEY. Back up both:
- Keys: on Docker the
~/spitfire/deploy/docker/.envfile, on Kubernetes thespitfire-secretsSecret. Copy it to a safe place (such as a password vault). - Database: updates take
~/spitfire/backups/*.dumpautomatically when the version changes; restore them withpg_restore. For regular backups, add this folder or the Postgres volume to your own backup system.
If SPITFIRE_SECRET_KEY is lost, stored connection secrets (database, Kafka… passwords) cannot be read; you have to enter them all again. The TLS identity the controller presents to runners is also stored encrypted with this key.
Ports and network
| Port | For | Who must reach it |
|---|---|---|
| 8470 (Docker; NodePort 30470 on Kubernetes) | Web UI and REST API | Users, CI pipelines |
| 8471 | gRPC endpoint remote runners connect to, TLS | Runner servers in other locations (inbound TCP) |
| 8475 | Plaintext gRPC for runners on the same machine/cluster | Only the installation's own runners; never published |
| 8472 (optional) | Mock services (turned on with SPITFIRE_MOCK_ADDR) |
The system under test |
Runners connect out to the controller; no inbound port is needed on a runner server.
With a reverse proxy (ingress, nginx) in front of the UI, the client address is taken from X-Forwarded-For only when the request comes from loopback or a private network. Declare a proxy on a public address (a cloud load balancer, Cloudflare) in SPITFIRE_TRUSTED_PROXIES (comma-separated CIDRs); otherwise the audit log and the sign-in limits see the proxy's address.
Sign-in is throttled: one client address may try 30 times at once, then once every 2 s; an account accepts 10 wrong passwords, then one a minute. When many users sit behind one proxy/NAT, raise the first limit with SPITFIRE_SIGNIN_BURST.
TLS and runner pin basics
- Port 8471 is always TLS. The controller creates its own identity on first start and stores it in the database (encrypted with
SPITFIRE_SECRET_KEY). - A remote runner verifies the controller by the pin of that key (
sha256:…). The pin and the ready-made install command are in the key dialog on the Runners page. The pin is required because connection secrets travel to runners over this channel. - To use your own certificate, give the controller
SPITFIRE_GRPC_TLS_CERTandSPITFIRE_GRPC_TLS_KEY; runners then verify with--tls(system CAs) or--ca <PEM file>instead of a pin. - The controller address remote runners see is set at installation with
--grpc-public-addr HOST:PORTor withSPITFIRE_GRPC_PUBLIC_ADDR.
Details: Runners → TLS pin and certificates.
Uninstalling
~/spitfire/uninstall.sh docker
~/spitfire/uninstall.sh kubernetes --context C --namespace NS
~/spitfire/uninstall.sh runner # remote runners installed with install.sh runnerWindows: .\uninstall.ps1 docker or .\uninstall.ps1 runner.
By default the data (Postgres volume / PVC) and the generated keys (.env / spitfire-secrets) are kept; a later install.sh brings everything back. To delete everything, add --purge (Windows: -Purge).
--purge deletes the database and SPITFIRE_SECRET_KEY; it cannot be undone. Take a backup first.
Common problems
Symptom: HATA: Docker daemon'una ulaşılamıyor. (the Docker daemon cannot be reached)
Cause: Docker is not running, or your user is not in the docker group.
Fix: Start Docker Desktop or sudo systemctl start docker; add your user to the docker group and log in again.
Symptom: HATA: Docker Compose bulunamadı. (Docker Compose not found)
Cause: The Compose v2 plugin is not installed.
Fix: Install the Docker Compose v2 plugin (https://docs.docker.com/compose/install/).
Symptom: HATA: Port 8470 başka bir uygulama tarafından kullanılıyor. (port in use)
Cause: Another service on the machine uses that port.
Fix: Pick another port: install.sh docker --port 8480 --grpc-port 8481.
Symptom: HATA: İmaj indirilemedi: algebransoft/spitfire:... (image could not be pulled)
Cause: The machine cannot reach Docker Hub, or the version is wrong.
Fix: Try internet access with docker pull; behind a proxy, configure the Docker daemon's proxy; check the version number.
Symptom: The setup screen says "Wrong setup code".
Cause: The code was copied incompletely, or it belongs to another installation.
Fix: Copy it again from the .env file or the controller log (First sign-in and setup code).
Symptom: The sign-in page opens instead of the setup screen, saying "Setup is already complete".
Cause: The first admin already exists (perhaps through --admin-email).
Fix: Sign in with that account. If its password is unknown, use spitfire-controller reset-password on the server: Users and access.
Symptom: HATA: Controller 180 sn içinde hazır olmadı. (the controller was not ready within 180 s)
Cause: The controller failed while starting (database, missing setting…).
Fix: Read the log with docker compose -p spitfire -f deploy/docker/docker-compose.yml logs -f controller; if you cannot solve it, prepare a support bundle with ./install.sh --support-bundle (Troubleshooting).
Symptom: The Version and updates card shows Check failed.
Cause: The controller cannot reach spitfire.tr.
Fix: Behind a proxy, run the install command again with HTTPS_PROXY set; without internet access set SPITFIRE_UPDATE_CHECK=off.
Symptom: After a reinstall, saved connections no longer work; secrets cannot be read or Test fails.
Cause: SPITFIRE_SECRET_KEY changed (e.g. .env was deleted and the installation redone).
Fix: Put back the .env you backed up and run the installer again; without a backup, enter the secrets again.