magnum-cloudDanskSwitch to Danish

Magnus Marcus Hansen — software developer, Slagelse, Denmark

I build .NET services, and I run the machine they sit on.

Backend work in C# and ASP.NET Core, front ends in Angular, delivery through Azure DevOps. The other half — the database, the private package feed, the build runner, the certificates and the tunnel that puts any of it online — is the half most developers hand off. I run mine myself, on a machine at home.

The page you are reading is served by one of the boxes below — a container on a Debian machine at home, reachable only through a tunnel it opened itself.

  • Visitors

  • Cloudflare edge

  • cloudflared

  • Debian host running Docker

    • This siteYou are here
    • ConfigService
    • BaGet
    • Docker registry
    • MSSQL
    • GitHub Actions runner

    Nginx Proxy Manager · wildcard TLS — LAN only, never on the tunnel

Diagram: visitors reach Cloudflare's edge, which passes the request down an outbound-only cloudflared tunnel to a Debian host running Docker. On that host sit this site, ConfigService, a private BaGet NuGet feed, a private Docker registry, MSSQL, and a self-hosted GitHub Actions runner. The host has no inbound ports open.

About

The short version

I am 28, I live in Slagelse, and I have worked as a software developer since 2022 — two years at Formpipe Software, and at Veng ApS since February 2026. Mostly C# and ASP.NET Core on the backend, Angular on the front, and Azure DevOps in between.

What I keep coming back to is the whole path from code to something that is actually running, so in my own time I built that path at home: MSSQL in Docker, a private BaGet feed that my own NuGet packages publish to and my own services install from, a private Docker registry, a self-hosted GitHub Actions runner, Nginx Proxy Manager holding a wildcard certificate, and Cloudflare Tunnel in front of all of it.

It shows up in how I work with other people too. I keep the pipeline green, write down what I find out, and would rather fix the thing that keeps breaking than route around it.

Experience

Where I have worked

  1. 2026–present

    Programmer, IT consultant and developer

    Veng ApS

  2. 2024–2026

    Seeking work

    I built most of my own systems in this period: the homelab platform and the Debian host it runs on, ConfigService and TokenForge, published to a private package feed, and the rest of my private services.

  3. 2022–2024

    Software developer

    Formpipe Software A/S · Ballerup

    Two years on a product team, split between the product itself and the tooling that shipped it.

    • Co-responsible for one of the products' internal Azure DevOps: build and release pipelines, agents, and whatever broke in them.
    • Developer on that product's deployment tool, the one used to roll the product out at customers.
    • Part of the regular development team and of an improvement team that took on the things slowing everyone else down.
  4. 2016–2018

    IT supporter, apprenticeship

    Skolepraktik · Ringsted

    Second-line support and helpdesk during my IT-supporter apprenticeship.

    • Took helpdesk tickets and whatever first line escalated: workstations, accounts, printers and network.
    • Skolepraktik is the school-run track of a Danish apprenticeship, for apprentices without a company placement.
  5. 2013–2014

    Service assistant

    Jem & Fix · Sorø

    Retail floor work alongside school — stock, tills and customers.

Education

How I got here

  1. 2019–2022

    Datamatiker (AP degree in computer science)

    Zealand – Sjællands Erhvervsakademi · Roskilde

    Two and a half years of applied computer science. I did the ten-week internship at Formpipe, was hired there after graduating, and finished with 12 — the top mark on the Danish scale.

  2. 2018–2019

    HF Enkeltfag

    HF & VUC Klar · Slagelse

    Single-subject upper-secondary courses, taken to qualify for the datamatiker programme.

  3. 2015–2018

    IT-supporter

    ZBC Ringsted · Ringsted

    Vocational IT-supporter training, finished with the Svendeprøve — the Danish journeyman's test — and 12 in both parts of it.

Infrastructure

The machine this page came from

One Debian machine at home, a handful of containers, and a tunnel out. I set it up and keep it running myself. No inbound ports are open — everything arrives through Cloudflare.

Visitors
Anyone opening this page, from wherever they are.
Cloudflare edge
DNS, TLS and caching in front of everything. Nothing reaches the host without coming through here.
cloudflared
Dials out to Cloudflare and holds the connection open. The router forwards nothing inward.
This site
The Next.js container serving the page you are reading.
ConfigService
Central configuration. Every other service asks it for its settings on startup.
BaGet
Private NuGet feed. My own packages are published here and my services install from here.
Docker registry
Private image registry. CI pushes images to it and Compose pulls them back down.
MSSQL
The database behind the services, in its own container with a persistent volume.
GitHub Actions runner
Self-hosted runner. It builds the images and deploys them on the same machine.

Nginx Proxy Manager sits beside all of this, holding the wildcard certificate for everything I open over the LAN. It is not a hop on the path above: nothing it serves goes through the tunnel, so none of it is reachable from outside the house.

