7 små regler for secrets der redder dit team fra kaos
Secrets er ikke magi – det er bare ting du ville fortryde at lægge på Twitter
At håndtere secrets i et team er lidt som at have en nøgle til opgangen i et kollektiv. Alle skal kunne komme ind, men ingen har lyst til at være den, der mister nøglen og får en sur mail fra viceværten.
API keys, database-logins og tokens føles hurtigt som sådan noget “det ordner vi senere”. Indtil en .env-fil ryger med op på GitHub, eller nogen deler produktions-nøglen i en Slack-tråd, der aldrig forsvinder igen.
Jeg går igennem en lille playbook her: hvad et secret egentlig er, hvordan I bruger .env uden at lække alt, hvordan GitHub Actions og hosting-secrets spiller ind, og hvad I gør, når noget allerede er gået galt. Alt med udgangspunkt i et lille team uden enterprise-budget.
1. Hvad er et secret – og hvad er bare kedelig config?
Første regel: alt er ikke et secret. Hvis alt er hemmeligt, er intet det i praksis, for så ender det hele som kaos i en README eller i en tilfældig chat.
Typiske secrets:
- API nøgler (Stripe, SendGrid, Maps, osv.)
- Database credentials (brugernavn, password, connection string)
- JWT secret keys eller andre signeringsnøgler
- SSH-nøgler, private keys, OAuth client secrets
Typisk config, som ikke er secret:
- Feature flags (“SHOW_NEW_NAV” = true)
- Miljønavne (“NODE_ENV” = development / production)
- Offentlige API base-URLs
En simpel test: ville du have det ok med at lægge værdien i et offentligt GitHub repo? Hvis svaret er nej, så er det et secret. Hvis du er i tvivl, så er det som regel også et secret. Du kan dykke mere ned i forskellen i artiklen om hvordan miljøvariabler ofte bliver misbrugt allerede i udvikling.
2. Baseline i teamet – .env lokalt uden at lække
.env-filer er fine, hvis du accepterer én ting: de må aldrig ryge i git. Aldrig.
Minimum-opsætning for et lille team:
- En
.envlokalt hos hver udvikler - En
.env.examplei repoet uden rigtige secrets .envi.gitignore
Eksempel:
# .env.example
DATABASE_URL=<set i dit lokale miljø>
STRIPE_SECRET_KEY=<ikke commit denne>
NEXT_PUBLIC_API_BASE_URL=https://api.example.com
.env.example hjælper nye folk med at se, hvilke variabler der findes, uden at du deler nøgler i klartekst. Det gør onboarding meget mindre smertefuld.
Og ja, du kommer en dag til at skrive git add . for hurtigt. Derfor er det en god idé at kombinere det her med lidt “repo hygiene”, som jeg vender tilbage til.
3. CI og hosting – secrets der ikke bor i koden
Når det kun er dig og din egen laptop, kan du slippe afsted med ret meget. Når der kommer CI/CD (fx GitHub Actions) og en hostingplatform (Vercel, Netlify, Fly.io, whatever) ind i billedet, skal secrets bo et andet sted end i .env-filer, der ligger og flyder.
GitHub Actions secrets i praksis
Flowet er ret simpelt:
- Læg secrets ind under Settings → Secrets and variables → Actions
- Brug dem i workflows som
${{ secrets.MIT_SECRET_NAVN }}
Eksempel på workflow:
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm test
Bemærk: vi mapper secret ind i env på job-niveau. Det gør det tydeligt, hvilke jobs der faktisk har adgang til hvad. Det passer godt ind i en generel forståelse af deployment og drift, hvor du helst vil kunne se, hvem der rører ved hvad.
Vercel / Netlify / lignende
I hosting-panelet har du typisk tre miljøer: Development, Preview, Production. Brug dem.
- Prod-nøgler må kun ligge under Production
- Dev og preview kan bruge test-nøgler
Det vigtige er, at du ikke længere pusher .env til serveren manuelt. Serveren læser fra sine egne secrets, og din CI pusher kun koden.
4. Hvem må se hvad – del op mellem dev og prod
Her går mange små teams forkert: alle har adgang til alt. Det føles nemt i starten, men det gør enhver læk meget værre.
En simpel model, der faktisk kan bruges uden enterprise-adgangskontrol:
- Dev secrets: alle i dev-teamet må se dem. De er bundet til testmiljøer og falske data.
- Prod secrets: kun folk der deployer eller drifter systemet til daglig, må have direkte adgang.
Det kan være så lavteknologisk som:
- En person der opretter prod-nøgler og lægger dem ind i Vercel/Netlify/GitHub
- En kort intern note: “Prod-keys ligger kun i hosting og Actions, ikke i vores personlige .env”
Og nej, det er ikke perfekt. Men det gør forskel, når nogen får adgang til nogens laptop, eller nogen kommer til at uploade sin egen .env til en bug report.
5. Rotation af secrets – hvornår og uden downtime
Secret rotation lyder meget større end det er. I praksis er det bare: få lavet en ny nøgle, skift den ind, og invalidér den gamle.
Hvornår bør I rotere?
- Når en person forlader teamet
- Når en .env-fil er havnet et forkert sted (fx i et delt drive eller en forkert chat)
- Efter et muligt leak i repoet (mere om det lige om lidt)
- Som fast rutine, fx hver 3. eller 6. måned for de vigtigste nøgler
Hvordan roterer man uden at vælte alt?
En sikker og nogenlunde smertefri metode:
- Opret ny nøgle i den tjeneste du bruger (fx ny API key i Stripe).
- Læg både gammel og ny ind som gyldige et kort stykke tid, hvis tjenesten tillader det.
- Opdater dine secrets i hosting/CI til at bruge den nye nøgle.
- Deploy.
- Tjek at alt virker (logins, betalinger, jobs osv.).
- Fjern den gamle nøgle hos tredjeparten.
Hvis tjenesten ikke understøtter overlappende nøgler, så planlæg et lille “maintenance” vindue og vær klar til at rulle hurtigt tilbage, hvis noget knækker.
6. Hvis en nøgle er lækket – stop blødningen i 6 trin
På et tidspunkt sker det. En .env i et offentligt repo, en screenshot i et issue, en nøgle postet i den forkerte Slack-kanal. Jeg har selv prøvet det med en test-Stripe nøgle. Det er ikke sjovt, men det er til at overleve, hvis du handler hurtigt.
6-trins “jeg har lige lækket en nøgle” checkliste
- Bliv specifik – hvilken nøgle, til hvilken tjeneste, og hvilket miljø (dev/prod)?
- Fjern eksponeringen – gør repo privat, slet beskeden, fjern skærmbilledet.
- Revokér nøglen i den eksterne tjeneste (Stripe, SendGrid, database osv.).
- Opret en ny nøgle og læg den ind de rigtige steder (hosting, CI, lokale .env).
- Deploy en version der kører med de nye secrets.
- Kig logs igennem for mærkelig aktivitet i tidsrummet mellem læk og rotation.
Det her er også grunden til, at du altid skal kunne rotere hurtigt. Hvis rotation føles som en kæmpe operation, udskyder folk den, og så står man med noget meget værre, hvis nøglen bliver misbrugt.
Hvis du vil øve din evne til at reagere roligt, er det faktisk en fin øvelse at lave et lille test-setup og “lege” læk, mens du holder øje med logs og stacktraces.
7. Scan, tjek og automatisér de kedelige ting
Det sidste lag er automation. Du behøver ikke en kæmpe security-platform for at undgå de værste fejl.
Git-ignore og scanning
Nogle basale ting, som sparker jer ret langt:
- Sørg for at
.env,.env.*og evt..env.localligger i.gitignore - Brug en pre-commit hook til at stoppe commits med åbenlyse secrets
Eksempel med pre-commit (Python-værktøj, men fungerer fint i JS-projekter):
# .pre-commit-config.yaml
repos:
- repo: https://github.com/zricethezav/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
Så får du en fejl, inden du overhovedet pusher, hvis du har smidt noget ind der ligner en API-nøgle. Ikke perfekt, men det fanger mange “ups”-øjeblikke.
Audit light – et lille overblik over jeres secrets
Du behøver ikke et stort system for at få et overblik. Et simpelt shared dokument eller README i et privat repo kan faktisk hjælpe meget, hvis I gør det ordentligt:
- Liste over hvilke secrets der findes (navn og formål, ikke selve værdien)
- Hvor de er konfigureret (GitHub Actions, Vercel, Netlify osv.)
- Hvornår de sidst blev roteret, og af hvem
Det gør det meget lettere, når I en dag står med en mistanke om læk og skal tjekke, hvad der overhovedet fandtes. Det passer faktisk rigtig godt ind i samme tankegang som at have styr på projektstruktur og arkitektur: kæden skal kunne følges uden at gætte.
En lille playbook du kan bruge i morgen
Hvis du lige nu tænker “det her er meget fint, men vi har nul tid og tusind andre ting”, så her er den absolut mindste pakke, jeg ville indføre i et lille team:
- .env lokalt + .env.example i repoet
- .env i .gitignore + en simpel secret-scanner i pre-commit
- GitHub Actions secrets i stedet for env-ting hårdkodet i workflows
- Prod-secrets kun i hosting/CI, aldrig i personlige .env-filer
- En kort tekstfil med jeres 6-trins “vi har lækket en nøgle” plan
Det er ikke perfekt sikkerhed. Men det flytter jer fra “alt ligger i en zip-fil på skrivebordet” til noget, der faktisk kan holde til, at I bliver flere på holdet.
Jeg opdagede selv hvor skrøbeligt det hele var, da jeg en sen aften fandt en gammel .env i et arkiv på min egen maskine med en produktions-database-url i. Jeg havde glemt, den fandtes. Min kat gik selvfølgelig over tastaturet, mens jeg febrilsk roterede nøgler og fik styr på tingene. Det var der, jeg besluttede, at secrets helst skal være kedelige og meget forudsigelige, ikke noget der først bliver spændende, når alt brænder.









Send kommentar
Du skal være logget ind for at skrive en kommentar.