Environment Configuration
Most applications need different configuration per environment: a staging database, a production Stripe key, debug logging in dev but warn in production. This guide covers the Satusky patterns for managing that cleanly.
The problem
Section titled “The problem”You have one codebase deploying to three environments. The values that differ:
- Database connection strings
- API keys and secrets
- Log levels, feature flags, service URLs
- Resource sizes (staging can be smaller than production)
Satusky gives you two tools for this: config files for structural differences (port, CPU, memory) and environment variables / secrets for runtime values.
Multiple config files
Section titled “Multiple config files”satusky.toml is the default config 1ctl reads. You can maintain separate files for each environment:
satusky.toml ← dev defaultssatusky.staging.toml ← staging overridessatusky.production.toml ← production specCreate them with 1ctl init --config <name>:
# Create staging config1ctl init --config staging✅ Created satusky.staging.toml💡 Edit satusky.staging.toml to configure resources and domain for this target.💡 Then run: 1ctl deploy --config staging# Create production config1ctl init --config production✅ Created satusky.production.toml💡 Edit satusky.production.toml to configure resources and domain for this target.💡 Then run: 1ctl deploy --config productionIf a satusky.toml already exists in the same directory, init --config <name> inherits its name, port, cpu, memory, and domain fields as a starting point. Edit the generated file to set the values you want for that environment. Your satusky.production.toml might look like:
[app] name = "my-api" port = 8080 dockerfile = "Dockerfile" cpu = "1" memory = "512Mi"And satusky.staging.toml with lighter resources:
[app] name = "my-api" port = 8080 dockerfile = "Dockerfile" cpu = "0.5" memory = "256Mi"Commit these files. They contain no secrets — only structural config.
Deploy to a specific environment
Section titled “Deploy to a specific environment”Pass --config <name> to target a specific config file:
# Deploy to staging1ctl deploy --config staging💡 Packaging build context...💡 Submitting build to cloud...Step 1/5: Building image (cloud) my-api ✓...✅ 🚀 Deployment for my-api is successful! Your app is live at: https://swiftbadger-f9e8d7c.satusky.com# Deploy to production1ctl deploy --config production💡 Packaging build context...💡 Submitting build to cloud...Step 1/5: Building image (cloud) my-api ✓...✅ 🚀 Deployment for my-api is successful! Your app is live at: https://happyotter-x3k9m2.satusky.comThe --config flag accepts the environment name (staging) and resolves to satusky.staging.toml. The --config flag propagates automatically to subcommands like 1ctl env create and 1ctl logs.
Non-sensitive config: environment variables
Section titled “Non-sensitive config: environment variables”Runtime values that aren’t secrets — log levels, service URLs, feature flags — go through 1ctl env create. They’re stored in Kubernetes ConfigMaps and visible in 1ctl env list.
# Set production env vars1ctl env create \ --config production \ --env NODE_ENV=production \ --env LOG_LEVEL=warn \ --env API_BASE_URL=https://api.myapp.comExpected output:
✅ Environment my-api created successfully# Set staging env vars1ctl env create \ --config staging \ --env NODE_ENV=staging \ --env LOG_LEVEL=debug \ --env API_BASE_URL=https://staging-api.myapp.comVerify what’s set. env list accepts --deployment-id to scope to a specific deployment:
1ctl env list --deployment-id 7f1fab9e-5f87-4612-b306-3da846b95d18NAME ENV ID DEPLOYMENT ID CREATEDmy-api 798cf7bc-a85a-45b9-9a91-720e3fcade62 7f1fab9e-5f87-4612-b306-3da846b95d18 just nowTo see the individual keys and values, use -o json:
1ctl env list -o json | jq '.[0].key_values'Sensitive config: secrets
Section titled “Sensitive config: secrets”Passwords, API keys, tokens — anything you wouldn’t commit to a repo — go through 1ctl secret create. Values are encrypted with AES-256-GCM before storage and are never shown after creation.
# Set production secrets1ctl secret create \ --config production \ --kv DATABASE_PASSWORD=p4ssw0rd-prod \ --kv JWT_SECRET=supersecret-prod \ --kv STRIPE_SECRET_KEY=sk_live_abc123Expected output:
✅ Secret my-api created successfully# Set staging secrets1ctl secret create \ --config staging \ --kv DATABASE_PASSWORD=p4ssw0rd-staging \ --kv JWT_SECRET=supersecret-staging \ --kv STRIPE_SECRET_KEY=sk_test_xyz789Verify (key names only — values are never returned):
1ctl secret listNAME SECRET ID DEPLOYMENT ID CREATEDmy-api bcbeb9d7-958c-4aa6-b1a1-51846504cfe8 7f1fab9e-5f87-4612-b306-3da846b95d18 just nowAfter setting new secrets, restart pods to pick them up:
1ctl deploy restart --config productionCI/CD: deploying with an API key
Section titled “CI/CD: deploying with an API key”In CI, skip 1ctl auth login entirely. Set SATUSKY_API_KEY as an environment variable and 1ctl uses it directly:
SATUSKY_API_KEY=${{ secrets.SATUSKY_TOKEN }} 1ctl deploy --config productionSATUSKY_API_KEY takes priority over any stored context file. This is safe for ephemeral CI runners because no credential file is written to disk.
A complete GitHub Actions example that deploys staging on pull requests and production on merge to main:
name: Deploy
on: pull_request: branches: [main] push: branches: [main]
jobs: deploy-staging: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install 1ctl run: curl -fsSL https://install.satusky.com | sh - name: Deploy to staging env: SATUSKY_API_KEY: ${{ secrets.SATUSKY_TOKEN }} run: 1ctl deploy --config staging --wait
deploy-production: if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install 1ctl run: curl -fsSL https://install.satusky.com | sh - name: Deploy to production env: SATUSKY_API_KEY: ${{ secrets.SATUSKY_TOKEN }} run: 1ctl deploy --config production --waitSee CI/CD Integration for a deeper walkthrough including rollback patterns.
What to commit vs what to keep out
Section titled “What to commit vs what to keep out”| Item | Commit? |
|---|---|
satusky.toml | Yes |
satusky.staging.toml | Yes |
satusky.production.toml | Yes |
| Secret values | Never |
SATUSKY_API_KEY | Never — use CI secrets |
The config files contain only structural deployment spec. Secret values never touch the filesystem. Keep it that way.
Next steps
Section titled “Next steps”- CI/CD Integration — full GitHub Actions workflow with rollback
- Custom Domains — attach
api.myapp.comto the production deployment - Autoscaling — scale production based on traffic, keep staging at fixed replicas