Kubernetes
You could host your own Atuin server using the Kubernetes platform.
Create a secrets.yaml file for the database credentials:
apiVersion: v1kind: Secretmetadata: name: atuin-secretstype: OpaquestringData: ATUIN_DB_USERNAME: atuin ATUIN_DB_PASSWORD: seriously-insecure ATUIN_HOST: "127.0.0.1" ATUIN_PORT: "8888" ATUIN_OPEN_REGISTRATION: "true" ATUIN_DB_URI: "postgres://atuin:seriously-insecure@postgres/atuin"immutable: trueCreate a atuin.yaml file for the Atuin server:
---apiVersion: apps/v1kind: Deploymentmetadata: name: postgres namespace: atuinspec: replicas: 1 strategy: type: Recreate # This is important to ensure duplicate pods don't run and cause corruption selector: matchLabels: io.kompose.service: postgres template: metadata: labels: io.kompose.service: postgres spec: containers: - name: postgresql image: postgres:14 ports: - containerPort: 5432 env: - name: POSTGRES_DB value: atuin - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: atuin-secrets key: ATUIN_DB_PASSWORD optional: false - name: POSTGRES_USER valueFrom: secretKeyRef: name: atuin-secrets key: ATUIN_DB_USERNAME optional: false lifecycle: preStop: exec: # This ensures graceful shutdown see: https://stackoverflow.com/a/75829325/3437018 # Potentially consider using a `StatefulSet` instead of a `Deployment` command: ["/usr/local/bin/pg_ctl stop -D /var/lib/postgresql/data -w -t 60 -m fast"] resources: requests: cpu: 100m memory: 100Mi limits: cpu: 250m memory: 600Mi volumeMounts: - mountPath: /var/lib/postgresql/data/ name: database volumes: - name: database persistentVolumeClaim: claimName: database---apiVersion: apps/v1kind: Deploymentmetadata: name: atuinspec: replicas: 1 selector: matchLabels: io.kompose.service: atuin template: metadata: labels: io.kompose.service: atuin spec: containers: - args: - server - start env: - name: ATUIN_DB_URI valueFrom: secretKeyRef: name: atuin-secrets key: ATUIN_DB_URI optional: false - name: ATUIN_HOST value: 0.0.0.0 - name: ATUIN_PORT value: "8888" - name: ATUIN_OPEN_REGISTRATION value: "true" image: ghcr.io/atuinsh/atuin:latest name: atuin ports: - containerPort: 8888 resources: limits: cpu: 250m memory: 1Gi requests: cpu: 250m memory: 1Gi volumeMounts: - mountPath: /config name: atuin-claim0 volumes: - name: atuin-claim0 persistentVolumeClaim: claimName: atuin-claim0---apiVersion: v1kind: Servicemetadata: labels: io.kompose.service: atuin name: atuinspec: type: NodePort ports: - name: "8888" port: 8888 nodePort: 30530 selector: io.kompose.service: atuin---apiVersion: v1kind: Servicemetadata: labels: io.kompose.service: postgres name: postgresspec: type: ClusterIP selector: io.kompose.service: postgres ports: - protocol: TCP port: 5432 targetPort: 5432---kind: PersistentVolumeapiVersion: v1metadata: name: database-pv labels: app: database type: localspec: storageClassName: manual capacity: storage: 300Mi accessModes: - ReadWriteOnce hostPath: path: "/Users/firstname.lastname/.kube/database"---apiVersion: v1kind: PersistentVolumeClaimmetadata: labels: io.kompose.service: database name: databasespec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 300Mi---apiVersion: v1kind: PersistentVolumeClaimmetadata: labels: io.kompose.service: atuin-claim0 name: atuin-claim0spec: accessModes: - ReadWriteOnce resources: requests: storage: 10MiFinally, you may want to use a separate namespace for atuin, by creating a namespaces.yaml file:
apiVersion: v1kind: Namespacemetadata: name: atuin-namespace labels: name: atuinNote that this configuration will store the database folder outside the kubernetes cluster, in the folder /Users/firstname.lastname/.kube/database of the host system by configuring the storageClassName to be manual. In a real enterprise setup, you would probably want to store the database content permanently in the cluster, and not in the host system.
You should also change the password string in ATUIN_DB_PASSWORD and ATUIN_DB_URI in thesecrets.yaml file to a more secure one.
The atuin service on the port 30530 of the host system. That is configured by the nodePort property. Kubernetes has a strict rule that you are not allowed to expose a port numbered lower than 30000. To make the clients work, you can simply set the port in in your config.toml file, e.g. sync_address = "http://192.168.1.10:30530".
Deploy the Atuin server using kubectl:
kubectl apply -f ./namespaces.yaml kubectl apply -n atuin-namespace \ -f ./secrets.yaml \ -f ./atuin.yamlThe sample files above are also in the k8s folder of the atuin repository.
Creating backups of the Postgres database
Now you’re up and running it’s a good time to think about backups.
You can create a CronJob which uses pg_dump to create a backup of the database. This example runs weekly and dumps to the local disk on the node.
apiVersion: batch/v1kind: CronJobmetadata: name: atuin-db-backupspec: schedule: "0 0 * * 0" # Run every Sunday at midnight jobTemplate: spec: template: spec: containers: - name: atuin-db-backup-pg-dump image: postgres:14 command: [ "/bin/bash", "-c", "pg_dump --host=postgres --username=atuin --format=c --file=/backup/atuin-backup-$(date +'%Y-%m-%d').pg_dump", ] env: - name: PGPASSWORD valueFrom: secretKeyRef: name: atuin-secrets key: ATUIN_DB_PASSWORD optional: false volumeMounts: - name: backup-volume mountPath: /backup restartPolicy: OnFailure volumes: - name: backup-volume hostPath: path: /somewhere/on/node/for/database-backups type: DirectoryConfigure/update the example yaml with the following:
- Set a more or less frequent schedule with the
scheduleproperty. - Replace
/somewhere/on/node/for/database-backupswith a path on your node or reconfigure to use aPersistentVolumeinstead ofhostPath. --format=couputs a format that can be restored withpg_restore. Useplainif you want.sqlfiles outputted instead.