Tales Of Details
Here I collect details I encounter that seem worth putting into a tale.
If you’re interested in tech, software, ways of working and a bit of nagging, step right in :-)
Sure, Claude Code is nothing short of magic… until you run out of tokens :-P But here’s a thought I found interesting. By now, we know that given a specific deliverable, your chances of getting it from the LLM increase if you provide as many details as you can about what you need done and how you’d prefer to have it done you’re in a position to evaluate the output and ask for amendments actually take the time to evaluate the output and ask for amendments Well, as it turns out ...
Selfishness is usually frowned upon. Largely because it’s taken to mean looking after my own interests to the detriment of others. I find this definition a bit too simplistic. All relationships, all interactions contain a transaction. While it’s not at all romantic to voice as much ( ask me how I know :-P ), there is something to gain in everything we do. Maintaining a friendship because you get a sympathetic ear. Saying hi to your neighbor so it’s not awkward when you ask them for some coffee. Sometimes the motive is evident and hurts others (so it’s labeled selfish). Sometimes it’s more subtle and it avoids detection by this crude filter. ...
I’ve been using traefik in various contexts over the years. It’s a bit much at first glance but once you get to know it, it can do anything ( at least anything I’ve thrown at it) and it’s extensible via plugins. The winning feature it had when first introduced was letsencrypt support. You could have the ingress controller manage your certificates and inject them in any ingress you instructed it to. I’ve been using that feature for a long time. ...
In my formative years, I would try to apply logic to any and all matters. How do I decide what to do? Why should I do this? What does this impact? etc etc. Any kind of intuition of predisposition seemed dangerous as I had no way of knowing why I leaning that way (biases, misinformation etc) This analytical process was lengthy and exhausting but I like to think it helped shape a way of thinking and form a (mostly) reliable intuition. I can still remember the exhilarating feeling of hearing a question, leaning one way about it, then analyzing it and discovering I still liked my original inclination. I could now trust my gut and stop the (over)analysis, right? ...
There are two main problems in programming: Invalidating Cache Naming things Off-by-one errors Let’s do cache in the web today :-) Suppose you have a static frontend that you need to serve. And you care about having globally available with low latency. That’s the prime use case for a CDN, right? So you deploy a CDN ( Cloudflare, Cloudfront etc). And you point it to a source ( an S3 bucket with your static files or a publicly accessible web-server serving your files). ...
In the never-ending quest for env parity, I ran into another interesting issue. mkcert does not deal with client certificates, it only creates server certs. What if we want to do mutual TLS and need them? Well, buckle up, we’ll take openssl for a ride. We’ll need the three files shown below in a folder named ca and the scripts that follow. # ca/ca.cnf [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] prompt = no distinguished_name = dn default_md = sha256 default_bits = 4096 x509_extensions = v3_ca [ dn ] countryName = GR organizationName = MyCompany localityName = Athens commonName = mycompany-ca [ v3_ca ] subjectKeyIdentifier=hash basicConstraints = critical,CA:true authorityKeyIdentifier=keyid:always,issuer:always keyUsage = critical,keyCertSign,cRLSign # ca/client.cnf [req] prompt = no distinguished_name = dn default_md = sha256 default_bits = 4096 req_extensions = v3_req [ dn ] countryName = GR organizationName = MyCompnay localityName = Athens commonName = mycompany-ca commonName=*.random.k8s [ v3_ca ] subjectKeyIdentifier=hash basicConstraints = critical,CA:true authorityKeyIdentifier=keyid:always,issuer:always keyUsage = critical,keyCertSign,cRLSign [ v3_req ] subjectKeyIdentifier = hash basicConstraints = CA:FALSE nsComment = "OpenSSL Generated Certificate" keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth subjectAltName = @alt_names [ alt_names ] DNS.1 = *.random.k8s DNS.2 = random.k8s DNS.3 = localhost DNS.4 = 127.0.0.1 DNS.5 = myservice DNS.6 = myotherservice DNS.7 = *.infra DNS.8 = *.app DNS.9 = *.somedomain.iwantotouse # ca/server.cnf [req] prompt = no distinguished_name = dn default_md = sha256 default_bits = 4096 req_extensions = v3_req [ dn ] countryName = GR organizationName = mycompany localityName = Athens commonName = mycompany-ca commonName=*.random.k8s [ v3_ca ] subjectKeyIdentifier=hash basicConstraints = critical,CA:true authorityKeyIdentifier=keyid:always,issuer:always keyUsage = critical,keyCertSign,cRLSign [ v3_req ] subjectKeyIdentifier = hash basicConstraints = CA:FALSE nsComment = "OpenSSL Generated Certificate" keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [ alt_names ] DNS.1 = *.random.k8s DNS.2 = random.k8s DNS.3 = localhost DNS.4 = 127.0.0.1 DNS.5 = myservice DNS.6 = myotherservice DNS.7 = *.infra DNS.8 = *.app DNS.9 = *.somedomain.iwantotouse function create_certs() { local CERTS_DIR="${CERTS_DIR:-"/opt/my_certs"}" local STORE_PASS="${STORE_PASS:-changeit}" # uninstall any existing CAs handled by mkcert mkcert -uninstall # then delete the CA files # and existing client/server certs rm -rf $(mkcert -CAROOT)/* rm -rf ${CERTS_DIR}/* # create new ca openssl req -new -nodes \ -x509 \ -days 3650 \ -newkey rsa:2048 \ -keyout "${CERTS_DIR}"/ca.key \ -out "${CERTS_DIR}"/ca.crt \ -config ./ca/ca.cnf # create ca pem from crt and key cat "${CERTS_DIR}"/ca.crt "${CERTS_DIR}"/ca.key > "${CERTS_DIR}"/ca.pem # create ca p12 from existing java trust store docker run --rm -it -v "${CERTS_DIR}":/certs \ eclipse-temurin:17-jdk -- keytool -importkeystore \ -srckeystore/opt/java/openjdk/lib/security/cacerts \ -srcstoretype PKCS12 \ -srcstorepass changeit \ -destkeystore /certs/ca.p12 \ -deststoretype PKCS12 \ -deststorepass "${STORE_PASS}" # change files to have proper user permissions sudo chown $(id -u):$(id -g) "${CERTS_DIR}"/ca.p12 # add our new ca to newly created store docker run --rm -it -v ${CERTS_DIR}:/certs \ eclipse-temurin:17-jdk \ -- keytool -importcert -alias my_ca_cert \ -file /certs/ca.pem \ -keystore /certs/ca.p12 \ -deststorepass "${STORE_PASS}" \ -noprompt # create key and csr for server EKU openssl req -new \ -newkey rsa:2048 \ -keyout "${CERTS_DIR}"/server.key \ -out "${CERTS_DIR}"/server.csr \ -config ./ca/server.cnf \ -nodes # sign the server csr and create cert openssl x509 -req \ -days 3650 \ -in "${CERTS_DIR}"/server.csr \ -CA "${CERTS_DIR}"/ca.crt \ -CAkey "${CERTS_DIR}"/ca.key \ -CAcreateserial \ -out "${CERTS_DIR}"/server.crt \ -extfile ./ca/server.cnf \ -extensions v3_req # create server pem from crt and key cat "${CERTS_DIR}"/server.crt "${CERTS_DIR}"/server.key > "${CERTS_DIR}"/server.pem # create server p12 keystore openssl pkcs12 -export \ -in "${CERTS_DIR}"/server.crt \ -inkey "${CERTS_DIR}"/server.key \ -chain \ -CAfile "${CERTS_DIR}"/ca.pem \ -name server \ -out "${CERTS_DIR}"/server.p12 \ -password pass:"${STORE_PASS}" # change files to have proper user permissions sudo chown $(id -u):$(id -g) "${CERTS_DIR}"/server.p12 # import server p12 to store if needed docker run --rm -it -v ${CERTS_DIR}:/certs \ eclipse-temurin:17-jdk -- keytool \ -importcert -alias server_cert \ -file /certs/server.pem \ -keystore /certs/ca.p12 \ -deststorepass "${STORE_PASS}" \ -noprompt # create key and csr for client EKU openssl req -new \ -newkey rsa:2048 \ -keyout "${CERTS_DIR}"/client.key \ -out "${CERTS_DIR}"/client.csr \ -config ./ca/client.cnf \ -nodes # sign the client csr and create cert openssl x509 -req \ -days 3650 \ -in "${CERTS_DIR}"/client.csr \ -CA "${CERTS_DIR}"/ca.crt \ -CAkey "${CERTS_DIR}"/ca.key \ -CAcreateserial \ -out "${CERTS_DIR}"/client.crt \ -extfile ./ca/client.cnf \ -extensions v3_req # create client pem from crt and key cat "${CERTS_DIR}"/client.crt "${CERTS_DIR}"/client.key > "${CERTS_DIR}"/client.pem # create client p12 keystore openssl pkcs12 -export \ -in "${CERTS_DIR}"/client.crt \ -inkey "${CERTS_DIR}"/client.key \ -chain \ -CAfile "${CERTS_DIR}"/ca.pem \ -name client \ -out "${CERTS_DIR}"/client.p12 \ -password pass:"${STORE_PASS}" # change files created to have proper user permissions sudo chown $(id -u):$(id -g) "${CERTS_DIR}"/client.p12 # import client p12 to store if needed docker run --rm -it -v ${PWD}:/certs \ eclipse-temurin:17-jdk \ -- keytool -importcert -alias client_cert \ -file /certs/client.pem \ -keystore /certs/ca.p12 \ -deststorepass "${STORE_PASS}" \ -noprompt # list certs in store to verify everything imported docker run --rm -it -v ${PWD}:/certs \ eclipse-temurin:17-jdk \ -- keytool -list -v -keystore /certs/ca.p12 \ -storepass "${STORE_PASS}" # cleanup files we don't need rm -rf "${CERTS_DIR}"/client.csr rm -rf "${CERTS_DIR}"/server.csr # copy ca files to mkcert folder cp "${CERTS_DIR}"/ca.key $(mkcert -CAROOT)/rootCA-key.pem cp "${CERTS_DIR}"/ca.crt $(mkcert -CAROOT)/rootCA.pem cp "${CERTS_DIR}"/ca.srl $(mkcert -CAROOT)/rootCA.srl # trust the ca for your system mkcert -install # concatenate server cert + ca.cert to use for ingress cat ${CERTS_DIR}/server.crt ${CERTS_DIR}/ca.crt > ${CERTS_DIR}/full.pem } function create_tls_secrets() { kubectl create namespace traefik kubectl create namespace infra kubectl create namespace app # create ingress certificate kubectl -n traefik create secret tls my-root-ca-tls \ --key ${CERTS_DIR}/server.key \ --cert ${CERTS_DIR}/server.crt \ --dry-run=client -o yaml \ | kubectl apply -f - # create secret for plain certificates in infra + app namespaces kubectl -n infra create secret generic certificates \ --from-file=ca.crt=${CERTS_DIR}/ca.crt \ --from-file=server.crt=${CERTS_DIR}/server.crt \ --from-file=server.key=${CERTS_DIR}/server.key \ --from-file=client.crt=${CERTS_DIR}/client.crt \ --from-file=client.key=${CERTS_DIR}/client.key \ --dry-run=client -o yaml \ | kubectl apply -f - kubectl -n app create secret generic certificates \ --from-file=ca.crt=${CERTS_DIR}/ca.crt \ --from-file=server.crt=${CERTS_DIR}/server.crt \ --from-file=server.key=${CERTS_DIR}/server.key \ --from-file=client.crt=${CERTS_DIR}/client.crt \ --from-file=client.key=${CERTS_DIR}/client.key \ --dry-run=client -o yaml \ | kubectl apply -f - # create secret for keystores in infra + app namespaces kubectl -n infra create secret generic keystores \ --from-file=ca.p12=${CERTS_DIR}/ca.p12\ --from-file=server.p12=${CERTS_DIR}/server.p12 \ --from-file=client.p12=${CERTS_DIR}/client.p12 \ --from-literal=password="${STORE_PASS}" \ --dry-run=client -o yaml \ | kubectl apply -f - kubectl -n app create secret generic keystores \ --from-file=ca.p12=${CERTS_DIR}/ca.p12\ --from-file=server.p12=${CERTS_DIR}/server.p12 \ --from-file=client.p12=${CERTS_DIR}/client.p12 \ --from-literal=password="${STORE_PASS}" \ --dry-run=client -o yaml \ | kubectl apply -f - } Now we’ve got 2 secrets per namespace. One contains certificates, the other keystores. We can mount them to our apps as needed to be used for mutual TLS. ...
We’re building a shared development environment in k8s The typical cloud managed k8s services are not available. We need ample resources and low-as-possible price for k8s. Requirements? We have them Private access. Given private access to the machine’s local IP address, it needs to be reachable and publish services to that interface. Public Access. Given a public IP assigned to its second interface, we need to be able to selectively publish services to the internet. Data is not important. We care about them as far as they are needed for the services to keep running properly. Wanna try a Bare Metal server for this? ...
You’ve got a backend in Java deployed in k8s and every once in a while it OOMs. What a surprise :-P How do you go about fixing this? Well, give it more memory since it’s out! About half the time this will help. But in case you’re not lucky and you need to fix the underlying issue, let’s take the engineering way around. It’s full of twists, turns and wasted time. But if you need it, it’s indispensable. ...
Another not, strictly, technical post. But one that’s very dear to me and has been instrumental to my development as a person and a professional. The IT sector is a hard skills sector with lots of depth. The more you know on your subject, the more valuable you are, the more respect you can get from your peers and compensation from your employer. But what once might have been a difficult quest ( know everything in my field) is now practically impossible. You cannot know everything, you should not be trying to know everything and you should not be expecting anyone else to know everything either. Even if you define everything as everything within my specific role or everything about a specific technology or tool, this is still a fool’s errand. ...
Wanted to save this quote somewhere visible. Impostor syndrome doesn’t mean you’re unqualified. It means you’re growing faster than your confidence can catch up. Sourced here, from engineering career coach Taha Hussain