All production secrets (SSH key, Android keystore, Play Store config, Firebase service account) are already typed as dagger.Secret and injected via WithMountedSecret / WithSecretVariable. Add a Secrets section to DAGGER.md to make this explicit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.5 KiB
Dagger CI/CD Setup
This project has migrated from Taskfile-based CI to Dagger. This document explains the infrastructure setup for the shared Dagger Server.
Architecture
We use a Shared Dagger Server approach for both local development and CI. This allows multiple users to share a single Dagger Engine and its cache, significantly speeding up builds.
- Container Engine: Rootless Podman (managed by the
dagger-svcuser). - Orchestration: System-wide
systemdservice. - Access: Users connect via TCP (localhost) or Unix Socket.
Server Setup (Admin)
1. Dedicated Service User
A dedicated user dagger-svc owns the Dagger Engine and its cache.
sudo useradd -m -s /bin/bash dagger-svc
sudo loginctl enable-linger dagger-svc
Why Lingering?
Lingering is required for rootless users to maintain a persistent background session. It ensures that /run/user/<UID> and the user-level Dagger/Podman namespaces are initialized at boot and remain active even when the user is not logged in.
2. Systemd Service
The engine is managed by a system-wide systemd service located at /etc/systemd/system/dagger-engine.service.
[Unit]
Description=Dagger Engine (Shared Server)
After=network.target
[Service]
Type=simple
User=dagger-svc
Group=dagger-svc
WorkingDirectory=/home/dagger-svc
# Replace 1003 with the actual UID of dagger-svc
Environment=DOCKER_HOST=unix:///run/user/1003/podman/podman.sock
Environment=XDG_RUNTIME_DIR=/run/user/1003
ExecStart=/usr/bin/nix run github:dagger/nix/v0.11.4#dagger -- engine --addr tcp://0.0.0.0:8080
Restart=always
[Install]
WantedBy=multi-user.target
Client Configuration
To connect to the shared engine, users should set the _DAGGER_RUNNER_HOST environment variable.
Local Development (.env)
The project uses a .env file to manage the connection string. Ensure your .env contains:
_DAGGER_RUNNER_HOST=tcp://127.0.0.1:8080
Usage
Once the environment is set up, you can run the Dagger pipeline. For non-interactive environments (CI, LLMs), use --progress=plain for readable logs:
nix develop --command dagger call --progress=plain -q -m ci --source=. check
Secrets
All sensitive credentials are passed as dagger.Secret (never as plain strings).
This prevents values from appearing in Dagger logs or being cached in the engine.
| Parameter | Functions |
|---|---|
sshKey *dagger.Secret |
Deployer, GenerateBuildHistory, BuildWebsite, PublishWebsite, DeployLinux, DeployApk |
keystoreBase64 *dagger.Secret |
setupKeystore, BuildAndroidApk, DeployApk, SignAndroidBundle, PublishAndroid |
keystorePassword *dagger.Secret |
same as above |
playStoreConfig *dagger.Secret |
UploadToPlayStore, PublishAndroid |
serviceAccountKey *dagger.Secret |
TestAndroidFirebase |
Secrets are injected via WithMountedSecret (file-based, e.g. SSH key) or
WithSecretVariable (env-var-based, e.g. keystore data, Play Store JSON).
The only credentials not typed as dagger.Secret are the test passwords
(STALWART_PASS_B, STALWART_PASS_C) in WithStalwart. These are hardcoded
development values defined in stalwart-dev/ — not production secrets.
CI Integration (Codeberg/Forgejo)
The CI workflow in .forgejo/workflows/ci.yml is configured to use the Dagger module located in the ci/ directory.
- Check Suite: Runs analysis and tests in parallel.
- Builds: Produces Linux and Android artifacts.
- Caching: When using the shared engine, CI runners benefit from the persistent cache on the host.