Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Parallel, Matrix, input and Deploy Stages in Jenkins
We deploy the same package first to staging and, after an input approval that holds no agent, to production with sshagent, rsync and systemctl; Lockable Resources solves concurrency and milestone solves ordering. A deploy script with a health check, real lock output where an old build deploys after a new one, inversePrecedence, failFast, a Node 22/24 matrix and the app_offline.htm structure for IIS.
An Angular Pipeline with Jenkins: Node Container, npm Cache, Headless Tests and stash/unstash
We build the Angular 22 app in a node:24 container with npm ci, ng lint, Vitest and ng build in parallel with the .NET API, and combine both into one package with stash/unstash. The npm cache volume, Vitest's JUnit reporter, budgets, the missing-package error for browser mode, not stashing a 329 MB node_modules, and parallel stage durations in Pipeline Graph View.
A .NET Pipeline with Jenkins: dotnet SDK Container, Test Results, Coverage and Publish Artifacts
We restore, build, test and publish Bookstore.Api in the .NET SDK container and record the JUnit report, Cobertura coverage and a fingerprinted artifact in Jenkins. The NuGet cache volume's permission error and the time it saves, xUnit v3's JUnit output with Microsoft.Testing.Platform in .NET 10, the coverage quality gate, and a build that turns red when no test report is found.
Jenkins Multibranch Pipelines and GitHub Integration: Webhooks, PR Builds and Status Checks
A multibranch pipeline opens a job automatically for every branch and PR; a webhook starts the build within seconds and the result returns to the commit as a status check. Branch source traits, a webhook blocked by a localhost URL and Gitea's SSRF protection, telling branches and PRs apart with when, a fork PR's Jenkinsfile read from the base branch, required checks, and a GitHub App instead of a PAT.
Jenkins Credentials: withCredentials, Credentials Binding and the Groovy String Interpolation Trap
You expose a secret in the narrowest scope with credentials() or withCredentials and read it in sh as a shell variable inside single quotes; Groovy interpolation with double quotes leaks it to the process. Credential types and SYSTEM/GLOBAL/folder scopes, readFile in JCasC, masking that catches base64 but misses a fragment, sshagent, team isolation with folder credentials and external secret stores.
Jenkins Agents: SSH Agents, Inbound Agents, Labels and Building Inside Docker Containers
With an SSH agent the controller opens the connection, with an inbound agent the agent does; you run the build on an agent chosen by label expressions or inside an SDK container with agent { docker }. Agent definitions with JCasC, real SSH and WebSocket connection logs, Docker Pipeline's workspace mount and the uid 1000 detail, disk usage with cleanWs, and a quick look at Kubernetes pod templates and Windows agents.
Your First Pipeline with a Jenkinsfile: Declarative Syntax, stages, steps, post and environment
A Jenkinsfile describes the pipeline in the same repository as the code; in Declarative syntax agent, stages and steps form the skeleton, while environment, options, parameters, triggers and post define the behavior. Linter output, the quoting rule, the parameter the shell sees as empty on the first build, a stage skipped by when, Snippet Generator and Replay, Scripted Pipeline, and NotSerializableException with @NonCPS.
Installing Jenkins: LTS with Docker, Java 21, the First Admin and Choosing Plugins
You install Jenkins in Docker with a version-pinned LTS image, a named JENKINS_HOME volume and Java 21, and you skip the setup wizard with plugins.txt and JCasC. The anonymous volume trap, initialAdminPassword, the Docker-in-Docker TLS certificate error, anonymous access, zero executors on the controller, the CSRF crumb, agent-to-controller security and installing from the Linux package.
What Is Jenkins? Controllers, Agents, Executors and When to Choose Jenkins Over GitHub Actions
Jenkins is a self-hosted CI/CD server made of a controller that plans the work and agents that run builds on their executors. Its history since Hudson, workspaces and labels, how an unmatched label leaves a build waiting in the queue, the price of the plugin ecosystem, Freestyle vs Pipeline, the LTS and weekly lines, and when Jenkins is the right choice over GitHub Actions.
What Changed in Hosting from .NET 6 to .NET 10: Port 8080, HTTP_PORTS, KnownIPNetworks and More
Since .NET 8, ASP.NET Core images listen on 8080 instead of 80 and ship a ready-made app user, but the default user is still root; on .NET 10 the images are Ubuntu-based and KnownNetworks and WebHost are obsolete. With real runs we see the old -p 8000:80 command give a connection reset, why a non-root port 80 works on Docker but may not elsewhere, the traps in old tutorials and the .NET 11 breaking changes that touch hosting.
Choosing Hosting and a Production Checklist: Nginx, IIS, Caddy, Containers and PaaS
The hosting choice is decided first by what the team can operate, then by the number of services, deploy frequency and cost; a Linux VM with Nginx, IIS, Caddy, Traefik, YARP, PaaS and containers are different answers to the same questions. We try Caddy with seven lines of config and an active health check, and a ten-item pre-go-live check script catches a health endpoint invisible from outside and a missing default server on 443 in the seventh post's config.
IIS in Production: Deploying, app_offline.htm, Locked Files, Application Initialization and Angular
The DLLs of an app running on IIS are locked; deploy with app_offline.htm or with enableShadowCopy, supported since .NET 7, and keep those settings in the project's web.config rather than on the server, since publish preserves them. Recycling and overlapped recycle, Application Initialization and idle timeout, Data Protection on IIS, sub-applications, Angular with URL Rewrite and AddWindowsService instead of IIS; IIS wasn't run on this Mac, the web.config and build outputs are real.