131% fler rapporterade CVE:er per dag 2026 än förra året.

Runners

Så byter du runnerleverantör för GitHub Actions: etiketter, cacher, hemligheter, fakturering och reservlösning

För att byta kopplar du leverantören (oftast via en GitHub App), ändrar runs-on till dess etikett och kör jobbet. Kontrollera sedan sex saker som etikettbytet inte hanterar: runner-imagen, cacher, nätverksidentitet, OIDC-förtroende, reservlösning och fakturering. Börja med ett pilotrepo, med ett byte som du kan ångra med en enda ändring.

Uppdaterad

Den här guiden är leverantörsneutral. Den förklarar vad som flyttas när du byter runnerleverantör för GitHub Actions, vad som oftast går sönder och hur du backar. Vi bygger CRACI, en av leverantörerna; den nämns där ett dokumenterat faktum gäller, och i ett eget avsnitt i slutet. För att först välja leverantör, se runnerleverantörer för GitHub Actions i jämförelse och alternativ till GitHub-hostade runners.

Vad som ändras och vad som stannar när du byter

GitHub Actions har två halvor. GitHub är kontrollplanet: det lagrar repot och arbetsflödesfilerna, utlöser triggers, lagrar hemligheter, tilldelar jobb, visar loggar och checks, sparar artefakter och utfärdar OIDC-token. CI-runnern är där ett jobb körs: en maskin med en image, CPU, disk, en nätverksväg ut till internet och oftast en lokal cache. GitHub tilldelar ett jobb till en runner, levererar jobbets hemligheter när det startar, och runnern strömmar tillbaka loggarna.

En runnerleverantör ersätter bara den andra halvan.

Del Stannar hos GitHub Flyttas till leverantören
Repo, arbetsflödesfiler, triggersJaNej
Lagring av hemligheterJaHemligheter levereras till leverantörens maskin när jobbet startar
Tilldelning av jobb, loggar, gränssnitt för checksJaRunnern strömmar tillbaka loggarna
Artefakter från actions/upload-artifactJaNej
Utfärdare av OIDC-tokenJaNej, men token anger att runnern är egenhostad
Maskin, image, CPU, minne, diskNejJa
Utgående nätverksväg och IP-adresserNejJa
CachelagringBeror på leverantörenBeror på leverantören
Debitering per minut för de flyttade jobbenNejJa

En runner från tredje part registreras hos GitHub som en egenhostad runner. Därför gäller GitHubs regler för egenhostade runners för den: hur etiketter dirigerar jobb, hur runnergrupper begränsar åtkomst, hur OIDC-token beskriver den och hur GitHub fakturerar den.

Ändringen av runs-on och etiketter

GitHub letar efter en runner som matchar jobbets runs-on-etiketter och grupper. Om ingen matchande runner är online står jobbet i kö tills en kommer online; om en tilldelad runner inte plockar upp jobbet inom 60 sekunder köas det om; och ett jobb som står i kö i mer än 24 timmar misslyckas (GitHubs referens för egenhostade runners). Ett stavfel i en etikett, eller en leverantörsapp som inte är installerad på repot, syns som ett jobb som aldrig startar.

Leverantörerna anger maskinen på ett av två sätt:

  • I etiketten. Ubicloud använder etiketter som ubicloud-standard-2, Blacksmith blacksmith-2vcpu-ubuntu-2404 och Avrea avrea-ubuntu-latest-2-vcpu, med arm i etiketten för ARM-maskiner. Att byta storlek innebär att byta etikett.
  • I ett setup-steg. CRACI använder en etikett, runs-on: craci, och steget cracicorp/setup@v1 väljer storlek (1 till 32 beräkningsenheter med 1 vCPU och 3 GB, standard 2), image, nätverkspolicy eller en runnermall för organisationen via dess slug. Om CRACI inte kan tolka en indata kör den standardmiljön och skriver en varning i jobbloggen; en okänd image eller mall avvisas.

Gör bytet till en variabel

Lägg etiketten i en variabel på repo- eller organisationsnivå i stället för att hårdkoda den. Att byta fram eller tillbaka blir då en ändring i inställningarna, inte en pull request i varje repo.

