Fra null til live URL med Coolify
I disse urolige tider er det greit å vite hvilke alternativer vi har til de store amerikanske PaaS'ene. Jeg har begynt å se nærmere på Coolify, et open source-prosjekt som kan installeres på en Hetzner-server på få minutter. Fordelen er full kontroll, europeisk infrastruktur og ingen månedlig abonnementsregning for annet enn serverleie. Ulempen er at man ikke kommer til dekket bord slik man gjør med f.eks. Heroku, og at man må drifte maskinen selv.
I denne posten tar jeg alle snarveiene jeg kan i installasjon og oppsett for å komme raskt i gang med å teste Coolify. I neste post lager jeg et mer automatisert og strømlinjeformet oppsett som er raskere, sikrere og lettere å reprodusere.
Målet er å gjøre det enklere (og kanskje også billigere) for utviklere å hoste sine hobbyprosjekter på europeisk infrastruktur.
Hva er Hetzner?
Hetzner er en tysk leverandør av skytjenester, hosting og dedikerte servere, kjent for høy ytelse, lave priser og pålitelige løsninger.
Når jeg skal velge en europeisk skyleverandør er det naturlig å se på listen til Choose European.
Valget mitt falt på Hetzner pga pris og rykte.
Installasjon på Hetzner
Jeg logger inn på Hetzner Cloud Console og velger "Add Server" i default-prosjektet. Nå er jeg klar til å konfigurere serveren.
Type
Dokumentasjonen til Coolify sier:
(Coolify) Minimum Hardware Requirements
Your server should have at least:
CPU: 2 cores
Memory (RAM): 2 GB
Storage: 30 GB of free space
Siden jeg tar alle snarveiene jeg kan, kjører jeg Coolify, byggserver og applikasjonene på samme server.
Dokumentasjonen gir et eksempel på spesifikasjoner og hvor mye det er hensiktsmessig å kjøre på en slik server:
Andras runs his production apps on a server with:
Memory: 8GB (average usage: 3.5GB)
CPU: 4 cores (average usage: 20–30%)
Storage: 150GB (average usage: 40GB)
This setup comfortably supports:
3 NodeJS apps
4 Static sites
Plausible Analytics
Fider (feedback tool)
UptimeKuma (uptime monitoring)
Ghost (newsletters)
3 Redis databases
2 PostgreSQL databases
Det ser med andre ord ut som om jeg kommer langt med CAX21; en ARM64-server med 4 CPU, 8 GB minne og 80 GB disk til EUR 7,49 (ca. 80 kr) per måned. Jeg velger ARM64 utelukkende fordi det er billigere enn x86 (Intel/AMD).
En fin ting med Hetzner er at jeg betaler per time, ikke per måned. CAX21 koster EUR 0,012 per time, så å opprette en server for å leke litt med Coolify og så slette den igjen koster mindre enn en plastpose på butikken.

Location
På valg av location velger jeg "Helsinki - eu-central" fordi jeg ønsker en server i Europa som ligger nærmest mulig Norge.
Image
I stedet for å velge blant "OS Images" velger jeg Coolify fra "Apps".

Når jeg velger dette og starter serveren, installeres Coolify automatisk ved første innlogging.
Networking
Jeg lar denne stå urørt (både IPv4 og IPv6 er forhåndsvalgt).
SSH keys
Siden jeg allerede har lastet opp en ssh-nøkkel, får jeg mulighet til å velge denne. SSH-nøkkelen brukes for å gi meg tilgang til serveren. Hvis man ikke laster opp noen ssh-nøkkel, får man tilsendt rot-passord på e-post.
Volumes, Firewalls, Backups, Placement groups, Labels, Cloud config
Alle disse lar jeg stå urørt.
Name
Jeg gir serveren et beskrivende navn: coolify
Create & Buy now
Jeg trykker på "Create & Buy now"; serveren provisjoneres i løpet av ca 1 minutt. Coolify installeres nå så snart jeg logger inn vha ssh; det kan ta et par minutter.
Oppsett av Coolify
Opprett superbruker
Jeg åpner nettleseren og går til http://server-ip:8000 (IP-adressen finner jeg i Hetzner-panelet).

