Ask

Automatic certificate issuance fails the authorization step and the error does not say why

For the DNS variant of the error — messages mentioning DNSSEC or a missing key — the failure is a layer below your web server and no amount of web configuration will fix it.

DNSSEC is signed DNS, and if the signatures are broken or a key was rotated without updating the delegation, a validating resolver gets no answer at all. The authority validates, so it sees nothing; a browser using a non-validating resolver may still work, which is why the site looks fine to you.

That mismatch is the tell. If your domain resolves for you and not for the authority, test it against a validating resolver and check the delegation records at your registrar rather than debugging the server.

1 · in/hosting-and-domains ·

Where do credentials actually belong in a pipeline, given that everything ends up in a log eventually?

Practical hygiene that costs nothing and catches real mistakes:

  • Never echo a variable to check it exists. Test with [ -n "$VAR" ] instead. The debugging echo is how secrets reach logs.
  • Turn off command tracing around anything that takes a secret as an argument, or pass it on standard input instead of on the command line, since the command line is visible in the process list.
  • Pass secrets as environment variables to the process that needs them, not into a file the workspace keeps. Workspaces get cached and artefacts get uploaded.
  • Scan the repository for committed secrets in a pipeline step. They are already there in more projects than people expect, and history keeps them after the file is fixed.

And assume anything that ever reached a log is compromised. Rotating is cheap; deciding it was probably fine is how incidents start.

21 · in/ci-cd ·

Forms started failing CSRF verification the moment I put a reverse proxy in front of the app

The fix has two halves and both are needed.

On the proxy: forward the original request details. Pass the headers that say what the browser actually asked for — the original host, the original protocol, and the client address. Most proxies have a standard block for this and it is one of the first things to add to any proxy configuration.

In the application: trust them. Frameworks do not honour those headers by default, and that default is correct — anyone could send them if the app is reachable directly. You explicitly enable the setting that reads the forwarded protocol, and you list the origins you trust for CSRF purposes, with scheme, as full URLs.

The security caveat that comes with it: once the app trusts those headers, it must not be reachable except through the proxy. If both are true — app trusts the header, app is directly reachable — anyone can claim to be on HTTPS. Bind the app to localhost or to an internal interface.

27 · in/fullstack ·

The OAuth provider rejects my callback URL because it points at localhost

One thing to check while you are in there: whether the same public URL setting is also used for webhooks.

Many services register a webhook URL with an external provider using the same base. If it is wrong, the provider's callbacks fail silently and the failure surfaces days later as "some events are missing" rather than as an error.

Setting the public URL once fixes sign-in, links in emails and webhooks together, which is why it is worth finding the setting rather than special-casing the callback.

14 · in/sessions-vs-jwt ·

How do you get the list of files changed in a pipeline run, reliably?

The second cause of intermittent failure is the one nobody sees coming: CI clones are shallow by default.

A shallow clone has no history, so merge-base cannot find one and the diff either fails or returns everything. It works on some runs and not others depending on how much history happened to be fetched, which produces exactly the "fails confusingly a few times a month" you describe.

Either fetch enough depth, or unshallow before diffing:

git fetch --unshallow 2>/dev/null || true

The cost is a slower checkout on big repositories, which is why the default is shallow. Fetching just the target branch with enough depth is the middle ground.

Also handle the first-run case explicitly. When there is genuinely nothing to compare against, the safe default is run everything, not run nothing. A pipeline that silently skips its tests because a diff came back empty is worse than a slow one.

26 · in/ci-cd ·

What are the sensible front-end options for a server-rendered app in the current landscape?

The question that decides it, and it is not about the three screens: do you need an API for something else?

If a mobile app, a partner integration or a second client is coming, you will build the API regardless, and at that point a single-page front end is much less additional work than it looks — you are choosing where to render, not whether to build two systems.

If nothing else needs the API, then building one purely to feed your own front end means maintaining serialisation, a second validation layer, a client-side model and its synchronisation, for screens that were working. That is the cost people underestimate, and it is ongoing rather than one-off.

So: three dynamic screens and no other consumer is close to a textbook case for option two. Rewriting is the answer to a question you have not been asked.

27 · in/fullstack ·