jobs:
  build:
    # Falls back to GitHub-hosted when the variable is not set
    runs-on: ${{ vars.LINUX_RUNNER || 'ubuntu-latest' }}
    steps:
      - uses: actions/checkout@v7
      - run: make build

  deploy:
    needs: build
    # Stays on GitHub-hosted until you decide to move it
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

Valet görs per jobb, så bygg- och testjobb kan flyttas medan ett deployjobb stannar. Variabler kan sättas på organisationsnivå och åsidosättas per repo, så en inställning kan flytta en grupp repon och ett enskilt repo kan välja bort det.

Återanvändbara arbetsflöden

Om samma pipeline är kopierad till många repon, flytta den till ett återanvändbart arbetsflöde som läser runnern från en indata eller en variabel. Att ändra runs-on där ändrar varje repo som anropar det. Med rulesets kan du kräva att ett arbetsflöde körs i organisationens repon, vilket håller den delade versionen i bruk.

Runner-images: kompatibilitet och låsning

GitHubs hostade image har en stor uppsättning förinstallerade verktyg och en hostad verktygscache. Leverantörerna erbjuder antingen en image som är kompatibel med GitHubs eller en slimmad. Jobb är ofta beroende av saker de aldrig deklarerar:

  • förinstallerade språkversioner och kommandoradsverktyg;
  • sudo utan lösenord, och systemd för tjänster som startas med systemctl;
  • en Docker-daemon som körs, med Buildx och Compose;
  • den hostade verktygscachen som setup-*-actions läser innan de laddar ner;
  • ledigt diskutrymme för stora byggen.

Tumregel: börja på leverantörens GitHub-kompatibla image. Flytta ett jobb till en slimmad image först när det är grönt, och lägg till uttryckliga setup-*-steg för allt som det använde implicit.

Låsning: ubuntu-latest flyttas till en ny version enligt GitHubs schema, och ubuntu-24.04 låser operativsystemets version, inte paketversionerna på den. Lås det som spelar roll inne i jobbet: setup-actions med uttryckliga versioner och containerimages via digest. Fråga varje leverantör vad den låter dig låsa. Själva runner-applikationen måste fortsätta uppdateras för att kunna prata med GitHub.

På CRACI finns imagen CRACI Slim på x86-64 och ARM64 (Ubuntu 24.04, utan systemd) och en fullständig Ubuntu 24.04-image som är kompatibel med GitHub Actions, vald som ubuntu-24.04 eller ubuntu-latest, som följer GitHubs runner-image för Ubuntu 24.04 och innehåller den hostade verktygscachen. Varje image har Docker Engine, Buildx och Compose v2.

Cacher: vad som följer med och vad som börjar kallt

De första körningarna hos en ny leverantör är ofta långsammare, och den vanliga orsaken är en kall cache, inte en långsam maskin. Hur actions/cache fungerar avgör vad du ser (README för actions/cache):

  • En post hittas via sin nyckel och en version, som är en hash av de cachade sökvägarna och komprimeringsverktyget.
  • Poster är avgränsade per gren; standardgrenens poster är tillgängliga för andra grenar.
  • Som standard kan ett repo ha upp till 10 GB cacher innan de äldsta posterna rensas bort. Repo-administratörer och ägare av organisationen eller enterprise-kontot kan höja gränsen; användning över 10 GB faktureras kontot (GitHub om dependency caching).
  • En cache som sparats på Windows återställs inte på ett annat operativsystem, eller tvärtom, om inte enableCrossOsArchive är satt; ett annat komprimeringsverktyg ger också en annan version.

Leverantörerna serverar cachen på ett av två sätt:

Modell Första körningarna Avvägning
Runnern använder GitHubs cachetjänst, precis som GitHub-hostade runners Befintliga poster återställs Cachetrafiken går över internet mellan leverantören och GitHub
Leverantören serverar cache-API:t från lagring bredvid sina runners Oftast tom tills de första körningarna fyller den, om inte leverantören importerar eller faller tillbaka på GitHubs poster Snabbare återställning; poster som skrivs där syns oftast inte för GitHub-hostade runners

Den andra punkten spelar roll för blandade flottor och för återställning: om du byter tillbaka ett jobb kan det börja kallt även på GitHub. Fråga vilken modell leverantören använder och var posterna finns.