Projects

Things I have built

Six projects I built in my own time because I needed them, not as portfolio pieces — and I run every one of them myself.

The repositories are private: these are personal systems holding my own data and credentials, so there are no links to them. The one open-source project involved is the extension StreamScout is forked from, and that one is credited.

  • ConfigService

    One encrypted store for every setting and secret I run on.

    Problem
    Every service carried its own copy of the same settings and kept its own secrets in plain files, so one change meant editing and redeploying several.
    Approach
    An ASP.NET Core API that encrypts values at rest with a master key it is handed at startup and never stores beside the data, per-app keys kept hashed and rotatable, and roles for admin, editor and viewer. An Angular client edits all of it.
    Result
    Every service pulls its configuration in one startup call, and every minute a worker checks the apps that have a health check configured, so I can see which ones are alive.
    Stack
    • ASP.NET Core
    • EF Core
    • MSSQL
    • Angular
    • NuGet
  • TokenForge

    Two NuGet packages, so I solve authentication once.

    Problem
    Each new service started from scratch on the same work — issuing tokens, hashing passwords, wiring up policies — written slightly differently every time.
    Approach
    TokenForge.Core issues access and refresh tokens, hashes passwords with BCrypt and ships ready-made authorize policies, plus an API-key header for service-to-service calls. TokenForge.OAuth adds Discord login on the same tokens, checks guild membership and maps Discord roles to app roles.
    Result
    A new service gets working authentication from a package and a handful of options, and a background service can call it with a key instead of a user login.
    Stack
    • ASP.NET Core
    • JWT
    • BCrypt
    • Discord OAuth
    • API keys
    • NuGet
  • DiscordEconomy

    An economy and leaderboard system for a Discord server.

    Problem
    A server wanted taking part to count for something, and the bots on offer were rented, closed and hard to build on.
    Approach
    Four C# projects and no frontend: everything runs from slash commands — /balance, /leaderboard, /shop — with the bot reaching the API on its own API key. Voice time counts per session with a daily cap, muted and deafened time left out, and a restart mid-session is picked up again.
    Result
    Coins, XP, voice minutes and messages each have a leaderboard, transfers between members land in the same ledger, nicknames stay in sync, and earn rates come from ConfigService.
    Stack
    • ASP.NET Core
    • Discord.Net
    • EF Core
    • MSSQL
    • Docker
  • JobApplicationManager

    Job postings from my inbox, tracked through to a sent application.

    Problem
    Job alert emails pile up faster than I can read them, and the deadline in one is gone the moment the mail scrolls out of sight.
    Approach
    A mail agent holds an IMAP connection open and scrapes each alert as it lands — one parsing profile per sender, Danish dates included — into a pending posting with its deadline. From there it becomes a tracked entry, gets an application PDF generated, and is sent.
    Result
    Postings arrive with their deadlines attached, and the same app carries one through to a sent application, with the Angular client updating live as it moves.
    Stack
    • ASP.NET Core
    • EF Core
    • MSSQL
    • Angular
    • SignalR
    • MailKit
    • QuestPDF
  • StreamScout

    A fork of Twitch Lurker that follows NoPixel and Kick.

    Problem
    The upstream extension covered Twitch and YouTube; I wanted Kick instead, and NoPixel GTA V RP streams found by what is actually being played.
    Approach
    Split into four npm workspaces — a shared core, a shared component library, the extension and a Next.js site — with YouTube dropped, Kick added through its public API and NoPixel detection built on top. The site logs in with Twitch or Kick and runs in its own container.
    Result
    One extension and one site show who is live across Twitch and Kick, with tabs for categories, follows and NoPixel.
    Stack
    • TypeScript
    • React
    • Vite
    • Next.js
    • MUI
    • WebExtensions
    • npm workspaces
    Forked from
    Twitch Lurker
  • WorkSummary

    A year of calendar entries, counted into months.

    Problem
    My work pattern only existed as calendar entries, so counting office days, days at home, sick days and days off per month was something I did by hand.
    Approach
    A small ASP.NET Core API takes a year of calendar events, matches each one on its title and counts them per month into office days, days worked from home, sick days and days off. Each month also carries a flag for whether it has been reported to SKAT.
    Result
    One call answers what a month actually looked like and whether it has been reported yet, instead of me counting entries in a calendar.
    Stack
    • ASP.NET Core
    • EF Core
    • SQLite

Skills

What I work with

No percentages and no bars. The first list is what I reach for without thinking about it; the second is what I can work in when a task calls for it.

Daily

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

Working knowledge

  • React
  • Bash
  • Elasticsearch
  • n8n

Contact

Get in touch

I am in Slagelse, Denmark, and open to backend and full-stack .NET work — nearby or remote. Email is the most direct route; LinkedIn and GitHub work too.

Based in
Slagelse, Denmark