Her oppretter jeg en bruker og passord som skal være eier av Coolify-instansen.
Dette kjører over http, så det vil være mulig å snappe opp både brukernavn og passord. Dette passordet må jeg med andre ord bytte når https er oppe.




Sette opp domene
For å få på https trenger jeg et domene.
Jeg setter opp følgende i Domeneshop:
<mitt-domene>.no. 300 IN A <server-ip>
*.<mitt-domene>.no. 300 IN A <server-ip>
Den siste linjen gjør at Coolify selv kan ta kontroll over subdomener.
DNS-oppføringen må ha propagert før jeg kan gå videre. Dette kan jeg kontrollere på f.eks. https://dnschecker.org
HTTPS
Nå konfigurerer jeg domene for admin-grensesnittet. Ved å skrive https vil Coolify ordne sertifikat via Let's Encrypt. Dette kan ta noen minutter.

Deploy av prototype
Jeg har en prototype jeg ønsker å dele med andre. Istedenfor å bruke ngrok, som krever at min maskin er på og tilgjengelig, kan jeg nå deploye til Coolify og få en permanent URL.
Prototypen består av en Storybook med en komponent og en applikasjon som bruker komponenten i en realistisk kontekst.
For å få kortest mulig feedback-loop har jeg valgt å deploye ved hjelp av Dockerfile. Jeg har laget en Dockerfile med multi-stage build: første steg bygger alt med Node, andre steg kopierer kun de statiske filene inn i et minimalt Nginx-image. På denne måten har jeg full kontroll over hvilke verktøy som er tilgjengelig i byggemiljøet uten at de havner i den kjørende containeren.
# Stage 1: Bygg applikasjon og Storybook
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --legacy-peer-deps
COPY . .
# Bygg Storybook
RUN npx storybook build --output-dir=storybook-static
# Bygg applikasjonen som inneholder komponenten i kontekst
RUN VITE_BASE_PATH=/komponent-i-realistisk-kontekst/ npm run build
# Stage 2: Opprett et minimalistisk image for produksjon
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
# Kopier statiske filer direkte til Nginx sin root-mappe
COPY --from=builder /app/storybook-static ./storybook
COPY --from=builder /app/dist ./komponent-i-realistisk-kontekst
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Jeg tester dette lokalt ved å bygge imaget:
docker build -t prototype .
og kjøre det:
docker run -p 8080:80 prototype
Når det fungerer på localhost:8080 er jeg klar for å pushe koden til Codeberg. Codeberg er et europeisk,
open source-alternativ til GitHub, og passer godt med temaet i denne posten; europeisk infrastruktur hele veien.
Tilbake i Coolify oppretter jeg et nytt prosjekt som jeg kaller prototype. Codeberg-repoet er offentlig,
så jeg slipper å sette opp SSH-nøkler eller access tokens. Jeg limer inn URL-en til repoet og velger branchen jeg
ønsker å bruke for deploy. Deretter velger jeg å deploye ved hjelp av Dockerfile, setter subdomenet jeg vil
bruke (med https, slik at Coolify henter sertifikat via Let's Encrypt), og trykker deploy.
Coolify viser build-loggen i sanntid. En vanlig feil her er at Coolify gjetter feil port. Siden Nginx lytter på port 80, passer jeg på å sette dette eksplisitt i innstillingene, slik at Coolify ikke prøver seg på noe annet.
Når bygget er ferdig sjekker jeg at begge URLer fungerer: Storybook på /storybook/ og applikasjonen på
/komponent-i-realistisk-kontekst/. Hvis begge laster er prototypen live og kan deles med hvem som helst.
Dette oppsettet er ikke spesielt sikret, og det er heller ikke meningen. Det er godt nok for å teste og dele en prototype raskt, men ikke noe jeg ville kjørt sensitiv data eller produksjonstrafikk på. Det tar jeg i neste post.