Så skiljer du en kall cache från en långsam runner. Ta ett Node-bygge som cachar en stor node_modules-katalog. Vid första körningen hos en ny leverantör rapporterar actions/cache en miss, installationssteget laddar ner allt och efterstegen sparar cachen. Från nästa körning på samma gren rapporterar steget en träff och installationssteget krymper. Jämför körningar först när cachen är varm: läs utdatat cache-hit och mät återställningssteget och installationssteget separat från själva bygget. Se hur GitHub Actions-cachen fungerar för nycklar, avgränsningar och cacheförgiftning.

På CRACI fungerar actions/cache som i dag, och byggregistreringen markerar per paket om det återställdes från en CI-cache i stället för att hämtas.

Cachning av Docker-lager

Mekanism Var lagren finns Bra att veta
BuildKit type=gha GitHub Actions-cachen Samma regler för avgränsning och storlek som ovan; den kräver en builder som stöder den
BuildKit type=registry En separat image i ditt register Fungerar på alla runners och överlever ett leverantörsbyte; du betalar för lagring och överföring i registret
Leverantörens lokala lagercache eller beständiga disk Bredvid leverantörens runners Oftast snabbast; blir kvar om du lämnar leverantören

En registercache är det portabla alternativet (Dockers cache-backends):

- uses: docker/build-push-action@v7
  with:
    push: true
    tags: ghcr.io/acme/app:latest
    cache-from: type=registry,ref=ghcr.io/acme/app:buildcache
    cache-to: type=registry,ref=ghcr.io/acme/app:buildcache,mode=max

Två jobb som startar samtidigt återställer samma cache och bygger båda de lager som saknas. Det händer i all CI, så tolka det inte som ett leverantörsproblem.

CRACI erbjuder cachning av containerlager med en lokal lagercache, en fjärrlagercache och en bind mount-cache.

Hemligheter, OIDC och molnuppgifter

GitHub lagrar dina hemligheter och levererar dem till den runner som kör jobbet. Att flytta ett jobb till en leverantör innebär att du anförtror leverantören det jobbets hemligheter. Fråga:

  • Får varje jobb en egen virtuell maskin, eller en container på en delad värd?
  • Förstörs maskinen efter jobbet, och sparas något?
  • Vilka loggar sparar leverantören? GitHub maskerar registrerade hemligheter i jobbloggar och anger att automatisk maskering inte är garanterad för omvandlade värden; fråga också om leverantörens egna systemloggar.

OIDC fortsätter att fungera, med en hake. Det är GitHub som utfärdar OIDC-token, inte runnern, så permissions: id-token: write fungerar på alla runners. Men tokenens claim runner_environment är github-hosted eller self-hosted (GitHubs OIDC-referens), och på en runner från tredje part är det self-hosted. En förtroendepolicy i molnet som kräver github-hosted avvisar jobbet. Till exempel en workload identity pool i Google Cloud med det här attributvillkoret:

# Before: only GitHub-hosted runners in the acme organization
assertion.repository_owner == 'acme' && assertion.runner_environment == 'github-hosted'

# After: drop the runner check, and narrow by repository and branch instead
assertion.repository == 'acme/app' && assertion.ref == 'refs/heads/main'

Att ta bort runnerkontrollen vidgar vem som kan få inloggningsuppgifter, så skärp ett annat villkor samtidigt. Sök före bytet igenom varje förtroendepolicy i molnet och varje konfiguration för workload identity efter runner_environment.

Pusha images: GITHUB_TOKEN med packages: write pushar till GitHub Container Registry från alla runners, och registerinloggningar som använder lagrade hemligheter fungerar oförändrat.

På CRACI läser GitHub-appen din kod och dina Actions-körningar och hanterar de runners som den registrerar för din organisation. Varje jobb körs i en egen isolerad virtuell maskin, och CRACI lagrar inte din källkod.

Nätverksidentitet: IP-tillåtelselistor och egress

Den nya runnern ansluter från nya IP-adresser. Lista allt som filtrerar på källadress:

  • tillåtelselistor för databaser och artefaktrepon;
  • SaaS-API:er med IP-begränsningar;
  • partners SFTP-servrar och interna tjänster bakom en brandvägg.

Alternativen är leverantörens statiska eller stabila utgående IP-adresser, eller en proxy som du kontrollerar. Det är också läget att bestämma vad jobb alls får nå: en egress-policy på runnern hindrar ett komprometterat beroende från att skicka hemligheter till en värd som bygget aldrig behövde. Se egress-policy för GitHub Actions.

