magnum-cloudEnglishSkift til engelsk

Magnus Marcus Hansen — softwareudvikler, Slagelse

Jeg bygger .NET-services og driver selv maskinen, de kører på.

Backend i C# og ASP.NET Core, frontend i Angular og udrulning gennem Azure DevOps. Den anden halvdel — databasen, det private pakkefeed, build-runneren, certifikaterne og tunnelen, der overhovedet gør det tilgængeligt udefra — er den, de fleste udviklere sender videre. Den står jeg selv for, på en maskine hjemme hos mig.

Siden, du læser lige nu, bliver serveret af en af kasserne herunder — en container på en Debian-maskine hjemme hos mig, som kun kan nås gennem en tunnel, den selv har åbnet udad.

  • Besøgende

  • Cloudflares edge

  • cloudflared

  • Debian-maskine med Docker

    • Denne sideDu er her
    • ConfigService
    • BaGet
    • Docker-registry
    • MSSQL
    • GitHub Actions-runner

    Nginx Proxy Manager · wildcard-TLS — kun på LAN, aldrig gennem tunnelen

Diagram: besøgende rammer Cloudflares edge, som sender forespørgslen videre gennem en udgående cloudflared-tunnel til en Debian-maskine med Docker. På maskinen kører denne side, ConfigService, et privat BaGet-NuGet-feed, et privat Docker-registry, MSSQL og en selvhostet GitHub Actions-runner. Maskinen har ingen åbne indgående porte.

Om mig

Den korte version

Jeg er 28, bor i Slagelse og har arbejdet som softwareudvikler siden 2022 — to år hos Formpipe Software og siden februar 2026 hos Veng ApS. Mest C# og ASP.NET Core i backenden, Angular i frontenden og Azure DevOps ind imellem.

Det, jeg bliver ved med at vende tilbage til, er hele vejen fra kode til noget, der rent faktisk kører. Så den vej har jeg bygget selv i min fritid, hjemme hos mig: MSSQL i Docker, et privat BaGet-feed, som mine egne NuGet-pakker bliver udgivet til og mine services henter fra, et privat Docker-registry, en selvhostet GitHub Actions-runner, Nginx Proxy Manager med et wildcard-certifikat og Cloudflare Tunnel foran det hele.

Det smitter også af på, hvordan jeg er at arbejde sammen med. Jeg holder pipelinen grøn, skriver ned, hvad jeg finder ud af, og retter hellere det, der bliver ved med at gå i stykker, end jeg går uden om det.

Erfaring

Hvor jeg har arbejdet

  1. 2026–nu

    Programmør, it-konsulent og udvikler

    Veng ApS

  2. 2024–2026

    Jobsøgende

    Det var i den periode, jeg byggede det meste af mine egne systemer: homelab-platformen og den Debian-maskine, den kører på, ConfigService og TokenForge, som er udgivet på et privat pakkefeed, og resten af mine private services.

  3. 2022–2024

    Softwareudvikler

    Formpipe Software A/S · Ballerup

    To år på et produktteam, delt mellem selve produktet og de værktøjer, der fik det ud til kunderne.

    • Medansvarlig for det interne Azure DevOps på et af produkterne: build- og release-pipelines, agents og det, der gik galt i dem.
    • Udvikler på produktets deployment-værktøj, som bliver brugt til at rulle produktet ud hos kunderne.
    • Del af det almindelige udviklingsteam og af et forbedringsteam, der tog fat i det, som sinkede alle andre.
  4. 2016–2018

    IT-supporter, skolepraktik

    Skolepraktik · Ringsted

    Second-line support og helpdesk under IT-supporteruddannelsen.

    • Tog imod sager i helpdesken og det, første linje sendte videre: arbejdsstationer, brugerkonti, printere og netværk.
  5. 2013–2014

    Servicemedarbejder

    Jem & Fix · Sorø

    Butiksarbejde ved siden af skolen — varer, kasse og kunder.

Uddannelse

