Docker images are usually stored in docker repositories. Nexus server provides host, proxy and group type docker repositories. It can be deployed as a docker container itself with persistent storage. See https://hub.docker.com/r/sonatype/nexus3 for more info.
1. Using company PKI, generate nexus cert p12 cert for respective domain; for example, nexus.example.com
2. Store the cert passphrase in a k8s secret
kubectl create secret generic nexus-cert-pass --from-literal="password=**********"
3. Generate java keystore password and store in in k8s secret
openssl rand -base64 32 kubectl create secret generic nexus-keystore-pass --from-literal="password=******"
4. Store the nexus p12 certificate in k8s config map
kubectl create configmap nexus-cert --from-file=nexus.example.com.p12
5. Save CA certificates in k8s config map. They will later be imported into the java trusted store.
kubectl create configmap nexus-trusted-ca --from-file=nexus-trusted-ca.cert
6. Modify jetty-https.xml file from nexus and save it in k8s secret (to get the complete file, you may just run docker run -ti --rm sonatype/nexus3 bash)
...
<New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<Set name="KeyStorePath"><Property name="ssl.etc"/>/keystore.pkcs12</Set>
<Set name="KeyStorePassword">**************</Set>
<Set name="KeyManagerPassword">**************</Set>
<Set name="TrustStorePath"><Property name="ssl.etc"/>/truststore.pkcs12</Set>
<Set name="TrustStorePassword">**************</Set>
...
kubectl create secret generic jetty-https --from-file=jetty-https.xml7. Java comes with elevated security, which needs to be lowered to work with our poor MS AD LDAP servers. So we need to overwrite two java security files with config maps
vi java.security (re-enable MD5)
...
#keystore.type=jks
keystore.type=pkcs12
#jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
# RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
jdk.certpath.disabledAlgorithms=MD2, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 768, EC keySize < 224
#jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, DSA keySize < 1024
jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024, DSA keySize < 1024
#jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
# EC keySize < 224, 3DES_EDE_CBC, anon, NULL
jdk.tls.disabledAlgorithms=RC4, DES, DH keySize < 1024, \
EC keySize < 224, anon, NULL
...
vi java.config (reduce the key size back to 1024)
#cat /etc/crypto-policies/back-ends/java.config
#jdk.tls.ephemeralDHKeySize=2048
jdk.tls.ephemeralDHKeySize=1024
#jdk.certpath.disabledAlgorithms=MD2, MD5, DSA, RSA keySize < 2048
jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 1024
#jdk.tls.disabledAlgorithms=DH keySize < 2048, SSLv2, SSLv3, TLSv1, TLSv1.1, DHE_DSS, RSA_EXPORT, DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_DSS_EXPORT, DH_RSA_EXPORT, DH_anon, ECDH_anon, DH_RSA, DH_DSS, ECDH, 3DES_EDE_CBC, DES_CBC, RC4_40, RC4_128, DES40_CBC, RC2, HmacMD5
jdk.tls.disabledAlgorithms=DH keySize < 1024, SSLv2, DHE_DSS, RSA_EXPORT, DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_DSS_EXPORT, DH_RSA_EXPORT, DH_anon, ECDH_anon, DH_RSA, DH_DSS, ECDH, 3DES_EDE_CBC, DES_CBC, RC4_40, RC4_128, DES40_CBC, RC2, HmacMD5
jdk.tls.legacyAlgorithms=
kubectl create configmap java-security --from-file=java.security
kubectl create configmap java-config --from-file=java.config8. Export NFS mount nexus-data owned by used/group id 200:200 - the account that nexus server runs under mount nfs_server:/export /mnt mkdir /mnt/nexus-data chown 200:200 /mnt/nexus-data
9. Create deployment manifest nexus.yaml and apply it
apiVersion: v1
kind: Service
metadata:
name: nexus
spec:
selector:
app: nexus
ports:
- port: 8443
---
apiVersion: v1
kind: Service
metadata:
name: docker-repo
spec:
type: NodePort
selector:
app: nexus
ports:
- port: 8888
nodePort: 30888
---
apiVersion: v1
kind: Service
metadata:
name: docker
spec:
type: NodePort
selector:
app: nexus
ports:
- port: 4443
nodePort: 31443
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nexus-ssl-ingress
annotations:
ingress.kubernetes.io/ssl-passthrough: "true"
namespace: default
spec:
rules:
- host: nexus.example.com
http:
paths:
- backend:
serviceName: nexus
servicePort: 8443
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nexus
labels:
app: nexus
spec:
selector:
matchLabels:
app: nexus
template:
metadata:
labels:
app: nexus
spec:
containers:
- name: nexus
image: sonatype/nexus3
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: "4"
memory: "8Gi"
requests:
cpu: "4"
memory: "8Gi"
ports:
- containerPort: 8081
- containerPort: 8443
- containerPort: 4443
- containerPort: 8000
- containerPort: 8888
env:
- name: password
valueFrom:
secretKeyRef:
key: password
name: nexus-keystore-pass
optional: false
- name: nexuscertpass
valueFrom:
secretKeyRef:
key: password
name: nexus-cert-pass
optional: false
- name: INSTALL4J_ADD_VM_PARAMS
value: "-Xms1200m -Xmx1200m -XX:MaxDirectMemorySize=5g -Djava.util.prefs.userRoot=/nexus-data/javaprefs -Djavax.net.ssl.keyStore=/nexus-data/etc/ssl/keystore.pkcs12 -Djavax.net.ssl.keyStorePassword=$(password) -Djavax.net.ssl.trustStore=/nexus-data/etc/ssl/truststore.jks -Djavax.net.ssl.trustStorePassword=$(password)"
args: ['sh', '-c', "if [[ ! -d /nexus-data/etc/ssl ]]; then mkdir -p /nexus-data/etc/ssl; fi && if [[ ! -d /nexus-data/tmp ]]; then mkdir /nexus-data/tmp; fi && rm -f /nexus-data/etc/ssl/*.* && keytool -importkeystore -noprompt -destkeystore /nexus-data/etc/ssl/keystore.pkcs12 -deststoretype PKCS12 -srckeystore /mnt/nexus.lat.internal.p12 -srcstoretype PKCS12 -deststorepass $password -destkeypass $password -srcstorepass $nexuscertpass && cd /nexus-data/tmp && csplit -z -f crt- /etc/pki/ca-trust/source/anchors/nexus-trusted-ca.cert '/-----BEGIN CERTIFICATE-----/' '{*}' && for file in crt-*; do keytool -import -noprompt -keystore /nexus-data/etc/ssl/truststore.jks -file $file -storepass $password -alias crt-$file; done && keytool -importkeystore -noprompt -srcstorepass $password -deststorepass $password -srckeystore /nexus-data/etc/ssl/truststore.jks -srcstoretype JKS -destkeystore /nexus-data/etc/ssl/truststore.pkcs12 -deststoretype PKCS12 && /opt/sonatype/start-nexus-repository-manager.sh"]
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8081
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- name: data
mountPath: /nexus-data
- name: jetty-https
mountPath: /opt/sonatype/nexus/etc/jetty/jetty-https.xml
subPath: jetty-https.xml
readOnly: true
- name: nexus-cert
mountPath: /mnt
- name: java-security
mountPath: /etc/java/java-1.8.0-openjdk/java-1.8.0-openjdk-1.8.0.232.b09-2.el8_1.x86_64/lib/security/java.security
subPath: java.security
readOnly: true
- name: java-config
mountPath: /etc/crypto-policies/back-ends/java.config
subPath: java.config
readOnly: true
- name: nexus-trusted-ca
mountPath: /etc/pki/ca-trust/source/anchors
volumes:
- name: data
nfs:
path: /export/nexus-data
server: nfs_server
- name: nexus-cert
configMap:
name: nexus-cert
- name: nexus-trusted-ca
configMap:
name: nexus-trusted-ca
- name: jetty-https
secret:
secretName: jetty-https
- name: java-security
configMap:
name: java-security
- name: java-config
configMap:
name: java-config
---
kubectl apply -f nexus.yaml10. Once the nexus is up and running, which can be confirmed by kubectl logs nexus-* -f, modify /mnt/nexus-data/nexus.properties file to allow https and reload the server
vi /mnt/nexus-data/etc/nexus.properties
nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-http.xml,${jetty.etc}/jetty-https.xml,${jetty.etc}/jetty-requestlog.xml
ssl.etc=${karaf.data}/etc/ssl
application-port-ssl=8443
umount /mnt
kubectl delete pod nexus-***