CRACI erbjuder ett stabilt utgående IP-intervall och en egress-policy, som nekar eller tillåter som standard, som valideras innan jobbet startar och blockerar vid fel. Utan indata för network tillåter standardmallen andra utgående anslutningar, så kontroll av egress är något du konfigurerar.

Blandade flottor: flytta Linux, behåll macOS och iOS där de är

Runnern väljs per jobb, så ett arbetsflöde kan köra sina Linux-jobb hos en leverantör och sina macOS-jobb på GitHub-hostade runners. Artefakter som laddas upp med actions/upload-artifact lagras av GitHub, så ett jobb på en runner kan lämna över filer till ett jobb på en annan.

jobs:
  backend:
    runs-on: ${{ vars.LINUX_RUNNER || 'ubuntu-latest' }}
    steps:
      - uses: actions/checkout@v7
      - run: ./gradlew test

  android:
    runs-on: ${{ vars.LINUX_RUNNER || 'ubuntu-latest' }}
    steps:
      - uses: actions/checkout@v7
      - run: ./gradlew assembleRelease
      - uses: actions/upload-artifact@v7
        with:
          name: android
          path: app/build/outputs/apk/release/

  ios:
    # Signing and the iOS build stay on GitHub-hosted macOS
    runs-on: macos-latest
    needs: backend
    steps:
      - uses: actions/checkout@v7
      - run: xcodebuild -scheme App -configuration Release archive

Jobben som ligger kvar på GitHub drar fortfarande från planens inkluderade användning och faktureras av GitHub utöver den. CRACI kör i dag Linux på x86-64 och ARM64, med Windows och macOS på roadmapen, så en blandad flotta med CRACI innebär CRACI för Linux och GitHub-hostade runners för resten.

Reservlösning när en leverantör ligger nere

GitHub har ingen inbyggd reservlösning mellan runner-etiketter. Om ingen runner för etiketten är online väntar jobbet, och efter 24 timmar misslyckas det. Planera för det:

  • Variabelbytet ovan: sätt tillbaka den till ubuntu-latest så går nya körningar till GitHub-hostade runners.
  • En manuell åsidosättning för brådskande körningar: en indata för workflow_dispatch, läst som runs-on: ${{ inputs.runner || vars.LINUX_RUNNER || 'ubuntu-latest' }}.
  • timeout-minutes på jobb, så att ett jobb som hänger sig inte blockerar en driftsättning i timmar.
  • Övervakning av kötid, så att du märker när jobb väntar längre än vanligt.

Fråga varje leverantör om den erbjuder en automatisk reservlösning och vad som utlöser den. Planera också för det omvända: GitHub köar och tilldelar varje jobb, så ett avbrott i GitHub Actions stoppar jobb hos alla runnerleverantörer också.

Fakturering: tar GitHub fortfarande betalt?

GitHub tar inte betalt per minut för egenhostade runners, och runners från tredje part registreras som egenhostade, så de minuter du flyttar försvinner från GitHub-fakturan (fakturering för GitHub Actions). GitHub fakturerar fortfarande:

  • licenser i din plan;
  • lagring av artefakter och cacher utöver den inkluderade mängden;
  • jobb som ligger kvar på GitHub-hostade runners, utöver planens inkluderade användning, som inte återbetalas.

Under piloten betalar du två fakturor. Leverantörerna räknar byggminuter olika: GitHub avrundar varje jobb uppåt till hel minut, och vissa leverantörer mäter per sekund. För att uppskatta din användning före och efter, använd kostnadskalkylatorn för GitHub Actions. CRACI tar bara betalt för byggminuter: $0.002 per vCPU-minut ($0.004 för en standardrunner med 2 vCPU), mätt per sekund, utan månadsavgift.

Säkerhetsisolering: vad du bör fråga alla leverantörer