Vejen hertil

  1. 2019–2022

    Datamatiker

    Zealand – Sjællands Erhvervsakademi · Roskilde

    To et halvt år på datamatikeruddannelsen. Jeg var i ti ugers praktik hos Formpipe, blev ansat der efter endt uddannelse og gik ud med 12 i afgangskarakter.

  2. 2018–2019

    HF Enkeltfag

    HF & VUC Klar · Slagelse

    Enkeltfag på HF, taget for at få adgangsgrundlaget til datamatikeruddannelsen.

  3. 2015–2018

    IT-supporter

    ZBC Ringsted · Ringsted

    IT-supporteruddannelsen, afsluttet med svendeprøve og 12 i begge dele af den.

Infrastruktur

Maskinen, siden kommer fra

Én Debian-maskine hjemme, en håndfuld containere og en tunnel ud. Jeg har selv sat det op og holder det kørende. Der er ingen åbne porte ind — alt kommer ind gennem Cloudflare.

Besøgende
Alle, der åbner siden her, hvor de så end sidder.
Cloudflares edge
DNS, TLS og caching foran det hele. Intet når maskinen uden at komme forbi her.
cloudflared
Ringer ud til Cloudflare og holder forbindelsen åben. Routeren videresender ingenting indad.
Denne side
Next.js-containeren, der serverer den side, du læser.
ConfigService
Central konfiguration. Alle andre services spørger den om deres indstillinger, når de starter.
BaGet
Privat NuGet-feed. Mine egne pakker bliver udgivet hertil, og mine services henter dem herfra.
Docker-registry
Privat image-registry. CI lægger images op i det, og Compose henter dem ned igen.
MSSQL
Databasen bag mine services, i sin egen container med et persistent volume.
GitHub Actions-runner
Selvhostet runner. Den bygger mine images og ruller dem ud på den samme maskine.

Nginx Proxy Manager står ved siden af det hele med wildcard-certifikatet til alt det, jeg åbner over LAN'et. Den er ikke et led i vejen ovenfor: intet af det, den serverer, går gennem tunnelen, så det kan ikke nås udefra.

Projekter

Det, jeg har bygget

Seks projekter, jeg har bygget i min fritid, fordi jeg selv havde brug for dem — ikke som portfolio-projekter. Jeg driver dem også selv.

