1import { deployTmpl } from '../../k8sF/genericDeploymentF.mts'2import { kubeActionPvc } from '../../k8sF/pvcF/kubeActionPvcF.mts'3import { configMapWithHash } from '../../k8sF/configMapWithHashAI.mts'4import { pvcVolumeMounts } from '../../k8sF/pvcVolumeMountsF.mts'5import { resourcesAction } from '../../k8sF/resourcesActionF.mts'6import { waitForDeploymentRollout } from '../../k8sF/waitForDeployRolloutAI.mts'7import { getKlusterCtx, enterKlusterCtxs } from '../../k8sF/ctxF/klusterCtxF.mts'8import { getAction } from '../../ctxF/actionCtxF.mts'9import { appCfgCtx } from '../../k8sF/ctxF/appCfgCtxF.mts'10import { isDirectlyRun } from '../../../serverF/isDirectlyRunF.mts'11import { type importMetaUrlType } from '../../../ptDirF.mts'12import { torImage, torContCmd, torDataPath, torHiddenServiceDir, torDataSizeGb, genTorrc } from './torCfgF.mjs'13import { genTorOnionKeyIfMissing } from './genTorOnionKeyAI.mts'15export const eptTorOnionK8sRes = {kind: 'Deployment', apiVersion: 'apps/v1'}17export const eptTorOnion = async ({klusterCfg, name, targetServiceName, targetPortNo, importMetaUrl}: {18 klusterCfg: any, name: string, targetServiceName: string, targetPortNo: number, importMetaUrl?: string,19}) => {20 const fullConfig = {klusterCfg, name, targetServiceName, targetPortNo, importMetaUrl}21 if (importMetaUrl && !isDirectlyRun(importMetaUrl)) return fullConfig23 enterKlusterCtxs(klusterCfg)24 if (importMetaUrl) appCfgCtx.enterWith({importMetaUrl: importMetaUrl as importMetaUrlType})25 const {cluster_name} = getKlusterCtx()28 const kubeSecretName = `secrets2-${name}`29 const onionKey = action === 'delete' ? undefined : genTorOnionKeyIfMissing({secretName: name})32 const {configMap: torrcCfgMap, volume: torrcVol} = configMapWithHash({33 name: `${name}-torrc`, data: {torrc}, mountPath: '/etc/tor',34 })36 const secKeySecret = onionKey37 ? {apiVersion: 'v1', kind: 'Secret', metadata: {name: kubeSecretName}, data: {'hs_ed25519_secret_key': onionKey.secKeyFileBytes.toString('base64')}}38 : {apiVersion: 'v1', kind: 'Secret', metadata: {name: kubeSecretName}}39 const secKeyVolName = `${name}-seckey`40 const secKeyVolume = {name: secKeyVolName, secret: {secretName: kubeSecretName, defaultMode: 0o400}}41 const secKeyMount = {name: secKeyVolName, mountPath: '/tor-seckey', readOnly: true}43 const {volumes: pvcVols, volumeMounts: pvcMnts} = pvcVolumeMounts({name, mountPath: torDataPath})45 const initCmd = `mkdir -p ${torHiddenServiceDir} && ([ -f ${torHiddenServiceDir}/hs_ed25519_secret_key ] || cp /tor-seckey/hs_ed25519_secret_key ${torHiddenServiceDir}/) && chmod 700 ${torDataPath} ${torHiddenServiceDir} && chmod 600 ${torHiddenServiceDir}/*`47 const deployment = deployTmpl({48 name,49 volumes: [...pvcVols, torrcVol, secKeyVolume],50 initContainers: [{51 name: `${name}-init`,52 image: torImage,53 command: ['sh', '-c', initCmd],54 volumeMounts: [...pvcMnts, secKeyMount],55 }],56 containers: [{57 name,58 image: torImage,59 command: torContCmd,60 volumeMounts: [61 ...pvcMnts,62 {name: torrcVol.name, mountPath: '/etc/tor/torrc', subPath: 'torrc'},63 ],64 }],65 })67 const resources = [torrcCfgMap, secKeySecret, deployment]68 await Promise.all([69 resourcesAction({resources, action, cluster_name}),70 kubeActionPvc({action, cluster_name, name, sizeGb: torDataSizeGb}),71 ])73 if (action === 'apply') {74 await waitForDeploymentRollout({resource: deployment, cluster_name})75 console.log(`\nOnion service available at http://${onionKey?.onionAddr}`)76 }77}