Fråga Varför det spelar roll
En virtuell maskin per jobb, eller containrar på en delad värd? En delad värd låter ett komprometterat jobb nå sina grannar
Förstörs maskinen efter jobbet? En beständig maskin för med sig filer, inloggningsuppgifter och processer till nästa jobb
Var finns hårdvaran, och vem driver den? Dataplats, jurisdiktion och dina kunders avtal
Vad lagrar leverantören, och hur länge? Loggar, cacher och nätverksdata kan innehålla känsligt material
Vilka certifieringar har den? Din leverantörsgranskning kommer att fråga
Kan du kontrollera egress? Hindrar hemligheter från att lämna via ett skadligt paket
Vad kan dess GitHub App läsa och ändra? Appens behörigheter gäller varje repo som du installerar den på

GitHub säger att egenhostade runners nästan aldrig bör användas för publika repon, eftersom vem som helst kan öppna en pull request och kompromettera miljön, och att just-in-time-runners kör högst ett jobb innan de tas bort (GitHubs referens för säker användning). En ny virtuell maskin per jobb besvarar det mesta av den oron.

CRACI:s svar: varje jobb körs i en egen isolerad virtuell maskin på europeisk bare metal-infrastruktur. CRACI Corporation Oy:s ledningssystem för informationssäkerhet, för utveckling och drift av CRACI-plattformen, är certifierat enligt ISO/IEC 27001 av Into Certification, med detaljer i Trust Center. CRACI lagrar byggmetadata, paketdata, nätverksspårningar, SBOM:er, proveniens, cacher och granskningsposter, och aldrig din källkod. Se vad CRACI kan nå och säkerhet.

Provkör ett repo först

  1. Välj ett repo med ett representativt, ofta kört Linux-arbetsflöde, inte releasepipelinen.
  2. Mät en baslinje på GitHub-hostade runners: mediantid och mediankötid för de senaste 30 körningarna, och fakturerade minuter.
  3. Installera leverantörens GitHub App på bara det repot.
  4. Byt ett jobb via repovariabeln, på en gren.
  5. Kör det minst tio gånger, och bortse från de tre första som uppvärmning av cachen.
  6. Jämför körtid, kötid, cacheträffar, fel och kostnad; kontrollera loggar, OIDC och utgående anrop.
  7. Rulla tillbaka genom att ändra variabeln, och bekräfta att jobbet går tillbaka till GitHub-hostade runners.
Mått Baslinje på GitHub-hostade Leverantör Godkänt om
Mediantid per jobbDitt mål, till exempel 30 % kortare
MediankötidInte sämre än baslinjen
Andel cacheträffar efter uppvärmningSamma som baslinjen
Misslyckade körningar som inte orsakats av kodenInga
Kostnad per körningUnder baslinjen
OIDC, tillåtelselistor och utgående anropAllt fungerar

Mät hastigheten på ditt eget arbetsflöde. Varje leverantör publicerar sina egna siffror, och den enda siffra som avgör ditt fall är den från din pipeline.

Var CRACI passar in

CRACI är en runner för GitHub Actions. Den ersätter runnern, inte GitHub Actions: ett jobb flyttas med runs-on: craci, storlekar och images ställs in med cracicorp/setup@v1 eller en runnermall för organisationen, och körningarna syns fortfarande i GitHub. CRACI kör byggen ungefär dubbelt så snabbt som GitHub-hostade runners, tack vare snabbare hårdvara, kortare kötider och cachning.

Skälet att välja den framför andra leverantörer är vad varje jobb lämnar efter sig: en SBOM över det som bygget hämtade, med en fullständighetsstatus, registrerad under en egress-policy som blockerar vid fel. docs.craci.com erbjuder också en prompt för kodagenter som föreslår en migreringsplan per jobb för dina arbetsflöden. Se CI/CD-integration.

När CRACI inte är svaret

  • Du behöver macOS- eller Windows-runners: de finns på CRACI:s roadmap.
  • Du kör GitHub Enterprise Server, som CRACI inte stöder.
  • Din CI är GitLab CI eller Jenkins: båda finns på roadmapen.
  • Runnerna måste ligga i ditt eget molnkonto: kundhostade runners finns på roadmapen. RunsOn och WarpBuilds alternativ med eget moln gör det redan i dag; se CRACI vs RunsOn och CRACI vs WarpBuild.
  • Ditt huvudmål är observerbarhet och felsökning i CI; se CRACI vs Avrea. För att köra egna runners, se hanterade och egenhostade runners.

Byta runnerleverantör: vanliga frågor

Vad behöver jag ändra för att använda en annan runnerleverantör för GitHub Actions?