Repositorierne er private: det er personlige systemer med mine egne data og adgangsnøgler, så der er ingen links til dem. Det eneste open source-projekt, der indgår, er den udvidelse, StreamScout er forket fra, og den er krediteret.

  • ConfigService

    Ét krypteret sted til alle mine indstillinger og hemmeligheder.

    Problem
    Hver service havde sin egen kopi af de samme indstillinger og lå med sine hemmeligheder i klartekst, så én ændring betød, at flere skulle rulles ud igen.
    Løsning
    En ASP.NET Core-API krypterer værdierne med en hovednøgle, som den får ved opstart og aldrig gemmer sammen med data. Hver app har sin egen nøgle, der ligger hashet og kan skiftes ud, og der er roller til admin, redaktør og læser. En Angular-klient redigerer det hele.
    Resultat
    Hver service henter sin konfiguration i ét kald ved opstart, og et baggrundsjob tjekker hvert minut de apps, der har et health check sat op, så jeg kan se, hvilke der lever.
    Teknologi
    • ASP.NET Core
    • EF Core
    • MSSQL
    • Angular
    • NuGet
  • TokenForge

    To NuGet-pakker, så login kun skal løses én gang.

    Problem
    Hver ny service startede forfra på det samme arbejde — udstede tokens, hashe kodeord, sætte policies op — skrevet en anelse forskelligt hver gang.
    Løsning
    TokenForge.Core udsteder access- og refresh-tokens, hasher kodeord med BCrypt, har færdige adgangspolicies plus en API-nøgle i en header til kald mellem services. TokenForge.OAuth giver Discord-login på de samme tokens, tjekker medlemskab af serveren og kobler Discord-roller på app-roller.
    Resultat
    En ny service har login, der virker, efter én pakke og en håndfuld indstillinger, og en baggrundsservice kan kalde den med en nøgle i stedet for et brugerlogin.
    Teknologi
    • ASP.NET Core
    • JWT
    • BCrypt
    • Discord OAuth
    • API keys
    • NuGet
  • DiscordEconomy

    Økonomi- og leaderboardsystem til en Discord-server.

    Problem
    En server ville have, at det talte for noget at være aktiv, og de bots, man kan leje sig til, er lukkede og svære at bygge videre på.
    Løsning
    Fire C#-projekter, ingen frontend: alt kører fra slash-kommandoer — /balance, /leaderboard, /shop — og botten kalder API'et med egen nøgle. Taletid tælles pr. session med et dagligt loft, tid med mikrofon eller lyd slået fra tæller ikke med, og en genstart midtvejs bliver samlet op igen.
    Resultat
    Mønter, XP, taletid og beskeder har hvert sit leaderboard, overførsler mellem medlemmer ender i ét regnskab, kaldenavne holdes synkroniseret, og satserne kommer fra ConfigService.
    Teknologi
    • ASP.NET Core
    • Discord.Net
    • EF Core
    • MSSQL
    • Docker
  • JobApplicationManager

    Jobopslag fra indbakken, fulgt helt frem til afsendt ansøgning.

    Problem
    Jobagent-mails hober sig op hurtigere, end jeg kan nå at læse dem, og fristen i én af dem er væk, så snart mailen ruller ud af syne.
    Løsning
    En mailagent holder en IMAP-forbindelse åben og læser hver agentmail, så snart den lander — én profil pr. afsender, og den kan finde ud af danske datoer. Ud af det kommer et opslag med frist. Derfra følger jeg det, genererer en ansøgnings-PDF og sender den af sted.
    Resultat
    Opslagene kommer ind med deres frister, og den samme app fører et opslag helt frem til afsendt ansøgning, mens Angular-klienten opdaterer sig live undervejs.
    Teknologi
    • ASP.NET Core
    • EF Core
    • MSSQL
    • Angular
    • SignalR
    • MailKit
    • QuestPDF
  • StreamScout

    Et fork af Twitch Lurker, der følger NoPixel og Kick.

    Problem
    Den oprindelige udvidelse dækkede Twitch og YouTube; jeg ville have Kick i stedet og NoPixel GTA V RP-streams fundet ud fra, hvad der rent faktisk bliver spillet.
    Løsning
    Jeg delte det op i fire npm-workspaces — en fælles kerne, et komponentbibliotek, udvidelsen og et Next.js-site — smed YouTube ud, hentede Kick ind via deres offentlige API og byggede NoPixel-genkendelsen ovenpå. Man logger ind på sitet med Twitch eller Kick, og det kører i egen container.
    Resultat
    Én udvidelse og ét site viser, hvem der er live på Twitch og Kick, med faner til kategorier, dem jeg følger, og NoPixel.
    Teknologi
    • TypeScript
    • React
    • Vite
    • Next.js
    • MUI
    • WebExtensions
    • npm workspaces
    Forket fra
    Twitch Lurker
  • WorkSummary

    Et års kalenderposter, talt sammen måned for måned.

    Problem
    Mit arbejdsmønster fandtes kun som kalenderposter, så jeg måtte tælle i hånden, hvor mange kontordage, hjemmearbejdsdage, sygedage og egne fridage der lå i en måned.
    Løsning
    En lille ASP.NET Core-API tager et års kalenderposter, matcher hver enkelt på titlen og tæller dem sammen pr. måned i kontordage, hjemmearbejdsdage, sygedage og egne fridage. Hver måned har desuden et flag for, om den er indberettet til SKAT.
    Resultat
    Ét kald svarer på, hvordan en måned rent faktisk så ud, og om den er indberettet endnu, i stedet for at jeg tæller kalenderposter.
    Teknologi
    • ASP.NET Core
    • EF Core
    • SQLite

Kompetencer

Det, jeg arbejder med

Ingen procenter og ingen søjler. Det første er det, jeg griber til uden at tænke over det; det andet er det, jeg kan arbejde i, når opgaven kræver det.

Bruger dagligt

  • Git
  • Azure DevOps
  • C#
  • ASP.NET
  • Angular
  • JavaScript
  • HTML
  • CSS
  • PowerShell
  • Python
  • Server setup

Kan arbejde i

  • React
  • Bash
  • Elasticsearch
  • n8n

Kontakt

Tag fat i mig

Jeg bor i Slagelse og er åben for backend- og fullstack-arbejde i .NET — i nærheden eller remote. En mail er den mest direkte vej ind til mig; LinkedIn og GitHub virker også.

Bor i
Slagelse, Danmark