Installera leverantörens GitHub App och ändra sedan jobbets runs-on-etikett till leverantörens etikett. Arbetsflöden, triggers, hemligheter och GitHubs gränssnitt förblir desamma. Innan du flyttar viktiga jobb bör du kontrollera runner-imagen, cacher, utgående IP-adresser, molnets förtroendepolicyer som använder OIDC, reservlösning och fakturering.

Följer mina GitHub Actions-cacher med till en ny runnerleverantör?

Det beror på varifrån leverantören serverar cachen. Om dess runners använder GitHubs cachetjänst återställs befintliga poster. Om den serverar cache-API:t från lagring bredvid sina runners börjar cachen oftast tom och fylls under de första körningarna. Fråga leverantören vilken modell den använder, och om poster som skrivs på dess runners syns för GitHub-hostade runners.

Fungerar cachning av Docker-lager på runners från tredje part?

Ja, med någon av tre mekanismer: BuildKits type=gha-backend, som använder Actions-cachen; en registercache med type=registry, som fungerar på alla runners; eller en lagercache eller beständig disk som leverantören håller bredvid sina runners.

Kan jag behålla macOS- och iOS-byggen på GitHub medan Linux-jobben flyttas?

Ja. Runnern väljs per jobb, så Linux-jobb kan köras hos en leverantör medan macOS-jobb stannar på GitHub-hostade runners i samma arbetsflöde. Koppla ihop dem med needs: och skicka filer med actions/upload-artifact och actions/download-artifact, som GitHub lagrar.

Vad händer med ett jobb om runnern från tredje part ligger nere? Finns det en reservlösning?

GitHub har ingen inbyggd reservlösning mellan runner-etiketter. Ett jobb vars etikett inte matchar någon runner online står kvar i kön och misslyckas efter 24 timmar. Lägg etiketten i en variabel på repo- eller organisationsnivå så att det räcker med en ändring för att byta tillbaka, sätt timeout-minutes och fråga varje leverantör om den erbjuder en egen reservlösning.

Fungerar hemligheter och OIDC fortfarande på runners från tredje part?

Ja. GitHub lagrar hemligheterna och levererar dem till runnern när jobbet startar, och GitHub utfärdar OIDC-token, så id-token: write fungerar på alla runners. Haken: tokenens claim runner_environment är self-hosted på en runner från tredje part, så en förtroendepolicy i molnet som kräver github-hosted avvisar jobbet.

Fakturerar GitHub fortfarande minuter om jag använder en annan runnerleverantör?

Inte för de jobb du flyttar. Runners från tredje part registreras hos GitHub som egenhostade runners, och GitHub anger att egenhostade runners inte debiteras per minut. GitHub fakturerar fortfarande licenser, lagring utöver den inkluderade mängden och jobb som ligger kvar på GitHub-hostade runners. Leverantören fakturerar sina egna minuter.

Hur låser jag runner-imagen så att den inte ändras under mig?

ubuntu-latest flyttas enligt GitHubs schema, och ubuntu-24.04 låser operativsystemets version men inte paketversionerna på den. Lås det som spelar roll inne i jobbet: setup-actions med uttryckliga versioner och containerimages via digest. Fråga varje leverantör vad den låter dig låsa; själva runner-applikationen måste uppdateras för att fortsätta fungera med GitHub.

Hur isoleras jobb från varandra på en runner från tredje part?

Leverantörerna skiljer sig åt. Fråga om varje jobb får en egen virtuell maskin eller en container på en delad värd, om maskinen förstörs efter jobbet och vad leverantören sparar efteråt. En ny virtuell maskin per jobb är den starkaste av de vanliga modellerna, eftersom inget från ett jobb finns kvar till nästa.

Hur testar jag en runnerleverantör på ett repo först?

Installera leverantörens GitHub App på ett repo, byt ett ofta kört Linux-jobb via en repovariabel på en gren, kör det minst tio gånger och jämför körtid, kötid, cacheträffar, fel och kostnad mot en baslinje på GitHub-hostade runners. Rulla tillbaka genom att ändra variabeln.

Flytta ett arbetsflöde tillsammans med oss

Boka en demo så flyttar vi ett av dina arbetsflöden till CRACI tillsammans med dig och jämför sedan körtid, kostnad och den SBOM som skapades.

Boka en demo